【问题标题】:Why does windows spawn process sometimes trigger error STATUS_SXS_ASSEMBLY_NOT_FOUND?为什么 windows 生成进程有时会触发错误 STATUS_SXS_ASSEMBLY_NOT_FOUND?
【发布时间】:2012-06-10 14:27:29
【问题描述】:

所以,我有一小段 C 代码在 Windows 机器上运行,上面写着:

/* 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 并且它可以工作,没问题。

试图将它用于应用程序启动器...嘟嘟。因有用的错误而失败:

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

产量:

vargs 0: C:\windows\system32\notepad.exe
env 0: PATH=c:\WINDOWS\system32

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

有什么想法吗?

--

编辑:

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

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

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

所以说真的,这个问题的答案是:因为 PATH 变量是错误的。

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

编辑#2:

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

铌。想看看它的工作吗?更改为 _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

【问题讨论】:

  • 记录您在 Windows 应用程序事件日志中找到的内容。
  • 如果您在事件查看器中谈论“应用程序”日志,那么那里什么都没有。我运行了十几次失败的代码,没有出现新的日志条目。如果您在谈论其他内容,请更具体。
  • 这可能只是意味着您的应用需要一些不存在的 DLL。在 SO 上看到这个:stackoverflow.com/questions/1582844/…
  • vargs[0] 中的 windows.0 是怎么回事?你有一个 c:\windows 和一个 c:\windows.0 吗?如果是这样,哪个是真正的 Windows 目录?另外,您在哪个版本的 Windows 上进行测试?
  • 在安装了 windows.0 的机器上运行;我已经将代码移到了一台运行 XP 且默认路径为 C:\Windows\ 的新机器上,但它仍然存在同样的问题;我已经从问题中删除了奇怪的“.0”。这是在 XP SP 3 上

标签: c windows spawn


【解决方案1】:

这是错误的:

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

你需要

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

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

你用的是什么编译器?

【讨论】:

  • 您的示例代码没有传入 env 数组,但更改后它仍然适用于我。
  • 可能值得您花时间构建一个安装了普通版 Windows XP 的虚拟机,以确定是您的编译器还是您的测试机与我的行为不同。我确实可以访问各种不同版本的 Visual Studio,所以如果您使用其中之一,我也可以尝试。
  • 看起来是 args[] 导致了奇怪的错误(有趣的是,在 Windows 7 上,错误是不同的,并且作为无效参数出现;只有 xp 为我抛出 STATUS_SXS_ASSEMBLY_NOT_FOUND);该示例适用于您的更改!非常感谢!
【解决方案2】:

你是对的,_spawnev() 的第二个参数是要执行的应用程序的名称包括其完整路径

要了解路径,您可以调用命令处理器cmd.exe 并将其与应用程序的名称一起传递,以使用cmd.exe 的选项/C 作为参数执行。

这适用于您可以从cmd.exe 的命令行窗口之一启动应用程序的所有情况。

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

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

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

【讨论】:

  • 我的命令的参数 2 没有问题。如果我换成 _spawnv() 而不是 _spawnve() 它可以完美运行。 ...但显然我不能传递我想要的任何其他 env 值。 (即 'command' 与 vargs[0] 的值相同)
  • 另外,当我尝试在 _spawnve 中使用“cmd.exe /C blah”时,我得到一个 no-such-command 错误。您能否提供一个如何实现该功能的示例?
  • @doug 您需要使用 getenv() 函数在 "cmd.exe" 前面加上您读​​取的环境变量 COMSPEC 的值。
  • @doug 关于传递一组 env/var/s,您可能想尝试获取程序 int main( int argc, char *argv[], char *env[] ) 函数的第三个值(通常省略),该函数接收对程序环境的引用本身。
  • 是的,令人惊讶的是,在盲目地问这个问题之前,我实际上已经阅读了 msdn 文档。有用的示例不包括路径变量或启动任何依赖于 win dll -> ie 的东西。不能解决任何问题。我将尝试使用 getenv() 并将值传入,但我不得不说,它看起来并不乐观。 (getenv() 返回的路径值与我在 env[0] 中传入的值几乎相同)
【解决方案3】:

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

所以你需要这样做:

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

【讨论】:

  • 不正确。 _spawn 也继承了 PATH 变量。 _spawnvpe 继承 PATH 并且 允许您指定环境变量。但是,如果您尝试将 PATH 指定为这些环境变量之一,则会出现问题。
  • 嗯,官方文档说的很清楚了PATH环境变量用于_spawn函数后缀为p时查找要执行的文件,并没有说明它支持PATH 作为环境变量。
猜你喜欢
  • 1970-01-01
  • 2013-12-04
  • 2017-07-20
  • 2017-02-11
  • 2015-09-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多