通過匿名管道獲得CMD或其它程式的輸出(不彈窗)
阿新 • • 發佈:2021-02-03
技術標籤:c++
寫程式時候 需要呼叫CMD並獲得CMD輸出結果.
我使用VS2019.
最簡單的方法 是用 _popen() … 但在非控制檯程式下 ,它彈窗 ,一閃而過. 網上查了很多資料 都說沒辦法靜默執行.
還有一套方法是WIN32 的 CreatePipe + CreateProcess
雖說這裡是原創, 但也借鑑了很多文章. 無奈的是,程式碼基本都執行不起來. 要麼就雲裡霧裡, 讓我這小白看不懂…
折騰了有3-4天…弄出來了, 分享完整程式碼.註釋… 給同學們參考 少走彎路. 有可以改進的地方 請指教.
右邊是目前我找到最好的一篇文章了, 講得清楚 感謝老師. https://write-bug.com/article/1932.html
呼籲大家得閒時 把填過的坑,提煉過的內容,分享出來. 增加咱們網路文章含金量. 別一起苦哈哈的重複造輪子…這簡單的東西愣是沒找到適合的解決方案. 多一點點的付出, 在網路時代, 勝造七級浮屠. ヽ(ー_ー)ノ
PS :真不知道 應該使用char還是wchar_t 看的資料也眾說紛紜. 但就自己的使用體驗, 平時用char 需要時候轉wchar_t
就比如下面的程式碼, 如果GetAppOutput返回值是寬字串 那麼main函式中 列印的是%ws 寬字元, 會沒法顯示管道讀取的內容… 不知道為什麼. 但%s可以(即使GetAppOutput返回值是寬字串)… 是什麼原因呢?
#include <Windows.h>
#include <stdio.h>
char* GetAppOutput(const char* pszCmdLine, const unsigned& nResultBufferSize)
{
//在編譯前 可能根據需求調整陣列大小的變數
char szResultBuffer[3000] = ""; //返回字串的尺寸
wchar_t szCmdLine[300] = L""; //傳參傳遞的輸入命令及尺寸賦值到新陣列. CreateProcess函式不識別const和多位元組字元.
mbstowcs(szCmdLine, pszCmdLine, sizeof(szCmdLine) * 0.5); //多位元組字串轉寬字串
//設定安全屬性
SECURITY_ATTRIBUTES sa = { 0 };
sa.nLength = sizeof(sa);
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = NULL;
//建立匿名管道
HANDLE hRead = NULL;
HANDLE hWrite = NULL;
if (!CreatePipe(&hRead, &hWrite, &sa, 0))
{
MessageBoxW(NULL, L"CreatePipe錯誤", L"提示", MB_ICONERROR);
exit(0);
}
//設定新程序引數
PROCESS_INFORMATION pi = { 0 }; //新程序結構體
STARTUPINFO si = { 0 }; //指定新程序的主視窗特性
si.cb = sizeof(si);
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; //標記出需要控制的內容
si.wShowWindow = SW_HIDE; //隱藏視窗
si.hStdError = hWrite;
si.hStdOutput = hWrite;
//建立新程序, 將執行結果寫入匿名管道中
if (!CreateProcess(NULL, szCmdLine, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
{
MessageBoxW(NULL, L"CreateProcess錯誤", L"提示", MB_ICONERROR);
exit(0);;
}
//等待命令執行完畢
WaitForSingleObject(pi.hThread, INFINITE);
WaitForSingleObject(pi.hProcess, INFINITE);
//讀取匿名管道的輸出結果到緩衝區
RtlZeroMemory(szResultBuffer, nResultBufferSize);
ReadFile(hRead, szResultBuffer, nResultBufferSize, NULL, NULL);
//關閉控制代碼
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
CloseHandle(hWrite);
CloseHandle(hRead);
//返回結果
return szResultBuffer;
}
int main()
{
printf("---------cmd輸出---------\n%s\n", GetAppOutput("cmd /c getmac", 1000));
printf("---------PowerShell輸出--\n%s", GetAppOutput("PowerShell Get-Date", 1000));
return 0;
}