简体   繁体   中英

running a program from a service

I am working on a windows service written in C++ using vs2005 and I'm running into a problem.

The service must launch an other small executable and get it's output. I do that through a call to CreateProcess (well a library does that for me actually (libexecstream) ), it works.

The executable being launched, is somewhere on the disk, I don't know where, and it's directory is in the path environment variable. My service just launch "theTool.exe" and here we go.
If the path variable looks like this: smting;smthingelse;C:\\Program Files\\blah\\bin;meow it works.
But if the path looks like this: smting;smthingelse;%ProgramFiles%\\blah\\bin;meow it no longer works!

The problem is, on some machines it looks like the first, on others like the second...
The funny thing is that if I launch it in a console (as opposed to as a service) it works fine!

Is there a way to avoid that problem? programatically? A solution like changing it by hands is not an option (the client doesn't want it). Changing it in the install script or something like that is not an option either because the path might be changed afterwards.
And modifying the tool is not an option either because we didn't do it and we don't have the source code.

edit: the CreateProcess line looks like this:

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 );
}

where command is "theTool"

2nd edit : if my program is launched as a service it fails, if it is launched in a console it workds

Environment variable problems can be tricky, especially when you are talking about services. A few thoughts:

  1. Use process explorer to verify which user the process is running as. Make sure that the user under which the service is running has the appropriate environment vars setup (although this shouldn't be an issue with one as vanilla as %programfiles%)

  2. If you are somehow programatically changing the environment variable, there are know problems with caching the environment vars on startup .

Just some thoughts.

%ProgramFiles% is another environment variable within your environment variable value entry. You need to resolve it. If when parsing out the path you encounter this pattern you should then look it up and use the UNC path of all parts to point to your file.

Couple ways to skin the cat here:

  • Use GetEnvironmentStrings windows API to get everything up front and put them in a map for easy lookup by your service
  • Use GetEnviromentVariable to check the existence and get the value of a specific environment variable for example ProgramFiles
  • Query the registry for the environment variables at HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Control\\Session Manager\\Environment
  • Set your own environment variable rather than using PATH which should be reserved for system stuff and not fooled around with anyway
  • Use a more robust filesystem library which has functionality for dealing with environment variables
  • Forget environment variables and use a configuration file (this could be accompanied by a simple GUI program that allows them to use a open file dialog to browse and select paths which will be stored for your service to pick up and use later)
  • Etc

Instead of using CreateProcess , you could instead use the App Paths registry key and launch the application with ShellExecute . This avoids polluting the PATH environment variable.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM