Связанные с:
Должен ли я включить режим командной строки в моих приложениях?
Как получить стандартный вывод родительского процесса?
Может ли консольное приложение определить, запущено ли оно из Проводника?
Я хочу создать консольное приложение, которое обычно запускается из командной строки.
Но, если дважды щелкнуть его из Проводника (в отличие от запуска из командной строки cmd.exe), я бы хотел, чтобы программа НЕ отображала окно консоли.
Я хочу избежать этого:
Является ли это возможным?
РЕДАКТИРОВАТЬ Я думаю, еще один способ спросить это, может ли программа знать, как она была вызвана - двойным щелчком или командной строкой?
Я работаю в .NET, на Windows.
РЕДАКТИРОВАТЬ 2: Из этого поста в блоге Old New Thing я узнал кое-что хорошее. Вот что я знаю сейчас...
В Windows файлы EXE помечаются как GUI или не GUI. С помощью csc.exe это выбирается с помощью /target:winexe
или /target:exe
. Перед выполнением первой инструкции в процессе ядро Windows устанавливает среду выполнения. В этот момент, если EXE помечен как GUI, ядро устанавливает для stdin/stdout для процесса значение NULL, а если не для GUI (командной строки), ядро создает консоль и устанавливает для этого stdin/stdout для этого процесса. приставка.
При запуске процесса, если нет stdin/stdout (== /target:winexe
), вызов немедленно возвращается. Итак, запустив приложение с графическим интерфейсом из cmd.exe, вы сразу получите ответ cmd. Если есть stdin/stdout и запускается из cmd.exe, то родительский cmd.exe ожидает завершения процесса.
"Немедленный возврат" важен, потому что если вы закодируете приложение с графическим интерфейсом для присоединения к его родительской консоли, вы сможете выполнить console.writeline и т.д. Но приглашение cmd.exe активно. Пользователь может вводить новые команды, запускать новый процесс и так далее. Другими словами, от winexe простое подключение к родительской консоли с помощью AttachConsole(-1)
не "превратит его" в консольное приложение.
На данный момент я думаю, что единственный способ разрешить приложению использовать консоль, если она вызывается из cmd.exe, и НЕ использовать ее при двойном щелчке, это определить exe как обычный exe консоли (/target:exe
) и при необходимости скрыть окно при запуске. Вы все еще получаете окно консоли, появляющееся кратко.
Я до сих пор не понял, как узнать, запущен ли он из explorer или cmd.exe, но я все ближе...
ОТВЕТЫ
Невозможно создать консольное приложение, которое не отображает окно консоли.
Можно создать консольное приложение, которое очень быстро скрывает свое окно, но не так быстро, как если бы оно никогда не появлялось.
Теперь, чтобы определить, было ли запущено консольное приложение из проводника, некоторые предложили взглянуть на консоль, в которой оно запущено
(из ответа mgb и статьи базы знаний 99115):
int left = Console.CursorLeft;
int top = Console.CursorTop;
bool ProcessWasRunFromExplorer = (left==0 && top==0);
Это говорит вам, был ли процесс запущен в его собственной консоли, но не был ли это проводником. Двойной щелчок в проводнике сделает это, но и Start.Process() из приложения сделает то же самое.
Если вы хотите по-разному относиться к этим ситуациям, используйте это, чтобы узнать имя родительского процесса:
System.Console.WriteLine("Process id: {0}", Process.GetCurrentProcess().Id);
string name = Process.GetCurrentProcess().ProcessName ;
System.Console.WriteLine("Process name: {0}", name);
PerformanceCounter pc = new PerformanceCounter("Process", "Creating Process Id", name);
Process p = Process.GetProcessById((int)pc.RawValue);
System.Console.WriteLine("Parent Process id: {0}", p.Id);
System.Console.WriteLine("Parent Process name: {0}", p.ProcessName);
// p.ProcessName == "cmd" or "Explorer" etc
Чтобы быстро скрыть окно после запуска процесса, используйте это:
private static readonly int SW_HIDE= 0;
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern Boolean ShowWindow(IntPtr hWnd, Int32 nCmdShow);
....
{
IntPtr myHandle = Process.GetCurrentProcess().MainWindowHandle;
ShowWindow(myHandle, SW_HIDE);
}
Если вы winexe
(приложение WinForms) и при необходимости присоединяете его к родительской консоли с помощью AttachConsole(-1)
, вы не получаете эквивалент обычного консольного приложения. Для winexe родительский процесс (например, cmd.exe) вернется в командную строку сразу после запуска приложения с графическим интерфейсом. Другими словами, командная строка активна и готова к вводу, в то время как только что запущенный процесс может выдавать вывод. Это сбивает с толку и, вероятно, полезно только для отладки приложений winforms.
Это сработало для меня.