为了显示最小的可复制代码,我编写了一个代码,使用CreateProcessW()从给定位置删除文件。该文件不会被删除。知道为什么为什么不起作用时,一些帮助将非常有用。
dprintf(("Error %d", GetLastError()));
STARTUPINFO si = { sizeof(STARTUPINFO), 0 };
si.cb = sizeof(si);
PROCESS_INFORMATION pi = { 0 };
LPWSTR AppName = L"C:\\Windows\\System32\\cmd.exe";
string bstr = "C:\\Windows\\System32\\cmd.exe /C del"+trans_loc+"a.rtf";
LPWSTR Command = new WCHAR[bstr.length()];
int wchars_num = MultiByteToWideChar(CP_UTF8, 0, bstr.c_str(), -1, NULL, 0);
MultiByteToWideChar(CP_UTF8, 0, bstr.c_str(), -1, Command, wchars_num);
DWORD res = CreateProcessW(AppName, Command, 0, 0, 0, DETACHED_PROCESS, 0, 0, &si, &pi);
WaitForSingleObject(pi.hProcess, INFINITE);
定义TRANSCRIPT_LOCATION“ C:\ Users \ Administrator \ Desktop \”,这是要删除的文件的位置
GetLastError()继续返回50(ERROR_NOT_SUPPORTED),并且res的值= 1
答案 0 :(得分:2)
我首先想到的是
LPWSTR Command = new WCHAR[bstr.length()];
不正确。也许
LPWSTR Command = new WCHAR[bstr.length() + 1];
将起作用。更好的选择是使用wchars_num
分配内存。
代替
LPWSTR Command = new WCHAR[bstr.length()];
int wchars_num = MultiByteToWideChar(CP_UTF8, 0, bstr.c_str(), -1, NULL, 0);
MultiByteToWideChar(CP_UTF8, 0, bstr.c_str(), -1, Command, wchars_num);
DWORD res = CreateProcessW(AppName, Command, 0, 0, 0, DETACHED_PROCESS, 0, 0, &si, &pi);
使用
int wchars_num = MultiByteToWideChar(CP_UTF8, 0, bstr.c_str(), -1, NULL, 0);
LPWSTR Command = new WCHAR[wchars_num];
MultiByteToWideChar(CP_UTF8, 0, bstr.c_str(), -1, Command, wchars_num);
DWORD res = CreateProcessW(AppName, Command, 0, 0, 0, DETACHED_PROCESS, 0, 0, &si, &pi);
第二个问题是,在编写del
命令时,您可能错过了空格字符。
string bstr = "C:\\Windows\\System32\\cmd.exe /C del " + trans_loc + "a.rtf";
// ^^
答案 1 :(得分:1)
我发现您的代码存在许多问题:
LPWSTR AppName = L"C:\\Windows\\System32\\cmd.exe";
在C ++ 11和更高版本中无法编译。您需要(并且应该)改为使用LPCWSTR
,因为字符串文字是const
数据,并且LPCWSTR
是指向const
WCHAR的指针数据,但LPWSTR
是指向非const
WCHAR数据的指针。
在string bstr = "C:\\Windows\\System32\\cmd.exe /C del"+trans_loc+"a.rtf";
中,del
命令和要删除的文件名之间缺少必需的空格字符。
在LPWSTR Command = new WCHAR[bstr.length()];
中,您没有为空终止符分配足够的空间。另外,无论如何都不要将bstr.length()
用于转换后的长度,因为不能保证转换后的字符串不会大于原始字符串。您应该使用MultiByteToWideChar()
输出缓冲区调用NULL
一次来计算实际的转换长度(您正在执行的操作),然后分配内存(您没有执行的操作-您分配得太早了!) ,然后再次调用MultiByteToWideChar()
进行实际转换。
您正在泄漏已分配的内存(您未在调用delete[] Command;
)。我建议使用std::wstring
或std::vector<WCHAR>
代替new WCHAR[]
。
您说res
设置为1,这意味着CreateProcessW()
在运行cmd.exe
时实际上成功(现在,是否{{ 1}}成功执行命令是另一回事-使用GetExitCodeProcess()
找出来),因此cmd.exe
的返回值毫无意义!在致电GetLastError()
GetLastError()
当然很有意义
无论CreateProcessW()
是成功还是失败,您都在呼叫WaitForSingleObject()
。
尝试以下方法:
CreateProcessW()
或者,如果您使用的是Windows 10 build 17035或更高版本,并且在Windows设置中启用了“测试版:使用Unicode UTF-8进行全球语言支持”选项(或者,如果STARTUPINFO si = {};
si.cb = sizeof(si);
PROCESS_INFORMATION pi = {};
std::string bstr = "C:\\Windows\\System32\\cmd.exe /C del \"" + trans_loc + "a.rtf\"";
int wchars_num = MultiByteToWideChar(CP_UTF8, 0, bstr.c_str(), bstr.length(), NULL, 0);
if (wchars_num == 0)
{
dprintf(("MultiByteToWideChar Error %d", GetLastError()));
}
else
{
std::vector<WCHAR> Command(wchars_num + 1);
MultiByteToWideChar(CP_UTF8, 0, bstr.c_str(), bstr.length(), Command.data(), wchars_num);
if (!CreateProcessW(nullptr, Command.data(), nullptr, nullptr, FALSE, DETACHED_PROCESS, nullptr, nullptr, &si, &pi))
{
dprintf(("CreateProcessW Error %d", GetLastError()));
}
else
{
WaitForSingleObject(pi.hProcess, INFINITE);
DWORD dwExitCode = 0;
GetExitCodeProcess(pi.hProcess, &dwExitCode);
dprintf(("cmd.exe Exit Code %d", dwExitCode));
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
}
}
不包含任何内容非ASCII,非用户区域设置字符),则根本不需要trans_loc
转换:
MultiByteToWideChar()
话虽如此,一个更好的选择是简单地使用STARTUPINFO si = {};
si.cb = sizeof(si);
PROCESS_INFORMATION pi = {};
std::string Command = "C:\\Windows\\System32\\cmd.exe /C del \"" + trans_loc + "a.rtf\"";
if (!CreateProcessA(nullptr, const_cast<char*>(Command.c_str()), nullptr, nullptr, FALSE, DETACHED_PROCESS, nullptr, nullptr, &si, &pi))
{
dprintf(("CreateProcessA Error %d", GetLastError()));
}
else
{
WaitForSingleObject(pi.hProcess, INFINITE);
DWORD dwExitCode = 0;
GetExitCodeProcess(pi.hProcess, &dwExitCode);
dprintf(("cmd.exe Exit Code %d", dwExitCode));
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
}
而不是std::wstring
来开始:
std::string
当然,最简单的解决方案是根本不使用STARTUPINFO si = {};
si.cb = sizeof(si);
PROCESS_INFORMATION pi = {};
// make sure trans_loc is std::wstring instead of std::string...
std::wstring bstr = L"C:\\Windows\\System32\\cmd.exe /C del \"" + trans_loc + L"a.rtf\"";
if (!CreateProcessW(nullptr, Command.data(), nullptr, nullptr, FALSE, DETACHED_PROCESS, nullptr, nullptr, &si, &pi))
{
dprintf(("CreateProcessW Error %d", GetLastError()));
}
else
{
WaitForSingleObject(pi.hProcess, INFINITE);
DWORD dwExitCode = 0;
GetExitCodeProcess(pi.hProcess, &dwExitCode);
dprintf(("cmd.exe Exit Code %d", dwExitCode));
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
}
,而要使用DeleteFileW()
:
cmd.exe / C del
或者,如果您坚持使用UTF-8编码的// make sure trans_loc is std::wstring instead of std::string...
std::wstring bstr = trans_loc + L"a.rtf";
if (!DeleteFileW(bstr.c_str()))
{
dprintf(("DeleteFileW Error %d", GetLastError()));
}
:
std::string
或者,如果您使用的是启用了UTF-8支持的Windows 10(或者std::string bstr = trans_loc + "a.rtf";
int wchars_num = MultiByteToWideChar(CP_UTF8, 0, bstr.c_str(), bstr.length(), NULL, 0);
if (wchars_num == 0)
{
dprintf(("MultiByteToWideChar Error %d", GetLastError()));
}
else
{
std::vector<WCHAR> wstr(wchars_num + 1);
MultiByteToWideChar(CP_UTF8, 0, bstr.c_str(), bstr.length(), wstr.data(), wchars_num);
if (!DeleteFileW(wstr.c_str()))
{
dprintf(("DeleteFileW Error %d", GetLastError()));
}
}
不包含任何非ASCII,非用户区域设置的字符):
trans_loc