Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   Delphi Delphi 10.4 - Indy und SFTP (https://www.delphipraxis.net/208298-delphi-10-4-indy-und-sftp.html)

H.Bothur 11. Jul 2021 16:03

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

Papaschlumpf73 11. Jul 2021 16:06

AW: Delphi 10.4 - Indy und SFTP
 
Nein, geht leider nicht.

Klaus01 11. Jul 2021 20:19

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

albertMichel 12. Jul 2021 12:35

AW: Delphi 10.4 - Indy und SFTP
 
ICS - Internet Component Suite
http://www.overbyte.be/
http://wiki.overbyte.eu/wiki/index.php/Main_Page
Das besondere, es wird stetig weiterentwickelt.
Und es funktioniert.
Gruß
Albert

Klaus01 12. Jul 2021 13:10

AW: Delphi 10.4 - Indy und SFTP
 
.. hat meines Wissen keine SFTP Bibliothek.
Grüße
Klaus

mjustin 12. Jul 2021 14:59

AW: Delphi 10.4 - Indy und SFTP
 
Zitat:

Zitat von H.Bothur (Beitrag 1492178)
ich bin etwas verunsichert ... geht mit Indy denn auch SFTP oder nicht ?

Nur zur Sicherheit: SFTP oder FTPS? Das sind zwei unterschiedliche Protokolle, FTPS ist FTP über TLS/SSL, SFTP basiert auf SSH (Secure Shell) und ein ganz anderes Protokoll als FTP.

TurboMagic 12. Jul 2021 15:13

AW: Delphi 10.4 - Indy und SFTP
 
Bezüglich ICS könnte man das ja mal hier anfragen:

https://en.delphipraxis.net/forum/37...mponent-suite/

Harry Stahl 13. Jul 2021 16:57

AW: Delphi 10.4 - Indy und SFTP
 
Ich verwende das hier für SFTP (also FTP over ssh) : https://github.com/superflexible/TGPuttyLib

Da sind auch einfache und schnell nachvollziehbare Beispiele dabei.

H.Bothur 19. Jan 2023 12:49

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:
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.
Allerdings bekomme ich bereits beim create eine Exceprion der Klasse EEXternalException mit der Medlung "Externe Exception C06D007E"
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

stalkingwolf 19. Jan 2023 15:43

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.

Neumann 19. Jan 2023 19:29

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.

Klaus01 20. Jan 2023 06:20

AW: Delphi 10.4 - Indy und SFTP
 
.. möchte hier noch SecureBridge von DevArt erwähnen.
Kostet etwas - kommt ohne externe DLLs/Exen aus.
Sehr zuverlässig.

Grüße
Klaus

H.Bothur 20. Jan 2023 15:15

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:
  tgputtysftp in '..\tgputtysftp.pas',
  tgputtylib in '..\tgputtylib.pas';
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 ?

Zweitens: Im DemoProgramm wird die Variable (? Ist es das überhaupt) in dem private-Block vereinbart:

Delphi-Quellcode:
  private
    { Private declarations }
    PSFTP:TTGPuttySFTP;
Wenn ich das genauso mache und die TestSFTP Deklaration aus der var-Deklaration rausnehme und in den private-Block packe
Delphi-Quellcode:
type
  TForm1 = class(TForm)
    ListBox1: TListBox;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
    TestSFTP :TTGPuttySFTP;
  public
    { Public-Deklarationen }
  end;
dann wird beim compilieren der erste Ausdruck
Delphi-Quellcode:
  TestSFTP := TTGPuttySFTP.Create(true);
gleich als "undeklarierter Bezeichner 'TestSFTP '" markiert und das Programm lässt sich nicht kompilieren.

Nur ... warum - was mache ich anders als das Demoprogramm ??

Gruss und Danke !
Hans

Klaus01 20. Jan 2023 15:20

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

H.Bothur 20. Jan 2023 15:26

AW: Delphi 10.4 - Indy und SFTP
 
Zitat:

Zitat von Klaus01 (Beitrag 1517652)
.. 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.

Danke - da habe ich mal wieder was dazugelernt ... jetzt kann ich das Programm wieder kompilieren und starten .. bekomme aber immer noch die Exception beim
Delphi-Quellcode:
TestSFTP := TTGPuttySFTP.Create(true);
:-(

Hat jemand eine Idee dazu ?
Hans

TurboMagic 20. Jan 2023 16:23

AW: Delphi 10.4 - Indy und SFTP
 
Zitat:

Zitat von Klaus01 (Beitrag 1492183)
.. 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

Kommerziell gibt's auch noch: Clever Internet Suite. Lt. GetIt Trial Eintrag kann es SFTP (SSH).

Grüße
TurboMagic

Klaus01 20. Jan 2023 17:35

AW: Delphi 10.4 - Indy und SFTP
 
.. ich bekomme da keinerlei Fehlermeldung beim Create.

Delphi-Quellcode:
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;
Build 19 - 06 Mar 2022

Grüße
Klaus

H.Bothur 20. Jan 2023 18:52

AW: Delphi 10.4 - Indy und SFTP
 
Zitat:

Zitat von Klaus01 (Beitrag 1517660)
.. ich bekomme da keinerlei Fehlermeldung beim Create.

Build 19 - 06 Mar 2022

Grüße
Klaus

Und deswegen nehme ich an das ich bei den Einstellungen / Directorys usw. einen Fehler mache. Nur welchen ?
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:
procedure tggetstructsizes(const Pulongsize,Pnamesize,Pattrsize,Pnamessize:PInteger); cdecl; external tgputtydll {$ifdef HASDELAYED}delayed{$endif};
Nur leider sind das für mich endgültig bömische Dörfer ... sagt das jemandem was ??

Gruss
Hans

Klaus01 21. Jan 2023 08:46

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:
program Project1;
uses
  Vcl.Forms,
  Unit1 in 'Unit1.pas' {Form1},
  tgputtylib in 'tgputtylib.pas',
  tgputtysftp in 'tgputtysftp.pas',
  tgputtysftpclient in 'tgputtysftpclient.pas';
In der From Unit:
Delphi-Quellcode:
implementation
uses
  tgputtylib, tgputtysftp;
{$R *.dfm}
Mehr habe ich nicht geändert.

Grüße
Klaus

H.Bothur 21. Jan 2023 12:38

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:
function tggetlibrarycontextsize:Integer; cdecl; external tgputtydll {$ifdef HASDELAYED}delayed{$endif};
Sagt das jemandem was ??

Hans

Klaus01 21. Jan 2023 15:12

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:
//{$ifndef FPC}
//{$ifdef CONDITIONALEXPRESSIONS}
//{$if CompilerVersion >= 21.0}
//{$define HASDELAYED}
//{$ifend}
//{$endif}
//{$endif}
Welche Delphi Version benutzt denn Du?

Grüße
Klaus

mytbo 22. Jan 2023 00:20

AW: Delphi 10.4 - Indy und SFTP
 
Die Allzweckwaffe ist Curl. Das Programm curl.exe ist Bestandteil aktueller Windows Versionen. Links: GitHub, Download, Manual, libcurl C API und libcurl C Beispiele. Zum schnellen Einstieg schreibst du mit Hilfe der Beispiele aus dem Manual einfache Batch-Dateien zum Testen deiner Fälle. Wenn alles wie gewünscht funktioniert, lade das benötigte Package aus dem Download und lege die libcurl.dll in dein Programmverzeichnis. Eine Kapselung für diese DLL findest du in der mORMot Unit mormot.lib.curl. Die mORMot Bibliothek muss nicht installiert werden. Den aktuellen Commit und die static binaries aus dem letzten Tag herunterladen. In Delphi die entsprechenden Bibliotheks- und Suchpfade setzen. Beim Erstellen hilft dieses Muster:
Code:
// 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;
Für viele Anwendungsfälle findest du eine Vorlage in den libcurl C Beispielen. Das folgende Delphi Beispiel zeigt die Umsetzung für einen FTP/SFTP Download:
Delphi-Quellcode:
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;
Disclaimer: Ungetestet!

Ein Beispiel zum Studieren ist auch die Klasse TCurlHttp aus der Unit mormot.net.client.

Bis bald...
Thomas

H.Bothur 22. Jan 2023 15:09

AW: Delphi 10.4 - Indy und SFTP
 
Moin Klaus,

Zitat:

Zitat von Klaus01 (Beitrag 1517690)
.. vielleicht magst Du ja mal (testhalber) diese Einträge in der tgputtylib.pas
kommentieren ( so das sie nicht mehr wirksam sind):

Nachdem ich die Einträge auskommentiert habe kann ich das Programm starten und bekomme erst beim Connect einen Fehler:

"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:

Welche Delphi Version benutzt denn Du?
Delphi 10.4 Community Edition

Gruss
Hans

Klaus01 22. Jan 2023 15:27

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:
function TForm1.onVerifyHostKey(const host: PAnsiChar; const port: Integer;
  const fingerprint: PAnsiChar; const verificationstatus: Integer;
  var storehostkey: Boolean): Boolean;
begin
  storeHostKey := true;
end;
Grüße
Klaus

H.Bothur 22. Jan 2023 20:15

AW: Delphi 10.4 - Indy und SFTP
 
Danke - teste ich morgen aus!

Gruß
Hans

H.Bothur 20. Apr 2023 10:43

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:
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;
Die ersten Zeilen sind ja nur "Beiwerk", passieren tut es in "TGPuttySFTPClient1.ListDir('');".

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

DeddyH 20. Apr 2023 11:01

AW: Delphi 10.4 - Indy und SFTP
 
Delphi-Quellcode:
function TVCLSFTPClientComponentDemoForm.TGPuttySFTPClient1SFTPListing(Sender: TObject; const Items: TSFTPItems): Boolean;
Vermutlich ist das ein Ereignis, das irgendwo ausgelöst wird, so genau habe ich nicht in den Code geschaut.

H.Bothur 20. Apr 2023 11:36

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:
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;
Da wird das StringGrid gefüllt - nur woher hat die Produre die Items ?

Gruss
Hans

shebang 20. Apr 2023 12:17

AW: Delphi 10.4 - Indy und SFTP
 
Die Items bekommt die Funktion direkt vom
Delphi-Quellcode:
TTGPuttySFTPClient
Objekt übergeben:
Code:
OnSFTPListing = TGPuttySFTPClient1SFTPListing
siehe DelphiVCLComponentDemo/VCLSFTPClientComponentMainForm.dfm#L285

H.Bothur 20. Apr 2023 17:32

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:
TGPuttySFTPClient1.ListDir('');
aufrufe, dann wird automatisch der Inhalt des Directoerys übergeben .. nur ich verstehe nicht wohin bzw. wie ich dann darauf zugreife, denn in der procedure

Delphi-Quellcode:
function TGPuttySFTPClient1SFTPListing(Sender: TObject; const Items: TSFTPItems): Boolean;
sind die Items ja schon drin :-(

Wie funktioniert das denn ?

Gruss
Hans

jaenicke 20. Apr 2023 20:36

AW: Delphi 10.4 - Indy und SFTP
 
Der Ablauf:
Delphi-Quellcode:
procedure ListDir;
begin
  ...
  if Assigned(FOnSFTPListing) then
    FOnSFTPListing(Self, Items);
end;
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.

jaenicke 20. Apr 2023 21:47

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).

H.Bothur 21. Apr 2023 16:08

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

H.Bothur 27. Apr 2023 16:14

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:
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;
Hier wird also einmal das Objekt "PSFTP" erzeugt und für die verschiedenen Ereignisse (OnListing / OnMessage / OnProgress) jeweils definiert welche Procedure dann aufgerufen wird ?

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

H.Bothur 27. Apr 2023 17:11

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:
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.
Und dann passiert was ganz komisches:

Ich füge im Interface unter
Delphi-Quellcode:
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
die Funktion für das Listing ein - da wird dann im Compiler nur die Function unterschrieben - klar, ungenügende Forward-Deklaration - aber dann.


Dann füge ich im implementations-Teil die Funktion selber ein:

Delphi-Quellcode:
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;
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 !

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

H.Bothur 28. Apr 2023 18:09

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:
function TForm1.TGPuttySFTPClient1SFTPListing(Sender: TObject; const Items: TSFTPItems): Boolean;
var StartRow,
    i:Integer;
begin
  Result:=true;
end;
stehen lasse dann verschwinden die ganzen Fehlermeldungen ?! :shock::shock::shock:
Vielleicht kennt ja jemand dieses Verhalten.

Gruss
Hans

jaenicke 2. Mai 2023 17:53

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:
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;
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.

Ja, ich habe gesehen, dass du das beim begin ansonsten auch so gemacht hast. ;-)


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:54 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz