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的主要内容,如果未能解决你的问题,请参考以下文章

UNC 路径上的 VC++ Createprocess

用于批处理脚本的 Visual Studio 2010 CreateProcess()

windows 下在进程中使用createprocess创建一个窗口进程,并获取这个窗口HWND句柄

如何在 C# 中通过 lpEnvironment 调用 CreateProcess()

如何使用带有命令的向量列表来发送到 CreateProcess?

CreateProcess的前两个参数究竟怎么用