为什么Windows spawn进程有时会触发错误STATUS_SXS_ASSEMBLY_NOT_FOUND?

时间:2012-06-10 14:27:30

标签: c windows spawn

所以,我在Windows机器上运行了一小段C代码,内容如下:

/* 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");

我在这附近编写了一些单元测试,我的“命令”是C:\ windows \ system32 \ ipconfig.exe,它运行正常,没问题。

尝试将它用于应用程序启动器... doo doo。失败时出现有用的错误:

The application failed to initialize properly (0xc0150004). 
Click on OK to terminate the application.

好的...搜索我发现错误代码是STATUS_SXS_ASSEMBLY_NOT_FOUND,当我尝试启动notepad.exe时也会发生错误代码。缺少装配?

为什么会这样?

我该如何解决它?

我只是在这里猜测,但我怀疑它与需要在_spawnve()中设置PATH变量有关,但我不知道它应该是什么。我尝试过路径,但这似乎没有帮助。运行此代码:

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

即。我传入argv [0]和路径值;不是其他env变量或参数。

有什么想法吗?

-

编辑:

因此,似乎发生了此错误,因为在使用_spawnve()调用命令时未正确设置PATH。

通过调用_spawnv()或_spawnvpe()显而易见,这两者似乎都能正常工作。

然而,这对我没有帮助,因为我需要在运行时为应用程序指定一个额外的PATH组件。将PATH = ...传递给_spawnvpe()会导致相同的错误,显然没有使用_spawnv,因为它不允许您指定PATH。

实际上,这个问题的答案是:因为PATH变量是错误的。

...但我仍然不知道应该是什么。似乎没有任何可以在任何地方找到的工作示例。我将接受任何链接到使用_spawnve()或_spawnvpe()编码的示例并将PATH变量传递给它(并且正在工作)的答案。

编辑#2:

真。不,实际上,这不起作用。这是示例,它不起作用。忘记链接到一个有效的例子;只修改我的例子并发布一个差异,1)传入PATH,2)运行没有错误。

的Nb。想看看它有用吗?更改为_spawnv()或使env值为NULL并且运行正常。

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

输出:

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

3 个答案:

答案 0 :(得分:2)

这是错误的:

const char *args[1];
args[0] = NULL;

你需要

const char *args[2];
args[0] = "notepad";
args[1] = NULL;

除此之外,您的示例代码至少在使用Visual Studio 2010进行编译时可以正常工作。我已经在Windows 7和Windows XP上进行了测试,并且它可以正常工作。记事本运行。

您使用的是哪种编译器?

答案 1 :(得分:0)

你是对的,_ spawnev()的第二个参数是要执行的应用名称包含其完整路径

要了解可以调用命令处理程序cmd.exe的路径,并使用cmd.exe的选项{{1}将其作为参数执行传递给应用程序名称}。

这适用于您可以从/C的一个命令行窗口启动应用程序的所有情况。

cmd.exe知道环境变量cmd.exe的值,并用它来搜索应用程序的启动路径。

可以从环境变量PATH中读取cmd.exe本身的路径。

更新:有关此问题的更多信息(包括示例),请阅读here

答案 2 :(得分:-1)

如此处_spawn, _wspawn Functions所指定的,只有名称中带有'p'字母的函数才会隐含地使用PATH环境变量。其他人没有。

所以你需要这样做:

char *args[] =  {"notepad.exe", NULL };
_spawnvpe(_P_NOWAIT, args[0], args, NULL);