Когда что-то уже написано, оттестировано и достойно справляется со своей работой, то лучше использовать это средство, нежели изобретать велосипед. Например, есть консольная утилита 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 FilesCrypto ProCSPcsptest";
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
Автор: ColorCast