1

我有一个在 64 位 Windows Server 2008 机器上作为服务运行的 C++ 程序。该程序尝试使用以下命令启动批处理文件:

system(C:\pathtofile\file.bat)

在 32 位 Windows Server 2003 中,这工作正常(批处理文件已执行),但在 Windows Server 2008 上,批处理文件未执行,我得到返回值 0xC0000142(我让批处理文件将一些文本写入文件为一个测试,看看它是否执行)。即使我尝试执行不存在的东西,我实际上也会得到相同的返回值。

我在 Windows Server 2008 中阅读了有关 Session 0 隔离的信息,因此我使用 psexec 在 Session 0 中启动命令提示符,作为服务的“登录身份”用户列出的同一域用户:

psexec -i 0 -u DOMAIN\serviceuser -p passwd cmd.exe

然后我能够从命令提示符成功执行批处理文件。

列为该服务的登录身份用户的域用户位于管理员组中。此外,如果我手动启动 C++ 应用程序(而不是作为服务),它将启动批处理文件。

那么 Session 0 隔离是否有一些东西使 system() 调用在作为服务运行时不起作用?或者关于行为变化的其他解释?我知道 system() 不一定是最好的方法,但我正在寻找它不再有效的实际原因。

4

1 回答 1

1

根据我现在对该问题的了解,您无法在 Windows Server 2008 中使用 system() 从服务运行批处理文件的原因是因为 Windows 会考虑调用 cmd.exe 的任何尝试(就像运行批处理一样文件)作为启动交互式服务的尝试。由于 Session 0 隔离,这是不允许的,即使您可能不认为您的批处理文件是交互式的或具有 GUI(这让我失望),它也会失败。

我想出了如何使用 CreateProcess 获得我想要的效果。这里的关键是您必须将 dwCreationFlags 参数设置为 CREATE_NO_WINDOW。所以我的(简化的)电话最终看起来像这样:

CreateProcess(NULL,   // No module name (use command line)
    L"C:\\Windows\\System32\\cmd.exe /C myfile.bat", // Call cmd.exe with /C flag
    NULL,           // Process handle not inheritable
    NULL,           // Thread handle not inheritable
    FALSE,          // Set handle inheritance to FALSE
    CREATE_NO_WINDOW,              // Use CREATE_NO_WINDOW!!!
    NULL,           // Use parent's environment block
    NULL,           // Use parent's starting directory 
    &si,            // Pointer to STARTUPINFO structure
    &pi )           // Pointer to PROCESS_INFORMATION structure
于 2014-01-25T00:20:38.997 回答