![]() |
Delphi 10.4 - Indy und SFTP
Moin,
ich bin etwas verunsichert ... geht mit Indy denn auch SFTP oder nicht ? Und wenn ja - hat jemand ein Beispiel wie das funktioniert ? Ich muss mich anmelden und dann eine Datei runterladen können. Gruss Hans |
AW: Delphi 10.4 - Indy und SFTP
Nein, geht leider nicht.
|
AW: Delphi 10.4 - Indy und SFTP
.. wie schon geschrieben geht das mit Indy nicht.
DevArt - secure Bridge und nsoft - IpWorks haben SFTP Bibliotheken - kostenpflichtig. Auf Basis von putty kann man sich auch einen SFTP Client bauen - Beispiele sind im Netz zu finden. Seit Wiendows 10 kann man auch einen SFTP Client von der Console aufrufen. Grüße Klaus |
AW: Delphi 10.4 - Indy und SFTP
ICS - Internet Component Suite
![]() ![]() Das besondere, es wird stetig weiterentwickelt. Und es funktioniert. Gruß Albert |
AW: Delphi 10.4 - Indy und SFTP
.. hat meines Wissen keine SFTP Bibliothek.
Grüße Klaus |
AW: Delphi 10.4 - Indy und SFTP
Zitat:
|
AW: Delphi 10.4 - Indy und SFTP
Bezüglich ICS könnte man das ja mal hier anfragen:
![]() |
AW: Delphi 10.4 - Indy und SFTP
Ich verwende das hier für SFTP (also FTP over ssh) :
![]() Da sind auch einfache und schnell nachvollziehbare Beispiele dabei. |
AW: Delphi 10.4 - Indy und SFTP
Moin,
ich habe mir die einmal runtergeladen und kann DelphiVCLDemo auch (mit Delphi 10.4 CE) kompilieren und mit mit Strato verbinden. Daraufhin habe ich den Pfad zum Verzeichnis tputty.release unter tools/optionen/sprache/delphi/bibliothek/bibliothekspfad hinzugefügt jetzt habe ich testweise ein ganz einfaches Programm geschrieben:
Delphi-Quellcode:
Allerdings bekomme ich bereits beim create eine Exceprion der Klasse EEXternalException mit der Medlung "Externe Exception C06D007E"
unit SFTPUnit;
interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls; type TForm1 = class(TForm) ListBox1: TListBox; Button1: TButton; procedure Button1Click(Sender: TObject); private { Private-Deklarationen } public { Public-Deklarationen } end; var Form1: TForm1; implementation {$R *.dfm} uses tgputtylib, tgputtysftp; const Username = 'benutzername'; Passwort = 'passwort'; Host = 'ssh.strato.de'; Port = 22; var TGPSFTP :TTGPuttySFTP; procedure Verbinden; begin TGPSFTP := TTGPuttySFTP.Create(true); TGPSFTP.HostName := Host; TGPSFTP.UserName := UserName; TGPSFTP.Password := Passwort; TGPSFTP.Port := Port; try TGPSFTP.Connect; except on E:Exception do WriteLn('EXCEPTION: ',E.Message); end; if TGPSFTP.Connected then ShowMessage('verbunden :-)'); end; procedure TForm1.Button1Click(Sender: TObject); begin Verbinden; Button1.Caption := 'Ende'; end; end. Wenn ich dann auf "anhalten" klicke bekomme ich die Meldung "Quelldatei nicht gefunden" delayhlp.cpp ?? Wieso geht denn die Demo und so ein einfaches Programm knallt gleich ? Gruss Hans |
AW: Delphi 10.4 - Indy und SFTP
Ich mache SFTP über psftp.exe. Das ist ein Programm von PUTTY.
Das steure ich mittels Batchdateien. Das ist zwar von hinten durch die Brust ins Auge, aber funktioniert einwandfrei. IMO müsste Embarcadero hier was liefern. Oder INDY Kohle gehen, wenn die Manpowerprobleme haben, damit die was programmieren, weil keiner will mehr FTP machen weil es zu unsicher ist und jeder geht auf SFTP. |
AW: Delphi 10.4 - Indy und SFTP
Ich verwende Winscp. Lässt sich einfach über Script steuern, wobei so ein da ein 3-Zeiler reicht um z.B. alle Daten eines Verzeichnisses hochzuladen.
|
AW: Delphi 10.4 - Indy und SFTP
.. möchte hier noch
![]() Kostet etwas - kommt ohne externe DLLs/Exen aus. Sehr zuverlässig. Grüße Klaus |
AW: Delphi 10.4 - Indy und SFTP
Moin,
hat keine eine Idee warum das Demoprogramm läuft und mein Miniprogramm nicht ? Ich habe mal versucht die Unterschiede rauszufinden. Das erste was mir auffällt ist das im Demoprogramm bereits zwei Libarys eingebunden werden:
Delphi-Quellcode:
Warum macht man so was wenn das eigentliche Programm in der Unit steckt und die Unit auch noch einmal die beiden Libarys in der Uses-Klausel aufführt ?
tgputtysftp in '..\tgputtysftp.pas',
tgputtylib in '..\tgputtylib.pas'; Zweitens: Im DemoProgramm wird die Variable (? Ist es das überhaupt) in dem private-Block vereinbart:
Delphi-Quellcode:
Wenn ich das genauso mache und die TestSFTP Deklaration aus der var-Deklaration rausnehme und in den private-Block packe
private
{ Private declarations } PSFTP:TTGPuttySFTP;
Delphi-Quellcode:
dann wird beim compilieren der erste Ausdruck
type
TForm1 = class(TForm) ListBox1: TListBox; Button1: TButton; procedure Button1Click(Sender: TObject); private { Private-Deklarationen } TestSFTP :TTGPuttySFTP; public { Public-Deklarationen } end;
Delphi-Quellcode:
gleich als "undeklarierter Bezeichner 'TestSFTP '" markiert und das Programm lässt sich nicht kompilieren.
TestSFTP := TTGPuttySFTP.Create(true);
Nur ... warum - was mache ich anders als das Demoprogramm ?? Gruss und Danke ! Hans |
AW: Delphi 10.4 - Indy und SFTP
.. wenn du die Instanz in einer Methode Deiner Form erstellst,
sollte die Klasse gefunden werden. Wenn es eine Routine ausserhalb der TForm ist, kann sie nicht gefunden werden. Grüße Klaus |
AW: Delphi 10.4 - Indy und SFTP
Zitat:
Delphi-Quellcode:
:-(
TestSFTP := TTGPuttySFTP.Create(true);
Hat jemand eine Idee dazu ? Hans |
AW: Delphi 10.4 - Indy und SFTP
Zitat:
Grüße TurboMagic |
AW: Delphi 10.4 - Indy und SFTP
.. ich bekomme da keinerlei Fehlermeldung beim Create.
Delphi-Quellcode:
Build 19 - 06 Mar 2022
procedure TForm1.Button1Click(Sender: TObject);
var gsftp :TTGPuttySFTP; begin gsftp := TTGPuttySFTP.Create(true); gpsftp.HostName := '192.168.178.43'; gpsftp.UserName := 'pi'; gpsftp.Password := '********'; gpsftp.Port := 22; gpsftp.Connect; end; Grüße Klaus |
AW: Delphi 10.4 - Indy und SFTP
Zitat:
Ich habe den kompletten Pfad zu den Sources in der Bibliothek, setze das USE richtig ... und trotzdem PENG beim Connect. Ich habe auch mal die entsprechende Libaray mit debugged, beim Create wird dann geprüft ob die TGPuttyLibAvailable ist und darin dann wieder irgendwelche StructSizes:
Delphi-Quellcode:
unction TGPuttyLibAvailable:Boolean;
var libpath:string; ulongsize,namesize,attrsize,namessize:Integer; procedure CheckStructSizes; begin tggetstructsizes(@ulongsize,@namesize,@attrsize,@namessize); if (ulongsize<>sizeof(TUnsignedLong)) or (namesize<>sizeof(fxp_name)) or (attrsize<>sizeof(fxp_attrs)) or (namessize<>sizeof(fxp_names)) then begin raise Exception.Create('Invalid '+tgputtydll+ ': uses different struct sizes: '+ 'ulongsize='+IntToStr(ulongsize)+'/'+IntToStr(sizeof(TUnsignedLong))+ ',namesize='+IntToStr(namesize)+'/'+IntToStr(sizeof(fxp_name))+ ',attrsize='+IntToStr(attrsize)+'/'+IntToStr(sizeof(fxp_attrs))+ ',namessize='+IntToStr(namessize)+'/'+IntToStr(sizeof(fxp_names))); end end; begin {$ifdef MSWINDOWS} Result:=true; CheckStructSizes; {$else} if TGPLH>0 then begin Result:=Assigned(tgputty_initcontext); Exit; end; In meinem Testprogramm knallt es gleich bei dem ersten Test in folgender Zerile:
Delphi-Quellcode:
Nur leider sind das für mich endgültig bömische Dörfer ... sagt das jemandem was ??
procedure tggetstructsizes(const Pulongsize,Pnamesize,Pattrsize,Pnamessize:PInteger); cdecl; external tgputtydll {$ifdef HASDELAYED}delayed{$endif};
Gruss Hans |
AW: Delphi 10.4 - Indy und SFTP
Guten Morgen,
hast Du diese dll (tgputtylib.dll) in dem gleichen Verzeichnis wo Deine exe liegt? im Project Source
Delphi-Quellcode:
In der From Unit:
program Project1;
uses Vcl.Forms, Unit1 in 'Unit1.pas' {Form1}, tgputtylib in 'tgputtylib.pas', tgputtysftp in 'tgputtysftp.pas', tgputtysftpclient in 'tgputtysftpclient.pas';
Delphi-Quellcode:
Mehr habe ich nicht geändert.
implementation
uses tgputtylib, tgputtysftp; {$R *.dfm} Grüße Klaus |
AW: Delphi 10.4 - Indy und SFTP
Moin Klaus,
nein - die DLL hatte ich bisher nicht im Verzeichnis - jetzt ist sie drin. Es ändert sich nur leider überhaupt nichts, es knallt immer noch und Delphi sucht dann die Quelldatei "delayhlp.cpp" ?? Und zawr passiert das genau an dieser Stelle:
Delphi-Quellcode:
Sagt das jemandem was ??
function tggetlibrarycontextsize:Integer; cdecl; external tgputtydll {$ifdef HASDELAYED}delayed{$endif};
Hans |
AW: Delphi 10.4 - Indy und SFTP
.. vielleicht magst Du ja mal (testhalber) diese Einträge in der tgputtylib.pas
kommentieren ( so das sie nicht mehr wirksam sind):
Delphi-Quellcode:
Welche Delphi Version benutzt denn Du?
//{$ifndef FPC}
//{$ifdef CONDITIONALEXPRESSIONS} //{$if CompilerVersion >= 21.0} //{$define HASDELAYED} //{$ifend} //{$endif} //{$endif} Grüße Klaus |
AW: Delphi 10.4 - Indy und SFTP
Die Allzweckwaffe ist Curl. Das Programm curl.exe ist Bestandteil aktueller Windows Versionen. Links:
![]() ![]() ![]() ![]() ![]() ![]()
Code:
Für viele Anwendungsfälle findest du eine Vorlage in den
// Die Doppelpunkte einfach durch den Speicherpfad ersetzten
..\src;..\src\app;..\src\core;..\src\crypt;..\src\db;..\src\lib;..\src\misc;..\src\net;..\src\orm;..\src\rest;..\src\script;..\src\soa;..\src\tools\ecc;..\src\ui; ![]()
Delphi-Quellcode:
Disclaimer: Ungetestet!
uses
mormot.core.base, mormot.core.text, mormot.core.os, mormot.lib.curl; var hnd: TCurl; url: RawUtf8; res: TCurlResult; buffer: RawByteString; begin if not CurlIsAvailable then Exit; //=> hnd := curl.easy_init; if hnd <> Nil then begin // Schema: sftp://user:password@server/file.txt url := 'ftp.halifax.rwth-aachen.de/debian/README.html'; // https://curl.se/libcurl/c/sftpget.html curl.easy_setopt(hnd, coURL, Pointer(url)); curl.easy_setopt(hnd, coWriteFunction, @CurlWriteRawByteString); curl.easy_setopt(hnd, coWriteData, @buffer); res := curl.easy_perform(hnd); if res = crOk then begin FileFromString(buffer, MakePath([Executable.ProgramFilePath, 'file.txt'])); ShowMessage('Download completed'); end else ShowMessage(Format('Curl told us %d (%s)', [Ord(res), curl.easy_strerror(res)])); curl.easy_cleanup(hnd); end; end; Ein Beispiel zum Studieren ist auch die Klasse TCurlHttp aus der Unit mormot.net.client. Bis bald... Thomas |
AW: Delphi 10.4 - Indy und SFTP
Moin Klaus,
Zitat:
"Im Projekt SFTPTest.exe ist eine Exception der Klasse TGPuttySFTPException mit der Meldung 'tgsftp_connect: Unknown Error. Connecting with ssh.strato.de, port 22, as user h.bothur******** Looking up host "ssh.strato.de" for SSH connection connecting to <ip-Adresse> port 22 we claim version: SSH-2.0-tgputtylib_Release_0.76 Connecting to 81.169.145.126 Remote version: SSH-2.0-OpenSSH_8.2 Using SSH protocol version 2 No GSSAPI security context available Doing ECDH key exchange with curve25519 and hash SH-256 (SHA-NI accelerated) Server aslo has ecdsa-sha2-nistp256/rsa-ahs2-512/rsa-sha2-256/ssh-rsa host keys, but we don't know any of them Host key fingerprint is: ssh-ed25519 255 SHA256: <fingerprint> User aborted at host key verification psftp_connect result is 1 tgsftp_connect final result is Die fette Zeile habe ich markiert - da wird der Grund sein, allerdings weiß ich nicht was man da macht. Ich werde jetz einmal die - funktionierede Deo debuggen und kucken ob ich als Laie was sehe. Zitat:
Gruss Hans |
AW: Delphi 10.4 - Indy und SFTP
Hallo,
im einfachsten Fall kannst Du das so lösen:
Delphi-Quellcode:
TForm1 = class(TForm)
Button1: TButton; procedure Button1Click(Sender: TObject); private { Private declarations } function onVerifyHostKey(const host:PAnsiChar;const port:Integer; const fingerprint:PAnsiChar; const verificationstatus:Integer; var storehostkey:Boolean): Boolean; public { Public declarations } end;
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var GPSFTP :TTGPuttySFTP; begin GPSFTP := TTGPuttySFTP.Create(true); gpsftp.HostName := '192.168.178.43'; gpsftp.UserName := 'pi'; gpsftp.Password := '****'; gpsftp.Port := 22; gpsftp.OnVerifyHostKey := onVerifyHostkey; gpsftp.Connect; end;
Delphi-Quellcode:
Grüße
function TForm1.onVerifyHostKey(const host: PAnsiChar; const port: Integer;
const fingerprint: PAnsiChar; const verificationstatus: Integer; var storehostkey: Boolean): Boolean; begin storeHostKey := true; end; Klaus |
AW: Delphi 10.4 - Indy und SFTP
Danke - teste ich morgen aus!
Gruß Hans |
AW: Delphi 10.4 - Indy und SFTP
Moin,
hat lange gedauert - aber jetzt habe ich es ausprobiert - und ich bekomme ein Connect hin. Allerdings stoße ich gleich auf das nächster Problem das ich nicht verstehe (was allerdings auch an meinen beschränkten Fähigkeiten liegt): In der Demo gibt es ein StringGrid. Sobald es zum Connect kommt wird dieses Grid mit Dateinamen auf dem Server gefüllt. An der entsprechende Stelle in Souce steht aber nur:
Delphi-Quellcode:
Die ersten Zeilen sind ja nur "Beiwerk", passieren tut es in "TGPuttySFTPClient1.ListDir('');".
begin
sgRemoteFiles.RowCount:=1; sgRemoteFiles.ColCount:=3; sgRemoteFiles.ColWidths[0]:=480; sgRemoteFiles.ColWidths[1]:=300; sgRemoteFiles.ColWidths[2]:=150; sgRemoteFiles.Cells[0,0]:='Name'; sgRemoteFiles.Cells[1,0]:='Timestamp'; sgRemoteFiles.Cells[2,0]:='Size'; TGPuttySFTPClient1.ListDir(''); end; Aber wie kommt der Inhalt des Servers in das StringGrid ? Ich finde da nix wo das passiert :-( Kann mir da jemand auf die Sprüge helfen ? Danke Hans |
AW: Delphi 10.4 - Indy und SFTP
Delphi-Quellcode:
Vermutlich ist das ein Ereignis, das irgendwo ausgelöst wird, so genau habe ich nicht in den Code geschaut.
function TVCLSFTPClientComponentDemoForm.TGPuttySFTPClient1SFTPListing(Sender: TObject; const Items: TSFTPItems): Boolean;
|
AW: Delphi 10.4 - Indy und SFTP
Das hatte ich gesehen - und in der Items sind auch die entsprechenden Dateinamen. Die ganze Procedure sieht so aus:
Delphi-Quellcode:
Da wird das StringGrid gefüllt - nur woher hat die Produre die Items ?
function TVCLSFTPClientComponentDemoForm.TGPuttySFTPClient1SFTPListing(Sender: TObject; const Items: TSFTPItems): Boolean;
var StartRow,i:Integer; begin StartRow:=sgRemoteFiles.RowCount; sgRemoteFiles.RowCount:=StartRow+Length(Items); for i:=0 to Length(Items)-1 do begin sgRemoteFiles.Cells[0,StartRow+i]:=Items[i].filename; sgRemoteFiles.Cells[1,StartRow+i]:=DateTimeToStr(TTimeZone.Local.ToLocalTime(UnixToDateTime(Items[i].attrs.mtime))); if Items[i].attrs.permissions and $F000 = $4000 then sgRemoteFiles.Cells[2,StartRow+i]:='<dir>' else sgRemoteFiles.Cells[2,StartRow+i]:=IntToStr(Items[i].attrs.size); end; Result:=true; end; Gruss Hans |
AW: Delphi 10.4 - Indy und SFTP
Die Items bekommt die Funktion direkt vom
Delphi-Quellcode:
Objekt übergeben:
TTGPuttySFTPClient
Code:
siehe
OnSFTPListing = TGPuttySFTPClient1SFTPListing
![]() |
AW: Delphi 10.4 - Indy und SFTP
Moment - das ist OOP ... etwas was ich in den letzten 10 Jahren schon nicht verstanden habe :(
wenn ich also
Delphi-Quellcode:
aufrufe, dann wird automatisch der Inhalt des Directoerys übergeben .. nur ich verstehe nicht wohin bzw. wie ich dann darauf zugreife, denn in der procedure
TGPuttySFTPClient1.ListDir('');
Delphi-Quellcode:
sind die Items ja schon drin :-(
function TGPuttySFTPClient1SFTPListing(Sender: TObject; const Items: TSFTPItems): Boolean;
Wie funktioniert das denn ? Gruss Hans |
AW: Delphi 10.4 - Indy und SFTP
Der Ablauf:
Delphi-Quellcode:
Sprich du gibst der Komponente in der Eigenschaft OnSFTPListing eine Referenz auf deine Prozedur TGPuttySFTPClient1SFTPListing. Die Komponente ruft dann deine Prozedur auf, wenn sie das Listing erhalten hat. Hintergrund ist vermutlich, dass das asynchron funktioniert, sprich ListDir schon wieder beendet ist, wenn das Ergebnis ankommt und deine Ereignisprozedur aufgerufen wird.
procedure ListDir;
begin ... if Assigned(FOnSFTPListing) then FOnSFTPListing(Self, Items); end; |
AW: Delphi 10.4 - Indy und SFTP
Da ich sehe, dass du online bist, mache ich mal eine neue Antwort:
Stell dir das einfach so vor... Du gehst zur Hotelrezeption (die SFTP-Komponente) und lässt dir ein Taxi rufen. Dort hinterlegst du deine Telefonnummer (deine Ereignisfunktion TGPuttySFTPClient1SFTPListing), damit die Rezeption (die SFTP-Komponente) dir Bescheid sagen kann, wenn das Taxi da ist (das Listing abgerufen ist). Wenn das Taxi dann ankommt (das Listing da ist), ruft dich die Rezeption (die SFTP-Komponente) unter der hinterlegten Telefonnummer (der Ereignisfunktion) zurück und nennt dir dabei zur Identifikation das Kennzeichen des Taxis (der an die Funktion übergebene Inhalt des Listings). |
AW: Delphi 10.4 - Indy und SFTP
Moin Sebastian,
vielen Dnak für die Infos und deine Mühe !!! ... ich versuche das morgen mal in Source umzusetzen und zu kucken ob ich das hinbekomme. Gruss Hans |
AW: Delphi 10.4 - Indy und SFTP
Moin,
sorry das ich jetzt erst weitermache - aber die letzten Tage habe ich es nicht geschafft. Nur damit ich das richtig sehe ... im Source der Demo finde ich folgende Stelle:
Delphi-Quellcode:
Hier wird also einmal das Objekt "PSFTP" erzeugt und für die verschiedenen Ereignisse (OnListing / OnMessage / OnProgress) jeweils definiert welche Procedure dann aufgerufen wird ?
procedure TVCLSFTPClientDemoForm.FormCreate(Sender: TObject);
begin PSFTP:=TTGPuttySFTP.Create(true); PSFTP.OnListing:=ListingCallback; PSFTP.OnMessage:=MessageCallback; PSFTP.OnProgress:=ProgressCallback; PSFTP.OnGetInput:=GetInputCallback; PSFTP.OnVerifyHostKey:=VerifyHostKeyCallback; end; Sorry wenn ich so doff Frage aber das ist nicht mehr dieses "von-oben-nach-unten"-Programmieren das ich aus den 80ern kenne :-) Gruss Hans |
AW: Delphi 10.4 - Indy und SFTP
Liste der Anhänge anzeigen (Anzahl: 1)
Soo .. und trotzdem verwirrt mich alles - es passiert folgendes: Ich habe jetzt ein Programm das sich kompilieren lässt und dann den Connect sauber hinbekommt.
Delphi-Quellcode:
Und dann passiert was ganz komisches:
unit SFTPUnit;
interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, tgputtylib, tgputtysftp, Vcl.Grids; type TForm1 = class(TForm) Button1: TButton; InfoLB: TListBox; RemoteFilesSG: TStringGrid; procedure Button1Click(Sender: TObject); procedure FormCreate(Sender: TObject); private { Private-Deklarationen } TestSFTP :TTGPuttySFTP; function onVerifyHostKey(const host:PAnsiChar;const port:Integer; const fingerprint:PAnsiChar; const verificationstatus:Integer; var storehostkey:Boolean): Boolean; procedure Verbinden; procedure Trennen; procedure DatenAbruf; public { Public-Deklarationen } end; var Form1: TForm1; implementation {$R *.dfm} const Username = 'name'; Passwort = 'passwort'; Host = 'ssh.strato.de'; Port = 22; function TForm1.onVerifyHostKey(const host: PAnsiChar; const port: Integer; const fingerprint: PAnsiChar; const verificationstatus: Integer; var storehostkey: Boolean): Boolean; (* Verhindert einen Abbruch bei Connect *) begin storeHostKey := true; end; procedure TForm1.Verbinden; begin TestSFTP.HostName := Host; TestSFTP.UserName := UserName; TestSFTP.Password := Passwort; TestSFTP.Port := Port; TestSFTP.OnVerifyHostKey := onVerifyHostkey; try TestSFTP.Connect; except on E:Exception do WriteLn('EXCEPTION: ',E.Message); end; if TestSFTP.Connected then Form1.InfoLB.Items.Insert(0, 'Angeblich verbunden :-)'); end; procedure TForm1.Trennen; begin TestSFTP.Disconnect; end; procedure TForm1.DatenAbruf; begin RemoteFilesSG.RowCount:=1; RemoteFilesSG.ColCount:=3; RemoteFilesSG.ColWidths[0]:=480; RemoteFilesSG.ColWidths[1]:=300; RemoteFilesSG.ColWidths[2]:=150; RemoteFilesSG.Cells[0,0]:='Name'; RemoteFilesSG.Cells[1,0]:='Timestamp'; RemoteFilesSG.Cells[2,0]:='Size'; TestSFTP.ListDir(''); if RemoteFilesSG.RowCount>1 then RemoteFilesSG.FixedRows:=1; RemoteFilesSG.FixedCols:=0; end; procedure TForm1.FormCreate(Sender: TObject); begin TestSFTP := TTGPuttySFTP.Create(true); end; procedure TForm1.Button1Click(Sender: TObject); begin if Button1.Caption = 'Start' then begin Verbinden; Button1.Caption := 'Ende'; end else begin Trennen; Application.Terminate; end; end; end. Ich füge im Interface unter
Delphi-Quellcode:
die Funktion für das Listing ein - da wird dann im Compiler nur die Function unterschrieben - klar, ungenügende Forward-Deklaration - aber dann.
type
TForm1 = class(TForm) Button1: TButton; InfoLB: TListBox; RemoteFilesSG: TStringGrid; procedure Button1Click(Sender: TObject); procedure FormCreate(Sender: TObject); [B] function TGPuttySFTPClient1SFTPListing(Sender: TObject; const Items: TSFTPItems): Boolean;[/B] private Dann füge ich im implementations-Teil die Funktion selber ein:
Delphi-Quellcode:
Da werden dann aber - neben Fehlern in der procedure selber - plötzlich auch im Interface Button1Click und FormCreate unterstrichen. Und auch die Proceduren Verbinden, Trennen und DatenAbruf werden als unbekannt markiert !
function TForm1.TGPuttySFTPClient1SFTPListing(Sender: TObject; const Items: TSFTPItems): Boolean;
var StartRow,i:Integer; begin StartRow:=RemoteFilesSG.RowCount; RemoteFilesSG.RowCount:=StartRow+Length(Items); for i:=0 to Length(Items)-1 do begin RemoteFilesSG.Cells[0,StartRow+i]:=Items[i].filename; RemoteFilesSG.Cells[1,StartRow+i]:=DateTimeToStr(TTimeZone.Local.ToLocalTime(UnixToDateTime(Items[i].attrs.mtime))); if Items[i].attrs.permissions and $F000 = $4000 then sgRemoteFiles.Cells[2,StartRow+i]:='<dir>' else sgRemoteFiles.Cells[2,StartRow+i]:=IntToStr(Items[i].attrs.size); end; Result:=true; end; Und nun stehe ich da mit meiner Weißheit und verzweifle nur noch. Vielleicht mag sich das jemand mal ansehen der mehr davon versteht - ich weiß nicht wieso das passiert. Ich hab mal den ganzen Ordner als ZIP angehängt. Gruss Hans |
AW: Delphi 10.4 - Indy und SFTP
Moin,
nur noch einmal zu der function TForm1.TGPuttySFTPClient1SFTPListing(Sender: TObject; const Items: TSFTPItems): Boolean; wenn ich da den Code rausnehme und nur noch
Delphi-Quellcode:
stehen lasse dann verschwinden die ganzen Fehlermeldungen ?! :shock::shock::shock:
function TForm1.TGPuttySFTPClient1SFTPListing(Sender: TObject; const Items: TSFTPItems): Boolean;
var StartRow, i:Integer; begin Result:=true; end; Vielleicht kennt ja jemand dieses Verhalten. Gruss Hans |
AW: Delphi 10.4 - Indy und SFTP
Ich habe deine Antworten erst jetzt gesehen. Fällt dir wirklich nichts auf an deiner Einrückung (siehe Kommentar)?
Delphi-Quellcode:
Deshalb ist es äußerst schlechter Coding Style, wenn man das begin hinten an eine Zeile anhängt oder bei if..then in der gleichen Zeile weitermacht. Man übersieht es so viel zu leicht. Ein Befehl pro Zeile.
function TForm1.TGPuttySFTPClient1SFTPListing(Sender: TObject; const Items: TSFTPItems): Boolean;
var StartRow,i:Integer; begin StartRow:=RemoteFilesSG.RowCount; RemoteFilesSG.RowCount:=StartRow+Length(Items); for i:=0 to Length(Items)-1 do begin // <-- hier ist ein begin, aber wo ist das end? RemoteFilesSG.Cells[0,StartRow+i]:=Items[i].filename; RemoteFilesSG.Cells[1,StartRow+i]:=DateTimeToStr(TTimeZone.Local.ToLocalTime(UnixToDateTime(Items[i].attrs.mtime))); if Items[i].attrs.permissions and $F000 = $4000 then sgRemoteFiles.Cells[2,StartRow+i]:='<dir>' else sgRemoteFiles.Cells[2,StartRow+i]:=IntToStr(Items[i].attrs.size); end; Result:=true; end; Ja, ich habe gesehen, dass du das beim begin ansonsten auch so gemacht hast. ;-) |
Alle Zeitangaben in WEZ +1. Es ist jetzt 18:16 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz