Я вижу ряд проблем с вашим кодом:
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
(теперь, если cmd.exe
успешно при выполнении вашей команды, это другой вопрос - используйте GetExitCodeProcess()
, чтобы выяснить это), и, следовательно, возвращаемое значение GetLastError()
это бессмысленно ! Конечно, имеет смысл звонить GetLastError()
до , звонить CreateProcessW()
Вы звоните WaitForSingleObject()
независимо от того, удастся ли CreateProcessW()
или нет.
Попробуйте вместо этого:
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);
}
}
Или, если вы используете Windows 10 build 17035 или более поздней версии и включили «Beta: используйте Unicode UTF-8 для Параметр "поддержка языков по всему миру" в ваших настройках Windows (или, если trans_loc
не содержит символов, отличных от ASCII, не относящихся к языку пользователя), тогда преобразование 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);
}
Конечно, самое простое решение - просто не использовать cmd.exe / C del
вообще, но вместо этого используйте DeleteFileW()
:
// 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()));
}
Или, если вы настаиваете на использовании кодировки UTF-8 std::string
:
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()));
}
}
Или, если вы используете Windows 10 с включенной поддержкой UTF-8 (или, если trans_loc
не содержит никаких символов, отличных от ASCII, не относящихся к языку пользователя):
std::string bstr = trans_loc + "a.rtf";
if (!DeleteFileA(bstr.c_str()))
{
dprintf(("DeleteFileA Error %d", GetLastError()));
}