移除quickcommand.runCSharp,模拟操作中win下的屏幕截图使用runCsharpFeature实现

This commit is contained in:
fofolee 2025-01-19 16:07:06 +08:00
parent c177584274
commit 272cf488a3
5 changed files with 384 additions and 418 deletions

View File

@ -174,7 +174,6 @@ const runCsharpFeature = async (feature, args = [], options = {}) => {
console.log(featureExePath, args.join(" ")); console.log(featureExePath, args.join(" "));
currentChild = child_process.spawn(featureExePath, args, { currentChild = child_process.spawn(featureExePath, args, {
encoding: null, encoding: null,
windowsHide: true,
}); });
let stdoutData = Buffer.from([]); let stdoutData = Buffer.from([]);

View File

@ -5,328 +5,413 @@ using System.Net.NetworkInformation;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using Microsoft.Win32; using Microsoft.Win32;
using System.Drawing;
using System.Drawing.Imaging;
public class SystemUtils public class SystemUtils
{ {
#region Win32 API #region Win32 API
[DllImport("user32.dll", CharSet = CharSet.Auto)] [DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern int SystemParametersInfo(int uAction, int uParam, string lpvParam, int fuWinIni); private static extern int SystemParametersInfo(int uAction, int uParam, string lpvParam, int fuWinIni);
[DllImport("user32.dll")] [DllImport("user32.dll")]
private static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam); private static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
[DllImport("user32.dll")] [DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow(); private static extern IntPtr GetForegroundWindow();
[DllImport("PowrProf.dll", CharSet = CharSet.Auto, ExactSpelling = true)] [DllImport("PowrProf.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
private static extern bool SetSuspendState(bool hibernate, bool forceCritical, bool disableWakeEvent); private static extern bool SetSuspendState(bool hibernate, bool forceCritical, bool disableWakeEvent);
[DllImport("kernel32.dll")] [DllImport("kernel32.dll")]
private static extern EXECUTION_STATE SetThreadExecutionState(EXECUTION_STATE esFlags); private static extern EXECUTION_STATE SetThreadExecutionState(EXECUTION_STATE esFlags);
private const int SPI_SETDESKWALLPAPER = 20; [DllImport("user32.dll")]
private const int SPIF_UPDATEINIFILE = 0x01; static extern IntPtr GetDesktopWindow();
private const int SPIF_SENDCHANGE = 0x02;
private const int WM_SYSCOMMAND = 0x0112;
private const int SC_MONITORPOWER = 0xF170;
[Flags] [DllImport("user32.dll")]
private enum EXECUTION_STATE : uint static extern IntPtr GetWindowDC(IntPtr hWnd);
[DllImport("gdi32.dll")]
static extern bool BitBlt(IntPtr hdcDest, int nXDest, int nYDest,
int nWidth, int nHeight, IntPtr hdcSrc,
int nXSrc, int nYSrc, int dwRop);
[DllImport("gdi32.dll")]
static extern IntPtr CreateCompatibleBitmap(IntPtr hDC, int nWidth, int nHeight);
[DllImport("gdi32.dll")]
static extern IntPtr CreateCompatibleDC(IntPtr hDC);
[DllImport("gdi32.dll")]
static extern bool DeleteDC(IntPtr hDC);
[DllImport("gdi32.dll")]
static extern bool DeleteObject(IntPtr hObject);
[DllImport("gdi32.dll")]
static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject);
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
}
[DllImport("user32.dll")]
private static extern int GetWindowRect(IntPtr hWnd, ref RECT rect);
[DllImport("user32.dll")]
private static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDC);
private const int SPI_SETDESKWALLPAPER = 20;
private const int SPIF_UPDATEINIFILE = 0x01;
private const int SPIF_SENDCHANGE = 0x02;
private const int WM_SYSCOMMAND = 0x0112;
private const int SC_MONITORPOWER = 0xF170;
[Flags]
private enum EXECUTION_STATE : uint
{
ES_AWAYMODE_REQUIRED = 0x00000040,
ES_CONTINUOUS = 0x80000000,
ES_DISPLAY_REQUIRED = 0x00000002,
ES_SYSTEM_REQUIRED = 0x00000001
}
#endregion
public static void Main(string[] args)
{
if (args.Length == 0 || args[0] == "-h" || args[0] == "--help")
{ {
ES_AWAYMODE_REQUIRED = 0x00000040, ShowHelp();
ES_CONTINUOUS = 0x80000000, return;
ES_DISPLAY_REQUIRED = 0x00000002,
ES_SYSTEM_REQUIRED = 0x00000001
} }
#endregion
public static void Main(string[] args) string type = GetArgumentValue(args, "-type");
if (string.IsNullOrEmpty(type))
{ {
if (args.Length == 0 || args[0] == "-h" || args[0] == "--help") Console.Error.WriteLine("Error: 必须指定操作类型 (-type)");
{ return;
ShowHelp(); }
try
{
switch (type.ToLower())
{
case "wallpaper":
string wallpaperPath = GetArgumentValue(args, "-path");
if (string.IsNullOrEmpty(wallpaperPath))
{
Console.Error.WriteLine("Error: 必须指定壁纸路径 (-path)");
return; return;
} }
SetWallpaper(wallpaperPath);
break;
string type = GetArgumentValue(args, "-type"); case "monitor":
if (string.IsNullOrEmpty(type)) string action = GetArgumentValue(args, "-action");
{ if (string.IsNullOrEmpty(action))
Console.Error.WriteLine("Error: 必须指定操作类型 (-type)"); {
Console.Error.WriteLine("Error: 必须指定动作 (-action)");
return; return;
} }
ControlMonitor(action);
break;
try case "power":
{ string mode = GetArgumentValue(args, "-mode");
switch (type.ToLower()) if (string.IsNullOrEmpty(mode))
{ {
case "wallpaper": Console.Error.WriteLine("Error: 必须指定电源模式 (-mode)");
string wallpaperPath = GetArgumentValue(args, "-path"); return;
if (string.IsNullOrEmpty(wallpaperPath)) }
{ PowerControl(mode);
Console.Error.WriteLine("Error: 必须指定壁纸路径 (-path)"); break;
return;
}
SetWallpaper(wallpaperPath);
break;
case "monitor": case "network":
string action = GetArgumentValue(args, "-action"); string interfaceName = GetArgumentValue(args, "-interface");
if (string.IsNullOrEmpty(action)) string ip = GetArgumentValue(args, "-ip");
{ string mask = GetArgumentValue(args, "-mask");
Console.Error.WriteLine("Error: 必须指定动作 (-action)"); string gateway = GetArgumentValue(args, "-gateway");
return; string dns = GetArgumentValue(args, "-dns");
} ConfigureNetwork(interfaceName, ip, mask, gateway, dns);
ControlMonitor(action); break;
break;
case "power": case "startup":
string mode = GetArgumentValue(args, "-mode"); string appPath = GetArgumentValue(args, "-path");
if (string.IsNullOrEmpty(mode)) string appName = GetArgumentValue(args, "-name");
{ bool remove = HasArgument(args, "-remove");
Console.Error.WriteLine("Error: 必须指定电源模式 (-mode)"); ManageStartup(appPath, appName, remove);
return; break;
}
PowerControl(mode);
break;
case "network": case "shortcut":
string interfaceName = GetArgumentValue(args, "-interface"); string targetPath = GetArgumentValue(args, "-target");
string ip = GetArgumentValue(args, "-ip"); string shortcutPath = GetArgumentValue(args, "-path");
string mask = GetArgumentValue(args, "-mask"); string shortcutArgs = GetArgumentValue(args, "-args");
string gateway = GetArgumentValue(args, "-gateway"); CreateShortcut(targetPath, shortcutPath, shortcutArgs);
string dns = GetArgumentValue(args, "-dns"); break;
ConfigureNetwork(interfaceName, ip, mask, gateway, dns);
break;
case "startup": case "brightness":
string appPath = GetArgumentValue(args, "-path"); string brightness = GetArgumentValue(args, "-level");
string appName = GetArgumentValue(args, "-name"); if (string.IsNullOrEmpty(brightness))
bool remove = HasArgument(args, "-remove"); {
ManageStartup(appPath, appName, remove); Console.Error.WriteLine("Error: 必须指定亮度级别 (-level)");
break; return;
}
SetBrightness(int.Parse(brightness));
break;
case "shortcut": case "screenshot":
string targetPath = GetArgumentValue(args, "-target"); string savePath = GetArgumentValue(args, "-path");
string shortcutPath = GetArgumentValue(args, "-path"); if (string.IsNullOrEmpty(savePath))
string shortcutArgs = GetArgumentValue(args, "-args"); {
CreateShortcut(targetPath, shortcutPath, shortcutArgs); Console.Error.WriteLine("Error: 必须指定保存路径 (-path)");
break; return;
}
CaptureScreenToFile(savePath);
Console.WriteLine("成功保存截图");
break;
case "brightness": default:
string brightness = GetArgumentValue(args, "-level"); Console.Error.WriteLine("Error: 不支持的操作类型");
if (string.IsNullOrEmpty(brightness)) break;
{ }
Console.Error.WriteLine("Error: 必须指定亮度级别 (-level)"); }
return; catch (Exception ex)
} {
SetBrightness(int.Parse(brightness)); Console.Error.WriteLine(string.Format("Error: {0}", ex.Message));
break; }
}
default: private static void SetWallpaper(string path)
Console.Error.WriteLine("Error: 不支持的操作类型"); {
break; if (!File.Exists(path))
} {
} throw new Exception("壁纸文件不存在");
catch (Exception ex)
{
Console.Error.WriteLine(string.Format("Error: {0}", ex.Message));
}
} }
private static void SetWallpaper(string path) SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, path, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
{ Console.WriteLine("成功设置壁纸");
if (!File.Exists(path)) }
{
throw new Exception("壁纸文件不存在");
}
SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, path, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE); private static void ControlMonitor(string action)
Console.WriteLine("成功设置壁纸"); {
IntPtr hWnd = GetForegroundWindow();
switch (action.ToLower())
{
case "off":
SendMessage(hWnd, WM_SYSCOMMAND, SC_MONITORPOWER, 2);
break;
case "on":
SendMessage(hWnd, WM_SYSCOMMAND, SC_MONITORPOWER, -1);
break;
default:
throw new Exception("不支持的显示器操作");
}
Console.WriteLine("成功控制显示器");
}
private static void PowerControl(string mode)
{
switch (mode.ToLower())
{
case "sleep":
SetSuspendState(false, false, false);
break;
case "hibernate":
SetSuspendState(true, false, false);
break;
case "awake":
SetThreadExecutionState(EXECUTION_STATE.ES_CONTINUOUS | EXECUTION_STATE.ES_DISPLAY_REQUIRED | EXECUTION_STATE.ES_SYSTEM_REQUIRED);
break;
case "normal":
SetThreadExecutionState(EXECUTION_STATE.ES_CONTINUOUS);
break;
default:
throw new Exception("不支持的电源模式");
}
Console.WriteLine("成功设置电源模式");
}
private static void ConfigureNetwork(string interfaceName, string ip, string mask, string gateway, string dns)
{
// 使用netsh命令配置网络
StringBuilder command = new StringBuilder();
command.AppendFormat("interface ip set address \"{0}\" static {1} {2}", interfaceName, ip, mask);
if (!string.IsNullOrEmpty(gateway))
{
command.AppendFormat(" {0}", gateway);
} }
private static void ControlMonitor(string action) ProcessStartInfo startInfo = new ProcessStartInfo
{ {
IntPtr hWnd = GetForegroundWindow(); FileName = "netsh",
switch (action.ToLower()) Arguments = command.ToString(),
{ UseShellExecute = false,
case "off": RedirectStandardOutput = true,
SendMessage(hWnd, WM_SYSCOMMAND, SC_MONITORPOWER, 2); CreateNoWindow = true
break; };
case "on":
SendMessage(hWnd, WM_SYSCOMMAND, SC_MONITORPOWER, -1); using (Process process = Process.Start(startInfo))
break; {
default: process.WaitForExit();
throw new Exception("不支持的显示器操作"); if (process.ExitCode != 0)
} {
Console.WriteLine("成功控制显示器"); throw new Exception("设置IP地址失败");
}
} }
private static void PowerControl(string mode) if (!string.IsNullOrEmpty(dns))
{ {
switch (mode.ToLower()) command.Clear();
command.AppendFormat("interface ip set dns \"{0}\" static {1}", interfaceName, dns);
startInfo.Arguments = command.ToString();
using (Process process = Process.Start(startInfo))
{
process.WaitForExit();
if (process.ExitCode != 0)
{ {
case "sleep": throw new Exception("设置DNS失败");
SetSuspendState(false, false, false);
break;
case "hibernate":
SetSuspendState(true, false, false);
break;
case "awake":
SetThreadExecutionState(EXECUTION_STATE.ES_CONTINUOUS | EXECUTION_STATE.ES_DISPLAY_REQUIRED | EXECUTION_STATE.ES_SYSTEM_REQUIRED);
break;
case "normal":
SetThreadExecutionState(EXECUTION_STATE.ES_CONTINUOUS);
break;
default:
throw new Exception("不支持的电源模式");
} }
Console.WriteLine("成功设置电源模式"); }
} }
private static void ConfigureNetwork(string interfaceName, string ip, string mask, string gateway, string dns) Console.WriteLine("成功配置网络");
}
private static void ManageStartup(string appPath, string appName, bool remove)
{
string keyPath = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Run";
using (RegistryKey key = Registry.CurrentUser.OpenSubKey(keyPath, true))
{ {
// 使用netsh命令配置网络 if (key == null)
StringBuilder command = new StringBuilder(); {
command.AppendFormat("interface ip set address \"{0}\" static {1} {2}", interfaceName, ip, mask); throw new Exception("无法访问启动项注册表");
if (!string.IsNullOrEmpty(gateway)) }
{
command.AppendFormat(" {0}", gateway);
}
ProcessStartInfo startInfo = new ProcessStartInfo if (remove)
{ {
FileName = "netsh", key.DeleteValue(appName, false);
Arguments = command.ToString(), Console.WriteLine("成功移除开机启动项");
UseShellExecute = false, }
RedirectStandardOutput = true, else
CreateNoWindow = true {
}; key.SetValue(appName, appPath);
Console.WriteLine("成功添加开机启动项");
using (Process process = Process.Start(startInfo)) }
{
process.WaitForExit();
if (process.ExitCode != 0)
{
throw new Exception("设置IP地址失败");
}
}
if (!string.IsNullOrEmpty(dns))
{
command.Clear();
command.AppendFormat("interface ip set dns \"{0}\" static {1}", interfaceName, dns);
startInfo.Arguments = command.ToString();
using (Process process = Process.Start(startInfo))
{
process.WaitForExit();
if (process.ExitCode != 0)
{
throw new Exception("设置DNS失败");
}
}
}
Console.WriteLine("成功配置网络");
} }
}
private static void ManageStartup(string appPath, string appName, bool remove) private static void CreateShortcut(string targetPath, string shortcutPath, string args)
{ {
string keyPath = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Run"; // 使用PowerShell创建快捷方式
using (RegistryKey key = Registry.CurrentUser.OpenSubKey(keyPath, true)) StringBuilder command = new StringBuilder();
{ command.AppendFormat(@"
if (key == null)
{
throw new Exception("无法访问启动项注册表");
}
if (remove)
{
key.DeleteValue(appName, false);
Console.WriteLine("成功移除开机启动项");
}
else
{
key.SetValue(appName, appPath);
Console.WriteLine("成功添加开机启动项");
}
}
}
private static void CreateShortcut(string targetPath, string shortcutPath, string args)
{
// 使用PowerShell创建快捷方式
StringBuilder command = new StringBuilder();
command.AppendFormat(@"
$WshShell = New-Object -comObject WScript.Shell $WshShell = New-Object -comObject WScript.Shell
$Shortcut = $WshShell.CreateShortcut('{0}') $Shortcut = $WshShell.CreateShortcut('{0}')
$Shortcut.TargetPath = '{1}'", $Shortcut.TargetPath = '{1}'",
shortcutPath.Replace("'", "''"), shortcutPath.Replace("'", "''"),
targetPath.Replace("'", "''")); targetPath.Replace("'", "''"));
if (!string.IsNullOrEmpty(args)) if (!string.IsNullOrEmpty(args))
{ {
command.AppendFormat(@" command.AppendFormat(@"
$Shortcut.Arguments = '{0}'", $Shortcut.Arguments = '{0}'",
args.Replace("'", "''")); args.Replace("'", "''"));
} }
command.Append(@" command.Append(@"
$Shortcut.Save()"); $Shortcut.Save()");
ProcessStartInfo startInfo = new ProcessStartInfo ProcessStartInfo startInfo = new ProcessStartInfo
{ {
FileName = "powershell", FileName = "powershell",
Arguments = command.ToString(), Arguments = command.ToString(),
UseShellExecute = false, UseShellExecute = false,
RedirectStandardOutput = true, RedirectStandardOutput = true,
CreateNoWindow = true CreateNoWindow = true
}; };
using (Process process = Process.Start(startInfo)) using (Process process = Process.Start(startInfo))
{ {
process.WaitForExit(); process.WaitForExit();
if (process.ExitCode != 0) if (process.ExitCode != 0)
{ {
throw new Exception("创建快捷方式失败"); throw new Exception("创建快捷方式失败");
} }
}
Console.WriteLine("成功创建快捷方式");
} }
private static void SetBrightness(int level) Console.WriteLine("成功创建快捷方式");
}
private static void SetBrightness(int level)
{
if (level < 0 || level > 100)
{ {
if (level < 0 || level > 100) throw new Exception("亮度级别必须在0-100之间");
{
throw new Exception("亮度级别必须在0-100之间");
}
// 使用PowerShell命令设置亮度
ProcessStartInfo startInfo = new ProcessStartInfo
{
FileName = "powershell",
Arguments = string.Format("(Get-WmiObject -Namespace root/WMI -Class WmiMonitorBrightnessMethods).WmiSetBrightness(1,{0})", level),
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true
};
using (Process process = Process.Start(startInfo))
{
process.WaitForExit();
if (process.ExitCode != 0)
{
throw new Exception("设置亮度失败");
}
}
Console.WriteLine("成功设置亮度");
} }
private static void ShowHelp() // 使用PowerShell命令设置亮度
ProcessStartInfo startInfo = new ProcessStartInfo
{ {
string help = @" FileName = "powershell",
Arguments = string.Format("(Get-WmiObject -Namespace root/WMI -Class WmiMonitorBrightnessMethods).WmiSetBrightness(1,{0})", level),
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true
};
using (Process process = Process.Start(startInfo))
{
process.WaitForExit();
if (process.ExitCode != 0)
{
throw new Exception("设置亮度失败");
}
}
Console.WriteLine("成功设置亮度");
}
private static Image CaptureScreen()
{
IntPtr handle = GetDesktopWindow();
IntPtr hdcSrc = GetWindowDC(handle);
RECT windowRect = new RECT();
GetWindowRect(handle, ref windowRect);
int width = windowRect.right - windowRect.left;
int height = windowRect.bottom - windowRect.top;
IntPtr hdcDest = CreateCompatibleDC(hdcSrc);
IntPtr hBitmap = CreateCompatibleBitmap(hdcSrc, width, height);
IntPtr hOld = SelectObject(hdcDest, hBitmap);
BitBlt(hdcDest, 0, 0, width, height, hdcSrc, 0, 0, 0x00CC0020);
SelectObject(hdcDest, hOld);
DeleteDC(hdcDest);
Image img = Image.FromHbitmap(hBitmap);
DeleteObject(hBitmap);
ReleaseDC(handle, hdcSrc);
return img;
}
private static void CaptureScreenToFile(string path)
{
Image img = CaptureScreen();
img.Save(path, ImageFormat.Png);
img.Dispose();
}
private static void ShowHelp()
{
string help = @"
Windows 使 Windows 使
=================== ===================
@ -378,6 +463,11 @@ utils.exe -type <操作类型> [参数...]
-level <> 0-100 -level <> 0-100
: utils.exe -type brightness -level 75 : utils.exe -type brightness -level 75
8. screenshot -
:
-path <>
: utils.exe -type screenshot -path ""C:\screenshot.png""
: :
-------- --------
1. 1.
@ -385,23 +475,23 @@ utils.exe -type <操作类型> [参数...]
3. 3.
4. 4.
"; ";
Console.WriteLine(help); Console.WriteLine(help);
} }
private static string GetArgumentValue(string[] args, string key) private static string GetArgumentValue(string[] args, string key)
{
for (int i = 0; i < args.Length - 1; i++)
{ {
for (int i = 0; i < args.Length - 1; i++) if (args[i].Equals(key, StringComparison.OrdinalIgnoreCase))
{ {
if (args[i].Equals(key, StringComparison.OrdinalIgnoreCase)) return args[i + 1];
{ }
return args[i + 1];
}
}
return null;
} }
return null;
}
private static bool HasArgument(string[] args, string key) private static bool HasArgument(string[] args, string key)
{ {
return Array.Exists(args, arg => arg.Equals(key, StringComparison.OrdinalIgnoreCase)); return Array.Exists(args, arg => arg.Equals(key, StringComparison.OrdinalIgnoreCase));
} }
} }

View File

@ -3,122 +3,29 @@ const { promisify } = require("util");
const fs = require("fs"); const fs = require("fs");
const path = require("path"); const path = require("path");
const os = require("os"); const os = require("os");
const { runCsharpFeature } = require("../../csharp");
const execFileAsync = promisify(execFile); const execFileAsync = promisify(execFile);
const readFileAsync = promisify(fs.readFile); const readFileAsync = promisify(fs.readFile);
const unlinkAsync = promisify(fs.unlink); const unlinkAsync = promisify(fs.unlink);
// Windows C# 截图代码
const csharpScript = `
using System;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Drawing.Imaging;
using System.Collections.Generic;
using Microsoft.VisualBasic;
public class ScreenCapture
{
[DllImport("user32.dll")]
static extern IntPtr GetDC(IntPtr hwnd);
[DllImport("user32.dll")]
static extern IntPtr GetDesktopWindow();
[DllImport("user32.dll")]
static extern IntPtr GetWindowDC(IntPtr hWnd);
[DllImport("user32.dll")]
static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDC);
[DllImport("gdi32.dll")]
static extern bool BitBlt(IntPtr hdcDest, int nXDest, int nYDest,
int nWidth, int nHeight, IntPtr hdcSrc,
int nXSrc, int nYSrc, int dwRop);
[DllImport("gdi32.dll")]
static extern IntPtr CreateCompatibleBitmap(IntPtr hDC, int nWidth, int nHeight);
[DllImport("gdi32.dll")]
static extern IntPtr CreateCompatibleDC(IntPtr hDC);
[DllImport("gdi32.dll")]
static extern bool DeleteDC(IntPtr hDC);
[DllImport("gdi32.dll")]
static extern bool DeleteObject(IntPtr hObject);
[DllImport("gdi32.dll")]
static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject);
public Image CaptureScreen()
{
return CaptureWindow(GetDesktopWindow());
}
private Image CaptureWindow(IntPtr handle)
{
IntPtr hdcSrc = GetWindowDC(handle);
User32.RECT windowRect = new User32.RECT();
User32.GetWindowRect(handle, ref windowRect);
int width = windowRect.right - windowRect.left;
int height = windowRect.bottom - windowRect.top;
IntPtr hdcDest = CreateCompatibleDC(hdcSrc);
IntPtr hBitmap = CreateCompatibleBitmap(hdcSrc, width, height);
IntPtr hOld = SelectObject(hdcDest, hBitmap);
BitBlt(hdcDest, 0, 0, width, height, hdcSrc, 0, 0, 0x00CC0020);
SelectObject(hdcDest, hOld);
DeleteDC(hdcDest);
Image img = Image.FromHbitmap(hBitmap);
DeleteObject(hBitmap);
ReleaseDC(handle, hdcSrc);
return img;
}
public void CaptureScreenToFile(string filename, ImageFormat format)
{
Image img = CaptureScreen();
img.Save(filename, format);
}
public class User32
{
public struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
}
[DllImport("user32.dll")]
public static extern IntPtr GetWindowRect(IntPtr hWnd, ref RECT rect);
}
public static void Main()
{
ScreenCapture sc = new ScreenCapture();
sc.CaptureScreenToFile(">>tempscreenshot<<", ImageFormat.Png);
}
}
`;
// Windows 截图实现 // Windows 截图实现
async function captureWindowsScreen() { async function captureWindowsScreen() {
const tmpFile = path.join(os.tmpdir(), `screen-${Date.now()}.png`); const tmpFile = path.join(os.tmpdir(), `screen-${Date.now()}.png`);
try { try {
await window.quickcommand.runCsharp( await runCsharpFeature("utils", [
csharpScript.replace(">>tempscreenshot<<", tmpFile.replace(/\\/g, "\\\\")) "-type",
); "screenshot",
"-path",
tmpFile,
]);
const imageBuffer = await readFileAsync(tmpFile); const imageBuffer = await readFileAsync(tmpFile);
return `data:image/png;base64,${imageBuffer.toString("base64")}`; return `data:image/png;base64,${imageBuffer.toString("base64")}`;
} catch (error) { } catch (error) {
console.error("Windows截图失败:", error); console.error("Windows截图失败:", error);
return null; return null;
} finally {
await unlinkAsync(tmpFile).catch(() => {});
} }
} }

View File

@ -42,12 +42,5 @@ export const scriptCommands = {
}, },
], ],
}, },
{
value: "quickcommand.runCsharp",
label: "执行C#脚本",
icon: "script",
outputVariable: "result",
saveOutput: true,
},
], ],
}; };

View File

@ -57,11 +57,11 @@ interface quickcommandApi {
* for (var i = 0; i < 15; i++) { * for (var i = 0; i < 15; i++) {
* // 每一个选项为 json 格式, 使用clickFn注册选项单击事件时id属性是必需的 * // 每一个选项为 json 格式, 使用clickFn注册选项单击事件时id属性是必需的
* opt.push({ * opt.push({
* id: i, * id: i,
* title: `选项${i}`, * title: `选项${i}`,
* description: `选项${i}的描述`, * description: `选项${i}的描述`,
* icon: `http://www.u.tools/favicon.ico`, * icon: `http://www.u.tools/favicon.ico`,
* abcd: `选项${i}的自定义属性`, * abcd: `选项${i}的自定义属性`,
* clickFn:function(e){console.log(e)} * clickFn:function(e){console.log(e)}
* }) * })
* } * }
@ -347,29 +347,6 @@ interface quickcommandApi {
*/ */
runPowerShell(script: string): Promise<string>; runPowerShell(script: string): Promise<string>;
/**
* C# (Promise)
*
* .NET Framework
*
* ```js
* const script = `using System;
* class Program {
* static void Main(string[] args) {
* Console.WriteLine("Hello, World!");
* }
* }`
* quickcommand.runCsharp(script).then(res => {
* console.log(res)
* }).catch(err => {
* console.log(err)
* })
* ```
*
* @param script C#
*/
runCsharp(script: string): Promise<string>;
/** /**
* MacOS AppleScript (Promise) * MacOS AppleScript (Promise)
* *