You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Node.js/Electron获取并操作Windows虚拟桌面信息?

解决方案:Electron实现Windows虚拟桌面管理功能

针对你遇到的node-gyp编译问题,推荐两种无需复杂编译的实现方案,均适配Windows 10+系统:


方案一:使用预编译npm包(推荐)

virtual-desktop-accessor是一款预编译的第三方包,无需node-gyp编译,直接调用Windows原生虚拟桌面API,能完美实现你的需求。

步骤1:安装依赖

npm install virtual-desktop-accessor

步骤2:修改main.js实现完整功能

const { app, Tray, Menu } = require("electron");
const vda = require("virtual-desktop-accessor");

let tray = null;
let currentDesktop = null;
let allDesktops = [];

// 更新托盘提示和右键菜单
function updateUI() {
  const menuItems = allDesktops.map(desktop => ({
    label: desktop.name,
    type: "radio",
    checked: desktop.id === currentDesktop.id,
    click: () => vda.switchToVirtualDesktop(desktop.id)
  }));
  menuItems.push({ type: "separator" });
  menuItems.push({ label: "Exit", role: "quit" });

  const contextMenu = Menu.buildFromTemplate(menuItems);
  tray.setToolTip(currentDesktop.name);
  tray.setContextMenu(contextMenu);
}

app.whenReady().then(async () => {
  tray = new Tray("./assets/icons/monitor.ico");

  // 初始化获取桌面信息
  allDesktops = await vda.getAllVirtualDesktops();
  currentDesktop = await vda.getCurrentVirtualDesktop();
  updateUI();

  // 监听虚拟桌面切换事件
  vda.onVirtualDesktopChanged(async () => {
    currentDesktop = await vda.getCurrentVirtualDesktop();
    // 刷新桌面列表(适配用户增删/重命名桌面)
    allDesktops = await vda.getAllVirtualDesktops();
    updateUI();
  });
});

方案二:无依赖调用PowerShell脚本

如果不想引入第三方包,可以通过child_process调用PowerShell脚本直接操作Windows COM接口,完全避免npm包的编译问题。

核心功能实现代码

const { app, Tray, Menu } = require("electron");
const { exec } = require("child_process");

let tray = null;

// 获取所有虚拟桌面信息(ID+名称)
function getAllDesktops() {
  return new Promise((resolve, reject) => {
    const psScript = `
Add-Type @"
using System;
using System.Runtime.InteropServices;
using System.Collections.Generic;

public class VirtualDesktopHelper {
    [ComImport, Guid("f31574d6-b682-4cdc-bd56-1827860abec6"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    private interface IVirtualDesktopManagerInternal {
        int GetCount();
        void GetDesktopIds(out Guid[] desktopIds);
        object GetDesktopById(Guid desktopId);
    }

    [ComImport, Guid("c5e0cdca-7b6e-41b2-9fc4-d93975cc467b")]
    private class CVirtualDesktopManagerInternal { }

    [ComImport, Guid("a1841308-3d7b-4f6d-947e-06540820213"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    private interface IVirtualDesktop {
        int GetID(out Guid id);
        int GetName(out string name);
    }

    public static List<object> GetAllDesktops() {
        var list = new List<object>();
        IVirtualDesktopManagerInternal manager = (IVirtualDesktopManagerInternal)new CVirtualDesktopManagerInternal();
        Guid[] ids = null;
        manager.GetDesktopIds(out ids);
        foreach (var id in ids) {
            var desktop = (IVirtualDesktop)manager.GetDesktopById(id);
            string name = "";
            desktop.GetName(out name);
            list.Add(new { Id = id.ToString(), Name = name });
        }
        return list;
    }
}
"@

[VirtualDesktopHelper]::GetAllDesktops() | ConvertTo-Json
    `;
    exec(`powershell -Command "${psScript.replace(/"/g, '\\"')}"`, (error, stdout) => {
      error ? reject(error) : resolve(JSON.parse(stdout));
    });
  });
}

// 切换到指定虚拟桌面
function switchToDesktop(desktopId) {
  const psScript = `
Add-Type @"
using System;
using System.Runtime.InteropServices;

public class VirtualDesktopHelper {
    [ComImport, Guid("f31574d6-b682-4cdc-bd56-1827860abec6"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    private interface IVirtualDesktopManagerInternal {
        void SwitchDesktop(Guid desktopId);
    }

    [ComImport, Guid("c5e0cdca-7b6e-41b2-9fc4-d93975cc467b")]
    private class CVirtualDesktopManagerInternal { }

    public static void SwitchToDesktop(string id) {
        IVirtualDesktopManagerInternal manager = (IVirtualDesktopManagerInternal)new CVirtualDesktopManagerInternal();
        manager.SwitchDesktop(Guid.Parse(id));
    }
}
"@

[VirtualDesktopHelper]::SwitchToDesktop("${desktopId}")
    `;
  exec(`powershell -Command "${psScript.replace(/"/g, '\\"')}"`);
}

// 轮询监听桌面切换事件
function startDesktopChangeListener(callback) {
  let lastDesktopId = null;
  setInterval(async () => {
    const psScript = `
Add-Type @"
using System;
using System.Runtime.InteropServices;

public class VirtualDesktopHelper {
    [ComImport, Guid("f31574d6-b682-4cdc-bd56-1827860abec6"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    private interface IVirtualDesktopManagerInternal {
        int GetCurrentDesktopId(out Guid desktopId);
    }

    [ComImport, Guid("c5e0cdca-7b6e-41b2-9fc4-d93975cc467b")]
    private class CVirtualDesktopManagerInternal { }

    public static string GetCurrentDesktopId() {
        Guid id = Guid.Empty;
        IVirtualDesktopManagerInternal manager = (IVirtualDesktopManagerInternal)new CVirtualDesktopManagerInternal();
        manager.GetCurrentDesktopId(out id);
        return id.ToString();
    }
}
"@

[VirtualDesktopHelper]::GetCurrentDesktopId()
    `;
    exec(`powershell -Command "${psScript.replace(/"/g, '\\"')}"`, (error, stdout) => {
      if (!error) {
        const currentId = stdout.trim();
        if (currentId !== lastDesktopId && lastDesktopId !== null) callback();
        lastDesktopId = currentId;
      }
    });
  }, 500);
}

// 初始化应用
app.whenReady().then(async () => {
  tray = new Tray("./assets/icons/monitor.ico");

  // 更新托盘UI
  async function updateUI() {
    const allDesktops = await getAllDesktops();
    const currentId = await new Promise((resolve) => {
      const psScript = `
Add-Type @"
using System;
using System.Runtime.InteropServices;

public class VirtualDesktopHelper {
    [ComImport, Guid("f31574d6-b682-4cdc-bd56-1827860abec6"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    private interface IVirtualDesktopManagerInternal {
        int GetCurrentDesktopId(out Guid desktopId);
    }

    [ComImport, Guid("c5e0cdca-7b6e-41b2-9fc4-d93975cc467b")]
    private class CVirtualDesktopManagerInternal { }

    public static string GetCurrentDesktopId() {
        Guid id = Guid.Empty;
        IVirtualDesktopManagerInternal manager = (IVirtualDesktopManagerInternal)new CVirtualDesktopManagerInternal();
        manager.GetCurrentDesktopId(out id);
        return id.ToString();
    }
}
"@

[VirtualDesktopHelper]::GetCurrentDesktopId()
      `;
      exec(`powershell -Command "${psScript.replace(/"/g, '\\"')}"`, (error, stdout) => {
        resolve(stdout.trim());
      });
    });
    const currentDesktop = allDesktops.find(d => d.Id === currentId);

    const menuItems = allDesktops.map(desktop => ({
      label: desktop.Name,
      type: "radio",
      checked: desktop.Id === currentId,
      click: () => switchToDesktop(desktop.Id)
    }));
    menuItems.push({ type: "separator" });
    menuItems.push({ label: "Exit", role: "quit" });

    const contextMenu = Menu.buildFromTemplate(menuItems);
    tray.setToolTip(currentDesktop?.Name || "未知桌面");
    tray.setContextMenu(contextMenu);
  }

  await updateUI();
  startDesktopChangeListener(updateUI);
});

方案对比

方案优点缺点
预编译npm包原生事件监听、性能好、代码简洁仅支持Windows平台
PowerShell脚本无npm依赖、完全避免编译问题采用轮询监听、代码复杂度高

内容的提问来源于stack exchange,提问作者JShoe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 11:02:57