CreateProcess() 不适用于 lpCurrentDirectory
Posted
技术标签:
【中文标题】CreateProcess() 不适用于 lpCurrentDirectory【英文标题】:CreateProcess() not working with lpCurrentDirectory 【发布时间】:2013-10-10 12:30:33 【问题描述】:我使用带有参数 lpCurrentDirectory 的 createprocess() 从我的应用程序创建一个进程,但它不起作用。它给出错误“系统找不到指定的路径”。我的代码是
CreateProcess( "XYZ\\bin\\run.bat", NULL, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, "XYZ\\bin", &siStartupInfo, &piProcessInfo ) ;
我还通过使用 GetCurrentDir() 获取当前目录并将 XYZ\\bin
添加到当前目录,将完整路径作为 lpCurrentDirectory,但它仍然不起作用。
我希望我的批处理文件从 lpCurrentDirectory 运行。
我不明白 createProcess() 如何与 lpCurrentDirectory 参数一起工作。是期望完整路径还是相对路径?
我也尝试过硬编码完整路径,但它显示相同的错误。实际上我的原始代码是, `
char cCurrentPath[FILENAME_MAX];
if (!GetCurrentDir(cCurrentPath, sizeof(cCurrentPath)))
printf("\n error...");
string path(cCurrentPath);
path += "\\XYZ\\bin";
wstring_convert<std::codecvt_utf8<wchar_t>> converter;
wstring wstringData = converter.from_bytes(path);
TCHAR lpszClientPath[500]= TEXT("XYZ\\bin\\run.bat /y");
if(::CreateProcess(NULL, lpszClientPath, NULL, NULL, TRUE, CREATE_NEW_CONSOLE,NULL, wstringData.c_str(), &si, &pi) > 0)
`。
【问题讨论】:
文档明确指出lpCurrentDirectory
必须是完整路径。您是否尝试过将有效的完整路径硬编码到您的代码中?另请注意,您不能直接启动批处理文件,而必须运行 cmd /c xyz\\bin\\run.bat
。
所有字符串操作和转换都可能给您带来麻烦。您是否尝试过使用MessageBox(NULL, wstringData.c_str(), L"test", MB_OK)
代替CreateProcess
来查看您实际发送的目标目录是什么字符串?你有没有仔细检查过这个目标目录确实存在?为什么不使用GetCurrentDirectory
来获取Unicode 格式的当前目录?
注意:无论您的问题是什么,如果目录路径包含任何非 ASCII 字符,所编写的代码将不起作用。
感谢 Harry Johnston,我尝试 MessageBox,它显示正确的路径,并且目录也存在,我需要将目录路径添加到 currentDirectory 路径所以我使用 GetCurrentDir,我认为它失败了,因为我的路径在 GetCurrentDir 给出的路径中包含空格,它没有正确转换为 Unicode,它只需要空格之前的路径并给出错误 'XYZ' 内部或外部命令不存在。你有什么想法吗?
我发现如果我在 Windows-XP 中从桌面运行我的程序,它将无法工作,因为桌面路径是“c:\Documents and Settings\Desktop”,它在 Windows 7 上运行良好,我认为 CreateProcess() 无法识别它,或者它是转换为 Unicode 的问题。
【参考方案1】:
请查看this。您应该阅读整个帖子,因为它重申了在之前的帖子中给您的答案。
【讨论】:
感谢您的快速回复,但我认为您不了解我的要求,我的应用程序是从安装驱动程序创建的,如果我不指定 lpCurrentDirectory 它可以正常工作,但是当我指定它时,它不起作用.我的批处理文件对当前目录使用 CD 命令,因此,我需要从包含此批处理文件的目录运行它,而不是从运行我的实际应用程序的位置运行它。【参考方案2】:此代码适用于我,适用于 Windows 7 和 Windows XP。
#include <Windows.h>
void showcd(wchar_t * caption)
wchar_t buffer[512];
if (GetCurrentDirectory(512, buffer) == 0)
DWORD err = GetLastError();
MessageBox(NULL, L"GetCurrentDirectory failed", caption, MB_OK);
ExitProcess(err);
buffer[511] = L'\0';
MessageBox(NULL, buffer, caption, MB_OK);
void parent(wchar_t * cd)
wchar_t cmd[512];
wchar_t buffer[512];
STARTUPINFO sinfo;
PROCESS_INFORMATION pinfo;
GetStartupInfo(&sinfo);
showcd(L"Parent Process");
if (GetCurrentDirectory(512, buffer) == 0)
DWORD err = GetLastError();
MessageBox(NULL, L"GetCurrentDirectory failed", L"Parent Process", MB_OK);
ExitProcess(err);
buffer[511] = L'\0';
wcscat_s(buffer, 512, L"\\");
wcscat_s(buffer, 512, cd);
if (GetModuleFileName(NULL, cmd, 512) == 0)
MessageBox(NULL, L"GetModuleFileName failed", L"Parent Process", MB_OK);
ExitProcess(GetLastError());
cmd[511] = L'\0';
if (!CreateProcess(
cmd, NULL, NULL, NULL, FALSE, 0, NULL, buffer, &sinfo, &pinfo
))
DWORD err = GetLastError();
MessageBox(NULL, L"CreateProcess failed", L"Oops", MB_OK);
ExitProcess(err);
int CALLBACK WinMain(
_In_ HINSTANCE hInstance,
_In_ HINSTANCE hPrevInstance,
_In_ LPSTR lpCmdLine,
_In_ int nCmdShow
)
wchar_t * cmdline;
for (cmdline = GetCommandLine(); *cmdline; cmdline++)
if (*cmdline == L'*')
parent(cmdline + 1);
return 0;
showcd(L"Child Process");
return 0;
你可以这样测试:
C:\Documents and Settings\Administrator>dir
Volume in drive C has no label.
Volume Serial Number is 6080-CDD5
Directory of C:\Documents and Settings\Administrator
13/12/2012 09:56 a.m. <DIR> .
13/12/2012 09:56 a.m. <DIR> ..
18/05/2012 03:10 p.m. <DIR> Desktop
20/06/2008 11:45 a.m. <DIR> Favorites
19/10/2010 02:54 p.m. <DIR> My Documents
20/06/2008 04:15 a.m. <DIR> Start Menu
1 File(s) 43 bytes
6 Dir(s) 29,912,666,112 bytes free
C:\Documents and Settings\Administrator>\appendtocurrentdirectory.exe *My Documents
【讨论】:
问题是提问者正在将 .bat 文件传递给 CreateProcess。 @DavidHeffernan:是的,这是一个问题(已经指出),但它不能解释找不到路径错误。 :-)【参考方案3】:CreateProcess 用于启动进程,您必须传递一个可执行文件。您不能传递 .bat。相反,您需要使用 /C 选项启动 cmd.exe 并将批处理文件作为参数传递。
【讨论】:
以上是关于CreateProcess() 不适用于 lpCurrentDirectory的主要内容,如果未能解决你的问题,请参考以下文章
用于批处理脚本的 Visual Studio 2010 CreateProcess()
windows 下在进程中使用createprocess创建一个窗口进程,并获取这个窗口HWND句柄
如何在 C# 中通过 lpEnvironment 调用 CreateProcess()