如何获取CreateProcess / CreateProcessW来在路径中执行一个进程,该路径> MAX_PATH个字符

时间:2020-03-06 14:48:59  来源:igfitidea点击:

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

我尝试过,但是得到ERROR_PATH_NOT_FOUND。

我更改为CreateProcessW,但仍然收到相同的错误。当我在调用CreateProcessW时以http://msdn.microsoft.com/zh-cn/library/aa365247(VS.85).aspx中所述用\?\为lpApplicationName加上前缀时,我收到一个不同的错误,使我认为我是:更近一点:ERROR_SXS_CANT_GEN_ACTCTX。

我对CreateProcessW的调用是:

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

其中w_argv0是`\?\ <长绝对路径> \ foo.exe。

arg_string包含" <长绝对路径> \ 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:.Manifest的生成激活上下文失败。参考错误消息:操作成功完成。

我尝试执行的文件在<MAX_PATH个字符的路径中可以正常运行。

为了明确起见,<长绝对路径>的任何一个组成部分都不得超过MAX_PATH个字符。即使最后以.manifest结尾,可执行文件本身的名称也肯定不是。但是,整个路径在一起的长度大于MAX_PATH个字符。

无论是否嵌入清单,都会出现相同的错误。清单文件名为foo.exe.manifest,未嵌入时与可执行文件位于同一目录中。它包含:

<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type='win32' name='Microsoft.VC80.DebugCRT' version='8.0.50727.762' processorArchitecture='x86' publicKeyToken='1fc8b3b9a1e18e3b' />
    </dependentAssembly>
  </dependency>
</assembly>

任何人都知道如何使它工作吗?可能:

  • 调用CreateProcess或者CreateProcessW的其他方法,以> MAX_PATH个字符的路径执行进程
  • 我可以在清单文件中执行的操作

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

谢谢你的帮助。

解决方案

我在CreateProcess文档中没有看到任何引用说'\?'语法对于模块名称有效。 "命名文件或者目录"页面上也没有声明CreateProcess支持它,而诸如CreateFile之类的功能则链接到"命名文件"页面。

我确实看到,模块名称不能超过lpCommandLine中的MAX_PATH,这表明CreateProcess不支持额外的长文件名。该错误消息还表明,尝试将" .manifest"添加到应用程序路径时发生错误(即,该长度现在超过MAX_PATH)。

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

嵌入清单并使用GetShortPathNameW为我做到了。仅仅靠一个人还是一个人是不够的。

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

wchar_t *w_argv0;
wchar_t *w_short_argv0;

...

if (wcslen(w_argv0) >= MAX_PATH)
{
    num_chars = GetShortPathNameW(w_argv0,NULL,0);
    if (num_chars == 0) {
        syslog(LOG_ERR,"GetShortPathName(%S) to get size failed (%d)",
               w_argv0,GetLastError());
        /*
        ** Might as well keep going and try with the long name
        */
    } else {
        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) failed (%d)",w_argv0,
            GetLastError());
            free(w_short_argv0);
            w_short_argv0 = NULL;
        } else {
            syslog(LOG_DEBUG,"using short name %S for %S",w_short_argv0,
            w_argv0);
        }
    }
}

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

记住要释放(w_short_argv0);然后。

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