CreateProcess 的问题和不正确的参数
Issues with CreateProcess and incorrect parameters
这可能是 2 个问题,但它们大体上都是围绕 CreateProcess 展开的,而且它运行不正常。
我一直在开发一个应用程序,该应用程序收集文件、处理它们,然后将它们压缩作为最后一步,使用我压缩的目录的哈希值重命名压缩文件。为此,我使用了 7zip (7za.exe) 的独立副本,通过使用 CreateProcess 来创建/压缩存档,以及一个名为 DirHash 的单独程序来生成我要制作的存档的名称.
我遇到的问题是这两个程序都不能正常工作。我目前 运行 使用标志 -t "temp.txt" -nowait -quiet -overwrite"
宁 DirHash,它确实创建了一个名为 temp.txt
的文件,但是,当使用 CreateProcess 运行宁它时,该文件始终为空.当我在标准命令行上使用完全相同的参数时,它会产生正确的输出。
另一个问题是 7zip 在尝试压缩我的目录时似乎出错。当 运行 通过我的 CreateProcess 时,我收到“不支持的命令”错误,并且文件没有被压缩。但是,当我在命令行上使用完全相同的参数时,存档创建成功。
这里是DirHash的相关代码,同样的代码也用于7za。我已经确认给CreateProcess的值是正确的,而且参数和我在命令行中使用的一样。
auto hashLocation = searchPath + "\" + DIRHASH_NAME;
auto params = "\"" + targetDir + "\" MD5" + " -quiet -t \"temp.txt\" -nowait -overwrite";
// I know this part is gross and if there's any suggestions for how to do it better I'm willing to hear it.
std::wstring intermediate;
intermediate.assign(params.begin(), params.end());
LPWSTR trueParams = &intermediate[0];
std::wstring intermediate_ex;
intermediate_ex.assign(hashLocation.begin(), hashLocation.end());
LPCWSTR trueLocation = intermediate_ex.c_str();
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(STARTUPINFO));
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
si.cb = sizeof(STARTUPINFO);
// Ripped from stack overflow
bool success = CreateProcess(
trueLocation,
trueParams,
NULL,
NULL,
TRUE,
0, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi // Pointer to PROCESS_INFORMATION structure (removed extra parentheses)
);
// Close process and thread handles.
WaitForSingleObject(pi.hProcess, INFINITE);
if (!success)
{
addLog("Failed to run DirHash process.", ErrorLevel::ERROR_MESSAGE);
return ERROR_STR;
}
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
当同时使用 CreateProcess()
的 lpApplicationName
和 lpCommandLine
参数时,lpCommandLine
应该包括 EXE 路径作为命令行中的第一个标记。这甚至在 CreateProcess()
文档中有说明:
If both lpApplicationName
and lpCommandLine
are non-NULL, the null-terminated string pointed to by lpApplicationName
specifies the module to execute, and the null-terminated string pointed to by lpCommandLine
specifies the command line. The new process can use GetCommandLine
to retrieve the entire command line. Console processes written in C can use the argc
and argv
arguments to parse the command line. Because argv[0]
is the module name, C programmers generally repeat the module name as the first token in the command line.
因此,如果您要在命令行中包含 EXE 路径,则根本不需要使用 lpApplicationName
参数:
If lpApplicationName
is NULL, the first white space–delimited token of the command line specifies the module name. If you are using a long file name that contains a space, use quoted strings to indicate where the file name ends and the arguments begin (see the explanation for the lpApplicationName
parameter )...
此外,而不是将 char
字符串转换为 std::wstring
(你做的不正确)只是为了调用 CreateProcess()
(它被映射到 CreateProcessW()
这种情况),你可以使用 CreateProcessA()
代替。
试试这个:
std::string hashLocation = searchPath + "\" + DIRHASH_NAME;
std::string cmd = "\"" + hashLocation + "\" \"" + targetDir + "\" MD5 -quiet -t \"temp.txt\" -nowait -overwrite";
STARTUPINFOA si = {};
si.cb = sizeof(si);
PROCESS_INFORMATION pi = {};
bool success = CreateProcessA(
NULL,
&cmd[0], // or const_cast<char*>(cmd.c_str()), or params.data() in C++17...
NULL,
NULL,
FALSE,
0, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi // Pointer to PROCESS_INFORMATION structure
);
if (!success)
{
addLog("Failed to run DirHash process.", ErrorLevel::ERROR_MESSAGE);
return ERROR_STR;
}
// Close process and thread handles.
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
或者这个:
// change searchPath, DIRHASH_NAME, and targetDir to wide strings...
std::wstring hashLocation = searchPath + L"\" + DIRHASH_NAME;
std::wstring cmd = L"\"" + hashLocation + L"\" \"" + targetDir + L"\" MD5 -quiet -t \"temp.txt\" -nowait -overwrite";
STARTUPINFOW si = {};
si.cb = sizeof(si);
PROCESS_INFORMATION pi = {};
bool success = CreateProcessW(
NULL,
&cmd[0], // or params.data() in C++17...
NULL,
NULL,
FALSE,
0, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi // Pointer to PROCESS_INFORMATION structure
);
if (!success)
{
addLog("Failed to run DirHash process.", ErrorLevel::ERROR_MESSAGE);
return ERROR_STR;
}
// Close process and thread handles.
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
这可能是 2 个问题,但它们大体上都是围绕 CreateProcess 展开的,而且它运行不正常。
我一直在开发一个应用程序,该应用程序收集文件、处理它们,然后将它们压缩作为最后一步,使用我压缩的目录的哈希值重命名压缩文件。为此,我使用了 7zip (7za.exe) 的独立副本,通过使用 CreateProcess 来创建/压缩存档,以及一个名为 DirHash 的单独程序来生成我要制作的存档的名称.
我遇到的问题是这两个程序都不能正常工作。我目前 运行 使用标志 -t "temp.txt" -nowait -quiet -overwrite"
宁 DirHash,它确实创建了一个名为 temp.txt
的文件,但是,当使用 CreateProcess 运行宁它时,该文件始终为空.当我在标准命令行上使用完全相同的参数时,它会产生正确的输出。
另一个问题是 7zip 在尝试压缩我的目录时似乎出错。当 运行 通过我的 CreateProcess 时,我收到“不支持的命令”错误,并且文件没有被压缩。但是,当我在命令行上使用完全相同的参数时,存档创建成功。
这里是DirHash的相关代码,同样的代码也用于7za。我已经确认给CreateProcess的值是正确的,而且参数和我在命令行中使用的一样。
auto hashLocation = searchPath + "\" + DIRHASH_NAME;
auto params = "\"" + targetDir + "\" MD5" + " -quiet -t \"temp.txt\" -nowait -overwrite";
// I know this part is gross and if there's any suggestions for how to do it better I'm willing to hear it.
std::wstring intermediate;
intermediate.assign(params.begin(), params.end());
LPWSTR trueParams = &intermediate[0];
std::wstring intermediate_ex;
intermediate_ex.assign(hashLocation.begin(), hashLocation.end());
LPCWSTR trueLocation = intermediate_ex.c_str();
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(STARTUPINFO));
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
si.cb = sizeof(STARTUPINFO);
// Ripped from stack overflow
bool success = CreateProcess(
trueLocation,
trueParams,
NULL,
NULL,
TRUE,
0, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi // Pointer to PROCESS_INFORMATION structure (removed extra parentheses)
);
// Close process and thread handles.
WaitForSingleObject(pi.hProcess, INFINITE);
if (!success)
{
addLog("Failed to run DirHash process.", ErrorLevel::ERROR_MESSAGE);
return ERROR_STR;
}
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
当同时使用 CreateProcess()
的 lpApplicationName
和 lpCommandLine
参数时,lpCommandLine
应该包括 EXE 路径作为命令行中的第一个标记。这甚至在 CreateProcess()
文档中有说明:
If both
lpApplicationName
andlpCommandLine
are non-NULL, the null-terminated string pointed to bylpApplicationName
specifies the module to execute, and the null-terminated string pointed to bylpCommandLine
specifies the command line. The new process can useGetCommandLine
to retrieve the entire command line. Console processes written in C can use theargc
andargv
arguments to parse the command line. Becauseargv[0]
is the module name, C programmers generally repeat the module name as the first token in the command line.
因此,如果您要在命令行中包含 EXE 路径,则根本不需要使用 lpApplicationName
参数:
If
lpApplicationName
is NULL, the first white space–delimited token of the command line specifies the module name. If you are using a long file name that contains a space, use quoted strings to indicate where the file name ends and the arguments begin (see the explanation for thelpApplicationName
parameter )...
此外,而不是将 char
字符串转换为 std::wstring
(你做的不正确)只是为了调用 CreateProcess()
(它被映射到 CreateProcessW()
这种情况),你可以使用 CreateProcessA()
代替。
试试这个:
std::string hashLocation = searchPath + "\" + DIRHASH_NAME;
std::string cmd = "\"" + hashLocation + "\" \"" + targetDir + "\" MD5 -quiet -t \"temp.txt\" -nowait -overwrite";
STARTUPINFOA si = {};
si.cb = sizeof(si);
PROCESS_INFORMATION pi = {};
bool success = CreateProcessA(
NULL,
&cmd[0], // or const_cast<char*>(cmd.c_str()), or params.data() in C++17...
NULL,
NULL,
FALSE,
0, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi // Pointer to PROCESS_INFORMATION structure
);
if (!success)
{
addLog("Failed to run DirHash process.", ErrorLevel::ERROR_MESSAGE);
return ERROR_STR;
}
// Close process and thread handles.
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
或者这个:
// change searchPath, DIRHASH_NAME, and targetDir to wide strings...
std::wstring hashLocation = searchPath + L"\" + DIRHASH_NAME;
std::wstring cmd = L"\"" + hashLocation + L"\" \"" + targetDir + L"\" MD5 -quiet -t \"temp.txt\" -nowait -overwrite";
STARTUPINFOW si = {};
si.cb = sizeof(si);
PROCESS_INFORMATION pi = {};
bool success = CreateProcessW(
NULL,
&cmd[0], // or params.data() in C++17...
NULL,
NULL,
FALSE,
0, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi // Pointer to PROCESS_INFORMATION structure
);
if (!success)
{
addLog("Failed to run DirHash process.", ErrorLevel::ERROR_MESSAGE);
return ERROR_STR;
}
// Close process and thread handles.
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);