2011-06-20 199 views
15

我有一些库控制台和wpf应用程序使用的库代码。在库代码中,有一些Console.Read()调用。我只想做那些输入读取,如果应用程序是一个控制台应用程序,而不是它的GUI应用程序 - 如何告诉在DLL中,如果应用程序有一个控制台?如何判断是否有控制台

+0

[C#Windows控制台应用程序如何判断它是否以交互方式运行](http://stackoverflow.com/a/8711036/344541) –

+0

我的评论是一个链接 - 对于混淆抱歉。 –

+0

[C#Windows控制台应用程序如何判断它是否以交互方式运行]的可能重复(http://stackoverflow.com/questions/1188658/how-can-ac-sharp-windows-console-application-tell-if-它是交互式地运行) –

回答

15

最后我做了如下:

// Property: 
private bool? _console_present; 
public bool console_present { 
    get { 
     if (_console_present == null) { 
      _console_present = true; 
      try { int window_height = Console.WindowHeight; } 
      catch { _console_present = false; } 
     } 
     return _console_present.Value; 
    } 
} 

//Usage 
if (console_present) 
    Console.Read(); 

继thekips建议我增加了一个代表成员库类来获得用户的验证 - 这设置为上述使用的默认执行力度,检查那里有一个控制台,如果存在则使用它来获取用户验证,或者如果不存在则不做任何操作这意味着:

  1. 所有现有客户端(命令行应用程序,Windows服务(无用户交互),wpf应用程序)都可以使用更改。
  2. 任何需要输入的非控制台应用程序都可以用其他方法(GUI - msg box等)验证来代替默认的代理。

感谢所有回复的人。

+0

使用try catch来做到这一点并不是很好的做法 –

5

你应该在你的设计中解决这个问题。这是控制反转非常方便的地方的一个很好的例子。由于调用代码知道哪个UI可用,因此该代码应指定一个例如IInputReader接口的实例。通过这种方式,您可以在多个场景中使用相同的代码来获取用户的输入。

+0

谢谢 - 我意识到这是一个设计缺陷 - 并且你的建议是解决这个问题的正确方法 - 但这个特殊情况在这个时候并不能证明正确的重新设计 - 我只是想简单地关闭控制台读取。 – Ricibob

+0

在这种情况下,您可以使用从UI设置的属性? IsConsole并使用布尔逻辑? – thekip

0

如果你想要一个好的设计,使用一个接口抽象GUI依赖。 为控制台版本实现一个具体类,为WPF版本实现另一个类,并以任何方式(依赖注入,控制反转等)注入正确的版本。

3

您可以在初始化时传递参数。

例如:

在你的库类,添加具有 'IsConsole' 参数的构造函数。

public YourLibrary(bool IsConsole) 
{ 
    if (IsConsole) 
    { 
    // Do console work 
    } 
    else 
    { 
    // Do wpf work 
    } 
} 

并从控制台,您可以使用:

YourLibrary lib = new YourLibrary(true); 

形式WPF:

YourLibrary lib = new YourLibrary(false); 
1

This SO question可以提供你一些解决方案...

另一种解决方案是:

Console.Read()在Windows窗体应用程序中返回-1而不打开控制台窗口。在控制台应用程序中,它返回实际值。所以你可以写如

 int j = Console.Read(); 
     if (j == -1) 
      MessageBox.Show("Its not a console app"); 
     else 
      Console.WriteLine("It's a console app"); 

我在控制台和winform应用程序上测试了这段代码。在控制台应用程序中,如果用户输入'-1',则j的值为。所以它会起作用。

+1

谢谢 - 但我需要知道在应用程序启动时,我不想要求在此时从控制台输入(并在控制台应用程序Console.Read将这样做)。此外在wpf Console.Read导致挂起(或异常取决于它的调用时间)。 – Ricibob

5

您可以使用此代码:

public static bool HasMainWindow() 
{ 
    return (Process.GetCurrentProcess().MainWindowHandle != IntPtr.Zero); 
} 

工作正常与控制台与WinForms应用程序的快速测试。

+0

谢谢 - 这是我想要的那种answere - 不幸的是它对于我来说同样适用于控制台和wpf应用.. :-( – Ricibob

+0

@Rici这很奇怪..我的测试控制台返回普通的'false' - 你如何构建这个控制台应用程序?你如何运行它? –

+0

@Shadow Wizard:记住代码是在一个库dll中 - 客户端只是一个普通的控制台应用程序我已经发布了一个答案,下面这个适用于我 - 相当多,但得到的工作 – Ricibob

11

为我工作(使用本机方法)

首先声明:

[DllImport("kernel32.dll")] 
    static extern IntPtr GetConsoleWindow(); 

后,请与优雅...哈哈哈...:

if (GetConsoleWindow() != IntPtr.Zero) 
{ 
    Console.Write("has console"); 
} 
10
if (Environment.UserInteractive) 
{ 
    // A console is opened 
} 

参见:http://msdn.microsoft.com/en-us/library/system.environment.userinteractive(v=vs.110).aspx

获取一个值,该值指示当前进程是否以用户交互模式运行。

+2

适用于区分windows server和console/wpf app,但实际上并不能识别控制台,即区分console和wpf。 – Ricibob

+0

正确的是,服务可以在WIndows系统上以交互模式运行,这已经是很长一段时间了。对于简单的桌面应用程序,此方法可能是可接受的如果您编写的代码可能在Windows进程以及桌面环境(例如日志代码)中运行,那么此方法可能会产生意想不到的后果(如作为服务运行时编写控制台输出的浪费周期)。 –

1

我改写了@ Ricibob的回答

public bool console_present { 
    get { 
     try { return Console.WindowHeight > 0; } 
     catch { return false; } 
    } 
} 

//Usage 
if (console_present) { Console.Read(); } 

这是简单的,但我更喜欢这个本地实现:

[DllImport("kernel32.dll")] 
static extern IntPtr GetConsoleWindow(); 

//Usage 
if (GetConsoleWindow()) { Console.Read(); } 
0
var isReallyAConsoleWindow = Environment.UserInteractive && Console.Title.Length > 0; 

Environment.UserInteractive和Console.Title.Length的组合应该给出一个适当的答案来解决一个控制台窗口的问题。 这是一个简单而直接的解决方案。