繁体   English   中英

我如何知道我的应用程序是通过C#的控制台还是Windows打开的

[英]How do I know if my app was opened from console or windows in C#

我有一个既是gui又是控制台的应用程序。

控制台:它从Windows时间表执行以执行一些自动化任务,因此使用参数进行调用

GUI:用于输入配置参数,这是用户比控制台更好的方法。

所有这些都很好。 它主要是一个控制台应用程序,如果不带任何参数打开控制台并显示配置表单,则该控制台将被隐藏。

问题:如果我从控制台使用NO参数将其打开,则该控制台将被隐藏并显示该表单。 我如何检测从其中打开应用程序的内容或位置,如果它是从Windows打开的,则隐藏控制台,如果它是从控制台打开的,则保持控制台显示。

如果您真的想知道应用程序已在“何处”启动,则必须知道您的父进程是什么。 为了了解您的父进程,您可以阅读如何以托管方式在.NET中获取父进程的解决方案。

然后,您可以例如检查您的父进程名称是否为explorer (windows),以将您的应用程序作为GUI打开。

基于如何以托管方式在.NET中获取父进程中提供的解决方案的示例代码

namespace ConsoleApp1
{
    public static class ProcessExtensions
    {
        private static string FindIndexedProcessName(int pid)
        {
            var processName = Process.GetProcessById(pid).ProcessName;
            var processesByName = Process.GetProcessesByName(processName);
            string processIndexdName = null;

            for (var index = 0; index < processesByName.Length; index++)
            {
                processIndexdName = index == 0 ? processName : processName + "#" + index;
                var processId = new PerformanceCounter("Process", "ID Process", processIndexdName);
                if ((int)processId.NextValue() == pid)
                {
                    return processIndexdName;
                }
            }

            return processIndexdName;
        }
        private static Process FindPidFromIndexedProcessName(string indexedProcessName)
        {
            var parentId = new PerformanceCounter("Process", "Creating Process ID", indexedProcessName);
            return Process.GetProcessById((int)parentId.NextValue());
        }

        public static Process Parent(this Process process)
        {
            return FindPidFromIndexedProcessName(FindIndexedProcessName(process.Id));
        }
    }


    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(Process.GetCurrentProcess().Parent().ProcessName);
            Console.ReadKey();
        }
    }
}

此代码将输出:

  • 在Visual Studio中进行调试: devenv
  • 从Windows开始: explorer
  • 从cmd开始: cmd
  • 从Powershell控制台开始: powershell
  • ...

一种方法是将cli版本和gui版本分成2个可执行文件(例如7z使用命令行工具7z.exe和7zG Gui版本)

您可以在Visual Studio中拥有3个项目:

  • MyApp.Console(控制台应用程序)
  • MyApp.WindowsGui(winform / wpf应用)
  • MyApp.Logic(所有逻辑)

Console和WindowsGui引用了您的Logic项目

这将为您提供更简洁的代码,因为每个“前端”项目将仅处理其用途(处理GUI或控制台内容),并且两个前端均可调用您的逻辑

对于您要实现的目标,我还不清楚。 据我了解,无论是否有参数,该应用程序都将作为控制台应用程序启动。 为防止其消失,可以使用Boolean来防止在用户输入配置时关闭窗口。 例如(语法可能不是DialogResult 100%):

using System;
using System.Windows.Forms;

// Allows you to access the static objects of Console
//     without having to repeatedly type Console.Something.
using static System.Console;

static bool configured = false;
static bool showForm = false;
static void Main(string[] args) {
    showForm = args.Length < 1;
    if (showForm) {
        WriteLine("The application needs to be configured.");
        using (ConfigForm config = new ConfigForm()) {
            if (config.ShowDialog() == DialogResult.OK) {
                showForm = false;
                configured = true;
                // Set your configured arguments here.
            }
        }
    }

    // Prevents the console from closing.
    while (showForm)
        ReadKey();

    // Do your processing in this condition.
    if (!showForm && configured)
        WriteLine("Thanks for playing. Press any key to exit.");
    else // Retry or exit in this one.
        WriteLine("An error occurred. Press any key to exit.");

    ReadKey();
}

如果您的应用程序设置为控制台应用程序,则默认情况下它将启动控制台窗口。 现在,如果您需要在不同时间显示和隐藏控制台,则可以查看这篇文章 ,其中已接受的答案提供了一种适当的方法来利用Windows API来实现此目的,而不必执行一些可疑的逻辑来按标题或标题查找窗口身份。

using System.Runtime.InteropServices;

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

[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

const int SW_HIDE = 0;
const int SW_SHOW = 5;

var handle = GetConsoleWindow();

// Hide
ShowWindow(handle, SW_HIDE);

// Show
ShowWindow(handle, SW_SHOW);

如果这不能解决您的需要,请随时在帖子中进行更全面的介绍,并添加一些代码以对问题进行更多定义。 我无法发表评论并提出问题,因此我给出了基本解决方案。 如果你有任何问题随时问。

这可能会有所帮助:

using System;
using System.Diagnostics;

static class IsRanFromConsole
{
    private static readonly string[] consoleNames = {
        "cmd", "bash", "ash", "dash", "ksh", "zsh", "csh",
        "tcsh", "ch", "eshell", "fish", "psh", "pwsh", "rc",
        "sash", "scsh", "powershell", "tcc"
    };

    private static bool isCache = false;
    private static bool isConsole;

    public static bool IsConsole()
    {
        if (!isCache)
        {
            string parentProc = Process.GetCurrentProcess().Parent().ProcessName;
            isConsole = Array.IndexOf(consoleNames, parentProc) > -1;
        }
        return isConsole;
    }
}

用法:

Console.WriteLine(IsRanFromConsole.IsConsole());

对于.Parent()函数,您需要添加以下代码

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM