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  }