Feedback

C# - Kurze 8.3 Pfade (Short Path) mit C#

Veröffentlicht von am 4/20/2010
(2 Bewertungen)
Eigentlich gehören kurze Pfade der Vergangenheit an. Doch einige Kommandozeilentools oder auch um die maximale Pfadlänge für Parameter nicht zu überschreiten brauchen die alten DOS Pfade statt der langen Windows Pfade.

Grundsätzlich hilft hier natürlich die Win32 API Funktion:

        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
static extern uint GetShortPathName([MarshalAs(UnmanagedType.LPTStr)]string path, [MarshalAs(UnmanagedType.LPTStr)]StringBuilder shortPath, uint shortPathLength);


Leider kommt es mit der Funktion alleine zu einer Schutzverletzung, wenn z.B. die Datei oder der Pfad noch nicht existiert.

Schlecht ist auch, wenn man der Funktion einen UNC Pfad übergibt oder aber die Zugriffsrechte auf den Pfad eingeschränkt sind.

Aus diesem Grund habe ich mir folgende Funktion gebaut, die dieses Problem nun auf unterschiedliche Arten löst und immer zu einem Ergebniss kommt...

Es muss der Microsoft Scripting Host integriert werden...
        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        static extern uint GetShortPathName([MarshalAs(UnmanagedType.LPTStr)]string path, [MarshalAs(UnmanagedType.LPTStr)]StringBuilder shortPath, uint shortPathLength);


        private static string GetShortPath(string longPath)
        {
            try
            {
                Boolean DeleteBeforeReturn = false;
                String MyFile = String.Empty;
                String MyDir = String.Empty;

                if (File.Exists(longPath) == false)
                {
                    MyFile = Path.GetFileName(longPath);
                    if (MyFile == String.Empty)
                    {
                        MyFile = "loaszu.lop";
                    }
                    MyDir = Path.GetDirectoryName(longPath);
                    DeleteBeforeReturn = true;
                    File.WriteAllText(Path.Combine(MyDir, MyFile), "", Encoding.UTF8);
                }
                longPath = System.IO.Path.GetFullPath(Path.Combine(MyDir, MyFile));

                const int MAX_PATH = 260;

                StringBuilder shortPathBuffer = new StringBuilder(MAX_PATH);

                // Violates this rule
                GetShortPathName(Path.Combine(MyDir, MyFile), shortPathBuffer, (uint)shortPathBuffer.Capacity);
                if (DeleteBeforeReturn == true)
                {
                    try
                    {
                        File.Delete(Path.Combine(MyDir, MyFile));
                    }
                    catch
                    {
                    }
                }
                return shortPathBuffer.ToString().Replace("loaszu.lop", "");
            }
            catch
            {
                Boolean DeleteBeforeReturn = false;
                String MyFile = String.Empty;
                String MyDir = String.Empty;

                if (File.Exists(longPath) == false)
                {
                    MyFile = Path.GetFileName(longPath);
                    if (MyFile == String.Empty)
                    {
                        MyFile = "loaszu.lop";
                    }
                    MyDir = Path.GetDirectoryName(longPath);
                    DeleteBeforeReturn = true;
                    File.WriteAllText(Path.Combine(MyDir, MyFile), "", Encoding.UTF8);
                }
                Scripting.FileSystemObject FSO = new Scripting.FileSystemObject();
                Scripting.File F = FSO.GetFile(Path.Combine(MyDir,MyFile));
                String MyShortDir = F.ShortPath;
                if (DeleteBeforeReturn == true)
                {
                    try
                    {
                        File.Delete(Path.Combine(MyDir, MyFile));
                    }
                    catch
                    {
                    }
                }
                return MyShortDir.ToString().Replace("loaszu.lop", "");
            }
            
        }

1 Kommentare zum Snippet

bigdeak schrieb am 5/26/2010:
Leider kann man das so noch nicht ganz verwenden.

1. Viele Methoden aus den System.IO Klassen (Path.GetDirectoryName, Path.Combine, File.WriteAllText), schmeißen sofort eine PathTooLongException, wenn der longPath größer als 260 Zeichen ist. Um also den kurzen Pfad von einem bereits zu langen Pfad zu ermitteln, muss man sich wohl von der System.IO Klasse verabschieden.

2. Warum sind die strings MyDir und MyFile immer auf string.Empty wenn die Datei bereits vorhanden ist? In dem Fall kann man nur von nicht vorhandenen Dateien den kurzen Pfad ermitteln.

3. Übergibt man als Parameter nur den Pfad zu einem Ordner und keine Datei, so würde hier auch eine Ausnahme kommen, weil versucht wird, auf einen Ordner ein Text zu schreiben.
 

Logge dich ein, um hier zu kommentieren!