【问题标题】:ShellExecuteEx doesn't pass long commandShellExecuteEx 不传递长命令
【发布时间】:2017-02-10 09:00:34
【问题描述】:

当我将 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 代码。

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!

【问题讨论】:

  • 那个(LPCWSTR)强制转换只是阻止编译器告诉你代码错误,它并没有阻止你做错。如果您不想使用 mbstowcs() 或 MultiByteToWideString() 转换为 Unicode 字符串,请使用 SHELLEXECUTEINFOA 和 ShellExecuteExA()。
  • 您也没有正确检查错误。你必须检查函数的返回值。
  • @HansPassant:演员阵容总是很可疑,但在这种情况下,这只是不必要的。如果您的初步分析是正确的,将ShellExecuteEx 更改为ShellExecute 将无法解决问题。

标签: c++ windows winapi


【解决方案1】:

你的错误在这里:

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() 仍然返回一个临时值,它在完整表达式结束之前(即在整个函数调用过程中)都有效。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多