Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Problems.GrammaticalOptimization/SharpVectorConverters/Utils/DirectoryUtils.cs @ 13542

Last change on this file since 13542 was 12762, checked in by aballeit, 9 years ago

#2283 GUI updates, Tree-chart, MCTS Version 2 (prune leaves)

File size: 9.3 KB
Line 
1// This is based on MSDN Magazine article codes by Stephen Toub (stoub@microsoft.com)
2// The article is http://msdn.microsoft.com/en-us/magazine/cc163696.aspx
3
4using System;
5using System.IO;
6using System.Security;
7using System.ComponentModel;
8using System.Collections.Generic;
9using System.Security.Permissions;
10using Microsoft.Win32.SafeHandles;
11using System.Runtime.InteropServices;
12using System.Runtime.ConstrainedExecution;
13using ComTypes = System.Runtime.InteropServices.ComTypes;
14
15namespace SharpVectors.Converters.Utils
16{
17    internal static class DirectoryUtils
18    {
19        private sealed class SafeFindHandle : SafeHandleZeroOrMinusOneIsInvalid
20        {
21            [SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)]
22            private SafeFindHandle() : base(true)
23            {
24            }
25
26            protected override bool ReleaseHandle()
27            {
28                return FindClose(this.handle);
29            }
30
31            [DllImport("kernel32.dll")]
32            [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
33            [SuppressUnmanagedCodeSecurity]
34            private static extern bool FindClose(IntPtr handle);
35        }
36
37        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
38        [SuppressUnmanagedCodeSecurity]
39        private static extern SafeFindHandle FindFirstFile(string lpFileName, [In, Out, MarshalAs(UnmanagedType.LPStruct)] WIN32_FIND_DATA lpFindFileData);
40
41        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
42        [SuppressUnmanagedCodeSecurity]
43        private static extern bool FindNextFile(SafeFindHandle hndFindFile, [In, Out, MarshalAs(UnmanagedType.LPStruct)] WIN32_FIND_DATA lpFindFileData);
44
45        [DllImport("kernel32.dll", SetLastError = true)]
46        private static extern ErrorModes SetErrorMode(ErrorModes newMode);
47
48        [Serializable]
49        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
50        [BestFitMapping(false)]
51        private class WIN32_FIND_DATA
52        {
53            public FileAttributes dwFileAttributes;
54            public ComTypes.FILETIME ftCreationTime;
55            public ComTypes.FILETIME ftLastAccessTime;
56            public ComTypes.FILETIME ftLastWriteTime;
57            public int nFileSizeHigh;
58            public int nFileSizeLow;
59            public int dwReserved0;
60            public int dwReserved1;
61            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
62            public string cFileName;
63            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
64            public string cAlternateFileName;
65        }
66
67        private const int ERROR_FILE_NOT_FOUND = 0x2;
68        private const int ERROR_ACCESS_DENIED = 0x5;
69        private const int ERROR_NO_MORE_FILES = 0x12;
70
71        [Flags]
72        private enum ErrorModes
73        {
74            /// <summary>Use the system default, which is to display all error dialog boxes.</summary>
75            Default = 0x0,
76            /// <summary>
77            /// The system does not display the critical-error-handler message box.
78            /// Instead, the system sends the error to the calling process.
79            /// </summary>
80            FailCriticalErrors = 0x1,
81            /// <summary>
82            /// 64-bit Windows:  The system automatically fixes memory alignment faults and makes them
83            /// invisible to the application. It does this for the calling process and any descendant processes.
84            /// After this value is set for a process, subsequent attempts to clear the value are ignored.
85            /// </summary>
86            NoGpFaultErrorBox = 0x2,
87            /// <summary>
88            /// The system does not display the general-protection-fault message box.
89            /// This flag should only be set by debugging applications that handle general
90            /// protection (GP) faults themselves with an exception handler.
91            /// </summary>
92            NoAlignmentFaultExcept = 0x4,
93            /// <summary>
94            /// The system does not display a message box when it fails to find a file.
95            /// Instead, the error is returned to the calling process.
96            /// </summary>
97            NoOpenFileErrorBox = 0x8000
98        }
99
100        public static void DeleteDirectory(string directoryPath, bool recursive)
101        {
102            if (String.IsNullOrEmpty(directoryPath))
103            {
104                return;
105            }
106
107            DirectoryInfo dirInfo = new DirectoryInfo(directoryPath);
108            if (dirInfo.Exists)
109            {
110                // It is a directory...
111                try
112                {
113                    dirInfo.Attributes = FileAttributes.Normal;
114                    dirInfo.Delete(recursive);
115                }
116                catch (UnauthorizedAccessException)
117                {
118                    // One possible cause of this is read-only file, so first
119                    // try another method of deleting the directory...
120                    foreach (string file in DirectoryUtils.FindFiles(dirInfo, "*.*",
121                        recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly))
122                    {
123                        File.SetAttributes(file, FileAttributes.Normal);
124                        File.Delete(file);
125                    }
126
127                    dirInfo.Delete(recursive);
128                }
129            }
130        }
131
132        public static IEnumerable<string> FindFiles(DirectoryInfo dir,
133            string pattern, SearchOption searchOption)
134        {
135            // We suppressed this demand for each p/invoke call, so demand it upfront once
136            new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand();
137
138            // Validate parameters
139            if (dir == null)
140                throw new ArgumentNullException("dir");
141            if (pattern == null)
142                throw new ArgumentNullException("pattern");
143
144            // Setup
145            WIN32_FIND_DATA findData = new WIN32_FIND_DATA();
146            Stack<DirectoryInfo> directories = new Stack<DirectoryInfo>();
147            directories.Push(dir);
148
149            // Process each directory
150            ErrorModes origErrorMode = SetErrorMode(ErrorModes.FailCriticalErrors);
151            try
152            {
153                while (directories.Count > 0)
154                {
155                    // Get the name of the next directory and the corresponding search pattern
156                    dir = directories.Pop();
157                    string dirPath = dir.FullName.Trim();
158                    if (dirPath.Length == 0)
159                        continue;
160                    char lastChar = dirPath[dirPath.Length - 1];
161                    if (lastChar != Path.DirectorySeparatorChar &&
162                        lastChar != Path.AltDirectorySeparatorChar)
163                    {
164                        dirPath += Path.DirectorySeparatorChar;
165                    }
166
167                    // Process all files in that directory
168                    SafeFindHandle handle = FindFirstFile(dirPath + pattern, findData);
169                    if (handle.IsInvalid)
170                    {
171                        int error = Marshal.GetLastWin32Error();
172                        if (error == ERROR_ACCESS_DENIED ||
173                            error == ERROR_FILE_NOT_FOUND)
174                        {
175                            continue;
176                        }
177                        else
178                        {
179                            throw new Win32Exception(error);
180                        }
181                    }
182                    else
183                    {
184                        try
185                        {
186                            do
187                            {
188                                if ((findData.dwFileAttributes &
189                                    FileAttributes.Directory) == 0)
190                                    yield return (dirPath + findData.cFileName);
191                            }
192                            while (FindNextFile(handle, findData));
193                            int error = Marshal.GetLastWin32Error();
194                            if (error != ERROR_NO_MORE_FILES)
195                            {
196                                throw new Win32Exception(error);
197                            }
198                        }
199                        finally
200                        {
201                            handle.Dispose();
202                        }
203                    }
204
205                    // Add all child directories if that's what the user wants
206                    if (searchOption == SearchOption.AllDirectories)
207                    {
208                        foreach (DirectoryInfo childDir in dir.GetDirectories())
209                        {
210                            if ((File.GetAttributes(childDir.FullName) &
211                                FileAttributes.ReparsePoint) == 0)
212                            {
213                                directories.Push(childDir);
214                            }
215                        }
216                    }
217                }
218            }
219            finally
220            {
221                SetErrorMode(origErrorMode);
222            }
223        }
224    }
225}
Note: See TracBrowser for help on using the repository browser.