我希望有一个可执行文件可用于打开图形应用程序(默认用例,单击.exe时),或者我可以用来运行命令行任务。
这可能吗?
如果是这样,我将如何修改我的app.xaml / app.xaml.cs,以便它只打开特定条件的图形视图(例如没有命令行参数)?
答案 0 :(得分:2)
您可以检查应用程序是否已从控制台执行。如果没有,您可以动态分配控制台:
if (GetConsoleWindow() == IntPtr.Zero)
AllocConsole();
,其中
[DllImport("kernel32.dll")]
public static extern IntPtr GetConsoleWindow();
[DllImport("kernel32.dll")]
public static extern bool AllocConsole();
答案 1 :(得分:2)
@ BrunoKlein的回答将起作用,我的答案基于他的解决方案。引用@BrunoKlein,
首先,您必须使用WPF应用程序项目并更改app.xaml,以便您可以覆盖窗口创建。
<Application x:Class="WpfApplication1.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1">
<Application.Resources>
</Application.Resources>
</Application>
请注意,这缺少StartupUri属性。
现在,更简单(至少在Visual Studio 2015中有效),转到项目属性,并将输出类型从Windows应用程序更改为控制台应用程序。这使得项目构建为控制台应用程序,但仍具有Windows应用程序的功能。
(此照片中会突出显示类库,而是选择控制台应用程序)
你做到了!完成。
现在,您的“主要”方法不是拥有void Main(string[] args)
,而是自动生成的OnStautup
类的App
方法:
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
string[] args = e.Args;
if (SomeConditionBasedOnTheArgs(args))
{
// Instantiate view, call View.Show()
}
else
{
// Process the args
}
}
}
请注意,这个答案和@ BrunoKlein的答案之间的一个区别是,如果从explorer / start菜单/桌面运行它,这个将始终“显示”一个控制台,但如果从命令行运行,它将运行并指示所有标准输出到该控制台,就像任何普通的控制台应用程序一样。
答案 2 :(得分:0)
使用以上两种解决方案时,我一直遇到错误。在此处进行描述,并以相同的方式解决。 Visual Studio 2017 Debug Error: To prevent an unsafe abort when evaluating the function *.toString all threads where allowed to run
工具→选项→调试→常规→选中“使用托管的兼容模式”
继续寻找不需要关闭某些调试选项的解决方案,我发现本文对我来说非常有效。 https://benohead.com/blog/2015/04/22/c-wpf-console-hybrid-application/
应该删除它,添加一个Program.cs,将Windows App交换到控制台应用程序,并使App.Program成为启动对象。然后在Program.cs中,添加并调整以下代码。 DLL导入会确保能够隐藏控制台窗口。 所有的功劳归@Benohead。
我将默认状态更改为GUI模式,并使参数触发了控制台应用程序。 控制台窗口将显示并在进入GUI模式之前不久关闭。
using System;
using System.Runtime.InteropServices;
namespace HybridApp
{
public class Program
{
[DllImport("kernel32.dll")]
private static extern IntPtr GetConsoleWindow();
[DllImport("user32.dll")]
private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
[STAThread]
public static void Main(string[] args)
{
if (args.Length == 0)
{
// GUI mode
ShowWindow(GetConsoleWindow(), 0 /*SW_HIDE*/);
App.Main();
}
else if (args.Length > 0 && args[0] == "-c")
{
// console mode
Console.WriteLine("Console mode active!");
Console.ReadLine();
}
}
}
}
答案 3 :(得分:0)
正如@BrunoKlein 建议的那样,我从 StartupUri
中删除了 App.xml
属性,然后覆盖了 OnStartup
方法。但是我改用 AttachConsole
,因为我发现 AllocConsole
在从命令提示符运行时会导致出现一个额外的控制台窗口。
调用 FreeConsole
和 Shutdown
以彻底退出也很重要。
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
if (e.Args.Length == 0)
{
// No command line arguments, so run as normal Windows application.
var mainWindow = new MainWindow();
mainWindow.ShowDialog();
}
else
{
// Command-line arguments were supplied, so run in console mode.
try
{
const int ATTACH_PARENT_PROCESS = -1;
if (AttachConsole(ATTACH_PARENT_PROCESS))
{
CommandLineVersionOfApp.ConsoleMain(e.Args);
}
}
finally
{
FreeConsole();
Shutdown();
}
}
}
[DllImport("kernel32")]
private static extern bool AttachConsole(int dwProcessId);
[DllImport("kernel32")]
private static extern bool FreeConsole();
}