Einzelnen Beitrag anzeigen

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