So, I have a tiny fragment of C code running on a windows box, that reads:
/* invoke command */
impl->procHandle = _spawnve(_P_NOWAIT, command, vargs, env);
if (impl->procHandle == -1) {
printf("Failed to invoke command: %s\n", strerror(errno));
impl->busy = false;
}
printf("VICTORY\n");
I wrote some unit tests around this where my "command" was C:\windows\system32\ipconfig.exe and it works, no problem.
Tried to use it for an application launcher... doo doo. Failed with the helpful error:
The application failed to initialize properly (0xc0150004).
Click on OK to terminate the application.
Ok... searching around I discovered that the error code is STATUS_SXS_ASSEMBLY_NOT_FOUND, and it happens when I try to launch notepad.exe as well. Missing assemblies?
Why is this happening?
How can I work around it?
I'm just guessing here, but I suspect it has something to do with needing the PATH variable to be set in the _spawnve(), but I dont know what it should be. I tried passing in the path, but that doesn't seem to help. Running this code:
int offset = 0;
while (vargs[offset] != NULL) {
printf("vargs %d: %s\n", offset, vargs[offset]);
++offset;
}
offset = 0;
while (env[offset] != NULL) {
printf("env %d: %s\n", offset, env[offset]);
++offset;
}
Yeilds:
vargs 0: C:\windows\system32\notepad.exe
env 0: PATH=c:\WINDOWS\system32
ie. I am passing in argv[0], and a path value; not other env variables or arguments.
Any ideas?
--
Edit:
So, it seems this error is occurring because the PATH is not correctly set when I invoke the command using _spawnve().
This is made obvious by invoking either _spawnv() or _spawnvpe(), both of which seem to work correctly.
However, that doesn't really help me, because I need to specify an additional PATH component for the application when it runs. Passing PATH=... into _spawnvpe() causes the same error, and obviously _spawnv is no used because it doesn't allow you to specify the PATH.
So really, the answer to this question is: Because the PATH variable is wrong.
...but I still have no idea what it should be. There seem to be no working examples of this that I can find anywhere. I'll accept any answer that links to an example of coding using _spawnve() or _spawnvpe() and passing the PATH variable into it (and working).
Edit #2:
Really. No, actually, this doesn't work. Here's an example of it not working. Forget linking to an example that works; just modify my example and post a diff that 1) passes in PATH and 2) runs without an error.
Nb. Want to see it work? change to _spawnv() or make the env value NULL and it runs just fine.
#include <stdio.h>
#include <windows.h>
#include <process.h>
#include <errno.h>
int main(int argc, char *argv[]) {
char *path_value;
char buffer[4000];
const char *env[2];
const char *args[1];
char *command;
int result;
intptr_t procHandle;
path_value = getenv("PATH");
sprintf(buffer, "PATH=%s", path_value);
env[0] = buffer;
env[1] = NULL;
args[0] = NULL;
int offset = 0;
while (env[offset] != NULL) {
printf("env %d: %s\n", offset, env[offset]);
++offset;
}
offset = 0;
while (args[offset] != NULL) {
printf("arg %d: %s\n", offset, args[offset]);
++offset;
}
command = "C:\\windows\\system32\\notepad.exe";
procHandle = _spawnvpe(_P_NOWAIT, command, args, NULL);
if (procHandle == -1) {
printf("Failed to invoke command: %s\n", strerror(errno));
exit(1);
}
_cwait(&result, procHandle, 0);
if (result != 0)
printf("Command exited with error code %d\n", result);
}
Output:
env 0: PATH=.;c:\Program Files\Common Files\Microsoft Shared\Windows Live;c:\WINDOWS\system32;c:\WINDOWS;c:\WINDOWS\System32\Wbem;c:\Program Files\Microsoft SQL Server\100\Tools\Binn\;c:\Program Files\Microsoft SQL Server\100\DTS\Binn\;c:\Program Files\CMake 2.8\bin;c:\Program Files\Microsoft ASP.NET\ASP.NET Web Pages\v1.0\;c:\Program Files\Common Files\Microsoft Shared\Windows Live
Command exited with error code -1072365564