仅供参考: #pragma comment(lib,"user32") #include <stdio.h> #include <windows.h> int main() { SECURITY_ATTRIBUTES sa = {0}; STARTUPINFO si = {0}; PROCESS_INFORMATION pi = {0}; HANDLE hPipeOutputRead = NULL; HANDLE hPipeOutputWrite = NULL; HANDLE hPipeInputRead = NULL; HANDLE hPipeInputWrite = NULL; BOOL bTest = 0; DWORD dwNumberOfBytesRead = 0; DWORD dwNumberOfBytesWrite = 0; CHAR szMsg[100]; CHAR szBuffer[256]; sa.nLength = sizeof(sa); sa.bInheritHandle = TRUE; sa.lpSecurityDescriptor = NULL; // Create pipe for standard output redirection. CreatePipe(&hPipeOutputRead, // read handle &hPipeOutputWrite, // write handle &sa, // security attributes 0 // number of bytes reserved for pipe - 0 default ); // Create pipe for standard input redirection. CreatePipe(&hPipeInputRead, // read handle &hPipeInputWrite, // write handle &sa, // security attributes 0 // number of bytes reserved for pipe - 0 default ); // Make child process use hPipeOutputWrite as standard out, // and make sure it does not show on screen. si.cb = sizeof(si); si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; si.wShowWindow = SW_HIDE; si.hStdInput = hPipeInputRead; si.hStdOutput = hPipeOutputWrite; si.hStdError = hPipeOutputWrite; CreateProcess ( NULL, "cmd.exe", NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi); // Now that handles have been inherited, close it to be safe. // You don't want to read or write to them accidentally. CloseHandle(hPipeOutputWrite); CloseHandle(hPipeInputRead); // Now test to capture DOS application output by reading // hPipeOutputRead. Could also write to DOS application // standard input by writing to hPipeInputWrite. sprintf(szMsg, "dir *.txt /b\nexit\n"); WriteFile( hPipeInputWrite, // handle of the write end of our pipe &szMsg, // address of buffer that send data 18, // number of bytes to write &dwNumberOfBytesWrite,// address of number of bytes read NULL // non-overlapped. ); while(TRUE) { bTest=ReadFile( hPipeOutputRead, // handle of the read end of our pipe &szBuffer, // address of buffer that receives data 256, // number of bytes to read &dwNumberOfBytesRead, // address of number of bytes read NULL // non-overlapped. ); if (!bTest){ sprintf(szMsg, "Error #%d reading pipe.",GetLastError()); MessageBox(NULL, szMsg, "WinPipe", MB_OK); break; } // do something with data. szBuffer[dwNumberOfBytesRead] = 0; // null terminate MessageBox(NULL, szBuffer, "WinPipe", MB_OK); } // Wait for CONSPAWN to finish. WaitForSingleObject (pi.hProcess, INFINITE); // Close all remaining handles CloseHandle (pi.hProcess); CloseHandle (hPipeOutputRead); CloseHandle (hPipeInputWrite); return 0; }
1,共享内存
2,消息队列
3,套接字
4,管道以下为消息队列的:
1.消息结构模板
strut msgbuf
{
long int mtype;//消息类型
char mtext[1];//消息内容
}2.msgget创建消息
#include <sys/msg.h>
int msgget(key_t key, int flag);
此函数返回key指定消息的标识符
key 一般有ftok函数产生 ,该函数为key_t ftok(const char *pathname, int proj_id);
该函数把从pathname导出的信息与id低8位组合成一个整数IPC键, 调用时pathname必须存在,若不存在ftok调用失败,返回-1,成功返回该整数IPC键值
flag 为该消息队列的读写权限组合,可以与IPC_CREAT 或IPC_EXCL相与,其中创建对列时都要使用IPC_CREAT,其中IPC_CREAT|IPC_EXCL含义是若已有该队列则返回错误
此函数成功时,返回非负队列标识符;失败时返回-1#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
main()
{
key_t lKey;
int nMsgId;
if((lKey = ftok("/etc/profile",1)) == -1)
{
perror("ftok");
exit(1);
}
//带参数IPC_CREAT和IPC_EXCL,如果队列不存在则创建队列,已存在则返回EEXIST
if((nMsgId = msgget(lKey,IPC_CREAT|IPC_EXCL|0666)) == -1)
{
if(errno != EEXIST)//创建失败且不是由于队列已存在
{
perror("msgget");
exit(2);
}
if((nMsgId = msgget(lKey,0)) == -1)//已存在
{
perror("msgget");
exit(3);
}
}
printf("MsgID=%d\n",nMsgId);
return 0;
}
3.msgsnd消息发送
int msgsnd(int msqid, const void *ptr, size_t length, int flag);
此函数发送消息到指定的消息对列
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
typedef struct
{
long int nType;
char szText[256];
}MSG;
main()
{
key_t lKey;
int nMsgId;
MSG msg;
if((lKey = ftok("/etc/profile",1)) == -1)//生成键值
{
perror("ftok");
exit(1);
}
if((nMsgId = msgget(lKey,IPC_CREAT|IPC_EXCL|0666)) == -1)//创建消息队列
{
if(errno != EEXIST)
{
perror("msgget");
exit(2);
}
if((nMsgId = msgget(lKey,0)) == -1)
{
perror("msgget");
exit(3);
}
}
memset(&msg,0x00,sizeof(MSG));//清空队列
msg.nType = 2;//指定消息类型为2
memcpy(msg.szText,"123456",6);//指定消息内容
if(msgsnd(nMsgId,(const void *)&msg,strlen(msg.szText),IPC_NOWAIT) < 0)//非阻塞发送消息
{
perror("msgsnd");
}
return 0;
}队列中已经有一条消息,长度6字节4.msgrcv消息发送
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
typedef struct
{
long int nType;
char szText[256];
}MSG;
main()
{
key_t lKey;
int n,nMsgId;
MSG msg;
if((lKey = ftok("/etc/profile",1)) == -1)
{
perror("ftok");
exit(1);
}
if((nMsgId = msgget(lKey,0)) == -1)
{
perror("ftok");
exit(2);
}
memset(&msg,0x00,sizeof(MSG));
if((n = msgrcv(nMsgId,(void *)&msg,sizeof(msg.szText),2L,0)) < 0)//从队列接收消息,读出以后就不存在了
{
perror("msgrcv");
}
else
{
printf("msgrcv return length=[%d] text=[%s]\n",n,msg.szText);//输出
}
return 0;
}
输出:
msgrcv return length=[6] text=[123456]5.msgctl控制消息
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
消息队列控制函数
其中msqid为消息队列描述符
cmd有以下三种:
IPC_RMID:删除msgid指定的消息队列,当前在该队列上的任何消息都被丢弃,对于该命令,buf参数可忽略
IPC_SET:设置消息队列msgid_ds结构体的四个成员:msg_perm.uid,msg_perm_gid,msg_perm.mode和msg_qbytes。它们的值来自由buf指向的结构体中的相应成员。
IPC_STAT:给调用者通过buf返回指定消息队列当前对应msgid_ds结构体
函数执行成功返回0,失败返回-1#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
typedef struct
{
long int nType;
char szText[256];
}MSG;
main()
{
key_t lKey;
int n,nMsgId;
MSG msg;
struct msqid_ds qds;
if((lKey = ftok("/etc/profile",1)) == -1)
{
perror("ftok");
exit(1);
}
if((nMsgId = msgget(lKey,0)) == -1)
{
perror("ftok");
exit(2);
}
memset(&qds,0x00,sizeof(struct msqid_ds));
if(msgctl(nMsgId,IPC_STAT,&qds) < 0)//获取消息队列属性,获取状态放pds中
{
perror("msgctl IPC_STAT");
exit(3);
}
printf("msg_perm.mode=%d\n",qds.msg_perm.mode);
qds.msg_perm.mode &= (~0222);//去除消息队列的写权限
if(msgctl(nMsgId,IPC_SET,&qds) < 0)//设置消息队列权限
{
perror("msgctl IPC_SET");
exit(4);
}
memset(&msg,0x00,sizeof(MSG));
msg.nType = 2;
memcpy(msg.szText,"12345",5);
if(msgsnd(nMsgId,(void *)&msg,5,0) < 0)//发送消息
{
perror("msgsnd");
}
if(msgctl(nMsgId,IPC_RMID,NULL) < 0)//删除消息
{
perror("msgctl IPC_RMID");
exit(5);
}
return 0;
}
说明: (~0222)取反后做与实际上就是去除其他用户的写权限,在C语言中,八进制常用用前缀表示
简单的例子可能是这样CreateProcess(_T("cmd.exe"), _T("ping 192.168.10.25").......)
http://blog.sina.com.cn/s/blog_6cadcce70101apwv.html
WinExec:http://msdn.microsoft.com/query/dev10.query?appId=Dev10IDEF1&l=ZH-CN&k=k(%22WINBASE%2fWINEXEC%22);k(WINEXEC);k(DevLang-%22C%2B%2B%22);k(TargetOS-WINDOWS)&rd=true
http://blog.sina.com.cn/s/blog_6cadcce70101apwv.html 用管道的话是不是CMD可以一直读取、执行管道里写入的命令,知道判断管道内没有命令?这说明CMD一直在后台运行吗?我现在只可以根据这个例子执行一个命令,不知道怎么再继续输入命令(必须是在第一个命令的基础上执行) 谢谢
一般用语句si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES
查了一下资料,STARTF_USESTDHANDLES使用hstdInput、hstdOutput和hstdError成员:HANDLE hStdInput用于设定供控制台输入和输出用的缓存的句柄。按照默认设置,hstdInput 用于标识键盘缓存,hstdOutput和hstdError用于标识控制台窗口的缓存。
而我不想用键盘输入命令,是不是问题出在这里啊?
#pragma comment(lib,"user32")
#include <stdio.h>
#include <windows.h>
int main() {
SECURITY_ATTRIBUTES sa = {0};
STARTUPINFO si = {0};
PROCESS_INFORMATION pi = {0};
HANDLE hPipeOutputRead = NULL;
HANDLE hPipeOutputWrite = NULL;
HANDLE hPipeInputRead = NULL;
HANDLE hPipeInputWrite = NULL;
BOOL bTest = 0;
DWORD dwNumberOfBytesRead = 0;
DWORD dwNumberOfBytesWrite = 0;
CHAR szMsg[100];
CHAR szBuffer[256]; sa.nLength = sizeof(sa);
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = NULL; // Create pipe for standard output redirection.
CreatePipe(&hPipeOutputRead, // read handle
&hPipeOutputWrite, // write handle
&sa, // security attributes
0 // number of bytes reserved for pipe - 0 default
); // Create pipe for standard input redirection.
CreatePipe(&hPipeInputRead, // read handle
&hPipeInputWrite, // write handle
&sa, // security attributes
0 // number of bytes reserved for pipe - 0 default
); // Make child process use hPipeOutputWrite as standard out,
// and make sure it does not show on screen.
si.cb = sizeof(si);
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
si.wShowWindow = SW_HIDE;
si.hStdInput = hPipeInputRead;
si.hStdOutput = hPipeOutputWrite;
si.hStdError = hPipeOutputWrite; CreateProcess (
NULL, "cmd.exe",
NULL, NULL,
TRUE, 0,
NULL, NULL,
&si, &pi); // Now that handles have been inherited, close it to be safe.
// You don't want to read or write to them accidentally.
CloseHandle(hPipeOutputWrite);
CloseHandle(hPipeInputRead); // Now test to capture DOS application output by reading
// hPipeOutputRead. Could also write to DOS application
// standard input by writing to hPipeInputWrite.
sprintf(szMsg, "dir *.txt /b\nexit\n");
WriteFile(
hPipeInputWrite, // handle of the write end of our pipe
&szMsg, // address of buffer that send data
18, // number of bytes to write
&dwNumberOfBytesWrite,// address of number of bytes read
NULL // non-overlapped.
); while(TRUE)
{
bTest=ReadFile(
hPipeOutputRead, // handle of the read end of our pipe
&szBuffer, // address of buffer that receives data
256, // number of bytes to read
&dwNumberOfBytesRead, // address of number of bytes read
NULL // non-overlapped.
); if (!bTest){
sprintf(szMsg, "Error #%d reading pipe.",GetLastError());
MessageBox(NULL, szMsg, "WinPipe", MB_OK);
break;
} // do something with data.
szBuffer[dwNumberOfBytesRead] = 0; // null terminate
MessageBox(NULL, szBuffer, "WinPipe", MB_OK);
} // Wait for CONSPAWN to finish.
WaitForSingleObject (pi.hProcess, INFINITE); // Close all remaining handles
CloseHandle (pi.hProcess);
CloseHandle (hPipeOutputRead);
CloseHandle (hPipeInputWrite); return 0;
}
你给我参考的代码是要通过键盘,向输入 hPipeInputWrite输入命令吗?STARTF_USESTDHANDLES是不是限制了只能通过键盘输入命令?
能不能做成一个按键响应发送一个命令行给CMD的形式?
恐怕不行,我需要一个消息响应对应一个命令或两三个命令,应该会有好多个消息响应,而全部的命令都应该是相关的,也就是说CMD需要一直在执行。。这个可以实现吗?