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

时间:2018-06-29 11:12:51

标签: c# .net winforms console

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

控制台:它是根据Windows计划执行的,可以执行一些自动化任务,因此需要使用参数进行调用

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

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

问题: 如果我从控制台使用NO参数将其打开,则该控制台将被隐藏并显示该表单。 如果从Windows打开应用程序,然后隐藏控制台,如何隐藏从控制台打开的应用程序的位置或信息。

4 个答案:

答案 0 :(得分:1)

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

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

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

控制台和WindowsGui引用了您的Logic项目

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

答案 1 :(得分:1)

如果您真的想知道应用程序的“启动位置”,则必须知道父进程是什么。为了了解您的父进程,您可以阅读How to get parent process in .NET in managed way

的解决方案

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

基于How to get parent process in .NET in managed way

中提供的解决方案的示例代码
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
  • ...

答案 2 :(得分:0)

我不清楚您要达到什么目标。据我了解,无论是否有参数,该应用程序都将作为控制台应用程序启动。为防止其消失,您可以使用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();
}

如果您的应用程序设置为控制台应用程序,则默认情况下它将启动控制台窗口。现在,如果您需要在不同时间显示和隐藏控制台,则可以查看this post,其中已接受的答案提供了一种适当的方法来利用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);

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

答案 3 :(得分:0)

这可能会有所帮助:

for

用法:

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()); 功能,您需要添加this code