Вопрос по console-application, c#, user-interaction – Как консольное приложение C # Windows может определить, запущено ли оно в интерактивном режиме?

24

Как может консольное приложение Windows, написанное на C #, определить, вызывается ли оно в неинтерактивной среде (например, из службы или в виде запланированной задачи) или из среды, способной взаимодействовать с пользователем (например, из командной строки или PowerShell)?

Ваш Ответ

5   ответов
5

Environment.UserInteractive выглядит многообещающе

Хотя эта ссылка может ответить на вопрос, лучше включить сюда основные части ответа и предоставить ссылку для справки. Ответы, содержащие только ссылки, могут стать недействительными, если связанная страница изменится. -From Review
@Martin: Почему принятый ответ также не помечен для удаления? Они оба отвечают одинаково!
35

работает ли приложение .NET в режиме графического интерфейса:

bool is_console_app = Console.OpenStandardInput(1) != Stream.Null;
+1, потому что у меня был случай, когда этот метод работал, а метод Environment.UserInteractive - нет. Это был модульный тест NUnit, в котором я хотел прервать тест, когда нажал клавишу ESC. Вы не можете вызывать Console.KeyAvailable при запуске из графического интерфейса NUnit, поэтому мне нужно было проверить, когда пропустить этот код. Ответ Гленна был правильно определен, когда я работал в графическом интерфейсе NUnit, а не в консольном окне, тогда как свойство Environment.UserInteractive было ИСТИНА в обоих случаях.
Это очень плохо, что для этого требуется System.IO, но это все еще лучший метод, который я нашел до сих пор
0

bool isConsoleApplication = Console.In != StreamReader.Null;
3

If all you're trying to do is to determine whether the console will continue to exist after your program exits (so that you can, for example, prompt the user to hit Enter before the program exits), тогда все, что вам нужно сделать, это проверить, является ли ваш процесс единственным, подключенным к консоли. Если это так, то консоль будет уничтожена при выходе из вашего процесса. Если к консоли подключены другие процессы, консоль будет продолжать существовать (поскольку ваша программа не будет последней).

Например*:

using System;
using System.Runtime.InteropServices;

namespace CheckIfConsoleWillBeDestroyedAtTheEnd
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            // ...

            if (ConsoleWillBeDestroyedAtTheEnd())
            {
                Console.WriteLine("Press any key to continue . . .");
                Console.ReadKey();
            }
        }

        private static bool ConsoleWillBeDestroyedAtTheEnd()
        {
            var processList = new uint[1];
            var processCount = GetConsoleProcessList(processList, 1);

            return processCount == 1;
        }

        [DllImport("kernel32.dll", SetLastError = true)]
        static extern uint GetConsoleProcessList(uint[] processList, uint processCount);
    }
}

(*) Адаптировано из найденного кодаВот.

@JeffLeonardGetConsoleProcessList напрямую вызывался из C # через P / Invoke с любой версией .NET, если вы работали с Windows XP или более поздней версией Windows -docs.microsoft.com/en-us/windows/console/…
Я уверен, что GetConsoleProcessList () из Windows API не был вызван напрямую из C #, когда я впервые задал этот вопрос, так что это очень хорошее обновление. Jeff Leonard
33

Environment.UserInteractive Имущество

К вашему сведению: Как установить службу Windows (используя installutil) с параметрами командной строки (параметры запуска) можно найтиhere а такжеhere;
@JamesWilkins есть обходной путь?
Мое решение состояло в том, чтобы просто передать параметр командной строки, чтобы узнать, что я нахожусь в режиме обслуживания. Я думаю, что это был единственный верный способ, о котором кто-то мог подумать, когда я оглянулся. ;) Я уверен, что есть способ или взлом, мне просто не нужно было тратить время, чтобы его найти. ;) Возможно, есть способ узнать, что вы каким-то образом связаны с хостом службы (родительский процесс? Не уверен). Возможно, вы можете использовать другой ответ на этой странице (stackoverflow.com/a/8711036/1236397) для проверки, открыто ли окно.
К вашему сведению: "Environment.UserInteractive" возвращает true для службы, когда «Разрешить службе взаимодействовать с рабочим столом» опция отмечена.
Это не работает, если FreeConsole () (в kernel32.dll) был вызван. В нашем случае сценарий - это программа, которая поддерживает как командную строку, так и интерактивный режим. Он запускается как консольная программа, но когда пользователь не указывает параметры командной строки, консоль закрывается с помощью FreeConsole (). После этого Environment.UserInteractive все еще остается верным. Затем лучше проверить, возвращает ли GetConsoleWindow () действительный указатель. Если нет, то консоли нет.

Похожие вопросы