C++ 如何在 Visual Studio 中正确设置 exe 的入口点?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8790923/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I correctly set the entry point for an exe in Visual Studio?
提问by Gavin Williams
I have set the entry point to WinMain but when I run the app it starts and doesn't display, I then have to shut it with task manager. Here's the code upto WinMain() :
我已将入口点设置为 WinMain,但是当我运行该应用程序时,它启动但不显示,然后我必须使用任务管理器将其关闭。这是 WinMain() 的代码:
#include <Windows.h>
// forward declarations
LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
// The entry point into a windows program
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int windowStyle )
{
....
I'm not experienced in C++, and I don't know what this is doing, except making my exe smaller, which is what I'm trying to achieve.
我在 C++ 方面没有经验,我不知道这是在做什么,除了让我的 exe 更小,这就是我想要实现的目标。
edit : What I'm trying to do is create a very small window exe to understand how demo coder's work. So I'm thinking of creating a small c++ window app that provides a window handle to which I can attach SlimDX (if i can statically link the final c++ dll to a C# app, but I'm not there yet) I have my BasicWindow.exe down to 6,656 bytes. So I'm experimenting with anything I can find to get that size down to <3k.
编辑:我想要做的是创建一个非常小的窗口 exe 来了解演示编码器的工作方式。所以我正在考虑创建一个小的 c++ 窗口应用程序,它提供一个窗口句柄,我可以将 SlimDX 附加到它(如果我可以将最终的 c++ dll 静态链接到 C# 应用程序,但我还没有)我有我的 BasicWindow .exe 减少到 6,656 字节。所以我正在尝试任何我能找到的东西,以将这个大小降低到 <3k。
[2012.Jan.10] Well I've had some success by rebuilding minicrt (available from http://www.benshoof.org/blog/small-programs/) under VS2010 and adding it as an additional dependency. I couldn't Ignore All Default Libraries as suggested, but I now have a Windowed application with an exe size of 4,096 bytes. I'd say that's some significant success. I'm within striking distance now. Every reduction from here on in, is more room for SlimDX. I'm pretty happy considering the only c++ apps I've ever written are console apps and a basic window :) I've been lucky I know !
[2012.Jan.10] 通过在 VS2010 下重建 minicrt(可从http://www.benshoof.org/blog/small-programs/ 获得)并将其添加为附加依赖项,我取得了一些成功。我无法按照建议忽略所有默认库,但我现在有一个 exe 大小为 4,096 字节的窗口化应用程序。我会说这是一些重大的成功。我现在在惊人的距离内。从现在开始,每减少一次,SlimDX 就有更多的空间。考虑到我写过的唯一的 C++ 应用程序是控制台应用程序和一个基本窗口,我很高兴 :) 我很幸运我知道!
回答by Pavel Zhuravlev
A typical application should not mess up with Entry point
setting of linker. Entry point should be set on a function included in the standard runtime library (which is wWinMainCRTStartup
for unicode application for windows subsystem). This function does stuff like the proper initialization of CRT and creation of global objects. By rerouting entry point to your WinMain
you will get undefined behavior unless you know precisely what you are doing and somehow implementing CRT initialization in your own WinMain
. In my opinion the resulting size decrease will be negliable and the whole affair is hardly worth the risk.
一个典型的应用程序不应该搞乱Entry point
链接器的设置。入口点应设置在标准运行时库(wWinMainCRTStartup
用于 windows 子系统的 unicode 应用程序)中包含的函数上。该函数执行诸如正确初始化 CRT 和创建全局对象之类的工作。通过将入口点重新路由到WinMain
您的WinMain
. 在我看来,由此产生的尺寸减小可以忽略不计,整个事件几乎不值得冒险。
回答by Seth Carnegie
When you set the entry point to WinMain
, Windows doesn't give your program a console window, because WinMain
is for programs with GUIs that don't need a console window. Your program is indeed running, though with no GUI you don't see anything happen.
当您将入口点设置为 时WinMain
,Windows 不会为您的程序提供控制台窗口,因为WinMain
用于具有不需要控制台窗口的 GUI 的程序。您的程序确实正在运行,尽管没有 GUI,您什么也看不到。
回答by asrm
I had the same issue. I wasn't satisfied with the answer marked here. So, I started digging in more and found that WS_VISIBLE was missing from CreateWindowEx
function.
我遇到过同样的问题。我对这里标记的答案不满意。所以,我开始深入挖掘,发现CreateWindowEx
函数中缺少 WS_VISIBLE 。
WS_OVERLAPPEDWINDOW
with WS_VISIBLE
makes the code work perfectly.
WS_OVERLAPPEDWINDOW
withWS_VISIBLE
使代码完美运行。
And regarding the file size, I was able to bring down the size of the code for x64 build to 3,072 bytes1,600 bytesusing Visual Studio Community Edition 2013running on Windows 7 Ultimate SP1 x64. All this, without using minicrt.lib, you mentioned above.
关于文件大小,我能够将 x64 构建的代码大小降低到 3,072 字节1,600 字节,使用在 Windows 7 Ultimate SP1 x64 上运行的Visual Studio Community Edition 2013。所有这些,不使用 minicrt.lib,你上面提到的。
Here's a screenshot of the executable properties.
这是可执行属性的屏幕截图。
回答by Gavin Williams
For reference, here is the full program :
作为参考,这里是完整的程序:
#include <Windows.h>
// forward declarations
LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); // WindowProcedure function
// The entry point into a windows program
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int windowStyle )
{
// create and register a local window class > exit on failure
WNDCLASSEX wcx;
HINSTANCE zhInstance = GetModuleHandle(NULL);
wcx.cbSize = sizeof(WNDCLASSEX); // size of structure
wcx.style = CS_HREDRAW | CS_VREDRAW; // redraw if size changes
wcx.lpfnWndProc = WndProc; // window procedure
wcx.cbClsExtra = 0; // no extra class memory
wcx.cbWndExtra = 0; // no extra windows memory
wcx.hInstance = zhInstance; // handle to instance (owner)
wcx.hIcon = LoadIcon(NULL, IDI_APPLICATION); // predefined icon
wcx.hCursor = LoadCursor (NULL, IDC_ARROW); // predefined arrow
wcx.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);//(HBRUSH) (COLOR_WINDOW + 1);// white background brush
wcx.lpszMenuName = NULL; // name of menu resource
wcx.lpszClassName = TEXT("BasicWindow"); // name of window class
wcx.hIconSm = (HICON)LoadImage(zhInstance, // small class icon
MAKEINTRESOURCE(5),
IMAGE_ICON,
GetSystemMetrics(SM_CXSMICON),
GetSystemMetrics(SM_CYSMICON),
LR_DEFAULTCOLOR);
if (!RegisterClassEx(&wcx))
{
MessageBoxA(0, "Error registering window class!","Error",MB_ICONSTOP | MB_OK);
DWORD result = GetLastError();
return 0;
}
// create window > exit on failure
HWND hwnd; // the window handle
hwnd = CreateWindowEx(
WS_EX_STATICEDGE,
wcx.lpszClassName,
TEXT("Basic Window"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
320,
240,
NULL,
NULL,
zhInstance,
NULL);
if (hwnd == NULL)
{
MessageBoxA(0,"Error creating window!","Error",MB_ICONSTOP | MB_OK);
return 0;
}
// show window
ShowWindow(hwnd, SW_MAXIMIZE);
// send a WM_PAINT message to the window
UpdateWindow(hwnd);
// enter message loop, break out of loop if there is an error (result = -1)
MSG msg; // for storing the windows messages
int status; // for storing the status of the windows message service where -1 = error, 0 = WM_QUIT, n = any other message)
while ((status = GetMessage(&msg,(HWND) NULL,0,0)) != 0 && status != -1)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
UNREFERENCED_PARAMETER(lpCmdLine);
}
LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_CLOSE:
DestroyWindow(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
default:
return DefWindowProc(hWnd,message,wParam,lParam);
}
return 0;
}