使用c#调用API函数CreateProcess来运行外部程序

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#中分别如下定义:

[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;
        }

这里我把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);


   

posted on 2005-10-27 10:40  DoNet鸟  阅读(10864)  评论(10编辑  收藏  举报

导航