Мне нужно выполнить процесс SFTP через код С#. Я использую службу Windows. Ниже приведен код, который я использую.
WebCash.writeToFile(WebCash.outerbatchpath, command);
WebCash.writeToFile(WebCash.outerbatchpath, "exit");
ProcessStartInfo psi = new ProcessStartInfo("cmd.exe", "/c "+WebCash.outerbatchpath);
psi.RedirectStandardOutput = true;
psi.RedirectStandardInput = true;
psi.RedirectStandardError = true;
psi.UseShellExecute = false;
psi.CreateNoWindow = true;
psi.WindowStyle = ProcessWindowStyle.Hidden;
Process p = new Process();
p.StartInfo = psi;
p.Start();
p.WaitForExit();
psi = null;
WebCash.writeToFile(WebCash.GetErrorLog(), DateTime.Now.ToString() + "- Running SFTP end - " + p.ExitCode);
return p.ExitCode;
При попытке отладки вышеуказанного кода отладчик не может передать p.WaitforExit()
(т. p.WaitforExit()
) Служба не выполняется после p.WaitforExit()
.
Я запускаю следующую команду (SFTP) в моей внешней стороне.
psftp -b D:\Source_Data\SFTP\innerbatch.bat -l username -i D:\privatekey.ppk @servername
Внутренняя партия содержит команду ниже
put D:\Source_Data\SFTP\FileToTransfer.xml
Мне нужен код выхода, чтобы получить ошибку. Помощь Pls.
Я предполагаю, что запущенная вами программа ("внешняя партия") никогда не заканчивается.
Когда вы перенаправляете выход процесса, вы должны его прочитать. Там ограниченный буфер для перенаправленного вывода. Когда он заполняется, дочерний процесс останавливается при следующей попытке произвести вывод и ждет, пока родительский процесс не прочитает некоторые данные из буфера. Как вы никогда этого не делаете, и вы ждете завершения процесса, возникает взаимоблокировка.
См. MSDN для свойства ProcessStartInfo.RedirectStandardOutput
:
Операции синхронного чтения вводят зависимость между показанием вызывающего абонента из потока StandardOutput и записью дочернего процесса в этот поток. Эти зависимости могут привести к условиям взаимоблокировки. Когда вызывающий абонент читает из перенаправленного потока дочернего процесса, он зависит от дочернего элемента. Вызывающий абонент ждет операции чтения до тех пор, пока ребенок не будет записываться в поток или не закрывает поток. Когда дочерний процесс записывает достаточно данных для заполнения перенаправленного потока, он зависит от родителя. Детский процесс ждет следующей операции записи, пока родитель не прочитает полный поток или не закрывает поток. Условие взаимоблокировки возникает, когда вызывающий и дочерний процессы ждут друг друга для завершения операции, и они не могут продолжаться. Вы можете избежать взаимоблокировок, оценивая зависимости между вызывающим и дочерним процессами.
В этом случае всегда рекомендуется использовать p.StandardOutput.ReadToEnd()
вместо p.WaitForExit()
. Обе команды ждут выхода процесса, но первый гарантирует, что тупик не произойдет.
С другой стороны, поскольку вы передаете только один файл, я не уверен, что вывод psftp
самом деле достаточно велик, чтобы заполнить буфер. Если приведенное выше предложение не поможет, я бы рекомендовал вам упростить код, непосредственно запуская psftp.exe
, удалив ненужные слои cmd.exe
и внешнего командного файла.
EDIT: Если вы никогда не запускаете psftp
под учетной записью службы, возможно, это psftp
к подтверждению подтверждения ключа хоста.
Ключ хоста сервера не кэшируется в реестре. Вы
не имеют гарантии, что сервер - это компьютер, на котором вы
думаю.
Отпечаток ключа сервера dss:
ssh-dss 1024 0b: 77: 8b: 68: f4: 45: b1: 3c: 87: ad: 5c: be: 3b: c5: 72: 78
Если вы доверяете этому хосту, введите "y", чтобы добавить ключ к
PuTTY и продолжайте соединение.
Если вы хотите продолжать соединение только один раз, без
добавив ключ в кэш, введите "n".
Если вы не доверяете этому хосту, нажмите Return, чтобы отказаться от
подключение.
Сохранить ключ в кеше? (Г/л)
Вы должны использовать переключатель -hostkey
чтобы явно указать отпечаток доверенного ключа хоста.
В качестве альтернативы можно использовать некоторую собственную библиотеку SFTP.NET.
Замечание: Именование сценария psftp
.bat
запутанно. Это не файл (Windows).
Использование WinSCP.
Для SshHostKeyFingerprint
см. Диалог информации о сервере и протоколе
// Setup session options
SessionOptions sessionOptions = new SessionOptions
{
Protocol = Protocol.Sftp,
HostName = "000.00.00.000",
UserName = "xxxxxx",
Password = "xxxxxx",
PortNumber= 22,
SshHostKeyFingerprint = "ssh-rsa 2048 xxxxxxxxxxxxxxx"
};
using (Session session = new Session())
{
// Connect
session.Open(sessionOptions);
// Upload files
//TransferOptions transferOptions = new TransferOptions();
//transferOptions.TransferMode = TransferMode.Binary;
//TransferOperationResult transferResult;
var results = session.ListDirectory("/path");
foreach (RemoteFileInfo item in results.Files)
{
Console.WriteLine(item.Name);
}
// Throw on any error
//transferResult.Check();
// Print results
//foreach (TransferEventArgs transfer in transferResult.Transfers)
//{
// Console.WriteLine("Upload of {0} succeeded", transfer.FileName);
//}
}