Helper.cs
1 // Copyright (c) Microsoft Corporation 2 // The Microsoft Corporation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 using System; 6 using System.ComponentModel; 7 using System.Diagnostics; 8 using System.IO.Abstractions; 9 using System.Reflection; 10 using System.Text.Json; 11 using System.Text.Json.Serialization; 12 13 using Wox.Plugin.Logger; 14 15 namespace Wox.Infrastructure 16 { 17 public static class Helper 18 { 19 private static readonly IFileSystem FileSystem = new FileSystem(); 20 private static readonly IPath Path = FileSystem.Path; 21 private static readonly IFile File = FileSystem.File; 22 private static readonly IFileInfoFactory FileInfo = FileSystem.FileInfo; 23 private static readonly IDirectory Directory = FileSystem.Directory; 24 25 private static readonly JsonSerializerOptions _serializerOptions = new JsonSerializerOptions 26 { 27 WriteIndented = true, 28 Converters = 29 { 30 new JsonStringEnumConverter(), 31 }, 32 }; 33 34 /// <summary> 35 /// http://www.yinwang.org/blog-cn/2015/11/21/programming-philosophy 36 /// </summary> 37 public static T NonNull<T>(this T obj) 38 { 39 if (obj == null) 40 { 41 throw new ArgumentNullException(nameof(obj)); 42 } 43 else 44 { 45 return obj; 46 } 47 } 48 49 public static void RequireNonNull<T>(this T obj) 50 { 51 if (obj == null) 52 { 53 throw new ArgumentNullException(nameof(obj)); 54 } 55 } 56 57 public static void ValidateDataDirectory(string bundledDataDirectory, string dataDirectory) 58 { 59 if (!Directory.Exists(dataDirectory)) 60 { 61 Directory.CreateDirectory(dataDirectory); 62 } 63 64 foreach (var bundledDataPath in Directory.GetFiles(bundledDataDirectory)) 65 { 66 var data = Path.GetFileName(bundledDataPath); 67 var dataPath = Path.Combine(dataDirectory, data.NonNull()); 68 if (!File.Exists(dataPath)) 69 { 70 File.Copy(bundledDataPath, dataPath); 71 } 72 else 73 { 74 var time1 = FileInfo.New(bundledDataPath).LastWriteTimeUtc; 75 var time2 = FileInfo.New(dataPath).LastWriteTimeUtc; 76 if (time1 != time2) 77 { 78 File.Copy(bundledDataPath, dataPath, true); 79 } 80 } 81 } 82 } 83 84 public static void ValidateDirectory(string path) 85 { 86 if (!Directory.Exists(path)) 87 { 88 Directory.CreateDirectory(path); 89 } 90 } 91 92 public static string Formatted<T>(this T t) 93 { 94 var formatted = JsonSerializer.Serialize(t, _serializerOptions); 95 96 return formatted; 97 } 98 99 // Function to run as admin for context menu items 100 public static void RunAsAdmin(string path) 101 { 102 var info = new ProcessStartInfo 103 { 104 FileName = path, 105 WorkingDirectory = Path.GetDirectoryName(path), 106 Verb = "runAs", 107 UseShellExecute = true, 108 }; 109 110 try 111 { 112 Process.Start(info); 113 } 114 catch (System.Exception ex) 115 { 116 Log.Exception($"Unable to Run {path} as admin : {ex.Message}", ex, MethodBase.GetCurrentMethod().DeclaringType); 117 } 118 } 119 120 // Function to run as other user for context menu items 121 public static void RunAsUser(string path) 122 { 123 var info = new ProcessStartInfo 124 { 125 FileName = path, 126 WorkingDirectory = Path.GetDirectoryName(path), 127 Verb = "runAsUser", 128 UseShellExecute = true, 129 }; 130 131 try 132 { 133 Process.Start(info); 134 } 135 catch (System.Exception ex) 136 { 137 Log.Exception($"Unable to Run {path} as different user : {ex.Message}", ex, MethodBase.GetCurrentMethod().DeclaringType); 138 } 139 } 140 141 public static Process OpenInConsole(string path) 142 { 143 var processStartInfo = new ProcessStartInfo 144 { 145 WorkingDirectory = path, 146 FileName = "cmd.exe", 147 }; 148 149 return Process.Start(processStartInfo); 150 } 151 152 public static bool OpenCommandInShell(string path, string pattern, string arguments, string workingDir = null, ShellRunAsType runAs = ShellRunAsType.None, bool runWithHiddenWindow = false) 153 { 154 if (string.IsNullOrEmpty(pattern)) 155 { 156 Log.Warn($"Trying to run OpenCommandInShell with an empty pattern. The default browser definition might have issues. Path: '${path ?? string.Empty}' ; Arguments: '${arguments ?? string.Empty}' ; Working Directory: '${workingDir ?? string.Empty}'", typeof(Helper)); 157 } 158 else if (pattern.Contains("%1", StringComparison.Ordinal)) 159 { 160 arguments = pattern.Replace("%1", arguments); 161 } 162 163 return OpenInShell(path, arguments, workingDir, runAs, runWithHiddenWindow); 164 } 165 166 public static bool OpenInShell(string path, string arguments = null, string workingDir = null, ShellRunAsType runAs = ShellRunAsType.None, bool runWithHiddenWindow = false) 167 { 168 using (var process = new Process()) 169 { 170 process.StartInfo.FileName = path; 171 process.StartInfo.WorkingDirectory = string.IsNullOrWhiteSpace(workingDir) ? string.Empty : workingDir; 172 process.StartInfo.Arguments = string.IsNullOrWhiteSpace(arguments) ? string.Empty : arguments; 173 process.StartInfo.WindowStyle = runWithHiddenWindow ? ProcessWindowStyle.Hidden : ProcessWindowStyle.Normal; 174 process.StartInfo.UseShellExecute = true; 175 176 if (runAs == ShellRunAsType.Administrator) 177 { 178 process.StartInfo.Verb = "RunAs"; 179 } 180 else if (runAs == ShellRunAsType.OtherUser) 181 { 182 process.StartInfo.Verb = "RunAsUser"; 183 } 184 185 try 186 { 187 process.Start(); 188 return true; 189 } 190 catch (Win32Exception ex) 191 { 192 Log.Exception($"Unable to open {path}: {ex.Message}", ex, MethodBase.GetCurrentMethod().DeclaringType); 193 return false; 194 } 195 } 196 } 197 198 public enum ShellRunAsType 199 { 200 None, 201 Administrator, 202 OtherUser, 203 } 204 } 205 }