Windows支持两种类型的应用程序:GUI和CUI程序。前者是Graphical
User Interface的简称,后者是Console User Interface的简称。
用VS创建一个项目的时候,IDE会设置各种链接器开关,使链接器将子系统(注1)的正确类型嵌入最终生成的可执行文件中。对于CUI程序,这个链接器开关是/SUBSYSTEM:CONSOLE,对于GUI程序,则是/SUBSYSTEM:WINDOWS。用户运行应用程序时,操作系统的加载程序会检查可执行文件映像的文件头,并获取这个子系统值。如果此值表明是一个CUI程序,加载程序会确保有一个可用的文本控制台窗口。如果是GUI程序,加载器就不会创建控制台窗口;相反,它只是加载这个程序,一定应用程序开始运行,操作系统就不再关心程序的界面是什么了。
Windows应用程序必须有一个入口函数,应用程序开始运行时,这个函数会被调用。C/C++开发人员可以使用以下两种入口点函数。
int WINAPI _tWinMain(
HINSTANCE
hInstanceExe,
HINSTANCE,
PTSTR
pszCmdLine,
int
nCmdShow);
int _tmain(
int
argc,
TCHAR
*argv[],
TCHAR
*envp[]);
注意,具体的符号取决于我们是否要使用Unicode字符串。操作系统实际并不调用我们所写的入口点函数,相反,它会调用由C/C++运行库实现并在连接时使用-entry:命令行选项来设置一个C/C++运行时启动函数。该函数将初始化C/C++运行库,使我们能调用malloc和free之类的函数。它还确保了在我们的代码开始执行之前,我们声明的任何全局和静态C++对象都被正确地构造。下表总结了源代码要实现什么入口点函数,以及每个入口点函数应该在什么时候使用。
应用程序类型
|
入口点函数
|
嵌入可执行文件的启动函数
|
处理ANSI字符和字符串的GUI应用程序
|
_tWinMain(WinMain)
|
WinMainCRTStartup
|
处理unicode字符和字符串的GUI程序
|
_tWinMain(wWinMain)
|
wWinMainCREStartup
|
处理ANSI字符和字符串的CUI程序
|
_tmain(Main)
|
mainCRTStartup
|
处理unicode字符和字符串的CUI程序
|
_tmain(Wmain)
|
wmainCRTStartup
|
在链接可执行文件时,链接器将选择正确的C/C++运行库启动函数,如果指定了/SUBSYSTEM:WINDOWS链接器开关,链接器就会寻找WinMain或wWinMain函数,如果这两个函数都没有找到,链接就会返回一个“unresolved external sumbol”错误,否则它将根据具体情况分别选择WinMainCRTStartup或者wWinMainCRTStartup。
类似的,如果指定了/SUBSYSTEM:CONSOLE链接器也遵循同样的规则。
一个鲜为人知的事实是,我们完全可以从自己的项目中移除/SUBSYSTEM链接器开关,一旦这样做,链接器就会自动判断应该为应用程序设置为哪个子系统。
所有C/C++运行库启动函数所做的事情基本都是一样的,区别在于他们要处理的是ANSI还是Unicode字符串;以及在初始化C运行库之后,他们调用的是哪一个入口函数。Visual C++自带了C运行库源码。可以在crtexe.c文件中找到4个启动函数的源码,这些启动函数的用途简单总结如下:
l 获取指向新进程的完整命令行的一个指针。
l 获取执行新进程的环境变量的一个指针。
l 初始化C/C++运行库的全局变量。如果包含了stdlib.h,我们的代码可以访问这些变量。下表总结了这些变量。
l 初始化C运行库的内存分配函数(malloc和calloc)和其他底层I/O例程使用的堆。
l 调用所有全局和静态C++类对象的构造函数。
变量名称
|
类型
|
描述和推荐使用的windows函数
|
_osver
|
unsigned
int
|
操作系统的构建版本号。例如:windows vista RTM为build 6000,所以_osver的值就是6000。请换用GetVersionEx
|
_winmajor
|
unsigned
int
|
以16进制表示的windows系统的主版本号,对于vista为6。请换用GetVersionEx
|
_winminor
|
unsigned
int
|
以16进制表示的windows系统的次版本号,对于vista为0。请换用GetVersionEx
|
_winver
|
unsigned
int
|
(_winmajor<<8)+_winminor。请换用GetVersionEx
|
_argc
|
unsigned
int
|
命令行上传递的参数个数。请换用GetCommandLine
|
_argv
_wargv
|
char
wchar_t
|
长度为_argc的一个数组,每一项指向一个命令行参数。请换用GetCommandLine
|
_environ
_wenviron
|
char
wchar_t
|
一个指针数组,数组中的每一项指向一个环境字符串。请换用GetEnvironmentStrings或GetEnvironmentVariable
|
_pgmptr
_wpgmptr
|
char
wchar_t
|
正在运行的程序的名称及其ANSI/Unicode完整路径。请换用GetModuleFileName,将NULL作为第一个参数传进去。
|
完成这些初始化工作以后,C/C++才会调用我们的入口函数。
入口函数返回后,启动函数将调用C运行库的exit函数,向其传递入口函数的返回值。Exit函数将执行以下操作:
l 调用_onexit函数调用所注册的任何一个函数。
l 调用所有全局和静态C++类对象的析构函数。
l 在DEBUG生成中,如果设置了_CRTDBG_LEAK_CHECK_DF标志,就通过调用_CrtDumpMemoryLeaks函数生成内存泄漏报告。
l 调用操作系统的ExitProcess函数,向其传递入口函数的返回值。这会导致操作系统杀死我们的进程,并设置它的退出代码。
注意,为了安全起见,Microsoft不赞成使用所有这些变量,因为使用了这些变量的代码可能会在C运行库初始化这些变量之前运行。
分享到:
相关推荐
Windows_Phone_7_应用程序生命周期
Windows Phone 7 –应用程序生命周期–手机海洋
对Windows Phone 7应用程序生命周期的深度剖析,在与硬件进行交互和使用Expression Blend来创建更丰富的用户界面方面提供的建议,这些都有助于你学习创建独特而又实用的Windows Phone 7应用程序。
它为管理应用程序生命周期和导航提供了强大的模型。 它建立在三个重要的核心原则上: 将操作系统功能与应用程序逻辑解耦 使用任务等待模式从上到下异步 与其他框架配合使用 MVVM框架通过提供功能强大的服务系统使...
第4~18章则系统讲解了使用Visual C#语言开发Windows应用商店应用的相关技术,包括应用控件、界面布局与导航、数据绑定、推送通知、图形与画刷、多媒体、动画效果、多线程与后台任务、传感器、文件与数据存储、网络...
Windows 服务的生命周期与可执行文件有何不同? Windows 服务旨在在没有用户帮助的情况下运行。 可执行文件需要用户帮助,但可以编写脚本使其表现得像 Windows 服务。 使用 log4net 的示例。
还有其他电子书专注于容器/ Docker生命周期(DevOps,CI / CD等)与Microsoft Tools,已经发布,另外还有一本关于使用Xamarin.Forms的企业应用程序模式的电子书。您可以下载它们,并在这里开始审查这些指南/电子书:...
Silverlight for Windows Phone开发系列课程(9):在Windows Phone设备上进行调试 Silverlight for Windows Phone开发系列课程(10):应用程序生命周期
通用 Windows 应用程序示例的 Prism 有关在通用 Windows 应用程序中使用 Prism 的示例,这些示例已用于博客上发布的以下系列文章 基本概念: : ... 管理应用程序的生命周期: : 消息: : 布局管理: :
应用程序生命周期是现代OS管理资源的关键方式。 在Android,iOS以及最新的Windows版本上,可以通过平台随意启动和停止应用。 这使平台可以简化和重新分配最能使用户受益的资源。 在网络上,我们已经通过一次性功能...
教程名称: Win Phone 7.5专题讲座之WP7入门系列视频本课程主要讲解内容包括概述及Hello word、多媒体应用、独立存储、数据绑定、依赖属性、页面导航、应用程序生命周期、数据模板、启动器和选择器、推送通知目录:...
目录 第一部分 Windows编程基础 ...17.4.2 服务的生命周期 17.4.3 应用程序对服务的控制 17.4.4 服务DLL的人口函数 17.4.5 服务的IOCTL命令 17.4.6 超级服务 17.4.7 Services.exe的命令行 17.4.8 TickSrv示例服务
目录 第一部分 Windows编程基础 ...17.4.2 服务的生命周期 17.4.3 应用程序对服务的控制 17.4.4 服务DLL的人口函数 17.4.5 服务的IOCTL命令 17.4.6 超级服务 17.4.7 Services.exe的命令行 17.4.8 TickSrv示例服务
Juju实现了Kubernetes运算符模式,但它还是一个通用的OLM ,它将运算符模式扩展到Linux和Windows上的传统应用程序(没有Kubernetes)。 这样的机器操作员可以在裸机,虚拟机或云实例上工作,从而实现。 Juju使您...
第三,采用Eclipse+ADT的方式在Ubuntu系统下构建了Android应用程序开发环境,在详细研究Android应用程序开发的核心组件和应用程序生命周期的基础上,实现了音乐播放器和对对碰游戏两个Android应用程序,并在Android...
Sencha cmd 是一个跨平台的命令行工具,它从你应用程序的新创建到部署入产品中的整个生命周期都提供了许多自动化的执行任务。 Sencha Cmd 提供了一系列功能强大的节约时间的功能,结合Sencha Ext JS 和Sencha Touch...
所有升级到Windows 10的设备,微软都将提供永久生命周期的支持。 Windows 10是微软独立发布的最后一个Windows版本,下一代Windows将作为更新形式出现。Windows10发布了7个发行版本,分别面向不同用户和设备。 2015年...
应用程序生命周期的自动化管理。多层安全措施将程序彼此分离,这将使智能电话的系统稳定性达到前所未有的水平。最终用户不再需要担心哪些应用程序是活动的,也不必在运行新程序前先关闭原有的一些程序。Android...
2.4 程序生命周期 2.4.1 android周期 2.4.2 android进程 2.5 activity的生命周期 2.5.1 activity状态 2.5.2 剖析activity 2.6 android进程和线程 2.6.1 进程 2.6.2 线程 2.6.3 远程调用(remote procedure calls) ...
应用程序域、Remoting构架、传值封送(Marshal by value)、传引用封送(Marshal by reference)、Remoting的基本操作、分离服务程序元信息和实现、在Windows Service和IIS中寄宿宿主程序、远程方法回调(Callback)、远程...