如何打开一个程序或创建一个进程 (适用与执行CMD命令)

打开一个程序和创建一个进程基本上是同一个意思。我们的工具箱里面有几个函数备选:
system, WinExec, ShellExecuteEx, CreateProcess,他们有以下几点不同:
- 只有system是同步操作。
- 只有ShellExecuteEx, CreateProcess支持Unicode。
- 是否打开新的Console窗口: 只在父子都是console下有效
   system,WinExec总是不会打开。ShellExecuteEx,CreateProcess则可以控制是否打开新Console窗口
- 是否显示:在父子至少有一个不是console的情况下有效。

[system]
system是在简单的可怜,只需传入一个命令行。
system( "notepad C://boot.ini" );


[WinExec]
WinExec比之system能够控制目标窗口显示与否。
WinExec( "notepad C://boot.ini", SW_SHOW );
WinExec( "/"C://WINDOWS//system32//notepad.exe/" C://boot.ini", SW_HIDE );
cout << "xx" << endl;
WinExec( "taskkill", SW_HIDE );
cout << "xx" << endl; // 这个xx会先于taskkill的内容显示(因为创建进程是异步的,并且不会很快)


[ShellExecuteEx]
WinExec最大的缺陷是不支持宽字符,你无法找到WinExecW。另外你无法针对你打开的程序做进一步的操作,比如等待程序结束等。
如果你有这些需要,就应该使用ShellExecuteEx。
需要做的配置一个SHELLEXECUTEINFO结构,该结构描述如何打开以及打开什么样的程序。然后以ShellExecuteEx调用之。

SHELLEXECUTEINFO info;
ZeroMemory( &info, sizeof( info ) );
info.cbSize = sizeof( info );
// SEE_MASK_NOCLOSEPROCESS代表需要返回进程Handle
// SEE_MASK_NO_CONSOLE只在父子都是console时有作用,表示不要产生新的console窗口。
info.fMask = SEE_MASK_NOCLOSEPROCESS |SEE_MASK_NO_CONSOLE;
info.lpFile = _T( "notepad" ); // 注意如果没有提供路径则按下列顺序搜索文件(当前目录,系统目录,注意不包括环境变量path中的目录)
info.lpParameters = _T( "C://boot.ini" );
info.nShow = SW_SHOW;

ShellExecuteEx( &info );
// 可以进程Handle做些事情,最常见的就是等待进程结束。
WaitForSingleObject( info.hProcess, INFINITE );

 
[CreateProcess]
提供了比ShellExecuteEx更为精细的参数控制。
通常使用CreateProcess需要提供至关重要的4个参数
 - cmdLine 
 - creationFlag
 - startupInfo
 - processInfo
 
* cmdLine是你需要呼叫之process的命令行参数,比如要打开D:/test.txt, 你可以提供"notepad D://test.txt";
   值得注意的是Unicode版本的CreateProcessW要求cmdLine不能是const 
* creationFlag决定如何产生目标process
 creationFlag = CREATE_NEW_CONSOLE 将在新的console产生process
 creationFlag = CREATE_NO_WINDOW 将在后台产生process
* startupInfo决定产生的process的其实信息,通常我们会设置产生process时是否显示窗口,这样做:
  startupInfo.dwFlags = STARTIF_USESHOWWINDOW;
  startupInfo.wShowWindow = SW_SHOW; // SW_HIDE(表示在后台运作,与creationFlag呼应)
* processInfo则是个输出参数,目标进程创建成功后,此输出参数将包含进程相关信息。

下面是一个典型的示例

HANDLE ExecuteFile( const CString& fileName, const CString& arguments,
                   DWORD showWindowOption, 
                   const CString& windowTitle )
{
    DWORD creationFlag = 0;

    STARTUPINFO startupInfo;
    ZeroMemory( &startupInfo, sizeof( startupInfo ) );
    startupInfo.cb = sizeof( startupInfo );
    startupInfo.dwFlags = STARTF_USESHOWWINDOW; // 使特定成员有效
    startupInfo.wShowWindow = ( WORD )showWindowOption;
    startupInfo.lpTitle = const_cast< LPWSTR >( windowTitle.GetString() );

    CString commandLine = fileName + _T( " " ) + arguments;   
    
    PROCESS_INFORMATION processInfo;
    CreateProcess( 
        NULL, 
        const_cast< LPWSTR >( commandLine.GetString() ), 
        NULL, 
        NULL, 
        false, 
        creationFlag, 
        NULL, 
        NULL, 
        &startupInfo, 
        &processInfo 
        );    
    return processInfo.hProcess;
}


可以在创建进程后通过WaitForSingleObject来捕捉核心对象hProcess
当进程结束后,WaitForSingleObject(hProcess, INFINITE)返回。
当然你可以WaitForSingleObject(hProcess, 0) == WAIT_OBJECT_0来立刻检测进程是否结束。


最后一定要CloseHandle( hProcess ) 关闭进程句柄

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页