GUI обертка для консольного приложения на C#

Для тех кто не в курсе, GUI (Graphical user interface) — графический интерфейс пользователя. То есть это интерфейс в котором элементы управления представлены в виде изображений, анимации и так далее. Но существуют программы, которые не используют GUI. Обычно их называют «консольные приложения».

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

Заинтересованных прошу под кат.

И так, для начала напишем маленький класс, со статистической функцией, которая будет запускать наше приложение. Я буду использовать Visual Studio 2010, C# и .NET 4.0. Создадим отдельный файл и в нем напишем каркас класса.

В .NET есть классы для запуска *.exe файлов. Что бы их использовать, необходимо подключить пространство имен System.Diagnostics. Допишем в начало файла:

Для запуска любого *.exe файла я использовал класс Process. Простой запуск *.exe файла можно сделать так:

Что произойдет во время MyProc.Start()? Наша программа запустит *.exe файл указанный в filename, и продолжит выполнение. Есть и другие варианты, но я использовал такой, так как далее, с помощью свойства StartInfo удобно задавать другие параметры запуска.

А что если нужно, что бы управляющая программа(программа которая запускает) дождалась завершения запускаемой программы? Для этого есть метод у класса Process, который называется WaitForExit. Он не возвращает управление, пока запущенное приложение не завершиться. Его недостаток проявиться, если запущенное приложение зависнет — из-за него зависнет управляющая программа, или поток который ее запустил в случае использования многопоточности. WaitForExit можно использовать после вызова Start, например вот так:

Для удобства, необходимо изменить метод Start нашего класса EXEStarter так, что бы программист мог сам задать «ждать завершение процесса или нет». Это совсем не трудно:

Как видно из фрагмента кода, если waitforexit равно true, значит метод будет ждать завершения процесса, ну и наоборот. Идем дальше. Для задания параметров консольному приложению, нам нужно использовать аргументы командной строки. У свойства StartInfo класса Process, есть свойство Arguments, которое принимает строку содержащую все аргументы командной строки, для этого приложения. снова допишем наш метод Start.

Неплохо было бы еще скрыть окно, которое открывается при запуске приложения, так как оно не несет никакой полезной нагрузки в данном случае. Для этого в StartInfo есть булевое свойство CreateNoWindow. Как вы уже догадались, если присвоить ему true — окно открываться не будет. Добавим перед запуском приложения строчку:

Теперь консольное окошко не будет открываться. Можно так же добавить строку:

Свойство UseShellExecute как вы уже догадались булевое и отвечает за то, будет ли при запуске использоваться оболочка ОС. Если поставить его в true, то можно в FileName задать не только *.exe файл, а и любой другой, или даже ссылку, при этом будет запущенно приложение, которое установлено по умолчанию в ОС для этого типа файлов.

Опять для удобства, можно перегрузить метод Start нашего класса, что бы он мог принимать меньше аргументов. Например вот так:

Работа с аргументами командной строки все еще остается не очень удобной. Я решил написать маленький класс, который стал бы для меня удобным средством создания аргументов командной строки. Из чего состоит аргумент командной строки? Из имени и значения. Обычно это выглядит например так: «-t 60», то есть «-t» имя, а «60» — значения. Много аргументов могут не принимать значения. Начнем написание класса.

Но в таком состоянии это не класс, а лишний код. Добавим метод ToString. Кстати, очень часто консольные утилиты в качестве аргументом принимают путь к какому-либо файлу. Если в этом пути есть пробелы, нужно ставить кавычки. Необходимо это учесть.

Я перегрузил метод ToString, который достался классу от Object. Если Value существует, добавляю кавычки и возвращаю строку. Допишем ему еще 2 конструктора, один принимает только имя, другой имя и значение.

Теперь класс закончен. Но его все равно будет не достаточно, ведь для добавления 10 аргументов в запуск *.exe придется создать 10 объектов этого класса и для каждого вызвать ToString. Напишем еще один класс на основе List из System.Collections.Generic. Вот что у меня получилось:

Методы List будут служить для добавления элементов, а перегруженный ToString вернет правильную строку с пробелами.

С классами все. Напишем маленький пример, что бы понять, как это работает. Для примера я использовал архиватор 7zip. Что бы за архивировать файл необходимо выполнить следующую команду:

Где %7zip Path% — путь к 7z.exe, «a» — опция, которая означает добавления файлов в архив, %Output Path% — путь результата, %Input Path% — путь для входного файла. Список всех аргументов командной строки для 7zip вы можете получит, запустив 7zip через консоль. Я создал небольшую форму с помощью WinForms. Простая форма Упаковщика Поместил на нее 1 кнопку. Подключил к проекту свои файлы с классами EXEStarter, ComanLineArgument и ComandLineArgumentsList. После этого написал обработчик нажатия кнопки. Он вызывает сначала диалоги выбора файлов, а потом с помощью только что написанных классов архивирует выбранный файл. Код получился вот такой:

 

 

Вот собственно и все. Задавайте свои ответы. Пишите пожелания, критику и сообщайте о моих орфографических ошибках.

Комментарии 6

  • Ну хорошо это если программа запустилась и отработала, а как быть если я использую что то типа консольного ftp? как тогда?

    • Такого плана приложения еще не делал. Но! Думаю можно перехватить стандартный поток ввода и отсюда уже отталкиваться. Потому что поток вывода и ошибок легко через C# перехватывается.

      Попробуй поискать сам, если не получиться — пиши, я как освобожусь поищу информацию.

  • А как например запустить cmd в TabControl в приложении на C#? Тоесть чтобы cmd был виден, но только в табе.

  • А как можно считать в C# поток данных, возвращаемых консольным приложением? Например, я посылаю команду ipconfig в cmd, как мне перенести данные из cmd в свой GUI?

    • Давно в этом не упражнялся, и ответить не могу. Не обещаю, но если будет свободное время — попробую глянуть решение. Это возможно, просто я не сталкивался или просто забыл как это делал.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *