要实现这个功能其实挺简单的:
- 客户顿通信服务端(第二讲已经实现)
- 远程端 CreateProcess,创建一个 notepad
- 拿到这个 notepad 的句柄,在调用 SendMessage
创建记事本
进程编程相关知识请参阅:Windows API教程(四) 进程编程
BOOL CreateNotepad() { BOOL flag; STARTUPINFO start_info; ZeroMemory( &process_info, sizeof(process_info) ); ZeroMemory( &start_info, sizeof(start_info) ); start_info.cb = sizeof(start_info); flag = CreateProcess( NULL, // 不传程序路径, 使用命令行 "notepad.exe", // 命令行命令 NULL, // 不继承进程句柄(默认) NULL, // 不继承线程句柄(默认) FALSE, // 不继承句柄(默认) 0, // 没有创建标志(默认) NULL, // 使用默认环境变量 NULL, // 使用父进程的目录 &start_info, // STARTUPINFO 结构 &process_info );// PROCESS_INFORMATION 保存相关信息 if ( !flag ) { printf( "创建失败 Error: (%d).n", GetLastError() ); return 0; } return 1; }
将字符串写到记事本的 RichEdit 控件中
更多 RichEdit 控件的 Message 请参阅:Windows SDK 教程(四) 记事本与 SendMessage
void WriteNotepadText(char *str) { char text[250]; HWND hNotepad = FindWindow(TEXT("Notepad"), NULL); HWND hEdit = FindWindowEx(hNotepad, NULL, TEXT("Edit"), NULL); wsprintf(text, "%srn", str); SendMessage(hEdit, EM_REPLACESEL, NULL, (LPARAM)text); }
完整客户端代码
#include <Winsock2.h> #include <stdio.h> #pragma comment(lib, "ws2_32.lib") #define MSG_LEN 1024 PROCESS_INFORMATION process_info; BOOL strstart(char *text, char *begin); BOOL CreateNotepad(); void WriteNotepadText(char *str); void CloseNotepad(); int run(char *recvCmd, char *message) { if (strcmp(recvCmd, "test") == 0) { strcpy(message, "服务端你好,有什么事吗~"); } else if (strcmp(recvCmd, "open") == 0) { if(CreateNotepad()) { strcpy(message, "记事本创建成功"); } else { strcpy(message, "记事本创建失败!"); } } else if (strcmp(recvCmd, "close") == 0) { CloseNotepad(); strcpy(message, "Closed."); } else if (strstart(recvCmd, "write")) { WriteNotepadText(recvCmd + sizeof("write")); strcpy(message, "send"); } else if (strcmp(recvCmd, "exit") == 0) { return 1; } return 0; } void main() { int err = 0; char message[MSG_LEN] = {0}; char recvCmd[100] = {0}; SOCKET sockClient; // 客户端 Scoket SOCKADDR_IN addrServer; // 服务端地址 WSADATA wsaData; WORD wVersionRequested; wVersionRequested = MAKEWORD( 2, 2 ); err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { return; } if ( LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 2 ) { // 启动错误,程序结束 WSACleanup( ); return; } // 新建客户端 scoket sockClient = socket(AF_INET, SOCK_STREAM, 0); // 定义要连接的服务端地址 addrServer.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); // 目标IP (127.0.0.1是本机地址) addrServer.sin_family = AF_INET; // 协议类型是INET addrServer.sin_port = htons(6000); // 连接端口1234 // 让 sockClient 连接到 服务端 connect(sockClient, (SOCKADDR *)&addrServer, sizeof(SOCKADDR)); while(1) { // 清空字符串 ZeroMemory(recvCmd, sizeof(recvCmd)); ZeroMemory(message, sizeof(message)); // 从服务端获取数据 recv(sockClient, recvCmd, MSG_LEN, 0); // 打印数据 printf("-- 收到命令: [%s]n", recvCmd); run(recvCmd, message); if (strlen(recvCmd) > 0) { // 发送数据到服务端 send(sockClient, message, strlen(message) + 1, 0); } } // 关闭socket closesocket(sockClient); WSACleanup(); } /* * 创建一个记事本 */ BOOL CreateNotepad() { BOOL flag; STARTUPINFO start_info; ZeroMemory( &process_info, sizeof(process_info) ); ZeroMemory( &start_info, sizeof(start_info) ); start_info.cb = sizeof(start_info); flag = CreateProcess( NULL, // 不传程序路径, 使用命令行 "notepad.exe", // 命令行命令 NULL, // 不继承进程句柄(默认) NULL, // 不继承线程句柄(默认) FALSE, // 不继承句柄(默认) 0, // 没有创建标志(默认) NULL, // 使用默认环境变量 NULL, // 使用父进程的目录 &start_info, // STARTUPINFO 结构 &process_info );// PROCESS_INFORMATION 保存相关信息 if ( !flag ) { printf( "创建失败 Error: (%d).n", GetLastError() ); return 0; } return 1; } /* * 将字符串写到记事本的 RichEdit 控件中 */ void WriteNotepadText(char *str) { char text[250]; HWND hNotepad = FindWindow(TEXT("Notepad"), NULL); HWND hEdit = FindWindowEx(hNotepad, NULL, TEXT("Edit"), NULL); wsprintf(text, "%srn", str); SendMessage(hEdit, EM_REPLACESEL, NULL, (LPARAM)text); } /* * 关闭记事本 */ void CloseNotepad() { // 关闭进程句柄和线程句柄 DWORD dwDesiredAccess = PROCESS_TERMINATE; BOOL bInheritHandle = FALSE; HANDLE hProcess = OpenProcess(dwDesiredAccess, bInheritHandle, process_info.dwProcessId); if (hProcess == NULL) return; TerminateProcess(hProcess, 0); CloseHandle(hProcess); } /* * 判断 text 字符串是否以 begin 字符串开头 */ BOOL strstart(char *text, char *begin) { while(*begin) if (*begin++ != *text++) return FALSE; return TRUE; }
服务端代码
代码依旧是老样子:
#include <stdio.h> #include <string.h> #include <Winsock2.h> #pragma comment(lib, "ws2_32.lib") void main() { int err; // 错误信息 int len = sizeof(SOCKADDR); char cmdStr[100] = {0}; char sendBuf[100] = {0}; // 发送至客户端的字符串 char recvBuf[100] = {0}; // 接受客户端返回的字符串 char * ip; SOCKET sockServer; // 服务端 Socket SOCKADDR_IN addrServer;// 服务端地址 SOCKET sockClient; // 客户端 Scoket SOCKADDR_IN addrClient;// 客户端地址 WSADATA wsaData; // winsock 结构体 WORD wVersionRequested;// winsock 的版本 // 配置 Windows Socket版本 wVersionRequested = MAKEWORD( 2, 2 ); // 初始化 Windows Socket err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { // 启动错误,程序结束 return; } if ( LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 2 ) { // 启动错误,程序结束 WSACleanup(); // 终止Winsock 2 DLL (Ws2_32.dll) 的使用 return; } // 定义服务器端socket sockServer = socket(AF_INET, SOCK_STREAM, 0); // 设置服务端 socket addrServer.sin_addr.S_un.S_addr = htonl(INADDR_ANY); // 本机IP addrServer.sin_family = AF_INET; // 协议类型是INET addrServer.sin_port = htons(6000); // 绑定端口6000 // 将服务器端socket绑定在本地端口 bind(sockServer, (SOCKADDR *)&addrServer, sizeof(SOCKADDR)); // Listen 监听端口 listen(sockServer, 5); // 5 为等待连接数目 printf("服务器已启动:n监听中...n"); // 等待客户端连接 sockClient = accept(sockServer, (SOCKADDR *)&addrClient, &len); // 获取ip地址 ip = inet_ntoa(addrClient.sin_addr); // 输出连接提示 printf("-- IP %s 连接到服务端n", ip); while (1) { if (strcmp(cmdStr, "exit") == 0) { break; } printf("-- %s: %s n>>", ip, recvBuf); gets(cmdStr); send(sockClient, cmdStr, strlen(cmdStr) + 1, 0); recv(sockClient, recvBuf, 100, 0); } closesocket(sockClient); WSACleanup(); }
请问博主,该系列博文目录中的后面四篇文章什么时候出?
赞赞
最近,状态差,处于低谷。。尽量这个月更新。。欢迎督促。。
赞赞
博主 你好,后面的是不是不出了呀??这算是windows核心编程吗??
赞赞
Hi, 你好, 这些大部分是我 3, 4 年前关注的领域, 后来已经从 windows 弃坑转投 linux/mac 阵营 😂
赞赞
蟹蟹 辛苦了
赞赞
博主,这么多年了,我也来学习了,后面四篇是不是不能更新了,哈哈!
赞赞
博主 我最近在做这方面的程序 感觉很有帮助 要坚持更啊啊啊!!!!
赞赞