2017-02-10 13 views
0

Когда я использую ShellExecuteEx с такой командой "-unused parameter -action capturescreenshot -filename C:\\ATDK\\Screenshots\\abcd.jbg", все работает нормально, а Executor.exe начинается с char* argv[] со всеми ок. 9 параметров. Но когда команда имеет для пары символов больше, например, имя файла «abc ... xyz.jpg», то этот процесс имеет argc == 1, и команда пуста. Итак, команда в порядке до отправки в ShellExecute. После того, как я изменил это на ShellExecute, а не Ex, он работает! Команда может быть очень длинной, и она успешно прошла. Может ли кто-нибудь объяснить, в чем разница? Вот код с SHELLEXECUTEINFO, который я заполнил.ShellExecuteEx не проходит длинную команду

std::wstringstream wss; 
wss << L"-unused" << " " // added because we need to pass some info as 0 parameter 
    << L"parameter" << " " // added because EU parser sucks 
    << L"-action" << " " 
    << L"capturescreenshot" << " " 
    << L"-filename" << " " 
    << L"C:\\ATDK\\Screenshots\\abc.jpg"; 

SHELLEXECUTEINFO shell_info; 
ZeroMemory(&shell_info, sizeof(shell_info)); 

shell_info.cbSize = sizeof(SHELLEXECUTEINFO); 
shell_info.fMask = SEE_MASK_ASYNCOK | SEE_MASK_NO_CONSOLE; 
shell_info.hwnd = NULL; 
shell_info.lpVerb = NULL; 
shell_info.lpFile = L"C:/ATDK/Executor"; 
shell_info.lpParameters = (LPCWSTR)wss.str().c_str(); 
shell_info.lpDirectory = NULL; 
shell_info.nShow = SW_MINIMIZE; 
shell_info.hInstApp = NULL; 
// 1 
ShellExecuteEx(&shell_info); 
// this sucks, 
// GetLastError returns err code 2147483658, 
//FormatMessage returns The data necessary to complete this operation is not yet available 

// 2 
ShellExecute(NULL, NULL, L"C:/ATDK/Executor", (LPCWSTR)wss.str().c_str(), NULL, NULL); 
// OK! 
+1

То, что (LPCWSTR), только остановило компилятор, сообщив вам, что код был неправильным, это не помешало вам сделать это неправильно. Если вы не хотите конвертировать в строку Unicode с помощью mbstowcs() или MultiByteToWideString(), то используйте SHELLEXECUTEINFOA и ShellExecuteExA(). –

+0

Вы также не проверяете наличие ошибок. Вы должны проверить возвращаемое значение функции. –

+0

Возможный дубликат [странное поведение при преобразовании std :: string в LPCSTR] (http://stackoverflow.com/questions/11370536/weird-behavior-while-converting-a-stdstring-to-a-lpcstr) –

ответ

5

Ваша ошибка здесь:

shell_info.lpParameters = (LPCWSTR)wss.str().c_str(); 

wss.str() возвращает временный объект, который после окончания полного выражения, в котором она создается больше не существует. Используя его после этой точки не определено поведение.

Чтобы решить эту проблему, вам нужно будет построить объект std::wstring, который достаточно долго для вызова ShellExecuteEx для возврата.

std::wstringstream wss; 
wss << L"-unused" << " " 
    << L"parameter" << " " 
    // ... 

SHELLEXECUTEINFO shell_info; 
ZeroMemory(&shell_info, sizeof(shell_info)); 

// Construct string object from string stream 
std::wstring params{ wss.str() }; 

shell_info.cbSize = sizeof(SHELLEXECUTEINFO); 
shell_info.fMask = SEE_MASK_ASYNCOK | SEE_MASK_NO_CONSOLE; 
shell_info.hwnd = NULL; 
shell_info.lpVerb = NULL; 
shell_info.lpFile = L"C:\\ATDK\\Executor"; // Path separator on Windows is \ 
shell_info.lpParameters = params.c_str(); // Use string object that survives the call 
shell_info.lpDirectory = NULL; 
shell_info.nShow = SW_MINIMIZE; 
shell_info.hInstApp = NULL; 

ShellExecuteEx(&shell_info); 

Обратите внимание, что ваш второй вызов

ShellExecute(NULL, NULL, L"C:\\ATDK\\Executor", wss.str().c_str(), NULL, NULL); 

надежно работает. Несмотря на то, что wss.str() все еще возвращает временный, он действителен до конца полного выражения (т. Е. Во время вызова функции).