正文:
自己写一个函数来支持CGI运行...
思路:
当WEB SERVER的请求是一个执行文件,
那么就执行这个文件(利用进程),可是如果要传入数据给CGI该如何办,那么CGI运行后的结果,在自己的程序中该如何得到呀?
那么就可以是管道,来达到数据的共享!
WEB页提交的数据在自己的程序中是可以得到的(SOCKET来得到)!就把数据传入给管道!
CGI程序需要的数据就从管道中去读!
当CGI程序运行结束后,就将结果输出给管道,自己的程序去读管道中的内容!
然后用SOCKET将结果发送给IE/NS就可以了!
下面只是一个函数,
cgiFileName:要执行的CGI程序名称
pPostValue:WEB页提交的值(POST方法提交的)
pPipeValue:环境变量的值(GET方法提交的值是放在环境变量QUERY_STRING中的)
isStdRead:CGI程序是否需要从管道中读取值
注意:POST方法提交的值,在环境变量中有一个变量CONTENT_LENGTH是记录POST提交值的长度!
每个环境变量是用'\0'字符来隔开的!(QUERY_STRING=name=66&password=77\0CONTENT_LENGTH=0\0\0)
当环境变量结尾应使用\0\0来结束!
千万不用API:SetEnvironmentVariable()来设置环境变量,一但将POST的值写入管道传给CGI程序,那用这个API函数设置的环境变量会丢失.
AnsiString CgiScriptRun(AnsiString cgiFileName,AnsiString pPostValue,char *pPipeValue,bool isStdRead){
HANDLE hProcess,hWrite,hRead, //进程句柄,管道写句柄,管道读句柄
SECURITY_ATTRIBUTES sa, //安全性结构
STARTUPINFO mysi, //子进程窗口属性结构
PROCESS_INFORMATION mypi, //子进程信息
bool bTest, //API是否调用成功
//填充安全性结构使句柄被继承
sa.nLength=sizeof(SECURITY_ATTRIBUTES),
sa.lpSecurityDescriptor=NULL,
sa.bInheritHandle=true,
bTest=CreatePipe(&hRead,&hWrite,&sa,0), //创建管道
if(!bTest){
return "",
}
//填充进程启动信息
memset(&mysi,0,sizeof(STARTUPINFO)),
mysi.cb=sizeof(STARTUPINFO),
mysi.dwFlags=STARTF_USESTDHANDLES,
if(!isStdRead)
//如果CGI(或PHP程序)不要从PIPE中取值(用了GET方法),则使用标准输入
mysi.hStdInput=GetStdHandle(STD_INPUT_HANDLE),
else
//则使用从管道中读
mysi.hStdInput=hRead,
mysi.hStdOutput=hWrite,//CGI程序运行结束后,会将结果送给标准输出(屏幕),在这里告诉CGI让它把
//结果送出个建立的管道中
mysi.hStdError=hWrite, //CGI程序出错,将出错信息改从管道中输出,(也就是向管道中写进信息)
//创建子进程
bTest=CreateProcess(NULL,
cgiFileName.c_str(),NULL,
NULL,true,//true为让这个进程继承上面设置的一些输入输出信息
DETACHED_PROCESS,
(LPVOID)pPipeValue,NULL,&mysi,&mypi),
//(LPVOID)pPipeValue ---传的环境变量
if(bTest)hProcess=mypi.hProcess,
else return"",
if(isStdRead){
if(bTest){
CloseHandle(mypi.hThread),
DWORD dwWritten,
bool bReturn,
char *g=pPostValue.c_str(),
//将提交的值写进管道
bReturn=WriteFile(hWrite,g,strlen(g),&dwWritten,NULL),
if(!bReturn)return "",
}
if(!bTest)return "",
//等待CGI程序执行完毕
WaitForSingleObject(hProcess,WAIT_ABANDONED),
}
//一定要关闭管道的读句柄
CloseHandle(hWrite),
char readBuf[100],
DWORD bytesRead=0,
AnsiString cgiout="",
//上面的CGI程序执行完毕后已经将结果写进管道了,现在只要读出来就可以了!
while(ReadFile(hRead,readBuf,100,&bytesRead,NULL)){
readBuf[bytesRead]='\0',
cgiout=cgiout+AnsiString(readBuf),
}
CloseHandle(hRead),
CloseHandle(hProcess),
//返回执行结果用SOCKET发送个用户!
return cgiout,
}
CGI程序是从标准输入中读数据,输出给标准输出!
这里用了管道,在自己的程序中,建立PIPE,让CGI改从PIPE中读数据或从PIPE中输出运行结果!
共2页 第1页 第2页






