2008-12-03 3 views
6

Я пишу приложение, которое можно запустить либо в качестве стандартного приложения WinForms, либо в автоматическом режиме из командной строки. Приложение было построено с использованием стандартного шаблона WinForms VS 2k5.Выход в командную строку, если она запущена из командной строки

Когда приложение выполняется из командной строки, я хочу, чтобы он выводил информацию, которая может быть записана скриптом, выполняющим приложение. Когда я делаю это непосредственно из Console.WriteLine(), вывод не появляется, хотя он может быть захвачен путем подключения к файлу.

С другой стороны, я могу заставить приложение выставить вторую консоль, выполнив P/Invoke на AllocConsole() из kernel32. Это не то, что я хочу. Я хочу, чтобы вывод отображался в том же окне, из которого было вызвано приложение.

Это выдающийся код, который позволяет мне выскакивает консоль из командной строки:

<STAThread()> Public Shared Sub Main() 

    If My.Application.CommandLineArgs.Count = 0 Then 
     Dim frm As New ISECMMParamUtilForm() 
     frm.ShowDialog() 
    Else 
     Try 
      ConsoleControl.AllocConsole() 
      Dim exMan As New UnattendedExecutionManager(ConvertArgs()) 
      IsInConsoleMode = True 
      OutputMessage("Application started.") 
      If Not exMan.SetSettings() Then 
       OutputMessage("Execution failed.") 
      End If 
     Catch ex As Exception 
      Console.WriteLine(ex.ToString()) 
     Finally 
      ConsoleControl.FreeConsole() 
     End Try 

    End If 

End Sub 

Public Shared Sub OutputMessage(ByVal msg As String, Optional ByVal isError As Boolean = False) 
    Trace.WriteLine(msg) 
    If IsInConsoleMode Then 
     Console.WriteLine(msg) 
    End If 

    If isError Then 
     EventLog.WriteEntry("ISE CMM Param Util", msg, EventLogEntryType.Error) 
    Else 
     EventLog.WriteEntry("ISE CMM Param Util", msg, EventLogEntryType.Information) 
    End If 

End Sub 

ответ

2

Update 1:

Как сказал Майкл Burr ответ, Raymond Chen недавно posted a short article about this. Я рад видеть, что моя догадка не была абсолютно неправильной.

Update 0:

Отказ от ответственности: Этот "ответ" в основном спекуляции. Я публикую его только потому, что прошло достаточно времени, чтобы установить, что не многие люди имеют ответ на то, что выглядит фундаментальным вопросом.

Я думаю, что «решение», если приложение является gui или консолью, выполняется во время компиляции, а не во время выполнения. Поэтому, если вы скомпилируете свое приложение в качестве приложения gui, даже если вы не отобразите gui, его все еще GUI-приложение и не имеет консоли. Если вы решите скомпилировать его в качестве консольного приложения, то, как минимум, вы перейдете в консольные окна перед переходом в режим «gui». И я не знаю, возможно ли это в управляемом коде.

Эта проблема является фундаментальной, я думаю, потому что консольное приложение должно принимать «управление» приложения вызывающей консоли. И это нужно сделать до того, как будет запущен код дочернего приложения.

9

Raymond Chen недавно опубликовал (через месяц после того, вопрос был размещен здесь, на SO) небольшую статью об этом:

How do I write a program that can be run either as a console or a GUI application?

Вы не можете, но вы можете попробовать подделать.

Каждое приложение PE содержит поле в своем заголовке, которое указывает, какая подсистема предназначена для запуска под. Вы можете сказать, IMAGE_SUBSYSTEM_WINDOWS_GUI отметить себя в качестве приложения с графическим интерфейсом для Windows, или вы можете сказать IMAGE_SUBSYSTEM_WINDOWS_CUI сказать , что вы консольное приложение. Если вы GUI-приложение, то программа будет работать без консоли.

Подсистема определяет, как ядро ​​ готовит выполнение для среды .Если программа помечаются как работает в подсистеме консоли, то ядро ​​ соединит консоль программы для консоли своего родителя, создавая новой консоли, если родитель не имеет консоль. (Это неполное описание, но детали не отношения к обсуждению.) На другой стороны, если программа отмечена как работает как приложение с графическим интерфейсом, тем ядра будет запускать программу без любая консоль вообще.

В этой статье он указывает на другой по Junfeng Чжан, что обсуждается, как пару программ (Visual Studio и ILDASM) реализовать такое поведение:

How to make an application as both GUI and Console application?

В случае VisualStudio, Есть фактически два двоичных файла: devenv.com и devenv.exe. Devenv.com - это консольное приложение. Devenv.exe - графическое приложение. Когда вы вводите devenv, из-за правила проверки Win32, выполняется devenv.com. Если вход отсутствует, devenv.com запускает файл devenv.exe и выходит из него. Если есть входы, devenv.com обрабатывает их как обычное консольное приложение.

В случае ildasm имеется только один двоичный файл: ildasm.exe. Он сначала компилируется как приложение с графическим интерфейсом. Позже editbin.exe используется, чтобы пометить его как консольную подсистему. В своем основном методе он определяет, нужно ли его запускать в режиме консоли или графического интерфейса. Если это нужно для запуска в режиме графического интерфейса, оно возобновляет себя как графическое приложение.

В комментариях к статье Реймонда Чена, laonianren имеет это добавить краткое описание Junfeng Чжана, как Visual Studio работает:

devenv.com общего назначения приложение консольного режима заглушки. Когда он запускается, он создает три канала для перенаправления stdin, stdout и stderr консоли. Затем он находит свое собственное имя (обычно devenv.com), заменяет «.com» на «.exe» и запускает новое приложение (например, devenv.exe), используя прочитанный конец stdin-канала и концы записи stdout и stderr в качестве стандартных ручек. Затем он просто сидит и ждет, пока devenv.exe выйдет и скопирует данные между консолью и трубами.

Таким образом, несмотря на то, что devenv.exe является приложением gui, он может читать и писать «родительскую» консоль, используя стандартные ручки.

И вы можете использовать devenv.com самостоятельно для myapp.exe, переименовав его на myapp.com. Но вы не можете на практике, потому что это принадлежит MS.

Смежные вопросы