c#调用CreateProcess函数比较麻烦的地方就是该函数的那些参数用c#的语法如何定义,CreateProcess函数位于Kernel32.dll中,原形如下:
BOOL CreateProcess(
LPCTSTR lpApplicationName,
LPTSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
LPCTSTR lpCurrentDirectory,
LPSTARTUPINFO lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation
);
用c#语法声明时,LPCTSTR,LBTSTR,LPVOID这三个类型我都把它定义为StringBuilder类型,DWORD定义为int类型,关键是这三个Struct该怎么定义;在c#中定义传给API的Struct参数时,即可以将它定义为Struct也可以定义成class,于是我把LPSECURITY_ATTRIBUTES,LPSTARTUPINFO,LPPROCESS_INFORMATION 这三个Struct在c#中分别如下定义:
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;
}
这里我把LPSECURITY_ATTRIBUTES 定义为class,主要是为了接下来传null参数时方便些,下面是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
);
最后两个参数之所以在前面加上ref,是因为这两个参数的值需要回传.
在程序中使用CreateProcess:
string sCommand=@"isqlw /S "+TBServer.Text.Trim()+" /d "+TBDataBase.Text.Trim()+" /U "+TBUserName.Text.Trim()+
" /P "+TBPassWord.Text.Trim()+" /i "+sCurrtFile+" /o "+sProgramCurrectPath+sLogFile;
StringBuilder sbCommand=new StringBuilder(1000);
sbCommand.Append(sCommand);
STARTUPINFO sInfo=new STARTUPINFO();
PROCESS_INFORMATION pInfo=new PROCESS_INFORMATION();
if (!CreateProcess(null,sbCommand,null,null,false,0,null,null,ref sInfo,ref pInfo))
{
throw new Exception("isqlw调用失败["+sFileName+"]");
}
WaitForSingleObject(pInfo.hProcess,600000000);
CloseHandle(pInfo.hProcess);
CloseHandle(pInfo.hThread);
这里用到了WaitForSingleObject函数,使用该函数的作用是让CreateProcess创建的新进程与本程序的主进程同步执行,如果不加WaitForSingleObject则这两个进程是异步执行的,该函数的第二个参数是设函数的超时时间(毫秒),如果设一个很大的值则表示直到第一个参数所指的进程执行结束,才能执行该函授后面的代码;WaitForSingleObject的声明如下:
[DllImport("Kernel32.dll",CharSet=CharSet.Ansi)]
public static extern int WaitForSingleObject(IntPtr hHandle,int dwMilliseconds);
CloseHandle申明如下:
[DllImport("Kernel32.dll",CharSet=CharSet.Ansi)]
public static extern bool CloseHandle(IntPtr hObject);