Datei umbenennen: Name zu lang?



  • Ich habe es jetzt nochmal mit SHFILEOPSTRUCT und FO_RENAME versucht.
    Der Dateiname ist aber angeblich für die Aktion zu lang...hmm?

    Warum kann man den Namen dann per Hand ändern?

    CString strvon="C:\\ordnerx\\12345\\ein_langersehrlangertextmitvielen-lustigen-zeichendrindernichtumbenanntwerdenwillwarumauchimmernicht-ichbitteumhilfe-fruggle.doc";
    	CString to="C:\\ordnerx\\12345\\jetztmalmitRautezeichen-ein_langer##sehrlangertextmitvielen-lustigen-zeichendrindernichtumbenanntwerdenwillwarumauchimmernicht-ichbitteumhilfe-fruggle.doc";
    
    SHFILEOPSTRUCT foCopy; 
    
    foCopy.hwnd                  = NULL; 
    foCopy.wFunc                 = FO_RENAME; 
    foCopy.pFrom                 = strvon; 
    foCopy.pTo                   =to; 
    foCopy.fFlags                = FOF_NOCONFIRMATION
    foCopy.fAnyOperationsAborted = FALSE; 
    foCopy.hNameMappings         = NULL; 
    foCopy.lpszProgressTitle     = NULL;
    


  • Du solltest die Regeln für das benennen und die Länge von Namen beachten:
    http://msdn.microsoft.com/library/en-us/fileio/fs/naming_a_file.asp

    Die max. Länge liegt bei 259 Zeichen (plus NUL).

    Wenn Du längere Namen angeben willst, dann musst Du die Unicode-Variante verwenden und den "\?\" prefix voranstellen.

    Siehe den obigen Link.


  • Mod

    Jochen Kalmbach schrieb:

    Wenn Du längere Namen angeben willst, dann musst Du die Unicode-Variante verwenden und den "\?\" prefix voranstellen.

    Dann muss einema aber auch klar sein, dass alle Shell Funktionen tabu sind und man dann nur noch die Win32 API verwenden kann!



  • ich wuerde "_trename()" versuchen



  • Martin Richter schrieb:

    Jochen Kalmbach schrieb:

    Wenn Du längere Namen angeben willst, dann musst Du die Unicode-Variante verwenden und den "\?\" prefix voranstellen.

    Dann muss einema aber auch klar sein, dass alle Shell Funktionen tabu sind und man dann nur noch die Win32 API verwenden kann!

    Was meinst du mit Shell Funktionen sind tabu?
    Bis jetzt ist mir auch noch nicht klar was rename() zu _trename() nun
    genau unterscheided...Unicode-Variante?

    Und dann noch eine ganz peinliche Frage hinterher. Ich lasse mir von
    GetLastError den Rückgabewert anzeigen. Nun gibt es dafür ja eine entsprechende
    Umsetzung z.B. 5 bedeutet "kein Zugriff auf Datei".

    Wenn ich nun nachstehenden Code nehme um mir das letzte Ergebnis von
    GetLastError auswerten zu lassen, bezieht sich das Ergebnis nur auf
    meine Anwendung? Oder ermittel ich einfach nur den letzten Fehler
    den sich Windows gemerkt hat (egal welcher Anwendung)?

    LPVOID lpMsgBuf;
    if (!FormatMessage( 
        FORMAT_MESSAGE_ALLOCATE_BUFFER | 
        FORMAT_MESSAGE_FROM_SYSTEM | 
        FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL,
        GetLastError(),
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
        (LPTSTR) &lpMsgBuf,
        0,
        NULL ))
    {
       return;
    }
    
    MessageBox( (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION );
    LocalFree( lpMsgBuf );
    

    Danke für eure freundliche Unterstützung.



  • Fruggle schrieb:

    Wenn ich nun nachstehenden Code nehme um mir das letzte Ergebnis von
    GetLastError auswerten zu lassen, bezieht sich das Ergebnis nur auf
    meine Anwendung? Oder ermittel ich einfach nur den letzten Fehler
    den sich Windows gemerkt hat (egal welcher Anwendung)?

    Was steht denn in der Hilfe diesbezüglich?



  • So, MoveFileEx _trename und rename habe ich jetzt durch. Mit dem Ergebnis, dass
    bei extrem langen Dateipfaden oder Dateinamen nicht umbenannt wird.

    Mit dem Prefix "\?\" genau das gleiche Ergebnis...

    Jochen Kalmbach, hast du evtl. mal ein Beispiel für den von dir beschriebenen
    Lösungsweg? Ich bin jetzt mit einem Mix aus MFC und WinAPI zugange.


  • Mod

    Also CRT und Shell Funktionen kannst Du Haken! Die gehen alle nur bis MAX_PATH!
    @Mr Evil: Damit geht _trename auch nicht!

    Wichtig: Du hast die Infos nicht ganz gelesen!
    Du musst die Unicode Variante explizit verwenden: MoveFileExW bzw. MoveFileW!
    Sonst wird eben wieder eine Ansi/Unicode Konvertierung gemacht und diese ist beschränkt auf MAX_PATH!

    Win32 API pur mit Unicode ist der einzige Weg!



  • Aber sehe ich das richtig, dass man dann besser noch prüfen sollte, ob
    der neue Dateiname nicht evtl. zu lang wird? Dann hat man doch genau
    das gleiche Problem. GetLastError liefert dann ebenfalls Code 3 zurück
    ->ERROR_PATH_NOT_FOUND



  • Du *musst* die Unicode-Version der APIs verwenden!
    Also "MoveFileW"!
    Siehe auch Hilfe zu "MoveFile"...

    CStringW strvon="\\\\?\\C:\\ordnerx\\12345\\ein_langersehrlangertextmitmax255Zeichen";
    CStringW to="\\\\?\\C:\\ordnerx\\12345\\nochmalseinlangerTextMitMax255Zeichen";
    MoveFileW(from, to);
    

  • Mod

    Ich hatte gedacht ich hätte mich klar ausgedrückt!



  • Der Threadersteller meinte ja das er die Dateien per Explorer selbst erstellen kann. Und der Explorer benutzt ja die Shell Funktionen. Verwundert mich irgendwie.



  • Mit \\\?\\ und MoveFileEx() geht es jetzt offenbar. Allerdings auch
    nur mit 210 Zeichen im Dateinamen + Dateiendung

    Danke für eure Hilfe.


  • Mod

    MAX_PATH ist im Platform SDK auf 260 festegelegt. Das ist das Limit für alle Shell-Funktionen! Aber das wurde ja schon geschrieben, also nur noch mal zur Erinnerung.


Anmelden zum Antworten