本文参考如下文档:
后者也是转载前者,但代码排版看起来好一些。
在上面的基础上,又对代码做了一点改动,主要是加了日志文件,方便看到DOS命令中间执行结果。
下面的示例代码是以VC6为例,一个workspace中包括两个project,一个是简单的MFC对话框,另外一个是执行dos命令的lib。lib的宏定义参考了pcre的风格,参考Windows上面编译pcre的步骤。
lib包括两个文件:DosCommand.h,.c。代码如下:
DosCommand.h:
#ifndef __DOS_COMMAND_H
#define __DOS_COMMAND_H
#ifndef DOS_COMMAND_EXP_DECL
# ifdef _WIN32
# ifndef DOS_COMMAND_STATIC
# define DOS_COMMAND_EXP_DECL extern __declspec(dllimport)
# endif
# endif
#endif
/* By default, we use the standard "extern" declarations. */
#ifndef DOS_COMMAND_EXP_DECL
# ifdef __cplusplus
# define DOS_COMMAND_EXP_DECL extern "C"
# else
# define DOS_COMMAND_EXP_DECL extern
# endif
#endif
/* Have to include stdlib.h in order to ensure that size_t is defined;
it is needed here for malloc. */
#include <stdlib.h>
/* Allow for C++ users */
#ifdef __cplusplus
extern "C" {
#endif
#include <windows.h>
/*
The output of the dos command will be writen to a file specified by <fileName>.
e.g.:
command: ipconfig /all
fileName: c:\\test.txt
*/
DOS_COMMAND_EXP_DECL BOOL ExecuteDosCommand(const char* command, const char* fileName);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif
DosCommand.cpp的代码:
#include "DosCommand.h"
#ifndef DOS_COMMAND_EXP_DECL
# ifdef _WIN32
# ifdef DLL_EXPORT
# define DOS_COMMAND_EXP_DECL extern __declspec(dllexport)
# define DOS_COMMAND_EXP_DEFN __declspec(dllexport)
# define DOS_COMMAND_EXP_DATA_DEFN __declspec(dllexport)
# else
# define DOS_COMMAND_EXP_DECL extern
# define DOS_COMMAND_EXP_DEFN
# define DOS_COMMAND_EXP_DATA_DEFN
# endif
#
# else
# ifdef __cplusplus
# define DOS_COMMAND_EXP_DECL extern "C"
# else
# define DOS_COMMAND_EXP_DECL extern
# endif
# ifndef DOS_COMMAND_EXP_DEFN
# define DOS_COMMAND_EXP_DECL DOS_COMMAND_EXP_DECL
# endif
# ifndef DOS_COMMAND_EXP_DATA_DEFN
# define DOS_COMMAND_EXP_DATA_DEFN
# endif
# endif
#endif
#include <stdio.h>
#include <windows.h>
enum {BUFFER_SIZE = 4096};
static HANDLE hOutput = NULL;
static void MyCreateFile(const char* fileName);
static void MyWriteFile(const char* info);
static void MyCloseFile();
DOS_COMMAND_EXP_DECL BOOL ExecuteDosCommand(const char* command, const char* fileName)
{
SECURITY_ATTRIBUTES security_attributes = {0};
HANDLE hReadPipe = NULL;
HANDLE hWritePipe = NULL;
char dos_command[512];
STARTUPINFO startUpInfo;
PROCESS_INFORMATION processInfo;
char buffer[BUFFER_SIZE] = {0};
DWORD dwRead;
if (NULL == command || strlen(command) > 1024) return FALSE;
printf("%s", command);
security_attributes.nLength = sizeof(SECURITY_ATTRIBUTES);
security_attributes.lpSecurityDescriptor = NULL;
security_attributes.bInheritHandle = TRUE;
if (!CreatePipe(&hReadPipe, &hWritePipe, &security_attributes, 0)) {
return FALSE;
}
strcpy(dos_command, "Cmd.exe /C ");
strcat(dos_command, command);
startUpInfo.cb = sizeof(STARTUPINFO);
GetStartupInfo(&startUpInfo);
startUpInfo.hStdError = hWritePipe;
startUpInfo.hStdOutput = hWritePipe;
startUpInfo.wShowWindow = SW_HIDE;
startUpInfo.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
if (!CreateProcess(NULL, dos_command, NULL, NULL, TRUE, 0, NULL, NULL, &startUpInfo, &processInfo)) {
CloseHandle(hWritePipe);
CloseHandle(hReadPipe);
return FALSE;
}
Sleep(1000); // Need to be refactored.
CloseHandle(hWritePipe);
MyCreateFile(fileName);
for (;;) {
if (!ReadFile(hReadPipe, buffer, 4095, &dwRead, NULL)) break;
MyWriteFile(buffer);
}
MyCloseFile();
CloseHandle(hReadPipe);
return TRUE;
}
void MyCreateFile(const char* fileName)
{
if (hOutput != NULL) MyCloseFile();
hOutput = CreateFile(fileName,
GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (INVALID_HANDLE_VALUE == hOutput) hOutput = NULL;
}
void MyWriteFile(const char* info)
{
DWORD dwWritten = 0;
if (NULL == hOutput) return;
WriteFile(hOutput, info, strlen(info), &dwWritten, NULL);
}
void MyCloseFile()
{
if (NULL == hOutput) return;
CloseHandle(hOutput);
hOutput = NULL;
}
对话框exe对应的project,在生成的代码基础上,增加如下部分:
#include "CommandLib/DosCommand.h"
#ifdef _DEBUG
#pragma comment(lib, "CommandLib/Debug/CommandLib.lib")
#else
#pragma comment(lib, "CommandLib/Release/CommandLib.lib")
#endif
void CExeDosCmdDlg::OnOK()
{
ExecuteDosCommand("dir", "c:\\test.txt");
CDialog::OnOK();
}
另外,两个project中需要设置的宏:
- lib: DLL_EXPORT,DOS_COMMAND_STATIC
- exe: DOS_COMMAND_STATIC
源代码工程参考附件:
VC中执行DOS命令,获取返回值的例子