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.Diagnostics; 7 using System.IO; 8 using System.IO.Abstractions; 9 using System.Linq; 10 using System.Security.Principal; 11 12 using Microsoft.PowerToys.Settings.UI.Library.CustomAction; 13 14 namespace Microsoft.PowerToys.Settings.UI.Library.Utilities 15 { 16 public static class Helper 17 { 18 public static readonly IFileSystem FileSystem = new FileSystem(); 19 20 public static string UserLocalAppDataPath { get; set; } = string.Empty; 21 22 public static bool AllowRunnerToForeground() 23 { 24 var result = false; 25 var processes = Process.GetProcessesByName("PowerToys"); 26 if (processes.Length > 0) 27 { 28 var pid = processes[0].Id; 29 result = NativeMethods.AllowSetForegroundWindow(pid); 30 } 31 32 return result; 33 } 34 35 public static string GetSerializedCustomAction(string moduleName, string actionName, string actionValue) 36 { 37 var customAction = new CustomActionDataModel 38 { 39 Name = actionName, 40 Value = actionValue, 41 }; 42 43 var moduleCustomAction = new ModuleCustomAction 44 { 45 ModuleAction = customAction, 46 }; 47 48 var sendCustomAction = new SendCustomAction(moduleName) 49 { 50 Action = moduleCustomAction, 51 }; 52 53 return sendCustomAction.ToJsonString(); 54 } 55 56 public static IFileSystemWatcher GetFileWatcher(string path, Action onChangedCallback, IFileSystem fileSystem = null) 57 { 58 fileSystem ??= FileSystem; 59 60 var dirPath = Path.GetDirectoryName(path); 61 if (!fileSystem.Directory.Exists(dirPath)) 62 { 63 return null; 64 } 65 66 var watcher = fileSystem.FileSystemWatcher.New(); 67 watcher.Path = dirPath; 68 watcher.Filter = Path.GetFileName(path); 69 watcher.NotifyFilter = NotifyFilters.LastWrite; 70 watcher.EnableRaisingEvents = true; 71 72 watcher.Changed += (o, e) => onChangedCallback(); 73 74 return watcher; 75 } 76 77 public static IFileSystemWatcher GetFileWatcher(string moduleName, string fileName, Action onChangedCallback, IFileSystem fileSystem = null) 78 { 79 fileSystem ??= FileSystem; 80 81 var path = fileSystem.Path.Combine(LocalApplicationDataFolder(), $"Microsoft\\PowerToys\\{moduleName}"); 82 83 if (!fileSystem.Directory.Exists(path)) 84 { 85 fileSystem.Directory.CreateDirectory(path); 86 } 87 88 var watcher = fileSystem.FileSystemWatcher.New(); 89 watcher.Path = path; 90 watcher.Filter = fileName; 91 watcher.NotifyFilter = NotifyFilters.LastWrite; 92 watcher.EnableRaisingEvents = true; 93 94 watcher.Changed += (o, e) => onChangedCallback(); 95 96 return watcher; 97 } 98 99 public static string LocalApplicationDataFolder() 100 { 101 WindowsIdentity currentUser = WindowsIdentity.GetCurrent(); 102 SecurityIdentifier currentUserSID = currentUser.User; 103 104 SecurityIdentifier localSystemSID = new SecurityIdentifier(WellKnownSidType.LocalSystemSid, null); 105 if (currentUserSID.Equals(localSystemSID) && UserLocalAppDataPath != string.Empty) 106 { 107 return UserLocalAppDataPath; 108 } 109 else 110 { 111 return Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); 112 } 113 } 114 115 public static string GetPowerToysInstallationFolder() 116 { 117 // PowerToys.exe is in the parent folder relative to Settings. 118 var settingsPath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); 119 return Directory.GetParent(settingsPath).FullName; 120 } 121 122 public static string GetPowerToysInstallationWinUI3AppsAssetsFolder() 123 { 124 // return .\PowerToys\WinUI3Apps\Assets 125 return Path.Combine(GetPowerToysInstallationFolder(), "WinUI3Apps", "Assets"); 126 } 127 128 private static readonly global::PowerToys.Interop.LayoutMapManaged LayoutMap = new global::PowerToys.Interop.LayoutMapManaged(); 129 130 public static string GetKeyName(uint key) 131 { 132 return LayoutMap.GetKeyName(key); 133 } 134 135 public static uint GetKeyValue(string key) 136 { 137 return LayoutMap.GetKeyValue(key); 138 } 139 140 public static string GetProductVersion() 141 { 142 return global::PowerToys.Interop.CommonManaged.GetProductVersion(); 143 } 144 145 public static int CompareVersions(string version1, string version2) 146 { 147 try 148 { 149 // Split up the version strings into int[] 150 // Example: v10.0.2 -> {10, 0, 2}; 151 ArgumentNullException.ThrowIfNull(version1); 152 ArgumentNullException.ThrowIfNull(version2); 153 154 var v1 = version1.Substring(1).Split('.').Select(int.Parse).ToArray(); 155 var v2 = version2.Substring(1).Split('.').Select(int.Parse).ToArray(); 156 157 if (v1.Length != 3 || v2.Length != 3) 158 { 159 throw new FormatException(); 160 } 161 162 if (v1[0] - v2[0] != 0) 163 { 164 return v1[0] - v2[0]; 165 } 166 167 if (v1[1] - v2[1] != 0) 168 { 169 return v1[1] - v2[1]; 170 } 171 172 return v1[2] - v2[2]; 173 } 174 catch (Exception) 175 { 176 throw new FormatException("Bad product version format"); 177 } 178 } 179 180 public static void CopyDirectory(string source_directory, string destination_directory, bool copy_recursively) 181 { 182 var current_directory_info = new DirectoryInfo(source_directory); 183 184 DirectoryInfo[] source_subdirectories = current_directory_info.GetDirectories(); 185 186 Directory.CreateDirectory(destination_directory); 187 188 foreach (FileInfo file in current_directory_info.GetFiles()) 189 { 190 string destination_file_path = Path.Combine(destination_directory, file.Name); 191 file.CopyTo(destination_file_path, true); 192 } 193 194 if (copy_recursively) 195 { 196 foreach (DirectoryInfo subdirectory in source_subdirectories) 197 { 198 string newDestinationDir = Path.Combine(destination_directory, subdirectory.Name); 199 CopyDirectory(subdirectory.FullName, newDestinationDir, true); 200 } 201 } 202 } 203 204 public static readonly uint VirtualKeyWindows = global::PowerToys.Interop.Constants.VK_WIN_BOTH; 205 } 206 }