3

我试图让 CreateProcess 或 CreateProcessW 执行名称 < MAX_PATH 字符但路径大于 MAX_PATH 字符的进程。根据以下文档:http://msdn.microsoft.com/en-us/library/ms682425.aspx,我需要确保 lpApplicationName 不为 NULL,然后 lpCommandLine 最多可以包含 32,768 个字符。

我试过了,但我得到了 ERROR_PATH_NOT_FOUND。

我更改为 CreateProcessW,但仍然出现相同的错误。当我在 lpApplicationName 前面加上 \\?\ 时,如中所述http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx在调用 CreateProcessW 时我得到一个不同的错误,让我觉得我更接近一点:ERROR_SXS_CANT_GEN_ACTCTX。

我对 CreateProcessW 的调用是:

CreateProcessW(w_argv0,arg_string,NULL,NULL,0,NULL,NULL,&si,&ipi);

w_argv0 在哪里\\?\<long absolute path>\foo.exe.

arg_string 包含 "<long absolute path>\foo.exe" foo

si 设置如下:

    memset(&si,0,sizeof(si));
    si.cb = sizeof(si);
    si.dwFlags = STARTF_USESHOWWINDOW;
    si.wShowWindow = SW_HIDE;>

并且 pi 为空,如下所示:

    memset(&pi,0,sizeof(pi));

我查看了系统事件日志,每次尝试使用事件 id 59 进行此操作时都会出现一个新条目,源 SideBySide: Generate Activation Context failed for .Manifest。参考错误信息:操作成功完成。

我尝试执行的文件在 < MAX_PATH 字符的路径中运行良好。

澄清一下, <long absolute path> 的任何一个组成部分都不大于 MAX_PATH 个字符。可执行文件本身的名称当然不是,即使最后有 .manifest。但是,整个路径加起来的长度大于 MAX_PATH 个字符。

无论我是否嵌入其清单,我都会收到相同的错误。清单被命名为 foo.exe.manifest,当它没有嵌入时,它与可执行文件位于同一目录中。它包含:

<?xml 版本='1.0' 编码='UTF-8' 独立='yes'?>
<程序集 xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
  <依赖>
    <依赖程序集>
      <assemblyIdentity type='win32' name='Microsoft.VC80.DebugCRT' version='8.0.50727.762' processorArchitecture='x86' publicKeyToken='1fc8b3b9a1e18e3b' />
    </dependentAssembly>
  </依赖>
</汇编>

有谁知道如何让它工作?可能:

  • 调用 CreateProcess 或 CreateProcessW 以在路径 > MAX_PATH 字符中执行进程的其他方式

  • 我可以在清单文件中做的事情

我在 XP SP2 上使用 Visual Studio 2005 构建并运行本机。

谢谢你的帮助。

4

2 回答 2

2

嵌入清单并使用 GetShortPathNameW 为我做了。一个或另一个是不够的。

在使用要执行的进程的 \\? 前缀的绝对路径名作为第一个参数调用 CreateProcessW 之前,我检查:

wchar_t *w_argv0;
wchar_t *w_short_argv0;

...

if (wcslen(w_argv0) >= MAX_PATH)
{
    num_chars = GetShortPathNameW(w_argv0,NULL,0);
    如果(num_chars == 0){
        syslog(LOG_ERR,"GetShortPathName(%S) 获取大小失败 (%d)", 
w_argv0,GetLastError()); /* ** 不妨继续尝试使用长名称 */ } 别的 { w_short_argv0 = malloc(num_chars * sizeof(wchar_t)); memset(w_short_argv0,0,num_chars * sizeof(wchar_t)); if (GetShortPathNameW(w_argv0,w_short_argv0,num_chars) == 0) { syslog(LOG_ERR,"GetShortPathName(%S) 失败 (%d)",w_argv0,
GetLastError()); 免费(w_short_argv0); w_short_argv0 = NULL; } 别的 { syslog(LOG_DEBUG,"为 %S 使用短名称 %S",w_short_argv0,
w_argv0); } } }

然后调用 CreateProcessW(w_short_argv0 ? w_short_argv0 : w_argv0...);

记得释放(w_short_argv0);然后。

这可能无法解决所有情况,但它让我产生了比以前更多的子进程。

于 2008-09-28T01:16:33.150 回答
1

我在 CreateProcess 文档中没有看到任何参考说明 '\\?\' 语法对模块名称有效。“命名文件或目录”页面也没有说明 CreateProcess 支持它,而 CreateFile 等功能链接到“命名文件”页面。

确实看到您不能使用比MAX_PATHin更长的模块名称lpCommandLine,这表明 CreateProcess 不支持超长文件名。该错误消息还表明在尝试将“.manifest”附加到您的应用程序路径时发生错误(即,长度现在超过了 MAX_PATH)。

GetShortPathName() 在这里可能会有所帮助,尽管它不能保证返回小于 MAX_PATH 的名称(但它确实明确指出 '\\?\' 语法是有效的)。否则,您可以尝试调整PATH环境变量并将其传递给lpEnvironment. 或者您可以使用 SetCurrentDirectory() 并仅传递可执行文件名称。

于 2008-09-27T10:54:29.417 回答