-3

I want to invoke a command like this:

image

I am using this code:

 std::string szArg = " -i " + m_strSign;
 wstringstream wss;
 wss<<szArg.c_str();
 wstringstream wssa;
 wssa<<strToolupdater.c_str();
 ShellExecute(NULL,TEXT("open"), wssa.str().c_str(), wss.str().c_str(),TEXT(""),SW_NORMAL);
 wcout<<wssa.str().c_str()<<wss.str().c_str()<<endl;

The expected result is to execute ToolUpdater.exe -i Hackeroid_Qqhcs, but the actual result is executing ToolUpdater.exe, the input parameter is invalid.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
bai
  • 366
  • 2
  • 9
  • And what is the expected result ? BTW don't post pictures of code but post the code. – Jabberwocky Sep 08 '16 at 06:43
  • the expected result is ToolUpdater.exe -i Hackeroid_Qqhcs,actually the real result is ToolUpdater.exe. the parameter is invalid. – bai Sep 08 '16 at 06:48
  • Update your question please, as it stands here it is totally unclear. – Jabberwocky Sep 08 '16 at 06:49
  • Please read this: [MCVE]. – Jabberwocky Sep 08 '16 at 06:52
  • There are several issues with your code. The most important one, there is no error handling for your call to [ShellExecute](https://msdn.microsoft.com/en-us/library/windows/desktop/bb762153.aspx). None of the error codes this API reports resembles *"the parameter is invalid"*. Where did you get that from? This is not to say, that your parameters aren't wrong. They are. `wstringstream::str()` returns a temporary. Once you called `c_str()` on it, it's dead. You are passing pointers to dead beef into `ShellExecute` (and you should be using `ShellExecuteEx` anyway, if just for error reporting). – IInspectable Sep 08 '16 at 09:15
  • Your naming of variables leaves a lot to be desired. One might naively imagine that the difference between `wss` and `wssa` is that the latter contains the *arguments*, but apparently that is not the case. A *very* unclear question, made 10,000 times worse by the fact that you posted pictures of code instead of actual code. – Cody Gray - on strike Sep 08 '16 at 12:12
  • @IInspectable: temp variables are not destroyed until the complete statement is finished. Using `str().c_str()` directly in the `ShelExecute()` parameters is perfectly safe in this example. – Remy Lebeau Sep 08 '16 at 18:41
  • Why is this tagged as MFC? There isn't one piece of MFC in it. I think it is weird mixing your std::string and std::wstring and std::wstrstream objects. Looks like all your doing is appending strings. I'd just use a CString and append what I needed. – Joseph Willcoxson Sep 08 '16 at 18:49

1 Answers1

1

The problem is that you are mixing std::string and std::wstring data together, and doing so incorrectly.

std::wstringstream does not have an operator<< for char* input, so you are actually invoking its operator<< for void* input instead. That operator formats the value of the pointer itself, not the data that it is pointing at. So you end up passing bad input to ToolUpdater.exe.

You would have caught this error at compile time if you were not using c_str() so much. Don't use c_str() unless you really need a raw character pointer (like in the ShellExecute() parameters). If you avoid raw pointers, the compiler can perform better type-safe validations for you:

std::string szArg = " -i " + m_strSign;
std::wstringstream wss;
wss << szArg; // ERROR!
std::wstringstream wssa;
wssa << strToolupdater; // ERROR!
ShellExecute(NULL, TEXT("open"), wssa.str().c_str(), wss.str().c_str(), TEXT(""), SW_NORMAL);
std::wcout << wssa.str() << wss.str() << std::endl;

That being said, you really don't need the std::wstringstream objects in this example, you can remove them completely.

If you call ShellExecuteA() instead, you can pass your std::string values to it like this:

std::string szArg = "-i " + m_strSign;
ShellExecuteA(NULL, "open", strToolupdater.c_str(), szArg.c_str(), NULL, SW_NORMAL);
std::cout << strToolupdater << " " << szArg << std::endl;

Or, if you change everything to std::wstring:

std::wstring szArg = L"-i " + m_strSign;
ShellExecuteW(NULL, L"open", strToolupdater.c_str(), szArg.c_str(), NULL, SW_NORMAL);
std::wcout << strToolupdater << L" " << szArg << std::endl;

If you cannot change your m_strSign and strToolupdater variables themselves to std::wstring (because other code still expects std::string), you can convert them to std::wstring temporarily when needed:

std::wstring toWStr(const std::string &s)
{
    std::wstring ret;
    int len = MultiByteToWideChar(0, 0, s.c_str(), s.length(), NULL, 0);
    if (len > 0)
    {
        ret.resize(len);
        MultiByteToWideChar(0, 0, s.c_str(), s.length(), &ret[0], len);
    }
    return ret;
}

std::wstring szToolUpdater = toWStr(strToolupdater);
std::wstring szArg = L"-i " + toWStr(m_strSign);
ShellExecuteW(NULL, L"open", szToolUpdater.c_str(), szArg.c_str(), NULL, SW_NORMAL);
std::wcout << szToolUpdater << L" " << szArg << std::endl;
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770