Приложение .NET работает как Windows Form или как консольное приложение

Я хочу, чтобы одно из моих приложений Windows Forms запускалось программно - из командной строки. В процессе подготовки я отделил логику в своем классе от Формы. Теперь я застрял, пытаясь заставить приложение переключиться туда и обратно на основе наличия аргументов командной строки.

Вот код для основного класса:

static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        string[] args = Environment.GetCommandLineArgs();
        if (args.Length > 1) // gets passed its path, by default
        {
            CommandLineWork(args);
            return;
        }         

        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }

    private static void CommandLineWork(string[] args)
    {
        Console.WriteLine("It works!");
        Console.ReadLine();
    }

где Form1 - моя форма, а строка It works! является просто заполнителем для фактической логики.

Прямо сейчас, когда вы запускаете это из Visual Studio (с аргументами командной строки), фраза It works! печатается в Output. Однако при запуске файла /bin/Debug/Program.exe(или/Release, если на то пошло) приложение сбой.

Я собираюсь сделать это правильно? Будет ли иметь смысл (т.е. Меньше времени на разработку), чтобы мой логический класс был DLL, который загружается двумя отдельными приложениями? Или есть что-то совершенно иное, что я не знаю?

Спасибо заранее!

Ответ 1

Вам понадобится P/Invoke AllocConsole(), если вы обнаружите аргумент командной строки. Проверьте мой ответ в этот поток для требуемого кода. Образец С# находится далее на странице. Повторяется здесь, потому что я не доверяю этому сайту crummy:

using System;
using System.Windows.Forms;

namespace WindowsApplication1 {
  static class Program {
    [STAThread]
    static void Main(string[] args) {
      if (args.Length > 0) {
        // Command line given, display console
        AllocConsole();
        ConsoleMain(args);
      }
      else {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
      }
    }
    private static void ConsoleMain(string[] args) {
      Console.WriteLine("Command line = {0}", Environment.CommandLine);
      for (int ix = 0; ix < args.Length; ++ix)
        Console.WriteLine("Argument{0} = {1}", ix + 1, args[ix]);
      Console.ReadLine();
    }

    [System.Runtime.InteropServices.DllImport("kernel32.dll")]
    private static extern bool AllocConsole();
  }
}

Ответ 2

Да, было бы лучше сделать два frontend -exex (один для командной строки и один для оконного).

Основная причина заключается в том, что вы должны указать тип вывода для своего проекта (либо в командной строке, либо в приложении Windows, и вы не можете выбрать оба.

Таким образом, вы должны всегда использовать тип вывода приложения Windows (который приходит с накладными расходами для системы обмена сообщениями Windows и не дает вам "реальной" командной строки).

Ответ 3

Не уверен, что это имеет значение, но вместо

static void Main()
{
        string[] args = Environment.GetCommandLineArgs();

вы можете вместо этого поставить

static void Main(string[] args)
{

Ответ 4

Вы собираетесь запустить его в качестве реального консольного приложения, попросив пользователя ввести данные и т.д. или вы просто начнете его с некоторых аргументов, чтобы его можно было запустить из пакетного файла или запланированной задачи или подобное?

Если это настоящее консольное приложение, я согласен с Foxfire, что, вероятно, стоит иметь 2 exe файла, но в остальном я бы сохранил его как один exe. Я сделал много из них без каких-либо проблем.

Какое точное исключение происходит?

Ответ 5

Перейдите к свойствам проекта

На вкладке Application вы увидите раскрывающийся список с именем Output Type. Измените это на Console Application.

Там у вас есть как окно, так и консоль. Теперь ваш код с аргументом команды должен работать.