2025-01-03 00:01:57 +08:00

190 lines
5.4 KiB
JavaScript

const { execFile } = require("child_process");
const { promisify } = require("util");
const fs = require("fs");
const path = require("path");
const os = require("os");
const execFileAsync = promisify(execFile);
const readFileAsync = promisify(fs.readFile);
const unlinkAsync = promisify(fs.unlink);
// Windows C# 截图代码
const csharpScript = Buffer.from(
`
using System;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Drawing.Imaging;
public class ScreenCapture {
[DllImport("user32.dll")]
static extern IntPtr GetDC(IntPtr hwnd);
[DllImport("user32.dll")]
static extern int ReleaseDC(IntPtr hwnd, IntPtr hdc);
[DllImport("gdi32.dll")]
static extern IntPtr CreateCompatibleDC(IntPtr hdc);
[DllImport("gdi32.dll")]
static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, int width, int height);
[DllImport("gdi32.dll")]
static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);
[DllImport("gdi32.dll")]
static extern bool BitBlt(IntPtr hdcDest, int xDest, int yDest, int width, int height,
IntPtr hdcSrc, int xSrc, int ySrc, int rop);
[DllImport("gdi32.dll")]
static extern bool DeleteDC(IntPtr hdc);
[DllImport("gdi32.dll")]
static extern bool DeleteObject(IntPtr hObject);
[DllImport("user32.dll")]
static extern bool GetCursorPos(ref Point point);
[DllImport("user32.dll")]
static extern bool GetWindowRect(IntPtr hwnd, ref Rectangle rect);
public static void CaptureScreen(string outputPath) {
IntPtr desktopDC = GetDC(IntPtr.Zero);
Rectangle bounds = System.Windows.Forms.Screen.PrimaryScreen.Bounds;
IntPtr memoryDC = CreateCompatibleDC(desktopDC);
IntPtr bitmap = CreateCompatibleBitmap(desktopDC, bounds.Width, bounds.Height);
IntPtr oldBitmap = SelectObject(memoryDC, bitmap);
try {
BitBlt(memoryDC, 0, 0, bounds.Width, bounds.Height, desktopDC, 0, 0, 0x00CC0020);
using (var bmp = Image.FromHbitmap(bitmap)) {
bmp.Save(outputPath, ImageFormat.Png);
}
}
finally {
SelectObject(memoryDC, oldBitmap);
DeleteObject(bitmap);
DeleteDC(memoryDC);
ReleaseDC(IntPtr.Zero, desktopDC);
}
}
}`
).toString("base64");
// Windows 截图实现
async function captureWindowsScreen() {
const tmpFile = path.join(os.tmpdir(), `screen-${Date.now()}.png`);
try {
// 使用base64编码的C#代码执行
const command = `
$code = [System.Text.Encoding]::UTF8.GetString([Convert]::FromBase64String('${csharpScript}'));
Add-Type -TypeDefinition $code;
[ScreenCapture]::CaptureScreen('${tmpFile.replace(/\\/g, "\\\\")}');
`;
await execFileAsync("powershell", [
"-NoProfile",
"-NonInteractive",
"-ExecutionPolicy",
"Bypass",
"-Command",
command,
]);
// 读取截图
const imageBuffer = await readFileAsync(tmpFile);
return `data:image/png;base64,${imageBuffer.toString("base64")}`;
} catch (error) {
console.error("Windows截图失败:", error);
return null;
} finally {
// 清理临时文件
await unlinkAsync(tmpFile).catch(() => {});
}
}
// macOS 截图实现
async function captureMacScreen() {
const tmpFile = path.join(os.tmpdir(), `screen-${Date.now()}.png`);
try {
await execFileAsync("screencapture", ["-x", "-C", "-T", "0", tmpFile]);
const imageBuffer = await readFileAsync(tmpFile);
return `data:image/png;base64,${imageBuffer.toString("base64")}`;
} catch (error) {
console.error("macOS截图失败:", error);
return null;
} finally {
await unlinkAsync(tmpFile).catch(() => {});
}
}
// Linux 截图实现
async function captureLinuxScreen() {
const tmpFile = path.join(os.tmpdir(), `screen-${Date.now()}.png`);
try {
// 检查可用的截图工具
let tool = null;
try {
await execFileAsync("which", ["gnome-screenshot"]);
tool = "gnome-screenshot";
} catch {
try {
await execFileAsync("which", ["scrot"]);
tool = "scrot";
} catch {
try {
await execFileAsync("which", ["import"]);
tool = "import";
} catch {
console.error("未找到可用的Linux截图工具");
return null;
}
}
}
// 根据可用工具执行截图
switch (tool) {
case "gnome-screenshot":
await execFileAsync("gnome-screenshot", ["-f", tmpFile]);
break;
case "scrot":
await execFileAsync("scrot", [tmpFile]);
break;
case "import":
await execFileAsync("import", ["-window", "root", tmpFile]);
break;
}
const imageBuffer = await readFileAsync(tmpFile);
return `data:image/png;base64,${imageBuffer.toString("base64")}`;
} catch (error) {
console.error("Linux截图失败:", error);
return null;
} finally {
await unlinkAsync(tmpFile).catch(() => {});
}
}
// 统一的截图接口
async function captureScreen() {
try {
if (process.platform === "darwin") {
return await captureMacScreen();
} else if (process.platform === "win32") {
return await captureWindowsScreen();
} else if (process.platform === "linux") {
return await captureLinuxScreen();
}
} catch (error) {
console.error("截图失败:", error);
}
return null;
}
module.exports = { captureScreen };