2011-03-15 93 views
32

如何使用C#從Windows服務運行EXE程序?如何使用C#從Windows服務運行EXE程序?

這是我的代碼:

System.Diagnostics.Process.Start(@"E:\PROJECT XL\INI SQLLOADER\ConsoleApplication2\ConsoleApplication2\ConsoleApplication2\bin\Debug\ConsoleApplication2.exe"); 

當我運行此服務,應用程序沒有啓動。
我的代碼有什麼問題?

+1

據我可以告訴有什麼錯書面,你得到一個異常的代碼? –

+0

告訴我們你運行這個程序時發生了什麼? – NT88

回答

0

我想你是複製.exe到不同的位置。這可能是我猜測的問題。當你複製exe文件時,你不會複製它的依賴關係。

所以,你可以做的是,把所有相關DLL在GAC使任何.NET EXE可以訪問它

否則,不要複製EXE到新的位置。只需創建一個環境變量並在您的C#中調用exe。由於路徑是在環境變量中定義的,因此可以通過c#程序訪問exe。

更新:

以前我有某種相同的問題,在我的C#.NET 3.5的項目中,我試圖從運行C#.NET代碼的.exe文件和EXE那不過是另一個項目exe(我爲我的功能添加了很少的支持dll)以及我在exe應用程序中使用的那些dll方法。最後,我通過將該應用程序創建爲同一解決方案的單獨項目來解決此問題,並將該項目輸出添加到了我的部署項目中。根據這個場景我回答說,如果它不是他想要的,那我非常抱歉。

+1

什麼讓你覺得EXE被複制到不同的位置? –

46

這絕不會工作,至少不是在Windows Vista或更高版本下。關鍵的問題是你試圖從Windows服務中而不是標準的Windows應用程序中執行此操作。您所展示的代碼可以在Windows窗體,WPF或控制檯應用程序中正常工作,但在Windows服務中根本無法使用。

Windows服務無法啓動其他應用程序,因爲它們沒有在任何特定用戶的上下文中運行。不像普通的Windows應用程序,services are now run in an isolated session並禁止與用戶或桌面進行交互。這不會讓應用程序運行。

更多信息,回答這些相關的問題,請:

最好的解決你的問題,因爲你可能猜想到目前爲止,是創建一個標準的Windows應用程序而不是服務。它們被設計爲由特定用戶運行並且與該用戶的桌面相關聯。這樣,您可以使用您已經顯示的代碼隨時運行其他應用程序。

假設您的控制檯應用程序不需要任何接口或輸出,另一種可能的解決方案是指示進程不創建窗口。這將阻止Windows阻止您的流程創建,因爲它不會再請求創建控制檯窗口。你可以在this answer找到相關的代碼到相關的問題。

+3

基於EXE的名稱,我猜測他正試圖啓動一個控制檯應用程序,因此不期望與它進行交互 - 所以從服務運行它沒有任何問題。 – Gabe

+0

@Gabe:控制檯應用程序仍然顯示一個界面。應該在哪裏顯示該界面,缺少桌面? –

+0

感謝您的回答,但是如果我打電話給bat文件並且不是問題。 – xoops

1

您可以在Windows XP中很好地從Windows服務執行.exe。我過去自己做過。

您需要確保在Windows服務屬性中選中了「允許與桌面交互」選項。如果沒有完成,它將不會執行。

我需要在Windows 7或Vista中檢查,因爲這些版本需要額外的安全權限,因此可能會引發錯誤,但我確定可以直接或間接地實現此功能。對於XP我確信自己已經完成了。

+0

每當打開一個exe文件時它會提示贏取7。 –

-9

System.Diagnostics.Process.Start(「Exe Name」);

+0

其不工作.. –

2

首先,我們要創建一個運行在 系統帳戶下的Windows服務。該服務將負責在當前活動的用戶會話內產生一個 交互式進程。這個 新創建的進程將顯示一個用戶界面,並以完整的管理權限運行。當第一個用戶登錄到計算機時,此服務將啓動 並將在Session0中運行;但是此服務產生的進程將在當前登錄的用戶的當前 的桌面上運行。我們將這個服務稱爲LoaderService。

接下來,winlogon.exe進程負責管理用戶登錄 和註銷過程。我們知道每個登錄到計算機的用戶都將擁有唯一的會話ID和與其會話相關的相應的 winlogon.exe進程。現在,我們在上面提到了 ,LoaderService在System帳戶下運行。我們還通過 確認計算機上的每個winlogon.exe進程都在 系統帳戶下運行。因爲系統帳戶是 LoaderService和winlogon.exe進程的所有者,所以我們的LoaderService 可以複製winlogon.exe進程 的訪問令牌(和會話ID),然後調用Win32 API函數CreateProcessAsUser來啓動 處理成登錄用戶的當前活動會話。由於 位於複製的 winlogon.exe進程的訪問令牌中的會話ID大於0,我們可以使用該令牌啓動交互式 進程。

試試這個。 Subverting Vista UAC in Both 32 and 64 bit Architectures

3

我試過這篇文章Code Project,它對我來說工作正常。 我也使用過這些代碼。文章在屏幕截圖中很好解釋。

我加入必要的解釋,這種情況下

您剛纔啓動您的計算機,並即將登錄。登錄時,系統會爲您分配唯一的會話ID。在Windows Vista中,第一個登錄到計算機的用戶被操作系統分配的會話ID爲1。下一個要登錄的用戶將被分配一個會話ID 2.等等等等。您可以從任務管理器中的用戶選項卡查看分配給每個登錄用戶的會話ID。 enter image description here

但是,您的Windows服務被帶到會話ID爲0之下。此會話與其他會話隔離。這最終阻止Windows服務調用在用戶會話的1或2下運行的應用程序。

爲了從Windows服務調用應用程序,您需要從winlogon.exe複製控件,該控件作爲當前登錄用戶,如圖所示在下面的截圖。 enter image description here

重要代碼

// obtain the process id of the winlogon process that 
// is running within the currently active session 
Process[] processes = Process.GetProcessesByName("winlogon"); 
foreach (Process p in processes) 
{ 
    if ((uint)p.SessionId == dwSessionId) 
    { 
     winlogonPid = (uint)p.Id; 
    } 
} 

// obtain a handle to the winlogon process 
hProcess = OpenProcess(MAXIMUM_ALLOWED, false, winlogonPid); 

// obtain a handle to the access token of the winlogon process 
if (!OpenProcessToken(hProcess, TOKEN_DUPLICATE, ref hPToken)) 
{ 
    CloseHandle(hProcess); 
    return false; 
} 

// Security attibute structure used in DuplicateTokenEx and CreateProcessAsUser 
// I would prefer to not have to use a security attribute variable and to just 
// simply pass null and inherit (by default) the security attributes 
// of the existing token. However, in C# structures are value types and therefore 
// cannot be assigned the null value. 
SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES(); 
sa.Length = Marshal.SizeOf(sa); 

// copy the access token of the winlogon process; 
// the newly created token will be a primary token 
if (!DuplicateTokenEx(hPToken, MAXIMUM_ALLOWED, ref sa, 
    (int)SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, 
    (int)TOKEN_TYPE.TokenPrimary, ref hUserTokenDup)) 
    { 
     CloseHandle(hProcess); 
     CloseHandle(hPToken); 
     return false; 
    } 

STARTUPINFO si = new STARTUPINFO(); 
si.cb = (int)Marshal.SizeOf(si); 

// interactive window station parameter; basically this indicates 
// that the process created can display a GUI on the desktop 
si.lpDesktop = @"winsta0\default"; 

// flags that specify the priority and creation method of the process 
int dwCreationFlags = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE; 

// create a new process in the current User's logon session 
bool result = CreateProcessAsUser(hUserTokenDup, // client's access token 
          null,    // file to execute 
          applicationName, // command line 
          ref sa,   // pointer to process SECURITY_ATTRIBUTES 
          ref sa,   // pointer to thread SECURITY_ATTRIBUTES 
          false,   // handles are not inheritable 
          dwCreationFlags, // creation flags 
          IntPtr.Zero,  // pointer to new environment block 
          null,    // name of current directory 
          ref si,   // pointer to STARTUPINFO structure 
          out procInfo  // receives information about new process 
          ); 
+0

工作完美的我。通過Windows服務請求掃描時,我能夠顯示掃描儀中的錯誤。謝謝 –

+0

如果是這樣做解決方案的+1。 – Vijayaraghavan

+0

我已經+1了答案 –

相關問題