Question:
I am trying to execute powershell commands in C++ and get its output through pipes.
My program works perfectly for cmd.exe. However, when I try to do the same thing with powershell.exe, I only get “W” as an output.
I have commented the line in the code below that needs to be modified to execute powershell.exe
Below is my code that works for cmd.exe:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
HANDLE stdinRd, stdinWr, stdoutRd, stdoutWr; DWORD readFromCmd(); DWORD writeToCmd(CString command); int main(int argc,char* argv[]) { SECURITY_ATTRIBUTES sa={sizeof(SECURITY_ATTRIBUTES), NULL, true}; if(!CreatePipe(&stdinRd, &stdinWr, &sa, 1000000) || !CreatePipe(&stdoutRd,&stdoutWr, &sa, 1000000)) { printf("CreatePipe()"); } STARTUPINFO si; PROCESS_INFORMATION pi; GetStartupInfo(&si); si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; si.wShowWindow = SW_HIDE; si.hStdOutput = stdoutWr; si.hStdError = stdoutWr; si.hStdInput = stdinRd; // If powershell.exe is invoked, it does not work, however works for cmd.exe //if(!CreateProcess(TEXT("C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe"), NULL, NULL, NULL, TRUE,0, NULL, TEXT("C:\\Windows"), &si, &pi)) if(!CreateProcess(TEXT("C:\\Windows\\System32\\cmd.exe"), NULL, NULL, NULL, TRUE,0, NULL, TEXT("C:\\Windows"), &si, &pi)) { printf("CreateProcess()"); printf("CreateProcess() failed in initiatecmd(CString,int) method",0); return -1; } writeToCmd(L"dir"); Sleep(1000); readFromCmd(); getchar(); TerminateProcess(pi.hProcess,0); CloseHandle(pi.hProcess); return 0; } DWORD writeToCmd(CString command) { DWORD ret; DWORD numberofbyteswritten; command.AppendChar('\n'); LPSTR command_ANSI; int size_needed = WideCharToMultiByte(CP_UTF8,0,command.GetString(),-1,NULL,0,NULL,NULL); command_ANSI = (LPSTR) calloc(1, ( size_needed + 1 )* sizeof(char)); WideCharToMultiByte(CP_UTF8,0,command.GetString(),-1,command_ANSI,size_needed,NULL,NULL); ret = WriteFile(stdinWr, command_ANSI, size_needed-1, &numberofbyteswritten, NULL); if(ret==0) { printf("WriteFile()"); printf("WriteFile() method failed in writeToCmd(CString) method",0); return 0; } CStringA temp; temp.Format("%d",numberofbyteswritten); temp += " bytes (Command:"; temp+=command; temp+=") are successfully written to cmd"; printf("%s",temp); return 1; } DWORD readFromCmd() { CString output_jsonstring; DWORD ret; DWORD dwRead; while(1) { DWORD totalbytesavailable; if(PeekNamedPipe(stdoutRd, NULL, 0, NULL, &totalbytesavailable, 0) == 0) { printf("PeekNamedPipe()"); printf("PeekNamedPipe() method failed in responseHandler() method",0); return 0; } if(totalbytesavailable != 0) { char output_cmd[1000000]; if(ReadFile(stdoutRd, output_cmd, min(1000000,totalbytesavailable), &dwRead, NULL)==0) { printf("ReadFile()"); printf("ReadFile() method failed in responseHandler() method",0); return 0; } int min = min(1000000,totalbytesavailable); output_cmd[min]='\0'; printf("\n%s",output_cmd); } if(totalbytesavailable == 0) break; Sleep(100); } return 1; } |
If the CreateProcess() is used for powershell, it does not work the same way, but I get only W as output.
What is the reason for this?
And
How to get over this problem?
EDIT 1 : If I display the output_cmd in a loop character by character as output_cmd[i] where i = 0 to strlen(output_cmd), I get an output as given below:
i n d o w s P o w e r S h e l l
C o p y r i g h t ( C ) 2 0 1 4 M i c r o s o f t C o r p o r a t i o n . A l l r i g h t s r e s e r v e d .
P S C : \ W i n d o w s >
and the application hangs after that! It doesn’t take in any input, or give any output after that!
Answer:
You passed string to wrong place:
CreateProcess(TEXT("C:\\Windows\\System32\\cmd.exe")
actually the first parameter should be NULL:
CreateProcess(NULL, TEXT("C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe")