讓在nssm中執行的服務能顯示視窗

更新 發佈閱讀 7 分鐘

在工作上遇到nodejs呼叫執行檔執行失敗問題,最後發現是由於nodejs專案本身有用nssm包成服務,在服務環境的nodejs呼叫的執行檔也執行在服務中,造成程式不會跳出視窗而導致失敗。將程式用nssm包成服務詳細操作可以看這篇

原因是在 Windows Vista / Windows Server 2008 及之後的版本,為了安全性,系統服務預設執行在一個獨立的、非互動的 Session 0 中。而使用者登入後所看到的桌面和視窗是執行在其他 Session (例如 Session 1, Session 2...)。Session 0 中的程序無法直接與使用者的桌面互動,也就是說,它無法顯示圖形化使用者介面 (GUI) 或接收使用者的滑鼠、鍵盤輸入。

簡單範例

正常環境呼叫開啟計算器:

raw-image

在nssm服務環境中呼叫,無法看到計算器:

raw-image

透過psexec將執行檔執行到指定session,讓服務內程式能開啟並顯示powershell視窗

raw-image

準備psExec工具:

  1. 下載鏈接
  2. 下載完成後解壓到喜歡的資料夾

獲得session id:

raw-image

上面下載鏈接頁面的下方有這個工具的參數說明,其中需要我們提供-i參數,這就是我們上面提到的Session id參數;下面我們在nodejs中,通過呼叫window的powershell,獲得圖形界面進程explorer.exe所在的Session id:

const { exec } = require("child_process");
const { promisify } = require("util");
const execPromise = promisify(exec);

/**
 * 異步獲取當前活動的互動式 Session ID (使用 PowerShell Get-Process 和 Base64 編碼)
 * @returns {Promise<number>} 解析成功則返回 Session ID
 */
const getActiveSessionIdByPs = async () => {
const psCommandOriginal = `
        $foundSessionId = $null
        try {
            $explorer = Get-Process -Name explorer -ErrorAction SilentlyContinue | Select-Object -First 1;
            if ($explorer) {
                $foundSessionId = $explorer.SessionId;
            } else {
                $interactiveProcess = Get-Process | Where-Object { $_.SessionId -ne 0 -and $_.SessionId -ne 65536 } | Select-Object -First 1;
                if ($interactiveProcess) {
                     $foundSessionId = $interactiveProcess.SessionId;
                } else {
                     Write-Error "No interactive session process found.";
                }
            }
        } catch {
            Write-Error "Error querying processes: $($_.Exception.Message)";
        }
        Write-Output $foundSessionId
    `;

const psScriptBase64 = Buffer.from(psCommandOriginal, "utf16le").toString(
"base64"
);
const command = `powershell.exe -NoProfile -EncodedCommand ${psScriptBase64}`;
try {
const { stdout, stderr } = await execPromise(command);
const outputTrimmed = stdout.trim();
if (outputTrimmed === "")
throw new Error("PowerShell script did not find an active session ID.");
const activeSessionId = parseInt(outputTrimmed, 10);
if (isNaN(activeSessionId))
throw new Error(
`PowerShell script returned non-numeric output: "${outputTrimmed}"`
);
sessionId = activeSessionId;
return sessionId;
} catch (error) {
console.error("Error executing PowerShell command:", error.message);
if (error.stderr) console.error("Stderr:", error.stderr.trim());
if (error.stdout) console.error("Stdout:", error.stdout.trim());
throw new Error(
`Failed to get active session ID via PowerShell (Base64): ${error.message}`
);
}
};

(async () => {
const sessionId = await getActiveSessionIdByPs();
console.log(sessionId);
})();

透過psexec開啟在指定session開啟程式:

最後在nodejs中用以下指令呼叫psexec,就能在服務中開啟powershell並看到窗口:

await execPromise(`${psexecPath} -accepteula -nobanner -i ${await getActiveSessionIdByPs()} -s powershell.exe`)
提示:要在服務中才能使用-i參數,否則會報錯
raw-image

最後附上完整程式:psexec demo

留言
avatar-img
留言分享你的想法!
avatar-img
s_SoNg的沙龍
4會員
12內容數
s_SoNg的沙龍的其他內容
2025/04/08
準備專案 這邊首先準備一個新的專案,可以參考react官網,完成後參考README.md輸入npm run dev就可以啟動並在瀏覽器看到畫面 準備nssm工具 在google上搜nssm,第一個項目點進去後,找到並下載穩定版,附上下載鏈接 壓縮檔下載完畢後,解壓縮到喜歡的地方,然後進入資料
Thumbnail
2025/04/08
準備專案 這邊首先準備一個新的專案,可以參考react官網,完成後參考README.md輸入npm run dev就可以啟動並在瀏覽器看到畫面 準備nssm工具 在google上搜nssm,第一個項目點進去後,找到並下載穩定版,附上下載鏈接 壓縮檔下載完畢後,解壓縮到喜歡的地方,然後進入資料
Thumbnail
2024/10/30
如果有個算法是2秒以上很耗時的長任務,希望在執行長任務前後修改state渲染loading畫面,可能會難以達到預期效果,會看到loading畫面一閃而過。 把setState改非同步的方法...
2024/10/30
如果有個算法是2秒以上很耗時的長任務,希望在執行長任務前後修改state渲染loading畫面,可能會難以達到預期效果,會看到loading畫面一閃而過。 把setState改非同步的方法...
2024/10/15
利用shapecast函式參與過濾的過程
Thumbnail
2024/10/15
利用shapecast函式參與過濾的過程
Thumbnail
看更多
你可能也想看
Thumbnail
在小小的租屋房間裡,透過蝦皮購物平臺採購各種黏土、模型、美甲材料等創作素材,打造專屬黏土小宇宙的療癒過程。文中分享多個蝦皮挖寶地圖,並推薦蝦皮分潤計畫。
Thumbnail
在小小的租屋房間裡,透過蝦皮購物平臺採購各種黏土、模型、美甲材料等創作素材,打造專屬黏土小宇宙的療癒過程。文中分享多個蝦皮挖寶地圖,並推薦蝦皮分潤計畫。
Thumbnail
小蝸和小豬因購物習慣不同常起衝突,直到發現蝦皮分潤計畫,讓小豬的購物愛好產生價值,也讓小蝸開始欣賞另一半的興趣。想增加收入或改善伴侶間的購物觀念差異?讓蝦皮分潤計畫成為你們的神隊友吧!
Thumbnail
小蝸和小豬因購物習慣不同常起衝突,直到發現蝦皮分潤計畫,讓小豬的購物愛好產生價值,也讓小蝸開始欣賞另一半的興趣。想增加收入或改善伴侶間的購物觀念差異?讓蝦皮分潤計畫成為你們的神隊友吧!
Thumbnail
在工作上遇到nodejs呼叫執行檔執行失敗問題,最後發現是由於nodejs專案本身有用nssm包成服務,在服務環境的nodejs呼叫的執行檔也執行在服務中,造成程式不會跳出視窗而導致失敗。
Thumbnail
在工作上遇到nodejs呼叫執行檔執行失敗問題,最後發現是由於nodejs專案本身有用nssm包成服務,在服務環境的nodejs呼叫的執行檔也執行在服務中,造成程式不會跳出視窗而導致失敗。
Thumbnail
在這篇教學文章中,我們將展示如何使用 Node.js 建立一個簡單的伺服器,並解決常見的跨來源資源共享(CORS)問題,確保伺服器能夠接收並處理來自不同來源的資料。
Thumbnail
在這篇教學文章中,我們將展示如何使用 Node.js 建立一個簡單的伺服器,並解決常見的跨來源資源共享(CORS)問題,確保伺服器能夠接收並處理來自不同來源的資料。
Thumbnail
在網路速度有限的情況下,依序記錄不斷產生的資訊,能統計使用者在頁面上操作了哪些功能。
Thumbnail
在網路速度有限的情況下,依序記錄不斷產生的資訊,能統計使用者在頁面上操作了哪些功能。
Thumbnail
Node.js是一個JavaScript運行環境。它使用了一個非阻塞、事件驅動的I/O模型,使其非常適合用於數據密集型的即時應用程序。簡單來說,Node.js允許你使用JavaScript來編寫伺服器端代碼。 nvm 安裝nvm Windows : 點擊 Releases · coreybut
Thumbnail
Node.js是一個JavaScript運行環境。它使用了一個非阻塞、事件驅動的I/O模型,使其非常適合用於數據密集型的即時應用程序。簡單來說,Node.js允許你使用JavaScript來編寫伺服器端代碼。 nvm 安裝nvm Windows : 點擊 Releases · coreybut
Thumbnail
NPM 全稱為 ( Node Package Manager ),直接翻譯就是 "node套件管理器" ,是 Node.js 預設的,當下載 Node.js 時也會一並下載到本機端並安裝,而 Node.js 則是能讓 JavaScript 語法實現在後端伺服器運行的一種環境,可謂是前端開發的好朋友。
Thumbnail
NPM 全稱為 ( Node Package Manager ),直接翻譯就是 "node套件管理器" ,是 Node.js 預設的,當下載 Node.js 時也會一並下載到本機端並安裝,而 Node.js 則是能讓 JavaScript 語法實現在後端伺服器運行的一種環境,可謂是前端開發的好朋友。
Thumbnail
npm(全名 Node Package Manager,node套件管理器)
Thumbnail
npm(全名 Node Package Manager,node套件管理器)
Thumbnail
npm 做為 node 套件版本管理工具,今天來學習如何使用 npm 升級 package.json 版號管理,可以對一個專案版號管理更加制式化 major 目標升級版號 指令 npm version --new-version major 範例 v1.0.0 -> v2.0.0 mi
Thumbnail
npm 做為 node 套件版本管理工具,今天來學習如何使用 npm 升級 package.json 版號管理,可以對一個專案版號管理更加制式化 major 目標升級版號 指令 npm version --new-version major 範例 v1.0.0 -> v2.0.0 mi
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News