System.IO.PathHelper.Normalize C# (CSharp) Méthode

Normalize() static private méthode

Normalize the given path.
Normalizes via Win32 GetFullPathName(). It will also trim all "typical" whitespace at the end of the path (see s_trimEndChars). Will also trim initial spaces if the path is determined to be rooted. Note that invalid characters will be checked after the path is normalized, which could remove bad characters. (C:\|\..\a.txt -- C:\a.txt)
Thrown if the path is an illegal UNC (does not contain a full server/share) or contains illegal characters. Thrown if the path or a path segment exceeds the filesystem limits. Thrown if Windows returns ERROR_FILE_NOT_FOUND. (See Win32Marshal.GetExceptionForWin32Error) Thrown if Windows returns ERROR_PATH_NOT_FOUND. (See Win32Marshal.GetExceptionForWin32Error) Thrown if Windows returns ERROR_ACCESS_DENIED. (See Win32Marshal.GetExceptionForWin32Error) Thrown if Windows returns an error that doesn't map to the above. (See Win32Marshal.GetExceptionForWin32Error)
static private Normalize ( string path, bool checkInvalidCharacters, bool expandShortPaths ) : string
path string Path to normalize
checkInvalidCharacters bool True to check for invalid characters
expandShortPaths bool Attempt to expand short paths if true
Résultat string
        internal static string Normalize(string path, bool checkInvalidCharacters, bool expandShortPaths)
        {
            // Get the full path
            StringBuffer fullPath = t_fullPathBuffer ?? (t_fullPathBuffer = new StringBuffer(PathInternal.MaxShortPath));
            try
            {
                GetFullPathName(path, fullPath);

                // Trim whitespace off the end of the string. Win32 normalization trims only U+0020.
                fullPath.TrimEnd(s_trimEndChars);

                if (fullPath.Length >= PathInternal.MaxLongPath)
                {
                    // Fullpath is genuinely too long
                    throw new PathTooLongException(SR.IO_PathTooLong);
                }

                // Checking path validity used to happen before getting the full path name. To avoid additional input allocation
                // (to trim trailing whitespace) we now do it after the Win32 call. This will allow legitimate paths through that
                // used to get kicked back (notably segments with invalid characters might get removed via "..").
                //
                // There is no way that GetLongPath can invalidate the path so we'll do this (cheaper) check before we attempt to
                // expand short file names.

                // Scan the path for:
                //
                //  - Illegal path characters.
                //  - Invalid UNC paths like \\, \\server, \\server\.
                //  - Segments that are too long (over MaxComponentLength)

                // As the path could be > 30K, we'll combine the validity scan. None of these checks are performed by the Win32
                // GetFullPathName() API.

                bool possibleShortPath = false;
                bool foundTilde = false;

                // We can get UNCs as device paths through this code (e.g. \\.\UNC\), we won't validate them as there isn't
                // an easy way to normalize without extensive cost (we'd have to hunt down the canonical name for any device
                // path that contains UNC or  to see if the path was doing something like \\.\GLOBALROOT\Device\Mup\,
                // \\.\GLOBAL\UNC\, \\.\GLOBALROOT\GLOBAL??\UNC\, etc.
                bool specialPath = fullPath.Length > 1 && fullPath[0] == '\\' && fullPath[1] == '\\';
                bool isDevice = PathInternal.IsDevice(fullPath);
                bool possibleBadUnc = specialPath && !isDevice;
                uint index = specialPath ? 2u : 0;
                uint lastSeparator = specialPath ? 1u : 0;
                uint segmentLength;
                char* start = fullPath.CharPointer;
                char current;

                while (index < fullPath.Length)
                {
                    current = start[index];

                    // Try to skip deeper analysis. '?' and higher are valid/ignorable except for '\', '|', and '~'
                    if (current < '?' || current == '\\' || current == '|' || current == '~')
                    {
                        switch (current)
                        {
                            case '|':
                            case '>':
                            case '<':
                            case '\"':
                                if (checkInvalidCharacters) throw new ArgumentException(SR.Argument_InvalidPathChars);
                                foundTilde = false;
                                break;
                            case '~':
                                foundTilde = true;
                                break;
                            case '\\':
                                segmentLength = index - lastSeparator - 1;
                                if (segmentLength > (uint)PathInternal.MaxComponentLength)
                                    throw new PathTooLongException(SR.IO_PathTooLong + fullPath.ToString());
                                lastSeparator = index;

                                if (foundTilde)
                                {
                                    if (segmentLength <= MaxShortName)
                                    {
                                        // Possibly a short path.
                                        possibleShortPath = true;
                                    }

                                    foundTilde = false;
                                }

                                if (possibleBadUnc)
                                {
                                    // If we're at the end of the path and this is the first separator, we're missing the share.
                                    // Otherwise we're good, so ignore UNC tracking from here.
                                    if (index == fullPath.Length - 1)
                                        throw new ArgumentException(SR.Arg_PathIllegalUNC);
                                    else
                                        possibleBadUnc = false;
                                }

                                break;

                            default:
                                if (checkInvalidCharacters && current < ' ') throw new ArgumentException(SR.Argument_InvalidPathChars, nameof(path));
                                break;
                        }
                    }

                    index++;
                }

                if (possibleBadUnc)
                    throw new ArgumentException(SR.Arg_PathIllegalUNC);

                segmentLength = fullPath.Length - lastSeparator - 1;
                if (segmentLength > (uint)PathInternal.MaxComponentLength)
                    throw new PathTooLongException(SR.IO_PathTooLong);

                if (foundTilde && segmentLength <= MaxShortName)
                    possibleShortPath = true;

                // Check for a short filename path and try and expand it. Technically you don't need to have a tilde for a short name, but
                // this is how we've always done this. This expansion is costly so we'll continue to let other short paths slide.
                if (expandShortPaths && possibleShortPath)
                {
                    return TryExpandShortFileName(fullPath, originalPath: path);
                }
                else
                {
                    if (fullPath.Length == (uint)path.Length && fullPath.StartsWith(path))
                    {
                        // If we have the exact same string we were passed in, don't bother to allocate another string from the StringBuilder.
                        return path;
                    }
                    else
                    {
                        return fullPath.ToString();
                    }
                }
            }
            finally
            {
                // Clear the buffer
                fullPath.Free();
            }
        }

Usage Example

Exemple #1
0
        // Returns a unique temporary file name, and creates a 0-byte file by that
        // name on disk.
        public static string GetTempFileName()
        {
            var tempPathBuilder = new ValueStringBuilder(stackalloc char[PathInternal.MaxShortPath]);

            GetTempPath(ref tempPathBuilder);

            var builder = new ValueStringBuilder(stackalloc char[PathInternal.MaxShortPath]);

            uint result = Interop.Kernel32.GetTempFileNameW(
                ref tempPathBuilder.GetPinnableReference(), "tmp", 0, ref builder.GetPinnableReference());

            tempPathBuilder.Dispose();

            if (result == 0)
            {
                throw Win32Marshal.GetExceptionForLastWin32Error();
            }

            builder.Length = builder.RawChars.IndexOf('\0');

            string path = PathHelper.Normalize(ref builder);

            builder.Dispose();
            return(path);
        }
All Usage Examples Of System.IO.PathHelper::Normalize