Get-Ryan

[PowerShell] BetterFolderDialog

Sep 8th, 2017
212
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. <#
  2. The below code was found looking for a way to select folders using a GUI similar
  3. to System.Windows.Forms.OpenFileDialog vs System.Windows.Forms.FolderBrowserDialog.
  4. I found the FolderBrowserDialog class too limiting and outdated. Especially with potentially needing UNC paths.
  5. Reference URL: https://www.sapien.com/forums/viewtopic.php?t=8662
  6.  
  7. The code had to be corrected from the source URL.
  8. In the Reflector class GetType method, the for loop was adjusted as indicated:
  9. 1. Before - for (int i = 1; i < names.Length; ++i) {
  10. 1. After - for (int i = 1; i < names.Length; i++) {
  11. 2. Before - type = type.GetNestedType(names, BindingFlags.NonPublic);
  12. 2. After - type = type.GetNestedType(names[i], BindingFlags.NonPublic);
  13. #>
  14.  
  15. $sourcecode = @"
  16. using System;
  17. using System.Windows.Forms;
  18. using System.Reflection;
  19. namespace FolderSelect
  20. {
  21.     public class FolderSelectDialog
  22.     {
  23.         System.Windows.Forms.OpenFileDialog ofd = null;
  24.         public FolderSelectDialog()
  25.         {
  26.             ofd = new System.Windows.Forms.OpenFileDialog();
  27.             ofd.Filter = "Folders|\n";
  28.             ofd.AddExtension = false;
  29.             ofd.CheckFileExists = false;
  30.             ofd.DereferenceLinks = true;
  31.             ofd.Multiselect = false;
  32.         }
  33.         public string InitialDirectory
  34.         {
  35.             get { return ofd.InitialDirectory; }
  36.             set { ofd.InitialDirectory = value == null || value.Length == 0 ? Environment.CurrentDirectory : value; }
  37.         }
  38.         public string Title
  39.         {
  40.             get { return ofd.Title; }
  41.             set { ofd.Title = value == null ? "Select a folder" : value; }
  42.         }
  43.         public string FileName
  44.         {
  45.             get { return ofd.FileName; }
  46.         }
  47.         public bool ShowDialog()
  48.         {
  49.             return ShowDialog(IntPtr.Zero);
  50.         }
  51.         public bool ShowDialog(IntPtr hWndOwner)
  52.         {
  53.             bool flag = false;
  54.  
  55.             if (Environment.OSVersion.Version.Major >= 6)
  56.             {
  57.                 var r = new Reflector("System.Windows.Forms");
  58.                 uint num = 0;
  59.                 Type typeIFileDialog = r.GetType("FileDialogNative.IFileDialog");
  60.                 object dialog = r.Call(ofd, "CreateVistaDialog");
  61.                 r.Call(ofd, "OnBeforeVistaDialog", dialog);
  62.                 uint options = (uint)r.CallAs(typeof(System.Windows.Forms.FileDialog), ofd, "GetOptions");
  63.                 options |= (uint)r.GetEnum("FileDialogNative.FOS", "FOS_PICKFOLDERS");
  64.                 r.CallAs(typeIFileDialog, dialog, "SetOptions", options);
  65.                 object pfde = r.New("FileDialog.VistaDialogEvents", ofd);
  66.                 object[] parameters = new object[] { pfde, num };
  67.                 r.CallAs2(typeIFileDialog, dialog, "Advise", parameters);
  68.                 num = (uint)parameters[1];
  69.                 try
  70.                 {
  71.                     int num2 = (int)r.CallAs(typeIFileDialog, dialog, "Show", hWndOwner);
  72.                     flag = 0 == num2;
  73.                 }
  74.                 finally
  75.                 {
  76.                     r.CallAs(typeIFileDialog, dialog, "Unadvise", num);
  77.                     GC.KeepAlive(pfde);
  78.                 }
  79.             }
  80.             else
  81.             {
  82.                 var fbd = new FolderBrowserDialog();
  83.                 fbd.Description = this.Title;
  84.                 fbd.SelectedPath = this.InitialDirectory;
  85.                 fbd.ShowNewFolderButton = false;
  86.                 if (fbd.ShowDialog(new WindowWrapper(hWndOwner)) != DialogResult.OK) return false;
  87.                 ofd.FileName = fbd.SelectedPath;
  88.                 flag = true;
  89.             }
  90.             return flag;
  91.         }
  92.     }
  93.     public class WindowWrapper : System.Windows.Forms.IWin32Window
  94.     {
  95.         public WindowWrapper(IntPtr handle)
  96.         {
  97.             _hwnd = handle;
  98.         }
  99.         public IntPtr Handle
  100.         {
  101.             get { return _hwnd; }
  102.         }
  103.  
  104.         private IntPtr _hwnd;
  105.     }
  106.     public class Reflector
  107.     {
  108.         string m_ns;
  109.         Assembly m_asmb;
  110.         public Reflector(string ns)
  111.             : this(ns, ns)
  112.         { }
  113.         public Reflector(string an, string ns)
  114.         {
  115.             m_ns = ns;
  116.             m_asmb = null;
  117.             foreach (AssemblyName aN in Assembly.GetExecutingAssembly().GetReferencedAssemblies())
  118.             {
  119.                 if (aN.FullName.StartsWith(an))
  120.                 {
  121.                     m_asmb = Assembly.Load(aN);
  122.                     break;
  123.                 }
  124.             }
  125.         }
  126.         public Type GetType(string typeName)
  127.         {
  128.             Type type = null;
  129.             string[] names = typeName.Split('.');
  130.  
  131.             if (names.Length > 0)
  132.                 type = m_asmb.GetType(m_ns + "." + names[0]);
  133.  
  134.             for (int i = 1; i < names.Length; i++) {
  135.                 type = type.GetNestedType(names[i], BindingFlags.NonPublic);
  136.             }
  137.             return type;
  138.         }
  139.         public object New(string name, params object[] parameters)
  140.         {
  141.             Type type = GetType(name);
  142.             ConstructorInfo[] ctorInfos = type.GetConstructors();
  143.             foreach (ConstructorInfo ci in ctorInfos) {
  144.                 try {
  145.                     return ci.Invoke(parameters);
  146.                 } catch { }
  147.             }
  148.  
  149.             return null;
  150.         }
  151.         public object Call(object obj, string func, params object[] parameters)
  152.         {
  153.             return Call2(obj, func, parameters);
  154.         }
  155.         public object Call2(object obj, string func, object[] parameters)
  156.         {
  157.             return CallAs2(obj.GetType(), obj, func, parameters);
  158.         }
  159.         public object CallAs(Type type, object obj, string func, params object[] parameters)
  160.         {
  161.             return CallAs2(type, obj, func, parameters);
  162.         }
  163.         public object CallAs2(Type type, object obj, string func, object[] parameters) {
  164.             MethodInfo methInfo = type.GetMethod(func, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
  165.             return methInfo.Invoke(obj, parameters);
  166.         }
  167.         public object Get(object obj, string prop)
  168.         {
  169.             return GetAs(obj.GetType(), obj, prop);
  170.         }
  171.         public object GetAs(Type type, object obj, string prop) {
  172.             PropertyInfo propInfo = type.GetProperty(prop, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
  173.             return propInfo.GetValue(obj, null);
  174.         }
  175.         public object GetEnum(string typeName, string name) {
  176.             Type type = GetType(typeName);
  177.             FieldInfo fieldInfo = type.GetField(name);
  178.             return fieldInfo.GetValue(null);
  179.         }
  180.     }
  181. }
  182. "@
  183. $assemblies = ('System.Windows.Forms', 'System.Reflection')
  184. Add-Type -TypeDefinition $sourceCode -ReferencedAssemblies $assemblies -ErrorAction Stop
  185.  
  186. <#
  187. .USAGE
  188. $fsd = New-Object FolderSelect.FolderSelectDialog
  189.     $fsd.Title = "What to select";
  190.     [Void]($fsd.ShowDialog())
  191.    
  192. $SourceFolder = $fsd.FileName
  193. #>
Advertisement
Add Comment
Please, Sign In to add comment