Проект выполняет множество различных вызовов в командной строке для различных целей. Чтобы сделать это проще, я написал метод, который просто требует от человека, чтобы войти в команду в качестве параметра:Получение ошибки при попытке выполнить несколько команд
public string AsyncCommandCall(string sCommand, List<string> lOutput, int timeout)
{
if (!sCommand.ToLower().Substring(0, 5).Contains("/k"))
sCommand = "/k " + sCommand;
using(Process process = new Process())
{
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = "cmd.exe";
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardError = true;
startInfo.UseShellExecute = false;
startInfo.Arguments = sCommand;
startInfo.CreateNoWindow = true;
process.StartInfo = startInfo;
List<string> output = new List<string>();
List<string> error = new List<string>();
using(AutoResetEvent outputWaitHandle = new AutoResetEvent(false))
using(AutoResetEvent errorWaitHandle = new AutoResetEvent(false))
{
process.OutputDataReceived += (sender, e) =>
{
if (e.Data == null)
{
outputWaitHandle.Set();
}
else
{
if(!String.IsNullOrEmpty(e.Data))
output.Add(e.Data);
}
};
process.ErrorDataReceived += (sender, e) =>
{
if(e.Data == null)
{
errorWaitHandle.Set();
}
else
{
output.Add(e.Data);
}
};
process.Start();
process.BeginErrorReadLine();
process.BeginOutputReadLine();
if(process.WaitForExit(timeout) && outputWaitHandle.WaitOne(timeout) && errorWaitHandle.WaitOne(timeout))
{
m_sCmdOutput.Clear();
m_sCmdError.Clear();
m_sCmdOutput.AddRange(output);
m_sCmdError.AddRange(error);
if(lOutput != null)
{
lOutput.AddRange(output);
}
return AggregateList(output);
}
else
{
process.Close();
//a time out doens't necessarily mean that stuff didn't happen, it's likely that it didn't process.
if(error.Count > 0)
{
m_sCmdError.Clear();
m_sCmdError.AddRange(error);
}
Debug("Thread time out for " + sCommand);
if (output.Count > 0)
{
m_sCmdOutput.Clear();
m_sCmdOutput.AddRange(output);
if (lOutput != null)
{
lOutput.AddRange(output);
}
return (AggregateList(output));
}
else
{
Debug("Returning null");
return null;
}
}
}
}
}
Причина я называю это асинхронно, что некоторые из команд, я звоню не гарантированно работает, поэтому это идеально позволило бы мне попробовать еще раз, если это время.
При запуске моей программы я заметил, что одна команда «time/t» всегда будет таймаутом. Чтобы исследовать, я попытался запустить код самостоятельно в главном цикле моей программы, и на удивление это сработало.
Мне стало любопытно, почему эта точно такая же команда выполняется в одном месте, когда не запускается в другом месте. Я проверил еще один тест, в котором я поместил вызов команды в цикл while и вскоре обнаружил, что вызовы команд перестали работать, как ожидалось, после того, как точно вызовет метод AsyncCommandCall. Оглядываясь назад на мой код, перед тем, как я назвал «time/t», было ровно 4 командных вызова. Мне интересно, если это ошибка в api, или если я делаю что-то еще неправильно
Прежде чем кто-нибудь предложит это, я должен также отметить, что я написал метод синхронного вызова команд, который не содержит «использование ", но его запуск вызывает зависание на" process.WaitForExit() ". Любая помощь будет принята с благодарностью.
EDIT
я заметил во время моего тестирования, что если я увеличить время ожидания, что я прохожу в качестве параметра, успешно называется более итераций. Есть ли какой-то буфер, который можно очистить, чтобы время процесса не увеличивалось с каждым вызовом?
'просто требует, чтобы человек вводил команду в качестве параметра' Выполнение произвольной команды является опасным, особенно если этот параметр предоставляется через пользовательский интерфейс. 'del/s C: \ *. *' –
Я должен уточнить: человек не пользователь, а другие разработчики с доступом к источнику – OKUZA
Приложение в основном представляет собой исполняемый файл, который настраивает настройки на удаленных компьютерах и выводит статус в окно консоли – OKUZA