Вывод в командную строку при запуске из командной строки

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

когда приложение выполняется из командной строки, Я хочу, чтобы оно выводило информацию, которая может быть захвачена скриптом, выполняющим приложение. Когда я делаю это непосредственно из консоли.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 ответов


обновление 1:

Как сказано в ответе Майкла Берра,Реймонд Чен недавно опубликовал короткую статью об этом. Я рад видеть, что моя догадка не была полностью неверной.

0 обновление:

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

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

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


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

Как написать программу, которая может быть запущена либо как консоль, либо как приложение GUI?

вы не можете, но вы можете попытаться подделать его.

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

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

в этой статье он указывает на другой Junfeng Zhang, который обсуждает, как несколько программ (Visual Studio и ildasm) реализуют это поведение:

как сделать приложение как GUI и консоли заявление?

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

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

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

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

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

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