【问题标题】:C++ (VC2010) Help converting console app to hidden Windows app?C++ (VC2010) 帮助将控制台应用程序转换为隐藏的 Windows 应用程序?
【发布时间】:2015-09-17 10:46:12
【问题描述】:

我已经阅读了十多页,解释了如何将 Win32 控制台应用程序转换为无需短暂打开和关闭控制台窗口即可运行的 Windows 应用程序,但我太初学者了,无法让它工作.

例如,在 VC2010 中,我在此处描述的项目属性中进行了两项更改:

convert a console app to a windows app

并将 Main 更改为 WinMain,但当然会从编译器收到错误消息。

在其他页面之后,我还尝试创建一个控制台应用程序,然后在 Win32 应用程序向导中,并将应用程序类型更改为 Windows 应用程序,但我不知道下一步该做什么。我尝试将 int Main 更改为 int CALLBACK WinMain,但这当然也不起作用。

有没有人可以帮助初学者解决这个问题?这是我认为我的代码编辑的相关部分:完整的代码,对于任何想知道这是做什么的人来说,在这里:

https://www.dropbox.com/s/1h8x1k2zv0lc5d1/vPasteCPlus.txt?dl=0

#include <stdafx.h>
#include <windows.h>
#include <iostream>
#include <fstream>
#include <codecvt> // for wstring_convert
#include <locale>  // for codecvt_byname
using namespace std;

// helper to get path to this application
string ExePath() {
char buffer[MAX_PATH];
GetModuleFileNameA( NULL, buffer, MAX_PATH );
string::size_type pos = string( buffer ).find_last_of( "\\/" );
return string( buffer ).substr( 0, pos);
}

int main(int argc, char* argv[])
{
    // get the command-line argument if any, and do various things
} 

再次为这个初学者问题道歉。我对 C++ 的唯一经验是编写控制台应用程序,我们将不胜感激地接受任何建议。

【问题讨论】:

  • “无需短暂打开和关闭控制台窗口即可运行的应用程序”。我知道有数以千计的合法用途......但我不禁想知道......
  • and changed Main to WinMain but of course got error messages from the compiler. 有什么错误?此外,您可以从一个 Windows 应用程序开始,而不创建任何窗口。
  • 或者,您可以使用this program 使用隐藏窗口启动您的控制台程序。

标签: c++ console-application


【解决方案1】:

好的,你已经打开了 Visual Studio。你有Solution Explorer(如果没有,View -> Solution Explorer)。

首先,要制作 Windows 应用程序,您应该将入口点从 main()(C++ 标准)更改为特定于 Windows 的 WinMain()。请参阅 more detailed description 的 msdn。因此,您将 main() 更改为下一个(从文档中复制粘贴):

int CALLBACK WinMain(
  _In_ HINSTANCE hInstance,
  _In_ HINSTANCE hPrevInstance,
  _In_ LPSTR     lpCmdLine,
  _In_ int       nCmdShow)
{
    return 0;
}

当然,你应该包括&lt;Windows.h&gt;,因为Windows 提供了它自己的API 来处理系统(例如LPSTR 类型)。简而言之,您完成了编译程序所需的所有编译器。您可以构建您的解决方案 (Build -> Build Solution)...这将导致 linker 错误:

error LNK2019: unresolved external symbol _main referenced in function ___tmainCRTStartup

同样,编译器做了你想做的一切,并将你的源文件编译成.obj,但是,因为你的项目是为控制台应用程序配置的,linker需要控制台应用程序的标准入口点——main,它可以'在我们的案例中找到(解决)它,因为我们将 main 更改为 WinMain。为了让链接器开心,你应该告诉它:

  • 右键点击Solution Explorer里面的项目
  • 然后点击Properties
  • 转到Configuration Properties -> Linker -> System 并将SubSystem 设置为Windows

尝试再次构建您的应用程序,瞧 - 您已经没有链接器错误,因为您的链接器现在知道它需要生成 Windows 应用程序并找到 Windows 入口点:WinMain()

关于这个:

// get the command-line argument if any, and do various things

您应该使用WinMain()lpCmdLine 参数。但要小心,如果你像这样运行你的程序(例如 so.exe):

so.exe arg1 arg2

lpCmdLinearg1 arg2 字符串。您可以做很多事情来获取 arg1arg2 作为数组,例如 main() argv(使用 argc),但您可以探索:

和相关的东西(例如 Windows 上的 wchar_t)

【讨论】:

  • 抱歉这么久才回复。我在美国农村的电缆连接中断,我正在通过手机连接到互联网。将尝试这个非常有用的答案并报告。同时,对于任何怀疑我这样做的原因的人,我已经编辑了原始问题以包含指向完整代码的链接。 (它将当前剪贴板内容写入用户指定代码页中的文本文件,以便在 vDos 模拟器下运行的旧 DOS 应用程序中使用。)
  • 谢谢!您极其清晰的指示让我成功构建和运行程序。我不得不注释掉处理命令行参数的行,现在将查找将参数放入数组的技术。你对自己的时间和麻烦非常慷慨。
  • –1 “您应该将入口点从 main()(C++ 标准)更改为特定于 Windows 的 WinMain()”是不好的建议。它并没有太大的危害,但它是一种不必要的微软主义,而且术语(入口点)极具误导性。同样,“当然,你应该包含 ”,虽然更有可能造成伤害,但不是非常有害,但它是不必要的复杂性,没有任何意义。
  • 这个程序只能在 Windows 下运行,因为它被设计为与一个名为 vDos 的仅限 Windows 的 DOS 模拟器一起工作。在我最初的问题中,我指定它是针对 Win32 应用程序的。
  • @Cheersandhth.-Alf,嗯,我试图强调这段代码将不再可移植。 it's a needless Microsoft-ism,当然——我们只讨论为 Windows 编写应用程序。顺便说一句,恕我直言,您的回答更具误导性。
【解决方案2】:

如果这是一个 Visual Studio 项目(正如 &lt;stdafx.h&gt; 强烈表明的那样),那么:

  • 在链接器设置中将子系统设置为 Windows。
  • 将入口点设置为mainCRTStartup(调用标准main)。

但是你确定你想要这个吗?

听起来你想要的是一个Windows服务

【讨论】:

    猜你喜欢
    • 2011-04-22
    • 1970-01-01
    • 2011-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多