windows 服務中啟動互動式程式

2021-10-02 05:13:33 字數 3639 閱讀 9010

最近專案中需要在windows服務中啟動互動式程式,還是費了點勁,記錄一下

互動式程式也就是需要與人互動的程式,比如帶有介面的程式,需要接收使用者滑鼠鍵盤訊息的程式。比如 notepad.exe,cmd.exe

非互動式程式也就是跑在後台,不需要人工干預,自己能跑得歡的程式 比如各種服務端程式,類似sshd.exe,各種bat指令碼等

windows程式中啟動第三方程式通常有幾種方式

1)uint win exec(lpcstr lpcmdline, uint ucmdshow); 用得很少

winexec("notepad.exe",sw_show);//啟動notepad.exe

2)int system(char const* _command);

system("dir >dir.txt");//把當前目錄的內容寫入dir.txt

3)hinstance shellexecute(hwnd hwnd, lpctstr lpoperation, lpctstr lpfile, lpctstr lpparameters, lpctstr lpdirectory, int nshowcmd);

shellexecute (null,」open」,」readme.txt」,null,null,sw_show);//開啟readme.txt

lpprocessattributes,指向乙個security_attributes結構體,這個結構體決定是否返回的控制代碼可以被子程序繼承,如果lpprocessattributes引數為空(null),那麼控制代碼不能被繼承。

lpthreadattributes,同lpprocessattribute,不過這個引數決定的是執行緒是否被繼承.通常置為null.

binherithandles,指示新程序是否從呼叫程序處繼承了控制代碼

dwcreationflags,指定附加的、用來控制優先類和程序的建立的標誌。

lpenvironment,指向乙個新程序的環境塊。如果此引數為空,新程序使用呼叫程序的環境。

lpcurrentdirectory,指向乙個以null結尾的字串,這個字串用來指定子程序的工作路徑。這個字串必須是乙個包含驅動器名的絕對路徑。如果這個引數為空,新程序將使用與呼叫程序相同的驅動器和目錄。

lpstartupinfo,指向乙個用於決定新程序的主窗體如何顯示的startupinfo

結構體。

lpprocessinformation,指向乙個用來接收新程序的識別資訊的process_information結構體。

以下這段解釋來自於 解釋為什麼服務裡無法啟動帶互動式介面的程式

windows提供了三類物件:使用者介面物件(user inte***ce)、gdi物件和核心物件。核心物件有安全性,而前兩者沒有。為了對前兩者提供安全性,通過工作站物件(window station)和桌面物件(desktop)來管理使用者介面物件,因為工作站物件和桌面物件有安全特性。簡單說來,工作站是乙個帶有安全特性的物件,它與程序相關聯,包含了乙個或多個桌面物件。當工作站物件被建立時,它被關聯到呼叫程序上,並且被賦給當前session。互動式工作站winsta0,是唯一乙個可以顯示使用者介面,接受使用者輸入的工作站。它被賦給互動式使用者的登入session,包含了鍵盤、滑鼠和顯示裝置。所有其他工作站都是非互動式的,這就意味著它們不能顯示使用者介面,不能接受使用者的輸入。當使用者登入到一台啟用了終端服務的計算機上時,每個使用者都會啟動乙個session。每個session都會與自己的互動式工作站相聯絡。桌面是乙個帶有安全特性的物件,被包含在乙個視窗工作站物件中。乙個桌面物件有乙個邏輯的顯示區域,包含了諸如視窗、選單、鉤子等等這樣的使用者介面物件。

在vista之前,之所以可以通過開啟winsta0和預設桌面顯示對話方塊,是因為不管是服務還是第乙個登入的互動式使用者,都是登入到session 0中。因此,服務程式可以通過強制開啟winsta0和桌面來獲得互動能力。

然而,在vista和windows2008中,session 0專用於服務和其他不與使用者互動的應用程式。第乙個登入進來,可以進行互動式操作的使用者被連到session 1上。第二個登入進行的使用者被分配給session 2,以此類推。session 0完全不支援要與使用者互動的程序。如果採取在服務程序中啟動子程序來顯示對話方塊,子對話方塊將無法顯示;如果採取用openwindowstation系統api開啟winsta0的方法,函式呼叫會失敗。總之,vista和windows2008已經堵上了在session 0中產生介面互動的路。這就是原因所在。

那麼,是否真的沒法在服務中彈出對話方塊了呢?對於服務程序自身來說,確實如此,作業系統已經把這條路堵上了。但是,我們想要的並不是「在服務程序中彈出對話方塊」,我們想要的不過是「當服務出現某些狀況的時候,在桌面上彈出對話方塊」。既然在session 0中無法彈出對話方塊,而我們看到的桌面是session x,並非session 0,很自然的乙個想法是:能不能讓session 0通知其他的session,讓當前桌面正顯示著的session彈乙個對話方塊呢?

事實上是可以的,那麼,就需要獲取當前登入進來的使用者session x

**如下

bool createmyprocess3(lpwstr command_line, dword *exit_code)

zeromemory(&proc_entry, sizeof(proc_entry));

proc_entry.dwsize = sizeof(processentry32);

if (!process32first(snap, &proc_entry))

do }

} while (process32next(snap, &proc_entry));

closehandle(snap);

// 根據sessionid獲取token

if (!wtsqueryusertoken(session_id , &htoken))

//複製新的token

if (!duplicatetokenex(htoken, maximum_allowed, null, securityidentification, tokenprimary, &htokendup))

//建立環境資訊

if (!createenvironmentblock(&penv, htokendup, false))

//設定啟動引數

zeromemory(&si, sizeof(startupinfo));

si.cb = sizeof(startupinfo);

si.lpdesktop = _text("winsta0\\default");

zeromemory(&pi, sizeof(process_information));

//開始建立程序

dword dwcreateflag = normal_priority_class | create_new_console | create_unicode_environment;

if (!createprocessasuser(htoken, null, command_line, null, null, false, dwcreateflag, penv, null, &si, &pi))

destroyenvironmentblock(penv);

closehandle(htokendup);

closehandle(htoken);

return true;

}

這樣,新啟動的程式就可以接收鍵盤滑鼠輸入,來進行互動了

windows互動式登陸

nt和win2000針對域使用者賬號登陸的驗證分別是通過ntlm和kerberos協議,而對本地賬號登陸的驗證是msv1 0協議,使用者通過提供登陸資訊 如使用者名稱和密碼 伺服器將這些資訊傳送到伺服器上的驗證機構,驗證機構通過比較儲存在本地的資料庫檔案 sam 來判斷此使用者的身份真實性,如果通過...

互動式介面

互動式介面 啟動終端後,在終端裝置附加乙個互動式應用程式 runlevel 顯示當前執行的模式 root vm 163 113 centos runlevel n 3init 3 切換至命令列 init 0 停機 千萬不能把initdefault 設定為0 init 1 單使用者模式 init 2 ...

互動式 非互動式,登入式 非登入式Shell

互動式shell和非互動式shell 互動式模式 在終端上執行,shell等待你的輸入,並且立即執行你提交的命令。這種模式被稱作互動式是因為shell與使用者進行互動。這種模式也是大多數使用者非常熟悉的 登入 執行一些命令 退出。當你退出後,shell也終止了。非互動式模式 以shell scrip...