Когда что-то уже написано, оттестировано и достойно справляется со своей работой, то лучше использовать это средство, нежели изобретать велосипед. Например, есть консольная утилита cpctest.exe, которая позволяет выполнять все те-же действия что и графическая оболочка, и масса других утилит из стандартного набора Windows. На разработку, отладку и покрытие тестами аналогичной функциональности уйдет драгоценное время. Так зачем его прожигать? Приступим.
Для начала нам нужно залезть на MSDN и посмотреть синтаксис стандартных команд. В результате мы увидим, что запуск любого консольного приложения состоит из имени приложения и его параметров. Приложение инстанцируется системным классом Process. Прототип нашей функции для запуска консольного приложения будет выглядеть следующим образом:
bool Execute(string commandName, IEnumerable<string> paramsList)
Если мы захотим получать результат выполнения запущенного приложения и обрабатывать его, нам потребуется соответствующий метод:
string GetResult (string commandName, IEnumerable<string> paramsList)
Далее идем снова на MSDN и смотрим ProcessStartInfo Arguments, UseShellExecute, RedirectStandardOutput и RedirectStandardError, если Вы будете строго обрабатывать исключения как в Java. В итоге для инициализации процесса нам потребуется свойство, которое будет определять режим запуска консольного приложения и метод для инициации процесса. Для своего класса я использовал паттерн Facade.
public class CommandHelpers { public CommandHelpers() { Invisible = true; } public bool Invisible { get; set; } private Process CreateProcess(string commandName, IEnumerable<string> paramsList, bool output = false) { string paramString = paramsList.Aggregate<string, string>(null, (current, param) => current + " " + param); return new Process { StartInfo = { FileName = commandName, Arguments = paramString, UseShellExecute = output ? !output : !Invisible, RedirectStandardOutput = output } }; }
Необходимо учесть, что запускаемое приложение может работать бесконечно долго, например, ping –t youwebsite.org. Для его запуска нам потребуется соответствующий метод:
public Task<bool> ExecuteAsync(string commandName, IEnumerable<string> paramsList)
Исходный код:
public class CspHelpers { private readonly CommandHelpers _cryptoconsole; private readonly string _command = @"c:\Program Files\Crypto Pro\CSP\csptest"; public CspHelpers() { _cryptoconsole = new CommandHelpers(); } /// <summary> /// Импорт сертификата в контейнер /// </summary> /// <param name="driveName">Имя сменного носителя</param> /// <param name="containerName">Имя контейнера</param> /// <param name="type">Тип импортируемого серификата exchange или signature</param> /// <param name="certPath">Полный путь до сертификата</param> /// <param name="password">Пароль на контейнер</param> /// <returns>Сведения о выполнении</returns> public string ImportToContainer(string driveName, int containerName, KeyType type, string certPath, string password) { var Params = new List<string>(); Params.Add("-keyset"); Params.Add("-container"); Params.Add(string.Format(@"\\.\FAT12_{0}\{1}", driveName[0], containerName)); Params.Add("-password"); Params.Add(password); Params.Add("-keytype"); Params.Add(type.ToString()); Params.Add("-impcert"); Params.Add(certPath); return _cryptoconsole.GetResult(_command, Params); } }
using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Common.Security { /// <summary> /// See for correct use https://technet.microsoft.com/en-us/library/bb491070.aspx /// </summary> public class CommandHelpers { public CommandHelpers() { Invisible = true; } /// <summary> /// Not show CMD window /// </summary> public bool Invisible { get; set; } /// <summary> /// Execete CMD command /// </summary> /// <param name="commandName">Command name only</param> /// <param name="paramsList">Params and keys for command</param> public bool Execute(string commandName, IEnumerable<string> paramsList) { return CreateProcess(commandName, paramsList).Start(); } /// <summary> /// Async execete CMD command /// </summary> /// <param name="commandName">Command name only</param> /// <param name="paramsList">Params and keys for command</param> public Task<bool> ExecuteAsync(string commandName, IEnumerable<string> paramsList) { return Task<bool>.Factory.StartNew(() => CreateProcess(commandName, paramsList).Start()); } /// <summary> /// Returns result of command execution /// </summary> /// <param name="commandName">Command name only</param> /// <param name="paramsList">Params and keys for command</param> /// <returns></returns> public string GetResult(string commandName, IEnumerable<string> paramsList) { var bufer = new StringBuilder(); using (var proc = CreateProcess(commandName, paramsList, true)) { proc.Start(); while (!proc.StandardOutput.EndOfStream) { bufer.AppendLine(proc.StandardOutput.ReadLine()); } } return bufer.ToString(); } /// <summary> /// Returns result of command execution /// Experemental. Not Tested. /// </summary> /// <param name="commandName">Command name only</param> /// <param name="paramsList">Params and keys for command</param> /// <returns></returns> public string GetResultAsync(string commandName, IEnumerable<string> paramsList) { var bufer = new StringBuilder(); using (var proc = CreateProcess(commandName, paramsList, true)) { proc.OutputDataReceived += (sender, e) => { if (!string.IsNullOrEmpty(e.Data)) { bufer.AppendLine(e.Data); } }; proc.BeginOutputReadLine(); proc.EnableRaisingEvents = true; proc.WaitForExit(); } return bufer.ToString(); } private Process CreateProcess(string commandName, IEnumerable<string> paramsList, bool output = false) { var paramString = paramsList.Aggregate<string, string>(null, (current, param) => current + " " + param); return new Process { StartInfo = { FileName = commandName, Arguments = paramString, UseShellExecute = output ? !output : !Invisible, RedirectStandardOutput = output } }; } } }
UPD:
Дополнительные материалы:
Источник вдохновения для статьи:
От пользователя vedmaka: toster.ru/q/7644
GUI обертка для консольного приложения: ru.jakeroid.com/gui-obertka-dlya-konsolnogo-prilozheniya-na-csharp.html
От пользователя evgenyl: habrahabr.ru/post/136766
ссылка на оригинал статьи https://habrahabr.ru/post/276443/
Добавить комментарий