我正在使用vs2005编写用C ++编写的Windows服务,我遇到了问题。
服务必须启动另一个小的可执行文件并获取它的输出。我这样做是通过调用CreateProcess(实际上是一个库为我做这个(libexecstream)),它可以工作。
正在启动的可执行文件,在磁盘上的某个地方,我不知道在哪里,它的目录在路径环境变量中。我的服务只是启动“theTool.exe”,然后我们去了。
如果路径变量如下所示:smting;smthingelse;C:\Program Files\blah\bin;meow
它可以工作
但是如果路径看起来像这样:smting;smthingelse;%ProgramFiles%\blah\bin;meow
它就不再起作用了!
问题是,在某些机器上它看起来像第一个,在其他机器上看起来像第二个...... 有趣的是,如果我在控制台中启动它(而不是作为服务),它可以正常工作!
有没有办法避免这个问题?编程? 手动更改的解决方案不是一种选择(客户不需要它)。在安装脚本或类似的东西中更改它不是一个选项,因为之后可能会更改路径 并且修改工具也不是一种选择,因为我们没有这样做而且我们没有源代码。
修改 CreateProcess行如下所示:
STARTUPINFO si;
ZeroMemory( &si, sizeof( si ) );
si.cb=sizeof( si );
si.hStdError = err.w();
si.hStdOutput = out.w();
si.hStdInput = in.r();
si.dwFlags |= STARTF_USESTDHANDLES;
PROCESS_INFORMATION pi;
ZeroMemory( &pi, sizeof( pi ) );
if( !CreateProcess( 0, const_cast< char * >( command.c_str() ), 0, 0, TRUE, 0, 0, 0, &si, &pi ) ) {
throw os_error_t( "exec_stream_t::start: CreateProcess failed.\n command line was: "+command );
}
其中command
是“theTool”
第二次编辑:如果我的程序作为服务启动它失败,如果它在控制台中启动它就会运行
答案 0 :(得分:3)
环境变量问题可能很棘手,尤其是当您谈论服务时。一些想法:
使用process explorer验证进程正在运行的用户。确保运行该服务的用户具有相应的环境变量设置(尽管这不应该是一个像%programfiles%一样的问题)
如果您以某种方式以编程方式更改环境变量,则会出现缓存environment vars on startup的问题。
只是一些想法。
答案 1 :(得分:2)
%ProgramFiles%
是环境变量值条目中的另一个环境变量。你需要解决它。如果在解析出遇到此模式的路径时,您应该查找它并使用所有部分的UNC路径指向您的文件。
在这里结合使用皮肤的方法:
GetEnvironmentStrings
Windows API预先获取所有内容并将其放入地图中,以便您的服务轻松查找GetEnviromentVariable
检查是否存在并获取特定环境变量的值,例如ProgramFiles
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment
PATH
,而{{1}}应保留给系统内容,而不是以任何方式被欺骗答案 2 :(得分:0)
您可以改为use the App Paths
registry key而不是使用CreateProcess
,并使用ShellExecute
启动应用程序。这样可以避免污染PATH
环境变量。