通过Windows服务上的WinSCP下载SFTP文件将冻结
我正在尝试构建一个服务,该服务使用SFTP下载一些日志文件并将它们导入数据库 因为Delphi没有SFTP组件,所以我创建了一个BAT文件来使用WinSCP下载日志通过Windows服务上的WinSCP下载SFTP文件将冻结,windows,delphi,windows-services,sftp,winscp,Windows,Delphi,Windows Services,Sftp,Winscp,我正在尝试构建一个服务,该服务使用SFTP下载一些日志文件并将它们导入数据库 因为Delphi没有SFTP组件,所以我创建了一个BAT文件来使用WinSCP下载日志 DownloadLogs.bat: WinSCP.com < DownloadLogs.commands DownloadLogs.commands: open sftp://root:password@myserver.com option confirm off get -delete /var/lib/
DownloadLogs.bat:
WinSCP.com < DownloadLogs.commands
DownloadLogs.commands:
open sftp://root:password@myserver.com
option confirm off
get -delete /var/lib/3cxpbx/Instance1/Data/Logs/CDRLogs files
exit
这就是我如何称呼BAT文件的:
function ExecAppWait(AppName: string; Params: string = ''; Directory: string = ''; Hidden: boolean = False): Boolean;
var ShellExInfo: TShellExecuteInfo;
begin
FillChar(ShellExInfo, SizeOf(ShellExInfo), 0);
with ShellExInfo do begin
cbSize := SizeOf(ShellExInfo);
fMask := see_Mask_NoCloseProcess;
Wnd := Application.Handle;
lpFile := PChar(AppName);
lpDirectory := PChar(Directory);
lpParameters := PChar(Params);
if Hidden then nShow := sw_Hide
else nShow := sw_ShowNormal;
end;
Result := ShellExecuteEx(@ShellExInfo);
if Result then
while WaitForSingleObject(ShellExInfo.HProcess, 100) = WAIT_TIMEOUT do begin
Application.ProcessMessages; // give processor time to other tasks
if Application.Terminated then
Break;
end;
end;
function TdmLogs.DownloadLogs(Hidden: boolean = True): boolean;
var Path: string;
begin
Path := TPath.Combine(TPath.GetDirectoryName(Application.ExeName), 'SFTP');;
ExecAppWait(TPath.Combine(Path, 'LogsCentralita.bat'), '', Hidden);
Result := Length(TDirectory.GetFiles(TPath.Combine(Path, 'Files'), '*.log')) > 0
end;
在我的应用程序上调试DownloadLogs函数时,它工作正常,但作为服务运行时会冻结。你知道怎么回事吗?我不能从服务调用CMD.exe吗
多谢各位
更新
按照Martin Prikryl的回答,我现在以这种方式执行WinSCP:
function TdmCentralita.DownloadLogs(SaveOutput: boolean = False): boolean;
var IniFile: TIniFile;
Path, Params, User, Password, Server, Hostkey, RemotePath: string;
begin
IniFile := TIniFile.Create(TPath.ChangeExtension(GetModuleName(HInstance), '.ini'));
Server := IniFile.ReadString('Centralita', 'Servidor', '');
Hostkey := IniFile.ReadString('Centralita', 'Hostkey', '');
User := IniFile.ReadString('Centralita', 'Usuario', 'root');
Password := DecryptStr(IniFile.ReadString('Centralita', 'Password', ''), 223);
RemotePath := IniFile.ReadString('Centralita', 'PathRemoto', '');
IniFile.Free;
while (RightStr(RemotePath, 1) = '\') or (RightStr(RemotePath, 1) = '/') do RemotePath := Copy(RemotePath, 1, Length(RemotePath) - 1);
RemotePath := RemotePath + '/*.log';
Path := TPath.Combine(TPath.GetDirectoryName(GetModuleName(HInstance)), 'SFTP');
if not TDirectory.Exists(TPath.Combine(Path, 'files')) then TDirectory.CreateDirectory(TPath.Combine(Path, 'files'));
Params := '/ini=null /command "open sftp://' + User + ':' + Password + '@' + Server + ' -hostkey=""' + Hostkey + '""" "option confirm off" "get -delete ' + RemotePath + ' files\*" "exit"';
if SaveOutput then Params := Params + ' /log="' + Path + '\Log.txt" /loglevel=0';
ExecAppWait('WinSCP.com', Params, Path, True);
Result := Length(TDirectory.GetFiles(TPath.Combine(Path, 'Files'), '*.log')) > 0
end;
您的脚本不包含SSH主机密钥。由于您提供命令的方式很奇怪(输入重定向而不是
/script
或/command
开关),WinSCP以交互模式启动。因此,它会提示主机密钥验证,并挂起
将-hostkey
开关添加到打开
命令。见:
和用于使WinSCP在任何问题上中止,而不是挂起 您还应该读取批处理文件输出,以便将来更好地处理错误
function TdmCentralita.DownloadLogs(SaveOutput: boolean = False): boolean;
var IniFile: TIniFile;
Path, Params, User, Password, Server, Hostkey, RemotePath: string;
begin
IniFile := TIniFile.Create(TPath.ChangeExtension(GetModuleName(HInstance), '.ini'));
Server := IniFile.ReadString('Centralita', 'Servidor', '');
Hostkey := IniFile.ReadString('Centralita', 'Hostkey', '');
User := IniFile.ReadString('Centralita', 'Usuario', 'root');
Password := DecryptStr(IniFile.ReadString('Centralita', 'Password', ''), 223);
RemotePath := IniFile.ReadString('Centralita', 'PathRemoto', '');
IniFile.Free;
while (RightStr(RemotePath, 1) = '\') or (RightStr(RemotePath, 1) = '/') do RemotePath := Copy(RemotePath, 1, Length(RemotePath) - 1);
RemotePath := RemotePath + '/*.log';
Path := TPath.Combine(TPath.GetDirectoryName(GetModuleName(HInstance)), 'SFTP');
if not TDirectory.Exists(TPath.Combine(Path, 'files')) then TDirectory.CreateDirectory(TPath.Combine(Path, 'files'));
Params := '/ini=null /command "open sftp://' + User + ':' + Password + '@' + Server + ' -hostkey=""' + Hostkey + '""" "option confirm off" "get -delete ' + RemotePath + ' files\*" "exit"';
if SaveOutput then Params := Params + ' /log="' + Path + '\Log.txt" /loglevel=0';
ExecAppWait('WinSCP.com', Params, Path, True);
Result := Length(TDirectory.GetFiles(TPath.Combine(Path, 'Files'), '*.log')) > 0
end;