2011-03-15 94 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了答案 –

相关问题