-1

I want to use CreateProcess() to execute an ADB command that launches an application/activity. It works using the simpler system(command) function, but I want to eliminate the creation of the command line window by system(). Below is what I have right now. I have tried using different CreateProcess()es, like CreateProcessW and CreateProcessA, but to no avail.

char prog[] = "C:\\Program Files\\Android\\sdk\\platform-tools\\platform-tools\\adb.exe";
char args[] = "adb shell am start -a android.intent.action.MAIN -n com.example.dmiller.myapplication/.Blankscreen";

STARTUPINFO si;
PROCESS_INFORMATION pi;

ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));

CreateProcess((LPCWSTR)prog, (LPWSTR)args, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi);

I got this partially from this answer How to use createprocess to execute adb program in PATH? but when the command should be executed in my program, nothing happens (when running system(cmd.c_str()), the appropriate app is launched on the attached device). Could anyone provide some help? Alternative methods are welcome as well.

UPDATE: I have applied some things from the below post to try to provide a better question. Code has been updated to my latest version.

CreateProcess doesn't pass command line arguments

Community
  • 1
  • 1
MartyMiller
  • 15
  • 10
  • _"but it isn't working for me at all."_ Elaborate this in your question please. How in particular it doesn't work for you? – πάντα ῥεῖ Feb 20 '15 at 19:58
  • 1
    _"I have updated the answer"_ You probably meant _the question_. What about checking the documentation of [`CreateProcess()`](https://msdn.microsoft.com/en-us/library/windows/desktop/ms682425(v=vs.85).aspx) again. IMHO you have at least one invalid `NULL` pointer (`lpApplicationName`) passed to it. – πάντα ῥεῖ Feb 20 '15 at 20:10
  • 1
    Yes, I meant the question. BOOL WINAPI CreateProcess( _In_opt_ LPCTSTR lpApplicationName, _Inout_opt_ LPTSTR lpCommandLine, _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, _In_ BOOL bInheritHandles, _In_ DWORD dwCreationFlags, _In_opt_ LPVOID lpEnvironment, _In_opt_ LPCTSTR lpCurrentDirectory, _In_ LPSTARTUPINFO lpStartupInfo, _Out_ LPPROCESS_INFORMATION lpProcessInformation ); None of my NULL parameters are non-optional according to the documentation. – MartyMiller Feb 20 '15 at 20:17
  • Zeroing the memory at the address of a pointer would set it to NULL, right? I think maybe you meant `STARTUPINFO si;` instead of `LPSTARTUPINFO si;`, given the way you call `ZeroMemory(&si, sizeof(si))`. Also, does it make sense to have a completely empty STARTUPINFO? – Austin Mullins Feb 20 '15 at 20:18
  • @πάνταῥεῖ I tried passing in "C:\\system32\\cmd.exe" as the lpApplicationName parameter, but that does not solve the problem. – MartyMiller Feb 20 '15 at 20:24
  • @AustinMullins, I am not sure exactly, but intuitively it doesn't make sense. I have no experience with process creation unfortunately. I did mean `STARTUPINFO si`, question has been updated. – MartyMiller Feb 20 '15 at 20:28
  • You don't want to execute `cmd.exe` anyway. You want `adb`. – Austin Mullins Feb 20 '15 at 20:29
  • Also, you need to pass `&si` to `CreateProcess`. I assume you did that in your code because it wouldn't have compiled otherwise. – Austin Mullins Feb 20 '15 at 20:30
  • It actually does compile with just `si` being passed, but I was under the impression it wouldn't as well. You're right though. Updated again, thanks. – MartyMiller Feb 20 '15 at 20:33

1 Answers1

1

Type-casting a char array to have type LPCWSTR doesn't make it so. The former is an array of one-byte characters. The latter is (a pointer to) an array of two-byte characters. The type cast tells the compiler that the one is really the other, and the compiler trusts you. It does not perform a conversion.

To fix this, declare prog and args to have type WCHAR or wchar_t instead of char, and use the L prefix on the literals:

WCHAR prog[] = L"...";
WCHAR args[] = L"...";

Then you can remove the LPCWSTR type casts because they won't be necessary anymore.

As usual, whenever you call an API function, it's wise to check the return value and look for any error codes. The documentation advises that you should check whether the function returns zero. If it does, call GetLastError to find out what the OS thinks the problem was.

Rob Kennedy
  • 161,384
  • 21
  • 275
  • 467