WIN32汇编语言教程:第13章 进程控制 · 13.2 执行可执行文件(3)

          invoke RtlZeroMemory,addr @stOF,sizeof @stOF

          mov    @stOF.lStructSize,sizeof @stOF

          push      hWinMain

          pop    @stOF.hwndOwner

          mov    @stOF.lpstrFilter,offset szFileExt

          mov    @stOF.lpstrFile,offset szFileName

          mov    @stOF.nMaxFile,MAX_PATH

          mov    @stOF.Flags,OFN_FILEMUSTEXIST or OFN_PATHMUSTEXIST

          invoke GetOpenFileName,addr @stOF

          .if    eax

                 invoke SetDlgItemText,hWnd,IDC_FILE,addr szFileName

          .endif

;********************************************************************

                         .elseif ax ==  IDC_FILE

                                 invoke GetWindowTextLength,lParam

                                 mov ebx,eax

                                 invoke GetDlgItem,hWnd,IDOK

                                 invoke EnableWindow,eax,ebx

                        .endif

;********************************************************************

                  .elseif eax == WM_CLOSE

                         invoke EndDialog,hWnd,NULL

;********************************************************************

                 .elseif eax == WM_INITDIALOG

                         push      hWnd

                         pop    hWinMain

                         invoke SendDlgItemMessage,hWnd,IDC_FILE,\

                                 EM_LIMITTEXT,MAX_PATH,0

                         invoke SendDlgItemMessage,hWnd,IDC_CMDLINE,\

                                 EM_LIMITTEXT,MAX_PATH,0

;********************************************************************

                 .else

                         mov    eax,FALSE

                         ret

                  .endif

                 mov eax,TRUE

                 ret

 

_ProcDlgMain      endp

;####################################################################

start:

                invoke GetModuleHandle,NULL

                 mov    hInstance,eax

                 invoke DialogBoxParam,eax,DLG_MAIN,NULL,\

                         offset _ProcDlgMain,NULL

                 invoke ExitProcess,NULL

;####################################################################

                 end    start

当按下“浏览”按钮(IDC_BROWSE)的时候,程序在WM_COMMAND消息中显示一个“打开文件”通用对话框并让用户选择可执行文件。

当按下IDOK按钮的时候,如果有进程在执行中(hProcess不为0),表示现在按下的是“终止”按钮,这时程序调用TerminateProcess函数强制结束进程;如果没有进程在执行,表示按下的是“执行”按钮,程序创建一个新线程_ProcExec子程序,在这个子程序中完成创建新进程和等待它结束的工作。

函数CreateProcess在子进程创建以后是马上返回的,但是程序需要等待子进程结束,为了在等待的过程中主线程还能够处理对话框消息,所以程序在这里使用一个新的线程来完成创建和等待子进程的工作。

在线程函数_ProcExec中,程序灰化“文件名”输入框、“命令行”输入框和“浏览”按钮,并将文件名和命令行参数获取到缓冲区szFileName和szCmdLine中,接下来调用CreateProcess函数创建进程。

1. 创建进程

创建进程需要为新进程窗口的外观指定一些属性,就像使用Shell调用方式执行文件时的dwCmdShow参数一样,这些属性通过一个STARTUPINFO结构来指定:

STARTUPINFO STRUCT

 cb                 DWORD     ?    ;结构的长度

 lpReserved        DWORD     ?    ;保留字段

 lpDesktop         DWORD     ?    ;NT下使用,指定桌面名称

 lpTitle           DWORD     ?    ;控制台程序使用,指定控制台窗口标题

  dwX                DWORD     ?    ;当新进程使用CW_USEDEFAULT参数创建

 dwY                DWORD     ?    ;窗口的时候将使用这些位置和大小属性

 dwXSize           DWORD     ?

 dwYSize           DWORD     ?

 dwXCountChars    DWORD     ?    ;控制台程序使用,指定控制台窗口行数

 dwYCountChars    DWORD     ?

 dwFillAttribute  DWORD     ?    ;控制台程序使用,指定控制台窗口背景色

 dwFlags           DWORD     ?    ;标志

 wShowWindow      WORD      ?    ;窗口的显示方式

 cbReserved2      WORD      ?

 lpReserved2      DWORD     ?

 hStdInput         DWORD     ?    ;控制台程序使用:几个标准句柄

 hStdOutput        DWORD     ?

 hStdError         DWORD     ?

STARTUPINFO ENDS

在需要定制新进程的窗口的时候,才需要手工填写STARTUPINFO结构(比如需要将控制台程序的输入和输出重新定位时,可以改写hStdInput和hStdOutput字段),在大部分情况下,并不需要新进程的窗口有什么特殊之处,这时只要使用GetStartupInfo获取当前进程的STARTUPINFO并使用它的默认值就可以了:

                   .data?

stStartUp     STARTUPINFO    <?>

                   .code

                invoke    GetStartupInfo,addr stStartUp

获取STARTUPINFO结构以后,就可以把它用在创建进程的函数CreateProcess中:

   invoke CreateProcess,lpApplicationName,lpCommandLine,\

           lpProcessAttributes,lpThreadAttributes,bInheritHandles,\

           dwCreationFlags,lpEnvironment,lpCurrentDirectory,\

           lpStartupInfo,lpProcessInformation

函数的各个参数定义如下。

● lpApplicationName——指向一个以0结尾的字符串,用来指定可执行文件名,如果这个参数指定为NULL,那么文件名可以在lpCommandLine参数指定的命令行参数中包括。

● lpCommandLine—指向一个以0结尾的字符串,用来指定命令行参数,如果lpApplicationName参数为NULL,那么命令行字符串的第一个组成部分用来指定可执行文件名;如果两个参数都不为空,那么lpApplicationName用做文件名,lpCommandLine用做命令行参数。

● lpProcessAttributes——指向一个SECURITY_ATTRIBUTES结构,用来指定新进程的安全属性,如果进程句柄不需要被其他子进程继承,可以在这里使用NULL。

● lpThreadAttributes——指向一个SECURITY_ATTRIBUTES结构,用来指定新进程的安全属性,如果进程句柄不需要被其他线程继承,可以在这里使用NULL。

● bInheritHandles——指定当前进程的句柄是否可以被新进程继承,如果指定TRUE,那么可以继承,一般在这里使用FALSE。

● dwCreationFlags——创建标志,指定新进程的优先级以及其他标志,这个参数类似于CreateThread函数中的同名参数,它可以是一些标志的组合,下面列出了一些常用的标志:

■  CREATE_NEW_CONSOLE——如果新进程是控制台程序,那么为它新建一个控制台窗口,而不是使用父进程的控制台窗口。

■  CREATE_SUSPENDED—新建进程的主线程一开始处于挂起状态,需要以后用 ResumeThread函数来恢复它的执行。

■  DEBUG_PROCESS和DEBUG_ONLY_THIS_PROCESS——调试进程,相关内容在13.3一节的进程调试中会有详细介绍,如果同时指定DEBUG_ONLY_THIS_PROCESS标志,那么被调试的进程仅是被创建的子进程,否则子进程创建的“孙进程”也在被调试之列。

■  HIGH_PRIORITY_CLASS,IDLE_PRIORITY_CLASS,NORMAL_PRIORITY_CLASS和REALTIME_PRIORITY_CLASS——用来指定新进程的优先级。

● lpEnvironment——指向新进程的环境变量块,如果这个参数指定为NULL,表示让Windows拷贝当前进程的环境块当做子进程的环境块,如果程序需要将修改过的环境块传递给子进程,可以设置这个参数。

● lpCurrentDirectory——指向一个路径字符串,用来指定子进程的当前驱动器和当前目录,如果指定为NULL,子进程将引用父进程的当前路径。

● lpStartupInfo——指向前面介绍的STARTUPINFO结构。

● lpProcessInformation——指向一个PROCESS_INFORMATION结构,这个结构用来供函数返回新建进程的相关信息。

如果函数执行成功,返回值是非0值,否则函数返回0。新建进程的句柄在哪里呢?这些句柄就在lpProcessInformation参数指向的PROCESS_INFORMATION结构中。结构定义为:

上页:第13章 进程控制 · 13.2 执行可执行文件(2) 下页:第13章 进程控制 · 13.2 执行可执行文件(4)

第13章 进程控制

版权所有 © 中山市飞娥软件工作室 证书:粤ICP备09170368号