C技巧:VC中编译、运行程序的知识点(3)& o O! ?# A" u3 U% e3 g. }
__try {
: [0 p- |; M6 a3 D: K _ioinit(); /* initialize lowio */
0 L: B% o- ?# x, I; ` _acmdln = (char *)GetCommandLineA(); /* get cmd line info */
+ p+ m* {+ l% j7 J! ` _aenvptr = (char *)__crtGetEnvironmentStringsA(); /* get environ info */
* K' h$ V$ r5 m2 f6 U _setargv();
/ M6 o2 n8 o8 Y _setenvp();
" d/ C! o% e$ m' O( g1 l3 k8 Z __initenv = _environ;5 b9 J4 q3 S$ s6 \
mainret = main(__argc, __argv, _environ);+ n3 O# Y* {+ ^3 W5 U
exit(mainret);5 L3 q# j6 O. E. }4 f
}& j9 U6 m% @2 c5 ]% r5 O
__except ( _XcptFilter(GetExceptionCode(), GetExceptionInformation()) )' L" y% K% n; W$ C! M- m. v& Y
{
5 f9 q/ s1 u }7 I3 p6 B8 N/ ` _exit( GetExceptionCode() ); /* Should never reach here */9 @$ n& \4 o# {- X- h! X8 E
} /* end of try - except */5 T" [, w, W7 q# Y* f8 f: z; b
} 如果使用MFC框架,WinMain也会被埋藏在MFC库中(APPMODUL.CPP):# ^0 [; D- c* w& H5 [# t0 ^
extern "C" int WINAPI X/ X0 v6 c0 g
_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
+ ?' ^5 X. _. L* l LPTSTR lpCmdLine, int nCmdShow)
$ i6 e: ^6 Z* y/ K) Q$ { {
6 \0 r1 K* W z! l" P // call shared/exported WinMain8 p6 Y& {$ Y2 f+ L& P7 O
return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);' ~8 B4 b* B6 m- ]1 i+ m
}
* d/ w6 G p$ S5 E 对于ANSI版本,"_tWinMain"就是"WinMain";对于UINCODE版本,"_tWinMain"就是"wWinMain"。可参见afx.h:
8 ?% C7 S' B1 J5 B5 Q #ifdef _UNICODE/ O- T% o, ]% z, L
#define _tmain wmain
( Q$ Z: ~6 T: Q- | #define _tWinMain wWinMain
# S- r! H0 i x- b- k( e0 ^7 D! U1 | #else+ V" f7 |- [. n5 `6 P! A: J
#define _tmain main' }* v; O5 c ?0 \, e
#define _tWinMain WinMain
" t z2 F0 d5 F- g& ]2 f8 ~( z8 L #endif
4 a2 n; b5 [+ e* g- l1 P, L# Z 全局C++对象的构造函数是在什么地方调用的?答案是在进入应用程序的Entry Point后,考试大提示在调用main函数前的初始化操作中。所以MFC的theApp的构造函数是在_tWinMain之前调用的。
; ~# M& A4 V: d; ~: ^ 4、不显示Console窗口的Console程序
+ }8 {7 X+ x+ G( \# S2 M$ j& N) p F 在默认情况下/subsystem 和/entry开关是匹配的,也就是:9 K4 A$ k8 M% p- t
"console"对应"mainCRTStartup"或者"wmainCRTStartup"
) }* h& W: h& O7 o% d( \5 g; a "windows"对应"WinMain"或者"wWinMain"
) c; t! E+ J5 {7 u% R3 C _. y6 Z 我们可以通过手动修改的方法使他们不匹配。例如:7 p1 K# [6 I/ ?
#include "windows.h"
' [4 `0 S. N- _; T9 ^ #pragma comment( linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" ) // 设置入口地址! l; G7 t1 R4 V3 q
void main(void)
" u" N4 S& Z9 H% z1 S, O {
* }/ H1 v- X; c MessageBox(NULL, "hello", "Notice", MB_OK);
* x% D% C' }" y y E }
0 k4 X: O; ?/ D) M5 s l2 j 这个Console程序就不会显示Console窗口。如果选/MLd的话,这个程序只需要链接LIBCD.LIB user32.lib kernel32.lib。9 N. J4 Q9 j+ e" Z! Y
其实如果不想看到Console窗口,还有一个更直接的方法:那就是直接在EXE文件中将PE文件头的Subsystem从3改成2。在EXE文件中,PE文件头的偏移地址是0x3c,Subsystem是一个WORD,它在PE文件头中的偏移是0x5c。 |