2026/4/10 18:17:46
网站建设
项目流程
网站开发待遇,市场营销公司有哪些,苏宁易购网站建设分析,一个网站网站建设下来要花多少钱起因最近给公司的一个系统写了个启动的脚本#xff0c;但是领导说批处理这样的脚本太low了#xff0c;要使用EXE来启动#xff0c;未来还要使用加密工具对EXE进行加密。好吧#xff0c;我就在网上到处找bat转exe的工具#xff0c;找了很久#xff0c;都没有找到合适的但是领导说批处理这样的脚本太low了要使用EXE来启动未来还要使用加密工具对EXE进行加密。好吧我就在网上到处找bat转exe的工具找了很久都没有找到合适的只有一个用winrar制作自解压包的方法还算可以但是这玩意儿有两个坑爹的问题使用了自定义图标后安装时会被360报告有***用winrar制作的exe其本质还是解压后执行解压后的文件其实可以在系统临时目录下找到因此以后想要加密其实很容易就会被破解所以最好的办法看来就是自己写一个exe了考虑到我以前用过C因此下载了Dev-Cpp这个工具来编写代码。思路在C语言中执行DOS命令的方法很多如ShellExecute, WinExec, CreateProcess等但是这些接口都是只能一次执行一条命令在我的启动脚本里有很多命令有一些是设置环境变量的这样就没法在代码中一条条执行脚本中的命令必须要找到一个办法可以一次性执行多条命令。在网上找了很久最终确定使用CreateProcess同时要使用管道技术。也就是使用CreateProcess创建一个cmd进程然后通过输入管道将待执行的命令传递给cmd进程通过输出管道获取cmd进程的输出信息因为是通过管道进行所以可以模拟在DOS窗口一行行输入命令从而实现执行多条DOS命令了。实现从MSDN上找到管道的示例代码简单修改了一下。首先将CreateProcess的参数改为启动cmdchar cmdLine[] cmd; // Create the child process.bFuncRetn CreateProcess(NULL,cmdLine, // command lineNULL, // process security attributesNULL, // primary thread security attributesTRUE, // handles are inherited0, // creation flagsNULL, // use parents environmentNULL, // use parents current directorysiStartInfo, // STARTUPINFO pointerpiProcInfo); // receives PROCESS_INFORMATION然后将原来批处理里面的脚本复制一下放到一个变量里这里我改了一下没有用我实际的脚本因为那个不通用不适合做例子注意每一行最后要加上回车符\n这样才能正确模拟DOS窗口中输入命令的情况CHAR cmds[] ECHO OFF\ncd..\ndir\n再然后原来的示例代码中是把批处理文件作为EXE的参数传递进来的既然上面改为将批处理文件内容放到脚本里代码中从文件中读取命令的那部分就要去掉了这部分代码就不多说了。完整的示例代码如下#include stdio.h#include windows.h#define BUFSIZE 4096HANDLE hChildStdinRd, hChildStdinWr, hChildStdinWrDup,hChildStdoutRd, hChildStdoutWr, hChildStdoutRdDup,hInputFile, hStdout;BOOL CreateChildProcess(VOID);VOID WriteToPipe(VOID);VOID ReadFromPipe(VOID);VOID ErrorExit(const char *);VOID ErrMsg(LPTSTR, BOOL);int main(int argc, char *argv[]) { // SECURITY_ATTRIBUTES结构包含一个对象的安全描述符并指定检索到指定这个结构的句柄是否是可继承的。// 这个结构为很多函数创建对象时提供安全性设置SECURITY_ATTRIBUTES saAttr;BOOL fSuccess; // Set the bInheritHandle flag so pipe handles are inherited.// 设置句柄为可继承的使得子线程可以使用父线程saAttr.nLength sizeof(SECURITY_ATTRIBUTES);saAttr.bInheritHandle TRUE;saAttr.lpSecurityDescriptor NULL; // Get the handle to the current STDOUT.// 取得当前应用的标准输出句柄对于Windows控制台应用来说一般是输出到屏幕hStdout GetStdHandle(STD_OUTPUT_HANDLE); // Create a pipe for the child processs STDOUT.// 创建一个用于输出操作的匿名管道。if (! CreatePipe(hChildStdoutRd, hChildStdoutWr, saAttr, 0))ErrorExit(Stdout pipe creation failed\n); // Create noninheritable read handle and close the inheritable read handle.// 将输出管道的句柄绑定到当前进程fSuccess DuplicateHandle(GetCurrentProcess(), hChildStdoutRd,GetCurrentProcess(), hChildStdoutRdDup , 0,FALSE,DUPLICATE_SAME_ACCESS); if( !fSuccess )ErrorExit(DuplicateHandle failed);CloseHandle(hChildStdoutRd); // Create a pipe for the child processs STDIN.// 创建一个用于输入操作的匿名管道。if (! CreatePipe(hChildStdinRd, hChildStdinWr, saAttr, 0))ErrorExit(Stdin pipe creation failed\n); // Duplicate the write handle to the pipe so it is not inherited.// 将输入管道的句柄绑定到当前进程fSuccess DuplicateHandle(GetCurrentProcess(), hChildStdinWr,GetCurrentProcess(), hChildStdinWrDup, 0,FALSE, // not inheritedDUPLICATE_SAME_ACCESS); if (! fSuccess)ErrorExit(DuplicateHandle failed);CloseHandle(hChildStdinWr); // Now create the child process.// 创建DOS子进程fSuccess CreateChildProcess(); if (! fSuccess)ErrorExit(Create process failed); // Write to pipe that is the standard input for a child process.WriteToPipe(); // Read from pipe that is the standard output for child process.ReadFromPipe(); return 0;}BOOL CreateChildProcess() {PROCESS_INFORMATION piProcInfo;STARTUPINFO siStartInfo;BOOL bFuncRetn FALSE; // Set up members of the PROCESS_INFORMATION structure.ZeroMemory( piProcInfo, sizeof(PROCESS_INFORMATION) ); // Set up members of the STARTUPINFO structure.// 设定DOS进程的标准输入、输出和错误信息的管道// 使用前面创建的值DOS窗口的输入输出都会被定向到本应用中ZeroMemory( siStartInfo, sizeof(STARTUPINFO) );siStartInfo.cb sizeof(STARTUPINFO);siStartInfo.hStdError hChildStdoutWr;siStartInfo.hStdOutput hChildStdoutWr;siStartInfo.hStdInput hChildStdinRd;siStartInfo.dwFlags | STARTF_USESTDHANDLES; char cmdLine[] cmd; // Create the child process.bFuncRetn CreateProcess(NULL,cmdLine, // command lineNULL, // process security attributesNULL, // primary thread security attributesTRUE, // handles are inherited0, // creation flagsNULL, // use parents environmentNULL, // use parents current directorysiStartInfo, // STARTUPINFO pointerpiProcInfo); // receives PROCESS_INFORMATIONif (bFuncRetn 0)ErrorExit(CreateProcess failed); else {CloseHandle(piProcInfo.hProcess);CloseHandle(piProcInfo.hThread); return bFuncRetn;}}VOID WriteToPipe(VOID) {DWORD dwRead, dwWritten;CHAR chBuf[BUFSIZE];CHAR cmds[] ECHO ON\ncd..\ndir\n;WriteFile(hChildStdinWrDup, cmds, sizeof(cmds), dwWritten, NULL); // Close the pipe handle so the child process stops reading.if (! CloseHandle(hChildStdinWrDup))ErrorExit(Close pipe failed);}VOID ReadFromPipe(VOID) {DWORD dwRead, dwWritten;CHAR chBuf[BUFSIZE]; // Close the write end of the pipe before reading from the// read end of the pipe.if (!CloseHandle(hChildStdoutWr))ErrorExit(CloseHandle failed); // Read output from the child process, and write to parents STDOUT.// 获取子线程即DOS窗口的输出显示到标准输出设备上for (;;) { if( !ReadFile( hChildStdoutRdDup, chBuf, BUFSIZE, dwRead, NULL) || dwRead 0) break; if (! WriteFile(hStdout, chBuf, dwRead, dwWritten, NULL)) break;}}VOID ErrorExit (const char *lpszMessage) { fprintf(stderr, %s\n, lpszMessage);ExitProcess(0);}执行效果如下图C/C中一次性执行多个DOS命令main.exe的原始目录是D:\Workspace\research\C\Chrome\执行时首先执行了cd..退到上一层目录然后执行dir显示上一层目录的内容证明上面的代码确实可以一次执行多条DOS命令。