程序的启动和退出过程详解

Windows支持两种类型的应用程序。一种是基于图形用户界面(GUI)的应用程序,另一种是基于控制台用户界面(CUI)的应用程序。 基于G U I 的应用程序有一个图形前端程序。它能创建窗口,拥有菜单,可以通过对话框与用户打交道,并可使用所有的标准“Wi n d o w s ”组 件。Wi n d o w s 配备的所有应用程序附件(如Notepad 、Calculator 和WordPad ),几乎都是基于G U I 的应用程序。基 于控制台的应用程序属于文本操作的应用程序。它们通常不能用于创建窗口或处理消息,并且它们不需要图形用户界面。虽然基于C U I 的应用程序 包含在屏幕上的窗口中,但是窗口只包含文本。命令外壳程序CMD.EXE(用于Windows 2000 )和COMMAND.COM (用于Windows 98)都是典型的 基于CUI的应用程序。

这两种类型的应用程序之间的界限是非常模糊的。可以创建用于显示对话框的C U I 应用程序。例如,命令外壳程序可能拥有一个特殊的命令,使它 能够显示一个图形对话框,在这个对话框中,可以选定你要执行的命令,而不必记住该外壳程序支持的各个不同的命令。也可以创建一个基于G U I 的应用程序,它能将文本字符串输出到一个控制台窗口。我常常创建用于建立控制台窗口的G U I 应用程序,在这个窗口中,我可以查看应用程序执 行时的调试信息。当然你也可以在应用程序中使用图形用户界面,而不是老式的字符界面,因为字符界面使用起来不太方便。

当使用Microsoft Visual C++来创建应用程序时,这种集成式环境安装了许多不同的链接程序开关,这样,链接程序就可以将相应的子系统嵌入产生的可执行程序。用于C U I 应用程序的链接程序开关是/ S U B S Y S T E M : C O N D O L E ,而用于G U I 应用程序的链接程序开关是SUBSYSTEM : WINDOWS 。当用户运行一个应用程序时,操作系统的加载程序就会查看可执行图形程序的标题,并抓取该子系统的值。如果该值指明一个CUI应用程序,那么加载程序就会自动保证为该应用程序创建文本控制台窗口。

如果该值指明这是个G U I 应用程序,那么加载程序不创建控制台窗口,而只是加载应用程序。一旦应用程序启动运行,操作系统就不再考虑应用程 序拥有什么类型的用户界面。Wi n d o w s 应用程序必须拥有一个在应用程序启动运行时调用的进入点函数。可以使用的进入点函数有4 个:int WINAPI WinMain(HINSTANCE hinstExe, HINSTANCE, PSTR pszCmdLine, int nCmdShow);int WINAPT wWinMain(HINSTANCE hinstExe,HINSTANCE, PWSTR pszCmdLine,int nCmdShow);int __cdecl main(int argc,char *argv[],char *envp[]);int _cdecl wmain(int argc, wchar_t *argv[], wchar_t *envp[]);

操作系统实际上并不调用你编写的进入点函数。它调用的是C / C + +运行期启动函数。该函数负责对C / C + +运行期库进行初始化,这样,就可以 调用m a l l o c 和f r e e 之类的函数。它还能够确保已经声明的任何全局对象和静态C + +对象能够在代码执行以前正确地创建。下面说明源代 码中可以实现哪个进入点以及何时使用该进入点(见表4 – 1 )。

表4-1 应用程序的进入点

应用程序类型

进入点

嵌入可执行文件的启动函数

需要ANSI字符和字符串的GUI应用程序

WinMain

WinMainCRTStartup

需要Unicode字符和字符串的GUI应用程序

wWinMainw

WinMainCRTStartup

需要ANSI字符和字符串的CUI应用程序

main

mainCRTStartup

需要Unicode字符和字符串的CUI应用程序

wmain

wmainCRTStartup

链接程序负责在它连接可执行文件时选择相应的C / C + +运行期启动函数。如果设定了/ S U B S Y S T E M : W I N D O W S 链接程序开关,那 么该链接程序期望找到一个Wi n M a i n 或w Wi n m a i n函数。如果这两个函数都不存在,链接程序便返回一个“未转换的外部符号”的错误消 息。否则,它可以分别选择Wi n M a i n C RT S t a r t u p 函数或w Wi n M a i n C RT S t a r t u p 函数。

同样,如果设定了/ S U B S Y S T E M : C O N S O L E 链接程序开关,那么该链接程序便期望找到m a i n 或w m a i n 函数,并且可以分别选 择m a i n C RT S t a r t u p 函数或w m a i n C RT S t a r t u p 函数。同样,,如果m a i n 或w m a i n 都不存在,那么链接程序返回一条 “未转换外部符号”的消息。

但是,人们很少知道这样一个情况,即可以从应用程序中全部删除/ S U B S Y S T E M 链接程序开关。当这样做的时候,链接程序能够自动确定应 用程序应该连接到哪个子系统。当进行链接时,链接程序要查看代码中存在4 个函数(Wi n M a i n 、w Wi n M a i n 、m a i n 或w m a i n ) 中的哪一个。然后确定可执行程序应该是哪一个子系统,并且确定可执行程序中应该嵌入哪个C / C + +启动函数。

Wi n d o w s / Visual C++编程新手常犯的错误之一是,当创建新的应用程序时,不小心选择了错误的应用程序类型。例如,编程员可能创建一个 新的Wi n 3 2 应用程序项目,但是创建了一个进入点函数m a i n 。当创建应用程序时,编程员会看到一个链接程序错误消息,因为w i n 3 2 应 用程序项目设置了/ S U B S Y S T E M : W I N D O W S 链接程序开关,但是不存在Wi n M a i n 或w Wi n M a i n 函数。这时,编程员可以有 4 个选择:

所有的C / C + +运行期启动函数的作用基本上都是相同的。它们的差别在于,它们究竟是处理A N S I 字符串还是U n i c o d e 字符串,以及它 们在对C 运行期库进行初始化后它们调用哪个进入点函数。Visual C++配有C 运行期库的源代码。可以在CR t0.c 文件中找到这4 个启动函数的代码 。

现在将启动函数的功能归纳如下:

当所有这些初始化操作完成后,C / C + +启动函数就调用应用程序的进入点函数。如果编写了一个w Wi n M a i n 函数,它将以下面的形式被调用 :GetStartupInfo(&StartupInfo);int nMainRetVal = wWinMain(GetMjduleHandle(NULL), NULL, pszCommandLineUnicode, (StartupInfo.dwFlags & STARTF_USESHOWWINDOW) ?StartupInfo.wShowWindow:SW_SHOWDEFAULT);

旅游不在乎终点,而是在意途中的人和事还有那些美好的记忆和景色。

程序的启动和退出过程详解

相关文章:

你感兴趣的文章:

标签云: