今天还是继续说说C#调用系统Api启动外部程序的方法,今天要说的是CreateProcess这个Api函数,相比前两篇文章(
一、
二)中所说的Api,CreateProcess参数要更复杂一些,但使用起来,要更灵活。
1.
using
System.Runtime.InteropServices;
2. CreateProcess中用到了几个结构体类型,先声明他们:
[System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential)]
public
class
SECURITY_ATTRIBUTES
{
public
int
nLength;
public
string
lpSecurityDescriptor;
public
bool
bInheritHandle;
}
[StructLayout(LayoutKind.Sequential)]
public
struct
STARTUPINFO
{
public
int
cb;
public
string
lpReserved;
public
string
lpDesktop;
public
int
lpTitle;
public
int
dwX;
public
int
dwY;
public
int
dwXSize;
public
int
dwYSize;
public
int
dwXCountChars;
public
int
dwYCountChars;
public
int
dwFillAttribute;
public
int
dwFlags;
public
int
wShowWindow;
public
int
cbReserved2;
public
byte
lpReserved2;
public
IntPtr hStdInput;
public
IntPtr hStdOutput;
public
IntPtr hStdError;
}
[StructLayout(LayoutKind.Sequential)]
public
struct
PROCESS_INFORMATION
{
public
IntPtr hProcess;
public
IntPtr hThread;
public
int
dwProcessId;
public
int
dwThreadId;
}
3. 声明CreateProcess
[DllImport(
"
Kernel32.dll
"
, CharSet
=
CharSet.Ansi)]
public
static
extern
bool
CreateProcess(
StringBuilder lpApplicationName, StringBuilder lpCommandLine,
SECURITY_ATTRIBUTES lpProcessAttributes,
SECURITY_ATTRIBUTES lpThreadAttributes,
bool
bInheritHandles,
int
dwCreationFlags,
StringBuilder lpEnvironment,
StringBuilder lpCurrentDirectory,
ref
STARTUPINFO lpStartupInfo,
ref
PROCESS_INFORMATION lpProcessInformation
);
4. 下边这三个也是Api,作用看注释
#region Win32 Api : WaitForSingleObject
//检测一个系统核心对象(线程,事件,信号)的信号状态,当对象执行时间超过dwMilliseconds就返回,否则就一直等待对象返回信号
[DllImport("Kernel32.dll")]
public static extern uint WaitForSingleObject(System.IntPtr hHandle, uint dwMilliseconds);
#endregion
#region Win32 Api : CloseHandle
//关闭一个内核对象,释放对象占有的系统资源。其中包括文件、文件映射、进程、线程、安全和同步对象等
[DllImport("Kernel32.dll")]
public static extern bool CloseHandle(System.IntPtr hObject);
#endregion
#region Win32 Api : GetExitCodeProcess
//获取一个已中断进程的退出代码,非零表示成功,零表示失败。
//参数hProcess,想获取退出代码的一个进程的句柄,参数lpExitCode,用于装载进程退出代码的一个长整数变量。
[DllImport("Kernel32.dll")]
static extern bool GetExitCodeProcess(System.IntPtr hProcess, ref uint lpExitCode);
#endregion
5. 如果示例中argm指定的程序执行时间很长,进程会被阻塞到WaitForSingleObject行处,直到命令执行完毕或进程被中止才继续执行后边的语句。
string
argm
=
"
cmd.exe
"
;
STARTUPINFO sInfo
=
new
STARTUPINFO();
PROCESS_INFORMATION pInfo
=
new
PROCESS_INFORMATION();
if
(
!
CreateProcess(
null
,
new
StringBuilder(argm),
null
,
null
,
false
,
0
,
null
,
null
,
ref
sInfo,
ref
pInfo))
{
throw
new
Exception(
"
调用失败
"
);
}
uint
i
=
0
;
WaitForSingleObject(pInfo.hProcess,
int
.MaxValue);
GetExitCodeProcess(pInfo.hProcess,
ref
i);
CloseHandle(pInfo.hProcess);
CloseHandle(pInfo.hThread);