我目前正在尝试使用CreateProcess()API启动一个进程: http://msdn.microsoft.com/en-us/library/windows/desktop/ms682425(v=vs.85).aspx
我遇到的主要问题是,无论 lpCurrentDirectory 参数中指示了什么,子进程似乎都是使用父进程的工作目录启动的>
提供更多细节:lpCurrentDirectory似乎适用于简单的命令行程序,但对于更复杂的命令行程序(想想GUI),似乎没有考虑到,因为从调用目录进程中搜索所有的ressource依赖项。
我可以尝试将调用进程工作目录切换回来&第四个问题,但第二个问题是被调用进程不在目标目录中。目前,它与调用进程位于同一目录中,尽管将来可能会发生变化。当我试图将子进程调用到与父进程不同的目录时,由于某种原因,它会失败。我已多次检查目录结构,到目前为止无济于事。
我一直在寻找(包括进入S.O.)虽然有些人似乎抱怨同样的问题,但我现在还没有找到可用的工作。请注意,例如,我不能使用ShellExec,它必须是CreateProcess()。
如果它确实重要,我目前的测试系统是Windows 7 64位。该软件应该适用于更广泛的操作系统,从XP到Seven,32& 64位(我猜W8现在不在范围内)。
[编辑] 我已经找到了在调用流程工作目录之外调用子进程的解决方案。我正在使用lpApplicationName,这很好,但显然不需要引用,即使复杂的名称涉及空格字符。
这使我能够在调用CreateProcess()之前测试修改调用进程的工作目录(使用SetCurrentDirectory())的想法。令我惊讶的是,它不起作用:工作目录实际上是指定到lpApplicationName的完整路径中的目录,无论由于SetCurrentDirectory()(并使用GetCurrentDirectory()验证)已经设置到父工作目录的任何内容/ p>
这是我的问题,因为我希望进程运行到另一个选定的目录(都指定为lpCurrentDirectory参数,并在CreateProcess()之前调用SetCurrentDirectory())。
答案 0 :(得分:3)
我认为您的问题是您假设子进程应该尝试从当前目录加载其资源(如第三段中所示),而事实上,进程加载其资源的情况更为常见它从中启动的目录。换句话说,在大多数情况下,您所描述的行为都是预期的。
通过双击文档或使用拖放操作启动应用程序时,当前目录将设置为包含该文档的目录,因此如果应用程序从当前目录加载其资源,则会赢不行。
这个简单的测试应用程序演示了lpCurrentDirectory
的工作原理,因为子进程的当前目录设置为指定的目录:
#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];
STARTUPINFO sinfo;
PROCESS_INFORMATION pinfo;
GetStartupInfo(&sinfo);
showcd(L"Parent Process");
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, cd, &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;
}
要测试应用程序,请使用如下命令行运行它:
currentdirectorytest *c:\Users\Public
父进程的第一个对话框显示父进程当前目录。子进程的第二个对话框显示子进程当前目录,并且应该是命令行上给出的目录。 (请注意,指定的目录必须存在,否则子进程的创建将失败。)