如何获取CreateProcess / CreateProcessW来在路径中执行一个进程,该路径> MAX_PATH个字符
我试图获取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);然后。
这可能无法解决所有情况,但它使我产生了比以前更多的子进程。