AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

DragDrop mit Netzwerk-Path > 260 ?

Ein Thema von MicMic · begonnen am 24. Feb 2021 · letzter Beitrag vom 25. Feb 2021
Antwort Antwort
MicMic

Registriert seit: 26. Mai 2018
296 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#1

DragDrop mit Netzwerk-Path > 260 ?

  Alt 24. Feb 2021, 17:13
Hallo,
ich probiere gerade mit unten stehender Funktion herum. Es gehören hier noch mehrere Funktionen dazu (für das Drag&Drop) aber die Sache hängt hier irgendwo bei "PathShellFolder.ParseDisplayName" (ohne Fehler, nur gebe ich irgendwie falsche Infos weiter). Also lokal gehen Ordnerlängen (Zeichen) + Dateiname größer als 260. Also das Drag&Drop von einer ListBox auf den Desktop. Windows kopiert die Datei. Ein Netzwerk-Pfad geht auch (\\RECHNER\Freigabe\Ordner\Dateiname.txt) aber wenn dieser größer als 260 ist, dann wiederum nicht. Also nur Lokal geht das (ohne "\\?\C:\..."). Eigentlich findet man im Netz solche Routinen ohne "CreateBindCtx". Also bei den 2. Parameter von "ParseDisplayName" oder "BindToObject" ist in den Beispielen "Nil" angegeben. Mit "Nil" wird schon beim ersten "Desktop.ParseDisplayName" abgebrochen. Deshalb habe ich mal ein wenig mit diesem CreateBindCtx herumprobiert. Der Dateiname kommt bei Windows an (nach dem Drag&Drop auf den Desktop) aber mit der Fehlermeldung "Element wurde nicht gefunden (Dateinameinfo mit 0 Byte). Das mit dem ganzen "CreateBindCtx" ist mir sowieso zu hoch aber habe das halt mal ausprobiert. So geht jedenfalls noch das Drag&Drop nur findet Windows die Datei nicht (wenn Ordner/Dateilänge größer als 260 Zeichen). Achja, den Rechnernamen und so weiter mit "\\?\UNC\RECHNER..." geht auch nicht. Wenn dann überhaupt nur mit "\\RECNER..." aber halt nur unter 260 Zeichen. Kennt sich da jemand aus?

Info: Der Explorer selbst mach ein DragDrop (aus so einem >260 Netzwerk-Pfad) auf den Desktop ohne Fehler. Bei meiner Routine fehlt da irgendwas, denn wie gesagt, Windows meldet "Element nicht gefunden" aber Dateiname selbst kommt an (steht in dem Fehler-Info-Fenster).

Delphi-Quellcode:
function TListBox.GetFileListDataObject(APath: string; AFileNames: TStrings): IDataObject;
Type
  PPItemIDList = ^PItemIDList;

var
  Desktop: IShellFolder;
  Eaten, Attr: ULONG;
  i: Integer;
  PathIDList: PItemIDList;
  PathShellFolder: IShellFolder;
  IDLists: PPItemIDList;
  IDListsSize: Integer;
  Posi: PPItemIDList;
  pbc : IBindCtx;
  w32fd : TWin32FindDataW;
  ifs : TFileSystemBindData;
  r : HResult;
  FDO : TWin32FindDataW;
  ShellFolder: IShellFolder;
  BindContext: IBindCtx;
begin

  PathConvertShort(APath);

  if Pos ('UNC',APath) > 0 Then
  Begin
    apath := '\\'+copy(apath,5);
  End;

  Result := nil;
  if AFileNames.Count < 1 then Exit;

  R := SHGetDesktopFolder(Desktop);
  if R = S_OK then
  Begin
    Attr := 0;

    ZeroMemory(@FDO, Sizeof(TWin32FindDataW));
    FDO.DWFileAttributes := FILE_ATTRIBUTE_DIRECTORY;;
    StrCopy(FDO.cFileName,PWideChar(APath));
    Ifs := TFileSystemBindData.Create;
    ifs.fw32fd := FDO;

    If CreateBindCtx(0,Pbc) = S_OK Then
    Begin
      If Pbc.RegisterObjectParam(STR_FILE_SYS_BIND_DATA,Ifs) = S_OK Then
      Begin
        R := Desktop.ParseDisplayName(0,Pointer(Pbc),PWideChar(APath),Eaten,PathIDList,Attr);
        If R = S_OK Then
        Begin
          R := Desktop.BindToObject(PathIDList, Pointer(pbc), IShellFolder, PathShellFolder);
          If R = S_OK Then
          Begin
            IDListsSize := SizeOf(PItemIDList) * AFileNames.Count;
            GetMem(IDLists, IDListsSize);
            ZeroMemory(IDLists, IDListsSize);
            Posi := IDLists;
            for i := 0 to AFileNames.Count - 1 do
            begin
              Attr := 0; //FILE_ATTRIBUTE_NORMAL;;
              ZeroMemory(@FDO, Sizeof(TWin32FindDataW));
              FDO.DWFileAttributes := 0; //FILE_ATTRIBUTE_NORMAL;
              StrCopy(FDO.cFileName,PWideChar(AFileNames[i]));
              Ifs := TFileSystemBindData.Create;
              Ifs.fw32fd := FDO;
              CreateBindCtx(0, BindContext);
              BindContext.RegisterObjectParam(STR_FILE_SYS_BIND_DATA, IFs);
              R := PathShellFolder.ParseDisplayName(0, Pointer(BindContext), PWideChar(AFileNames[i]), Eaten, Posi^, Attr);
              if R = S_OK then Inc(Posi) else
              begin
                f.caption := 'PathShellFolder.ParseDisplayName';
                PathShellFolder := nil;
                CoTaskMemFree(PathIDList);
                Desktop := Nil;
                Result := Nil;
                Exit;
              end;
            end;
            R := PathShellFolder.GetUIObjectOf(0, AFileNames.Count, IDLists^, IDataObject, nil, Result);
            if R = S_OK Then
            Begin
              Posi := IDLists;
              for i := 0 to AFileNames.Count - 1 do
              begin
                if Assigned(Posi^) then CoTaskMemFree(Posi^);
                Inc(Posi);
              end;
              FreeMem(IDLists);
            End Else
            Begin
              PathShellFolder := nil;
              Desktop := Nil;
              CoTaskMemFree(PathIDList);
              Result := Nil;
              Exit;
            End;
          End Else
          Begin
            f.caption := 'BindToObject';
            CoTaskMemFree(PathIDList);
            Result := Nil;
          End;
        End Else
        Begin
          f.caption := 'Desktop.ParseDisplayName';
          Desktop := Nil;
          Result := Nil;
        End;
      End Else
      Begin
        f.caption := 'RegisterObjectParam';
        Desktop := Nil;
        Result := Nil;
      End;
    End Else
    Begin
      f.caption := 'CreateBindCtx';
      Desktop := Nil;
      Result := Nil;
    End;
  end Else Result := Nil;
end;
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.048 Beiträge
 
Delphi 12 Athens
 
#2

AW: DragDrop mit Netzwerk-Path > 260 ?

  Alt 24. Feb 2021, 17:26
Erstmal MAX_PATH mit 260 bedeuted eigentlich "Pfad" maximal 256 (1 Byte Längenangabe) zuzüglich dem Laufwerk ("C:\" also 3) und inkl. einer #0.

Lokal beim "\\?\server\freigabe" die 256 plus diese Länge,
aber wenn die Freigabe aufdem Server in einem Unterverzeichnis, dann womöglich auch noch abzüglich diesem Teil vom Zielpfad.

Bei UNC-Pfaden ist "oftmals" dieses Limmit schon deaktivert/umgangen

und seit 'ner kurzen Weile kann man für viele APIs dieses MAX_PATH-Limit komplett deaktivieren, ABER
* dies Funktion muß einmal im Windows
* und auch nochmal im Programm
aktiviert werden.
https://docs.microsoft.com/en-us/win...ath-limitation


ABER wenn jemand mit festen Speichergrößen arbeitet, dann hilft da absolut nichts ... wenn nicht mehr rein passt, dann passt nicht mehr rein.
Delphi-Quellcode:
type
  _WIN32_FIND_DATAW = record // TWin32FindDataW
    ..
    cFileName: array[0..MAX_PATH - 1] of WideChar;
  end;

var
  FDO : TWin32FindDataW;
Du brauchst also eine Lösung ohne TWin32FindData.
Ich würde etwas mit MSDN-Library durchsuchenIDropSource empfehlen.

Wir/Ich hatte keine Lust alles selbst zu machen, drum verwenden wir aktuell die Drag&Drop-Componenten von Melander.
Oder schau mal hier https://edn.embarcadero.com/article/26545
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.

Geändert von himitsu (24. Feb 2021 um 17:38 Uhr)
  Mit Zitat antworten Zitat
MicMic

Registriert seit: 26. Mai 2018
296 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#3

AW: DragDrop mit Netzwerk-Path > 260 ?

  Alt 25. Feb 2021, 14:01
MAX_PATH kenne ich und ja +#0 +c:\ etc. ... ich teste jedenfalls immer gleich mit größeren Ordnerlängen mit vielen Unterverzeichnissen.
Aber das MAX_PATH in "_WIN32_FIND_DATAW" steckt... auf diese Idee bin ich gar nicht gekommen
Logisch das dann am Ende eine Datei nicht gefunden wird, wenn der Ordnerpfad abgeschnitten wird.
Danke für die Info dazu. Hab ja gleich Panik bekommen, wegen meiner FindFirstFile Routine. Aber das geht und ein Dateiname selbst (so laut dem Explorer) darf hier nicht 500, 1000, 2000... Zeichen lang sein. Also hier passt dann "_WIN32_FIND_DATAW" (cFileName).

IDropSource nutze ich ja und die gezeigte Routine brauche ich ja wegen "DoDragDrop" bzw. ich brauche ein "IDataObject" dazu, was die Routine ja zurück liefert. Aber halt mit MAX_PATH wie ich jetzt gelernt habe Ich habe inzwischen was ohne FindData gefunden aber das geht genauso, sprich ein lokaler langer Pfad funktioniert aber ein langer Netzwerk-Pfad dann leider nicht. Netzwerkpfade nur, wenn unter MAX_PATH. Hab die Unit mal als Anhang hier dabei. Kurz mal drüber geschaut um sie evtl. anzupassen aber viel verstehe ich da noch nicht.

Eine ganze Drag&Drop-Komponente will ich eigentlich nicht installieren. Alles was ich nutze, verwende (meist Beispiele aus dem Netz zu einem Problem) will ich am Ende halbwegs verstehen können/lernen und für meine Bedürfnisse anpassen. Also mich nicht auf Komponenten verlassen, wo man sogar manchmal nur Teile nutzt und Source in seinem Projekt hat, diesen man gar nicht nutzt. Habe aber kurz mal reingeschaut. Wie so oft, nicht gleich übersichtlich. Ich probiere mal ein wenig weiter...
Angehängte Dateien
Dateityp: pas Unit7.pas (9,0 KB, 3x aufgerufen)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.048 Beiträge
 
Delphi 12 Athens
 
#4

AW: DragDrop mit Netzwerk-Path > 260 ?

  Alt 25. Feb 2021, 14:34
Beim FindFirstFile steht dort ja nur der Dateiname drin und nicht der komplette Pfad, drum passt dann mehr. (außer der Dateiname selbst ist auch überlang)
Und kann man auf die Verzeichnisse auch mit relativen Pfaden zugreifen.

Wir hatten anfangs nur Eigenes drin, aber es wurde mit der Zeit immer mehr und dann hatte ich keine Lust mehr für Alles jeden Scheiß selbst bauen zu müssen.
Drag&Drop von Explorer oder Thinderbird ist einfach, bei Outlook ging es dann irgendwann nur noch über die Interfaces und dann noch aus dem Programm zu Anderen ..... irgendwann wird es zuviel und man würde die Zeit lieber in was Anderes stecken.
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.

Geändert von himitsu (25. Feb 2021 um 14:37 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:29 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