├── App.config ├── Program.cs ├── Properties ├── App.config └── AssemblyInfo.cs ├── RightClickTools.csproj ├── RightClickTools.csproj.user ├── RightClickTools.ico ├── RightClickTools.sln └── app.manifest /App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Win32; 2 | using System; 3 | using System.Diagnostics; 4 | using System.IO; 5 | using System.Text; 6 | using System.Windows.Forms; 7 | using System.Drawing; 8 | using System.Drawing.Drawing2D; 9 | using System.Runtime.InteropServices; 10 | using System.Security.Principal; 11 | using System.Linq; 12 | using System.ServiceProcess; 13 | using System.Threading; 14 | 15 | namespace RightClickTools 16 | { 17 | class Program 18 | { 19 | static string myName = typeof(Program).Namespace; 20 | static string myPath = Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName); 21 | static string myExe = System.Reflection.Assembly.GetExecutingAssembly().Location; 22 | static string TempPath = Path.GetTempPath(); //Includes trailing backslash 23 | static string ElevateCfg = $@"{TempPath}Elevate.cfg"; 24 | static string appParts = $@"{myPath}\AppParts"; 25 | static string myIniFile = $@"{appParts}\{myName}.ini"; 26 | static string myIcon = $@"{myPath}\AppParts\Icons\{myName}.ico"; 27 | static string AdvKey = @"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced"; 28 | static string perKey = @"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize"; 29 | static string ExpKey = @"HKEY_LOCAL_MACHINE\Software\Classes\AppID\{CDCBCFCA-3CDC-436f-A4E2-0E02075250C2}"; 30 | static string bitPath = "64"; 31 | static bool Hidden = false; 32 | static string NTkey = @"HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion"; 33 | static int buildNumber = int.Parse(Registry.GetValue(NTkey, "CurrentBuild", "").ToString()); 34 | static bool Win11 = buildNumber >= 21996; 35 | static bool Win11Install = false; 36 | static bool AnyInstall = false; 37 | static string CCMfolder = FindCustomCommandsFolder(true); 38 | static string CCMA = @"Software\Classes\CLSID\{86CA1AA0-34AA-4E8B-A509-50C905BAE2A2}"; 39 | static string CCMB = $@"{CCMA}\InprocServer32"; 40 | static bool Win10ContextMenu = false; 41 | 42 | static string sMain = "Right-Click Tools"; 43 | static string sSetup = "Install or Remove this tool"; 44 | static string sOK = "OK"; 45 | static string sYes = "Yes"; 46 | static string sNo = "No"; 47 | static string sInstall = "Install"; 48 | static string sRemove = "Remove"; 49 | static string sDone = "Done"; 50 | static string[] CmdKeys = { "CmdHere", "CmdAdminHere", "CmdTrustedHere", "PowerShellHere", "PowerShellAdminHere", "PowerShellTrustedHere", "RegEdit", "RegEditAdmin", "RegEditTrusted", "ClearHistory", "TakeOwnHere", "AddDelPathHere", "ShowHide", "RefreshShellHere", "RestartExplorerHere", "FileManagerHere" }; 51 | static string[] CmdLabels = { "Cmd here", "Cmd here as Administrator", "Cmd here as TrustedInstaller", "PowerShell here", "PowerShell here as Administrator", "PowerShell here as TrustedInstaller", "RegEdit as User", "RegEdit as Administrator", "RegEdit as TrustedInstaller", "Clear History", "Take ownership and get access", "Add or Remove folder in Path variable", "Toggle display of hidden and system files", "Refresh shell", "Restart Explorer", "Privileged file manager here" }; 52 | static string sClearHistory = CmdLabels[9]; 53 | static string sTakeOwnHere = CmdLabels[10]; 54 | static string sRestartExplorer = CmdLabels[14]; 55 | static string sFolderNotAllowed = "Not allowed for this folder"; 56 | static string sWarningTakeOwn = "WARNING: Other users may lose access"; 57 | static string sUserPath = "User Path"; 58 | static string sSystemPath = "System Path"; 59 | static string sRecent = "Recent items"; 60 | static string sAutoSuggest = "Auto-suggest items"; 61 | static string sTemp = "Temporary files"; 62 | static string sDefender = "Defender history"; 63 | static string sCCM = "Classic context menu"; 64 | static string sRestartPC = "A restart is required to clear the Protection history. Restart now?"; 65 | static string sOpenFileManager = "Open file manager as..."; 66 | static string sAdministrator = "Administrator"; 67 | static string sTrustedInstaller = "Trusted Installer"; 68 | static string sShellRefresh = "Shell refresh only"; 69 | static string sResetIcons = "Reset icon cache"; 70 | static string sResetThumbs = "Reset thumbnail cache"; 71 | static string sFileManager = "File Manager"; 72 | static string sInstallTask = "Privilege elevation task"; 73 | 74 | static string Option = ""; 75 | static string StartDirectory = ""; 76 | static string CommandLine = ""; 77 | 78 | static float ScaleFactor = GetScale(); 79 | static bool Dark = isDark(); 80 | static bool isAdmin = false; 81 | static bool isFullAdmin = false; 82 | static bool ctrlKey = false; 83 | static bool fLatCB = true; 84 | static bool addTask = true; 85 | static bool removeTask = true; 86 | 87 | static string UserKey = @"HKEY_CURRENT_USER\Environment"; 88 | static string SystemKey = @"HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment"; 89 | static string UserPath = (string)Registry.GetValue(UserKey, "Path", ""); 90 | static string SystemPath = (string)Registry.GetValue(SystemKey, "Path", ""); 91 | static bool InUserPath = false; 92 | static bool InSystemPath = false; 93 | static int pathLength = UserPath.Length + SystemPath.Length; 94 | static string UIkey = @"HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Authentication\LogonUI"; 95 | static string userSID = ""; 96 | 97 | static string CmdExe = @"C:\Windows\System32\Cmd.exe"; 98 | static string PowerShellExe = @"C:\Windows\System32\WindowsPowerShell\v1.0\PowerShell.exe"; 99 | static string RegEditExe = @"C:\Windows\RegEdit.exe"; 100 | static string SchTasksExe = @"C:\Windows\System32\SchTasks.exe"; 101 | 102 | static string UserName = Environment.GetEnvironmentVariable("UserName"); 103 | static string TaskName = $@"MyTasks\{myName}-{UserName}"; 104 | static string helpPage = "install-and-remove"; 105 | static int bwidth = 75; 106 | 107 | static CheckBox userPathCheckbox; 108 | static CheckBox systemPathCheckbox; 109 | 110 | static CheckBox ShellRefreshCheckbox; 111 | static CheckBox iconCacheCheckbox; 112 | static CheckBox thumbCacheCheckbox; 113 | 114 | static CheckBox RecentItemsCheckbox; 115 | static CheckBox AutoSuggestCheckbox; 116 | static CheckBox TempFilesCheckbox; 117 | static CheckBox DefenderCheckbox; 118 | static CheckBox checkboxCCM; 119 | static CheckBox checkboxTask; 120 | 121 | [STAThread] 122 | static void Main(string[] args) 123 | { 124 | // If the current folder is a long path, the Elevate function will fail, so let's make C:\ the current folder. 125 | Directory.SetCurrentDirectory(@"C:\"); 126 | 127 | ctrlKey = (GetAsyncKeyState(0x11) & 0x8000) != 0; //Detect if Ctrl key is pressed 128 | 129 | if (!Environment.Is64BitOperatingSystem) bitPath = "32"; 130 | 131 | LoadLanguageStrings(); 132 | Application.EnableVisualStyles(); 133 | Application.SetCompatibleTextRenderingDefault(false); 134 | 135 | isAdmin = IsCurrentUserInAdminGroup(); 136 | isFullAdmin = isAdmin && TaskExists(); 137 | 138 | try { Hidden = (int)Registry.GetValue(AdvKey, "Hidden", 0) == 1; } catch { } 139 | 140 | try { userSID = (string)Registry.GetValue(UIkey, "LastLoggedOnUserSID", ""); } catch { } 141 | 142 | if (userSID == "") findUserSID(); 143 | 144 | if (args.Length == 0) { InstallRemove(); return; } 145 | 146 | Option = args[0]; 147 | 148 | if (args.Length > 1) 149 | { 150 | StartDirectory = args[1].Replace("|", ""); 151 | } 152 | 153 | switch (Option.ToLower()) 154 | { 155 | case "/dark": 156 | SetExplorerOptions(0); 157 | break; 158 | 159 | case "/light": 160 | SetExplorerOptions(1); 161 | break; 162 | 163 | case "/install": 164 | Install(false); 165 | break; 166 | 167 | case "/installmin": 168 | addTask = false; 169 | Install(false); 170 | break; 171 | 172 | case "/remove": 173 | Remove(false); 174 | break; 175 | 176 | case "/removemin": 177 | removeTask = false; 178 | Remove(false); 179 | break; 180 | 181 | case "/hkuinstall": 182 | HKUInstall(); 183 | break; 184 | 185 | case "/hkuinstallmin": 186 | addTask = false; 187 | HKUInstall(); 188 | break; 189 | 190 | case "/hkuremove": 191 | HKURemove(); 192 | break; 193 | 194 | case "/taskinstall": 195 | TaskInstall(true); 196 | break; 197 | 198 | case "/taskremove": 199 | TaskRemove(true); 200 | break; 201 | 202 | case "/taskinstallquiet": 203 | TaskInstall(false); 204 | break; 205 | 206 | case "/taskremovequiet": 207 | TaskRemove(false); 208 | break; 209 | 210 | case "/elevate": 211 | if (args.Length > 1) { ElevateCfg = args[1]; } 212 | Elevate(); 213 | break; 214 | 215 | case "/cmdhere": 216 | RunAsUser(CmdExe); 217 | break; 218 | 219 | case "/cmdadminhere": 220 | RunAsAdmin(CmdExe); 221 | break; 222 | 223 | case "/cmdtrustedhere": 224 | RunAsTrusted(CmdExe); 225 | break; 226 | 227 | case "/powershellhere": 228 | GetPSPath(); 229 | RunAsUser(PowerShellExe); 230 | break; 231 | 232 | case "/powershelladminhere": 233 | GetPSPath(); 234 | RunAsAdmin(PowerShellExe); 235 | break; 236 | 237 | case "/powershelltrustedhere": 238 | GetPSPath(); 239 | RunAsTrusted(PowerShellExe); 240 | break; 241 | 242 | case "/regedit": 243 | Environment.SetEnvironmentVariable("__COMPAT_LAYER", "RUNASINVOKER"); 244 | if (ctrlKey) clearRegEdit(); 245 | CommandLine = "/m"; 246 | RunAsUser(RegEditExe); 247 | break; 248 | 249 | case "/regeditadmin": 250 | CommandLine = "/m"; 251 | RunAsAdmin(RegEditExe); 252 | break; 253 | 254 | case "/regedittrusted": 255 | CommandLine = "/m"; 256 | RunAsTrusted(RegEditExe); 257 | break; 258 | 259 | case "/allowelevatedexplorer": 260 | object runAsValue = Registry.GetValue(ExpKey, "RunAs", null); 261 | if (runAsValue != null && runAsValue.ToString() == "Interactive User") 262 | { 263 | Registry.SetValue(ExpKey, "RunAs", "", RegistryValueKind.String); 264 | Thread.Sleep(5000); 265 | Registry.SetValue(ExpKey, "RunAs", "Interactive User", RegistryValueKind.String); 266 | } 267 | break; 268 | 269 | case "/minifilemanager": 270 | OpenFileDialog fd = new OpenFileDialog 271 | { 272 | Title = sFileManager, 273 | Filter = "", 274 | InitialDirectory = StartDirectory, 275 | Multiselect = true 276 | }; 277 | fd.ShowDialog(); 278 | break; 279 | 280 | case "/filemanagerhere": 281 | FileManagerHere(); 282 | break; 283 | 284 | case "/takeownhere": 285 | RunTakeOwnHerePS1AsAdmin(); 286 | break; 287 | 288 | case "/adddelpathhere": 289 | AddDelPathHere(); 290 | break; 291 | 292 | case "/addpathadmin": 293 | AddPathAdmin(); 294 | break; 295 | 296 | case "/delpathadmin": 297 | DelPathAdmin(); 298 | break; 299 | 300 | case "/showhide": 301 | ShowHide(); 302 | break; 303 | 304 | case "/clearhistory": 305 | ClearHistory(); 306 | break; 307 | 308 | case "/clearhistoryadmin": 309 | ClearDefenderHistoryTask(); 310 | break; 311 | 312 | case "/refreshshellhere": 313 | RefreshShellHere(); 314 | break; 315 | 316 | case "/restartexplorerhere": 317 | helpPage = "restart-explorer"; 318 | DialogResult result = CustomMessageBox.Show($"{sRestartExplorer}?", sMain); 319 | if (result == DialogResult.Cancel) return; 320 | RestartExplorer(); 321 | break; 322 | 323 | default: 324 | return; 325 | } 326 | } 327 | 328 | static void GetPSPath() 329 | { 330 | string PSPath = ReadString(myIniFile, "PowerShellHere", "Exe", ""); 331 | if (File.Exists(PSPath)) PowerShellExe = PSPath; 332 | } 333 | 334 | static void SetExplorerOptions(int light) 335 | { 336 | Registry.SetValue(perKey, "AppsUseLightTheme", light, RegistryValueKind.DWord); 337 | Registry.SetValue(perKey, "SystemUsesLightTheme", light, RegistryValueKind.DWord); 338 | Registry.SetValue(AdvKey, "Hidden", 1, RegistryValueKind.DWord); 339 | Registry.SetValue(AdvKey, "ShowSuperHidden", 1, RegistryValueKind.DWord); 340 | Registry.SetValue(AdvKey, "HideFileExt", 0, RegistryValueKind.DWord); 341 | Registry.SetValue(AdvKey, "UseCompactMode", 1, RegistryValueKind.DWord); 342 | } 343 | 344 | static void findUserSID() 345 | { 346 | string userName = ""; 347 | try { userName = (string)Registry.GetValue(UIkey, "LastLoggedOnUser", ""); } catch { } 348 | if (userName == "") return; 349 | userName = userName.Substring(userName.LastIndexOf('\\') + 1); 350 | 351 | using (RegistryKey hkeyUsers = Registry.Users) 352 | { 353 | foreach (string userSid in hkeyUsers.GetSubKeyNames()) 354 | { 355 | try 356 | { 357 | using (RegistryKey volatileEnvKey = hkeyUsers.OpenSubKey($@"{userSid}\Volatile Environment")) 358 | { 359 | if (volatileEnvKey != null) 360 | { 361 | object usernameValue = volatileEnvKey.GetValue("USERNAME"); 362 | if (usernameValue != null && usernameValue.ToString().Equals(userName, StringComparison.OrdinalIgnoreCase)) 363 | { 364 | userSID = userSid; 365 | return; 366 | } 367 | } 368 | } 369 | } 370 | catch { } 371 | } 372 | } 373 | userSID = ""; 374 | } 375 | 376 | static bool IsCurrentUserInAdminGroup() 377 | { 378 | var claims = new WindowsPrincipal(WindowsIdentity.GetCurrent()).Claims; 379 | var adminClaimID = new SecurityIdentifier(WellKnownSidType.BuiltinAdministratorsSid, null).Value; 380 | return claims.Any(c => c.Value == adminClaimID); 381 | } 382 | 383 | static bool TaskExists() 384 | { 385 | Process process = new Process(); 386 | process.StartInfo.FileName = "schtasks.exe"; 387 | process.StartInfo.Arguments = $"/query /tn {TaskName}"; 388 | process.StartInfo.RedirectStandardOutput = true; 389 | process.StartInfo.RedirectStandardError = true; 390 | process.StartInfo.UseShellExecute = false; 391 | process.StartInfo.CreateNoWindow = true; 392 | process.Start(); 393 | process.WaitForExit(); 394 | return process.ExitCode == 0; 395 | } 396 | 397 | static void RunUAC(string fileName) 398 | { 399 | Process p = new Process(); 400 | p.StartInfo.FileName = fileName; 401 | p.StartInfo.Arguments = CommandLine; 402 | p.StartInfo.UseShellExecute = true; 403 | p.StartInfo.CreateNoWindow = true; 404 | p.StartInfo.Verb = "runas"; 405 | p.Start(); 406 | p.WaitForExit(); 407 | } 408 | 409 | static void FileManagerHere() 410 | { 411 | helpPage = "privileged-file-manager-here"; 412 | bwidth = 120; 413 | DialogResult result = TwoChoiceBox.Show(sOpenFileManager, sMain, sAdministrator, sTrustedInstaller); 414 | if (result == DialogResult.Cancel) return; 415 | 416 | CommandLine = $"\"{StartDirectory}\""; 417 | 418 | string FMExe = ReadString(myIniFile, "FileManagerHere", "Exe", ""); 419 | 420 | // Set file manager to Explorer if no valid third-party file manager is set 421 | if (FMExe == "" || $@"\{FMExe}".ToLower().EndsWith("\\explorer.exe") || !File.Exists(FMExe)) 422 | { 423 | if (Win11 && result == DialogResult.No) 424 | { 425 | CommandLine = $"/MiniFileManager \"{StartDirectory}\""; 426 | FMExe = myExe; 427 | } 428 | else 429 | { 430 | FMExe = "explorer.exe"; 431 | 432 | // Check registry value that prevents Explorer to run elevated 433 | object runAsValue = Registry.GetValue(ExpKey, "RunAs", null); 434 | if (runAsValue != null && runAsValue.ToString() == "Interactive User") 435 | { 436 | if (isFullAdmin) 437 | { 438 | // Temporarily allow Explorer to run elevated 439 | CommandLine = "/AllowElevatedExplorer"; 440 | RunAsTrusted(myExe); 441 | // Wait for registry entry to be updated 442 | for (int i = 0; i < 100; i++) 443 | { 444 | Thread.Sleep(20); 445 | runAsValue = Registry.GetValue(ExpKey, "RunAs", null); 446 | if (runAsValue == null || runAsValue.ToString() != "Interactive User") break; 447 | } 448 | CommandLine = $"\"{StartDirectory}\""; 449 | } 450 | else 451 | { 452 | CommandLine = $"/MiniFileManager \"{StartDirectory}\""; 453 | FMExe = myExe; 454 | } 455 | } 456 | } 457 | }; 458 | 459 | if (result == DialogResult.Yes) RunAsAdmin(FMExe); 460 | if (result == DialogResult.No) RunAsTrusted(FMExe); 461 | } 462 | 463 | static void AddPathAdmin() 464 | { 465 | char[] trimThis = { '\\' }; 466 | string path = StartDirectory.Trim(trimThis); 467 | InUserPath = IsPathInEnvironmentVariable(path, UserPath); 468 | InSystemPath = IsPathInEnvironmentVariable(path, SystemPath); 469 | AddPathToEnvironmentVariable(path, SystemPath, SystemKey, false); 470 | } 471 | 472 | static void DelPathAdmin() 473 | { 474 | char[] trimThis = { '\\' }; 475 | string path = StartDirectory.Trim(trimThis); 476 | InUserPath = IsPathInEnvironmentVariable(path, UserPath); 477 | InSystemPath = IsPathInEnvironmentVariable(path, SystemPath); 478 | RemovePathFromEnvironmentVariable(path, SystemPath, SystemKey, false); 479 | } 480 | 481 | static void ClearHistory() 482 | { 483 | DialogResult result = ClearHistoryDialog.Show(sClearHistory, sMain); 484 | 485 | if (result == DialogResult.Cancel) return; 486 | 487 | if (RecentItemsCheckbox.Checked) 488 | { 489 | string Recent = Environment.GetFolderPath(Environment.SpecialFolder.Recent); 490 | try 491 | { 492 | Directory.GetFiles(Recent, "*", SearchOption.TopDirectoryOnly).ToList().ForEach(File.Delete); 493 | Directory.GetFiles($@"{Recent}\AutomaticDestinations", "*", SearchOption.TopDirectoryOnly).ToList().ForEach(File.Delete); 494 | Directory.GetFiles($@"{Recent}\CustomDestinations", "*", SearchOption.TopDirectoryOnly).ToList().ForEach(File.Delete); 495 | } 496 | catch 497 | { 498 | } 499 | } 500 | 501 | if (AutoSuggestCheckbox.Checked) 502 | { 503 | string parentKey = @"Software\Microsoft\Windows\CurrentVersion\Explorer"; 504 | ClearRegValues($@"{parentKey}\RunMRU"); 505 | ClearRegValues($@"{parentKey}\TypedPaths"); 506 | 507 | Process p = new Process(); 508 | p.StartInfo.FileName = "Rundll32.exe"; 509 | p.StartInfo.Arguments = "InetCpl.cpl,ClearMyTracksByProcess 1"; 510 | p.StartInfo.WorkingDirectory = @"C:\"; 511 | p.StartInfo.UseShellExecute = false; 512 | p.StartInfo.CreateNoWindow = true; 513 | p.Start(); 514 | } 515 | 516 | if (TempFilesCheckbox.Checked) 517 | { 518 | var filesAndFolders = Directory.GetFileSystemEntries(TempPath, "*", SearchOption.TopDirectoryOnly); 519 | 520 | foreach (var entry in filesAndFolders) 521 | { 522 | try 523 | { 524 | if (File.Exists(entry)) 525 | { 526 | File.Delete(entry); 527 | } 528 | else if (Directory.Exists(entry)) 529 | { 530 | Directory.Delete(entry, true); 531 | } 532 | } 533 | catch 534 | { 535 | } 536 | } 537 | } 538 | 539 | if (DefenderCheckbox.Checked) 540 | { 541 | ClearDefenderHistory(); 542 | } 543 | } 544 | 545 | static void ClearRegValues(string keyPath) 546 | { 547 | try 548 | { 549 | using (RegistryKey key = Registry.CurrentUser.OpenSubKey(keyPath, true)) 550 | { 551 | if (key != null) 552 | { 553 | foreach (string valueName in key.GetValueNames()) 554 | { 555 | key.DeleteValue(valueName); 556 | } 557 | } 558 | } 559 | } 560 | catch 561 | { 562 | } 563 | } 564 | 565 | static void AddDelPathHere() 566 | { 567 | string path = StartDirectory; 568 | 569 | InUserPath = IsPathInEnvironmentVariable(path, UserPath); 570 | InSystemPath = IsPathInEnvironmentVariable(path, SystemPath); 571 | 572 | if (path.EndsWith(":")) path += "\\"; 573 | 574 | DialogResult result = AddDelPathDialog.Show(path, sMain); 575 | 576 | if (result == DialogResult.Cancel) return; 577 | 578 | if (userPathCheckbox.Checked != InUserPath) 579 | { 580 | if (userPathCheckbox.Checked) 581 | AddPathToEnvironmentVariable(path, UserPath, UserKey, true); 582 | else 583 | RemovePathFromEnvironmentVariable(path, UserPath, UserKey, true); 584 | } 585 | 586 | if (systemPathCheckbox.Checked != InSystemPath) 587 | { 588 | 589 | if (systemPathCheckbox.Checked) 590 | { 591 | CommandLine = $"/AddPathAdmin \"{StartDirectory}\""; 592 | } 593 | else 594 | { 595 | CommandLine = $"/DelPathAdmin \"{StartDirectory}\""; 596 | } 597 | RunElevated(myExe, "Administrator"); 598 | } 599 | } 600 | 601 | static bool IsPathInEnvironmentVariable(string pathToCheck, string environmentVariable) 602 | { 603 | string[] paths = environmentVariable.Split(';'); 604 | char[] trimThis = { '\\' }; 605 | foreach (string p in paths) 606 | { 607 | if (string.Equals(p.Trim(trimThis), pathToCheck, StringComparison.OrdinalIgnoreCase)) 608 | { 609 | return true; 610 | } 611 | } 612 | return false; 613 | } 614 | 615 | static void AddPathToEnvironmentVariable(string pathToAdd, string environmentVariable, string Key, bool User) 616 | { 617 | if (User && InUserPath) return; 618 | if (!User && InSystemPath) return; 619 | 620 | if ((pathLength + pathToAdd.Length) > 4095) return; 621 | 622 | string newPath = $"{environmentVariable};{pathToAdd}"; 623 | newPath = newPath.Replace(";;",";"); 624 | Registry.SetValue(Key, "Path", newPath, RegistryValueKind.ExpandString); 625 | } 626 | 627 | static void RemovePathFromEnvironmentVariable(string pathToRemove, string environmentVariable, string Key, bool User) 628 | { 629 | if (User && !InUserPath) return; 630 | if (!User && !InSystemPath) return; 631 | 632 | string[] paths = environmentVariable.Split(';'); 633 | char[] trimThis = { '\\' }; 634 | pathToRemove = pathToRemove.Trim(trimThis); 635 | string newPath = ""; 636 | foreach (string p in paths) 637 | { 638 | if (!string.Equals(p.Trim(trimThis), pathToRemove, StringComparison.OrdinalIgnoreCase)) 639 | { 640 | if (!string.IsNullOrEmpty(newPath)) 641 | { 642 | newPath += ";"; 643 | } 644 | newPath += p; 645 | } 646 | } 647 | newPath = newPath.Replace(";;", ";"); 648 | Registry.SetValue(Key, "Path", newPath, RegistryValueKind.ExpandString); 649 | } 650 | 651 | static void ShowHide() 652 | { 653 | ToggleHiddenFiles(!Hidden); 654 | } 655 | 656 | static void RefreshShell() 657 | { 658 | SHChangeNotify(0x08000000, 0x1000, IntPtr.Zero, IntPtr.Zero); 659 | 660 | if (buildNumber >= 14393) 661 | { 662 | ToggleHiddenFiles(!Hidden); 663 | ToggleHiddenFiles(Hidden); 664 | } 665 | } 666 | 667 | static void RefreshShellHere() 668 | { 669 | DialogResult result = ShellRefreshDialog.Show("", sMain); 670 | 671 | if (result == DialogResult.Cancel) return; 672 | 673 | RefreshShell(); 674 | 675 | if (iconCacheCheckbox.Checked || thumbCacheCheckbox.Checked) 676 | { 677 | if (StartDirectory.ToLower().EndsWith("\\desktop")) 678 | { 679 | if (!DesktopWindowFound()) StartDirectory = ""; 680 | } 681 | 682 | using (Process p = new Process()) 683 | { 684 | p.StartInfo = new ProcessStartInfo 685 | { 686 | FileName = "taskkill.exe", 687 | Arguments = "/f /im explorer.exe", 688 | WindowStyle = ProcessWindowStyle.Hidden, 689 | UseShellExecute = true, 690 | CreateNoWindow = true, 691 | }; 692 | p.Start(); 693 | p.WaitForExit(); 694 | } 695 | 696 | Thread.Sleep(2000); 697 | 698 | if (iconCacheCheckbox.Checked) DeleteCacheFiles("iconcache_*.db"); 699 | 700 | if (thumbCacheCheckbox.Checked) DeleteCacheFiles("thumbcache_*.db"); 701 | 702 | Process.Start("explorer.exe"); 703 | if (StartDirectory != "") Process.Start("explorer.exe", StartDirectory); 704 | } 705 | } 706 | 707 | static void DeleteCacheFiles(string searchPattern) 708 | { 709 | string targetDirectory = $@"{Environment.GetEnvironmentVariable("LocalAppData")}\Microsoft\Windows\Explorer"; 710 | 711 | try 712 | { 713 | string[] files = Directory.GetFiles(targetDirectory, searchPattern, SearchOption.TopDirectoryOnly); 714 | 715 | foreach (string file in files) 716 | { 717 | try { File.Delete(file); } 718 | catch { } 719 | } 720 | } 721 | catch { } 722 | } 723 | 724 | static void ToggleHiddenFiles(bool bShow) 725 | { 726 | if (buildNumber >= 14393) 727 | { 728 | Structures.SHELLSTATE state = new Structures.SHELLSTATE(); 729 | state.FShowAllObjects = (uint)(bShow ? 1 : 2); 730 | state.FShowSuperHidden = (uint)(bShow ? 1 : 0); 731 | SHGetSetSettings(ref state, Structures.SSF.SSF_SHOWALLOBJECTS | Structures.SSF.SSF_SHOWSUPERHIDDEN, true); 732 | } 733 | else 734 | { 735 | int h1 = 1; int h2 = 1; 736 | if (Hidden) { h1 = 2; h2 = 0; } 737 | Registry.SetValue(AdvKey, "Hidden", h1, RegistryValueKind.DWord); 738 | Registry.SetValue(AdvKey, "ShowSuperHidden", h2, RegistryValueKind.DWord); 739 | Thread.Sleep(100); 740 | SendKeys.SendWait("{F5}"); 741 | } 742 | } 743 | 744 | [DllImport("shell32.dll", CharSet = CharSet.Auto, SetLastError = true)] 745 | public static extern void SHChangeNotify(uint wEventId, uint uFlags, IntPtr dwItem1, IntPtr dwItem2); 746 | 747 | [DllImport("shell32.dll", CharSet = CharSet.Auto, SetLastError = true)] 748 | public extern static void SHGetSetSettings(ref Structures.SHELLSTATE lpss, Structures.SSF dwMask, bool bSet); 749 | 750 | internal static class Structures 751 | { 752 | [Flags] 753 | public enum SSF : int 754 | { 755 | SSF_SHOWALLOBJECTS = 0x00000001, 756 | SSF_SHOWSUPERHIDDEN = 0x00040000, 757 | } 758 | [StructLayout(LayoutKind.Sequential)] 759 | public struct SHELLSTATE 760 | { 761 | public uint bitvector; 762 | 763 | public uint FShowAllObjects 764 | { 765 | get => this.bitvector & 1; 766 | set => this.bitvector = value | this.bitvector; 767 | } 768 | 769 | public uint FShowSuperHidden 770 | { 771 | get => (this.bitvector & 0x8000) / 0x8000; 772 | set => this.bitvector = (value * 0x8000) | this.bitvector; 773 | } 774 | } 775 | } 776 | 777 | [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] 778 | private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount); 779 | 780 | [DllImport("user32.dll", SetLastError = true)] 781 | private static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, string windowTitle); 782 | 783 | static bool DesktopWindowFound() 784 | { 785 | bool desktopFound = false; 786 | IntPtr hwnd = IntPtr.Zero; 787 | do 788 | { 789 | hwnd = FindWindowEx(IntPtr.Zero, hwnd, "CabinetWClass", null); 790 | 791 | if (hwnd != IntPtr.Zero) 792 | { 793 | StringBuilder windowTitle = new StringBuilder(256); 794 | GetWindowText(hwnd, windowTitle, windowTitle.Capacity); 795 | string t = windowTitle.ToString().ToLower(); 796 | if (t == "desktop" || t == "desktop - file explorer") 797 | { 798 | desktopFound = true; 799 | break; 800 | } 801 | } 802 | } 803 | while (hwnd != IntPtr.Zero); 804 | return desktopFound; 805 | } 806 | 807 | static void RestartExplorer() 808 | { 809 | if (StartDirectory.ToLower().EndsWith("\\desktop")) 810 | { 811 | if (!DesktopWindowFound()) StartDirectory = ""; 812 | } 813 | 814 | RefreshShell(); 815 | 816 | var processes = Process.GetProcessesByName("explorer"); 817 | foreach (var process in processes) 818 | { 819 | try 820 | { 821 | process.Kill(); 822 | process.WaitForExit(); 823 | } 824 | catch { } 825 | } 826 | if (StartDirectory != "") Process.Start("explorer.exe", StartDirectory); 827 | } 828 | 829 | static void CreateChangeDirectoryFile(string EXEFilename) 830 | { 831 | if (EXEFilename == CmdExe) 832 | { 833 | string cdFile = $@"{TempPath}ChangeDirectory.cmd"; 834 | StartDirectory = StartDirectory.Replace("%", "%%"); //Escape percent signs 835 | string Data = $"@echo off\r\nchcp 65001>nul\r\ncd /d \"{StartDirectory}\""; 836 | Data += "\r\nstart /b \"\" cmd /c del \"%~f0\""; 837 | File.WriteAllText(cdFile, Data); 838 | CommandLine = $"/k \"{cdFile}\""; 839 | } 840 | 841 | if (EXEFilename == PowerShellExe) 842 | { 843 | string cdFile = $@"{TempPath}ChangeDirectory.ps1"; 844 | StartDirectory = StartDirectory.Replace("'", "''"); //Escape single quotes 845 | string Data = $@"Set-Location -LiteralPath '{StartDirectory}'"; 846 | if (StartDirectory.Contains("~")) Data += "\r\nfunction Prompt {$shortPath = (New-Object -ComObject Scripting.FileSystemObject).GetFolder($pwd).ShortPath; return \"PS $($shortPath)> \"}"; 847 | Data += "\r\nStart-Sleep -Milliseconds 100; Remove-Item $MyInvocation.MyCommand.Path -Force\r\n"; //Delete itself when done 848 | File.WriteAllText(cdFile, Data, Encoding.UTF8); //UTF-8 with BOM 849 | CommandLine = $"-NoLogo -NoExit -NoProfile -ExecutionPolicy Bypass -file \"{cdFile}\""; 850 | } 851 | } 852 | 853 | static void CreateTakeOwnHerePS1() 854 | { 855 | StartDirectory = StartDirectory.Replace("'", "''"); //Escape single quotes 856 | string PS1Data = $"$SetACL = '{appParts.Replace("'", "''")}\\{bitPath}\\SetACL.exe'\r\n"; 857 | PS1Data += "$UserName = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name\r\n"; 858 | PS1Data += $"& $SetACL -on '{StartDirectory}' -ot file -actn setowner -ownr \"n:$UserName\" -rec cont_obj\r\n"; 859 | PS1Data += $"& $SetACL -on '{StartDirectory}' -ot file -actn setprot -op \"dacl:np;sacl:np\" -rec cont_obj\r\n"; 860 | PS1Data += "Start-Sleep -Milliseconds 100; Remove-Item $MyInvocation.MyCommand.Path -Force\r\n"; //Delete itself when done 861 | string PS1File = $@"{TempPath}TakeOwn.ps1"; 862 | File.WriteAllText(PS1File, PS1Data, Encoding.UTF8); 863 | ctrlKey = (GetAsyncKeyState(0x11) & 0x8000) != 0; 864 | string NoExit = ""; if (ctrlKey) NoExit = "-NoExit"; 865 | CommandLine = $"{NoExit} -NoLogo -NoProfile -ExecutionPolicy Bypass -file \"{PS1File}\""; 866 | } 867 | 868 | static void RunAsUser(string EXEFilename) 869 | { 870 | CreateChangeDirectoryFile(EXEFilename); 871 | 872 | Process p = new Process(); 873 | p.StartInfo.FileName = EXEFilename; 874 | p.StartInfo.Arguments = CommandLine; 875 | p.StartInfo.WorkingDirectory = @"C:\"; 876 | p.StartInfo.UseShellExecute = false; 877 | p.StartInfo.CreateNoWindow = false; 878 | p.Start(); 879 | } 880 | 881 | static void RunAsAdmin(string EXEFilename) 882 | { 883 | RunElevated(EXEFilename, "Administrator"); 884 | } 885 | 886 | static void RunAsTrusted(string EXEFilename) 887 | { 888 | RunElevated(EXEFilename, "TrustedInstaller"); 889 | } 890 | 891 | [DllImport("user32.dll")] 892 | public static extern short GetAsyncKeyState(int vKey); 893 | 894 | static void clearRegEdit() 895 | { 896 | try 897 | { 898 | Registry.CurrentUser.DeleteSubKey(@"Software\Microsoft\Windows\CurrentVersion\Applets\Regedit", false); 899 | } 900 | catch 901 | { 902 | } 903 | } 904 | 905 | static void Elevate() 906 | { 907 | string iniFile = ElevateCfg; 908 | 909 | string EXEFilename = ReadString(iniFile, "Process", "EXEFilename", ""); 910 | string CommandLine = ReadString(iniFile, "Process", "CommandLine", ""); 911 | string RunAs = ReadString(iniFile, "Process", "RunAs", ""); 912 | string Dark = ReadString(iniFile, "Process", "Dark", "false"); 913 | bool dark = Dark == "True"; 914 | 915 | File.Delete(ElevateCfg); 916 | 917 | if (RunAs == "TrustedInstaller") 918 | { 919 | ServiceController sc = new ServiceController 920 | { 921 | ServiceName = "TrustedInstaller", 922 | }; 923 | 924 | if (sc.Status != ServiceControllerStatus.Running) sc.Start(); 925 | 926 | Process[] proc = Process.GetProcessesByName("TrustedInstaller"); 927 | 928 | if (dark) TrustedInstaller.Run(proc[0].Id, $"{myExe} /Dark"); 929 | if (!dark) TrustedInstaller.Run(proc[0].Id, $"{myExe} /Light"); 930 | 931 | Thread.Sleep(100); 932 | proc = Process.GetProcessesByName("TrustedInstaller"); 933 | TrustedInstaller.Run(proc[0].Id, $"{EXEFilename} {CommandLine}"); 934 | } 935 | else 936 | { 937 | if (ctrlKey && (EXEFilename == RegEditExe)) clearRegEdit(); 938 | 939 | Process p = new Process(); 940 | p.StartInfo.FileName = EXEFilename; 941 | p.StartInfo.Arguments = CommandLine; 942 | p.StartInfo.WorkingDirectory = @"C:\"; 943 | p.StartInfo.UseShellExecute = false; 944 | p.StartInfo.CreateNoWindow = false; 945 | p.Start(); 946 | } 947 | } 948 | 949 | static void RunElevated(string EXEFilename, string mode) 950 | { 951 | CreateChangeDirectoryFile(EXEFilename); 952 | 953 | string cfg = $"[Process]\r\nEXEFilename={EXEFilename}\r\nCommandLine={CommandLine}\r\nRunAs={mode}\r\nDark={Dark}"; 954 | 955 | File.WriteAllText(ElevateCfg, cfg); 956 | 957 | if (isFullAdmin) 958 | { 959 | Process p = new Process(); 960 | p.StartInfo.FileName = SchTasksExe; 961 | p.StartInfo.Arguments = $"/run /tn \"{TaskName}\""; 962 | p.StartInfo.UseShellExecute = false; 963 | p.StartInfo.CreateNoWindow = true; 964 | p.Start(); 965 | } 966 | else 967 | { 968 | if (mode == "Administrator") 969 | { 970 | RunUAC(EXEFilename); 971 | } 972 | else 973 | { 974 | Process p = new Process(); 975 | p.StartInfo.FileName = myExe; 976 | p.StartInfo.Arguments = $"/Elevate \"{ElevateCfg}\""; 977 | p.StartInfo.UseShellExecute = true; 978 | p.StartInfo.CreateNoWindow = true; 979 | p.StartInfo.Verb = "runas"; 980 | p.Start(); 981 | } 982 | } 983 | } 984 | 985 | static void RunTakeOwnHerePS1AsAdmin() 986 | { 987 | string sStopAll = ReadString(myIniFile, "TakeOwnHere", "StopAll", ""); 988 | string[] StopAll = sStopAll.Split(new char[] { '|' }); 989 | 990 | string sStopRoot = ReadString(myIniFile, "TakeOwnHere", "StopRoot", ""); 991 | string[] StopRoot = sStopRoot.Split(new char[] { '|' }); 992 | 993 | bool Stop = false; 994 | 995 | for (int i = 0; i < StopAll.Length; i++) 996 | { 997 | if (StartsWith(StopAll[i], StartDirectory)) { Stop = true; break; } 998 | } 999 | 1000 | for (int i = 0; i < StopRoot.Length; i++) 1001 | { 1002 | if (StrCmp(StopRoot[i], StartDirectory)) { Stop = true; break; } 1003 | } 1004 | 1005 | helpPage = "take-ownership-and-get-access"; 1006 | 1007 | if (Stop) { CustomMessageBox.Show($"{sFolderNotAllowed}:\n\n{StartDirectory}\n\n", sMain); return; } 1008 | 1009 | string UserProfile = Environment.GetEnvironmentVariable("UserProfile"); 1010 | string sMsg = sTakeOwnHere; 1011 | if (StartsWith(StartDirectory, "C:\\Users\\") && !StartsWith(StartDirectory, UserProfile)) sMsg = $"{sWarningTakeOwn}\r\n\r\n{sTakeOwnHere}"; 1012 | 1013 | DialogResult result = CustomMessageBox.Show($"{sMsg}?\n\n{StartDirectory}\n\n", sMain); 1014 | 1015 | if (result == DialogResult.Cancel) return; 1016 | 1017 | CreateTakeOwnHerePS1(); 1018 | 1019 | string cfg = $"[Process]\r\nEXEFilename={PowerShellExe}\r\nCommandLine={CommandLine}\r\nRunAs=Administrator"; 1020 | 1021 | File.WriteAllText(ElevateCfg, cfg); 1022 | 1023 | if (isFullAdmin) 1024 | { 1025 | Process p = new Process(); 1026 | p.StartInfo.FileName = SchTasksExe; 1027 | p.StartInfo.Arguments = $"/run /tn \"{TaskName}\""; 1028 | p.StartInfo.UseShellExecute = false; 1029 | p.StartInfo.CreateNoWindow = true; 1030 | p.Start(); 1031 | } 1032 | else 1033 | { 1034 | RunUAC(PowerShellExe); 1035 | } 1036 | } 1037 | 1038 | static void ClearDefenderHistory() 1039 | { 1040 | CommandLine = "/ClearHistoryAdmin"; 1041 | 1042 | string cfg = $"[Process]\r\nEXEFilename={myExe}\r\nCommandLine={CommandLine}\r\nRunAs=Administrator"; 1043 | 1044 | File.WriteAllText(ElevateCfg, cfg); 1045 | 1046 | if (isFullAdmin) 1047 | { 1048 | Process p = new Process(); 1049 | p.StartInfo.FileName = SchTasksExe; 1050 | p.StartInfo.Arguments = $"/run /tn \"{TaskName}\""; 1051 | p.StartInfo.UseShellExecute = false; 1052 | p.StartInfo.CreateNoWindow = true; 1053 | p.Start(); 1054 | } 1055 | else 1056 | { 1057 | RunUAC(myExe); 1058 | } 1059 | 1060 | } 1061 | 1062 | static void ClearDefenderHistoryTask() 1063 | { 1064 | string scans = @"C:\ProgramData\Microsoft\Windows Defender\Scans"; 1065 | string service = $@"{scans}\History\Service"; 1066 | string db = $@"{scans}\mpenginedb.db*"; 1067 | 1068 | Process p = new Process(); 1069 | p.StartInfo.FileName = SchTasksExe; 1070 | p.StartInfo.Arguments = $"/create /f /tn MyTasks\\DWDH /xml \"{appParts}\\DWDH.cfg\""; 1071 | p.StartInfo.UseShellExecute = false; 1072 | p.StartInfo.CreateNoWindow = true; 1073 | p.Start(); 1074 | p.WaitForExit(); 1075 | 1076 | helpPage = "clear-history"; 1077 | 1078 | DialogResult result = CustomMessageBox.Show(sRestartPC, sMain); 1079 | 1080 | if (result == DialogResult.Cancel) return; 1081 | 1082 | Process.Start("shutdown", "/r /t 0"); 1083 | } 1084 | 1085 | static bool StrCmp(string str1, string str2) 1086 | { 1087 | return string.Equals(str1, str2, StringComparison.OrdinalIgnoreCase); 1088 | } 1089 | 1090 | static bool StartsWith(string str1, string str2) 1091 | { 1092 | int length = Math.Min(str1.Length, str2.Length); 1093 | return string.Equals(str1.Substring(0, length), str2.Substring(0, length), StringComparison.OrdinalIgnoreCase); 1094 | } 1095 | 1096 | // Get current screen scaling factor 1097 | static float GetScale() 1098 | { 1099 | using (Graphics graphics = Graphics.FromHwnd(IntPtr.Zero)) 1100 | { 1101 | float dpiX = graphics.DpiX; 1102 | return dpiX / 96; 1103 | } 1104 | } 1105 | 1106 | // Determine if dark colors (theme) are being used 1107 | public static bool isDark() 1108 | { 1109 | const string keyPath = @"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize"; 1110 | const string valueName = "AppsUseLightTheme"; 1111 | 1112 | using (RegistryKey key = Registry.CurrentUser.OpenSubKey(keyPath)) 1113 | { 1114 | if (key != null) 1115 | { 1116 | object value = key.GetValue(valueName); 1117 | if (value is int intValue) 1118 | { 1119 | return intValue == 0; 1120 | } 1121 | } 1122 | } 1123 | return false; // Return false if the key or value is missing 1124 | } 1125 | 1126 | // Make dialog title bar black 1127 | public enum DWMWINDOWATTRIBUTE : uint 1128 | { 1129 | DWMWA_USE_IMMERSIVE_DARK_MODE = 20, 1130 | } 1131 | 1132 | [DllImport("dwmapi.dll", CharSet = CharSet.Unicode, PreserveSig = false)] 1133 | public static extern void DwmSetWindowAttribute(IntPtr hwnd, DWMWINDOWATTRIBUTE attribute, ref int pvAttribute, uint cbAttribute); 1134 | 1135 | static void DarkTitleBar(IntPtr hWnd) 1136 | { 1137 | var preference = Convert.ToInt32(true); 1138 | DwmSetWindowAttribute(hWnd, DWMWINDOWATTRIBUTE.DWMWA_USE_IMMERSIVE_DARK_MODE, ref preference, sizeof(uint)); 1139 | 1140 | } 1141 | 1142 | // Load language strings from INI file 1143 | static void LoadLanguageStrings() 1144 | { 1145 | string iniFile = $@"{appParts}\language.ini"; 1146 | 1147 | if (!File.Exists(iniFile)) return; 1148 | 1149 | string lang = GetLang(); 1150 | 1151 | sMain = ReadString(iniFile, lang, "sMain", sMain); 1152 | sSetup = ReadString(iniFile, lang, "sSetup", sSetup); 1153 | sOK = ReadString(iniFile, lang, "sOK", sOK); 1154 | sYes = ReadString(iniFile, lang, "sYes", sYes); 1155 | sNo = ReadString(iniFile, lang, "sNo", sNo); 1156 | sInstall = ReadString(iniFile, lang, "sInstall", sInstall); 1157 | sRemove = ReadString(iniFile, lang, "sRemove", sRemove); 1158 | sDone = ReadString(iniFile, lang, "sDone", sDone); 1159 | sFolderNotAllowed = ReadString(iniFile, lang, "sFolderNotAllowed", sFolderNotAllowed); 1160 | sWarningTakeOwn = ReadString(iniFile, lang, "sWarningTakeOwn", sWarningTakeOwn); 1161 | sUserPath = ReadString(iniFile, lang, "sUserPath", sUserPath); 1162 | sSystemPath = ReadString(iniFile, lang, "sSystemPath", sSystemPath); 1163 | sRecent = ReadString(iniFile, lang, "sRecent", sRecent); 1164 | sAutoSuggest = ReadString(iniFile, lang, "sAutoSuggest", sAutoSuggest); 1165 | sTemp = ReadString(iniFile, lang, "sTemp", sTemp); 1166 | sDefender = ReadString(iniFile, lang, "sDefender", sDefender); 1167 | sCCM = ReadString(iniFile, lang, "sCCM", sCCM); 1168 | sRestartPC = ReadString(iniFile, lang, "sRestartPC", sRestartPC); 1169 | sOpenFileManager = ReadString(iniFile, lang, "sOpenFileManager", sOpenFileManager); 1170 | sAdministrator = ReadString(iniFile, lang, "sAdministrator", sAdministrator); 1171 | sTrustedInstaller = ReadString(iniFile, lang, "sTrustedInstaller", sTrustedInstaller); 1172 | sShellRefresh = ReadString(iniFile, lang, "sShellRefresh", sShellRefresh); 1173 | sResetIcons = ReadString(iniFile, lang, "sResetIcons", sResetIcons); 1174 | sResetThumbs = ReadString(iniFile, lang, "sResetThumbs", sResetThumbs); 1175 | sFileManager = ReadString(iniFile, lang, "sFileManager", sFileManager); 1176 | sInstallTask = ReadString(iniFile, lang, "sInstallTask", sInstallTask); 1177 | 1178 | string sCmdLabels = ReadString(iniFile, lang, "CmdLabels", ""); 1179 | string[] LangLabels = sCmdLabels.Split(new char[] { '|' }); 1180 | 1181 | for (int i = 0; i < Math.Min(CmdLabels.Length, LangLabels.Length); i++) 1182 | { 1183 | CmdLabels[i] = LangLabels[i]; 1184 | } 1185 | sClearHistory = CmdLabels[9]; 1186 | sTakeOwnHere = CmdLabels[10]; 1187 | sRestartExplorer = CmdLabels[14]; 1188 | } 1189 | 1190 | 1191 | static string ReadString(string iniFile, string section, string key, string defaultValue) 1192 | { 1193 | try 1194 | { 1195 | if (File.Exists(iniFile)) 1196 | { 1197 | return IniFileParser.ReadValue(section, key, defaultValue, iniFile); 1198 | } 1199 | } 1200 | catch { } 1201 | 1202 | return defaultValue; 1203 | } 1204 | 1205 | // INI file parser 1206 | public static class IniFileParser 1207 | { 1208 | public static string ReadValue(string section, string key, string defaultValue, string filePath) 1209 | { 1210 | try 1211 | { 1212 | var lines = File.ReadAllLines(filePath, Encoding.UTF8); 1213 | string currentSection = null; 1214 | 1215 | foreach (var line in lines) 1216 | { 1217 | string trimmedLine = line.Trim(); 1218 | 1219 | if (trimmedLine.StartsWith("[") && trimmedLine.EndsWith("]")) 1220 | { 1221 | currentSection = trimmedLine.Substring(1, trimmedLine.Length - 2); 1222 | } 1223 | else if (currentSection == section) 1224 | { 1225 | var parts = trimmedLine.Split(new char[] { '=' }, 2); 1226 | if (parts.Length == 2 && parts[0].Trim() == key) 1227 | { 1228 | return parts[1].Trim(); 1229 | } 1230 | } 1231 | } 1232 | } 1233 | catch (Exception) 1234 | { 1235 | } 1236 | return defaultValue; 1237 | } 1238 | } 1239 | 1240 | 1241 | // Get language from INI file or system 1242 | static string GetLang() 1243 | { 1244 | string lang = ReadString(myIniFile, "General", "Lang", ""); 1245 | if (lang != "") return lang; 1246 | 1247 | lang = "en"; 1248 | 1249 | try 1250 | { 1251 | RegistryKey key = Registry.CurrentUser.OpenSubKey("Control Panel\\International"); 1252 | if (key != null) 1253 | { 1254 | lang = key.GetValue("LocaleName") as string; 1255 | key.Close(); 1256 | } 1257 | } 1258 | catch { } 1259 | 1260 | try 1261 | { 1262 | RegistryKey key = Registry.CurrentUser.OpenSubKey("Control Panel\\Desktop"); 1263 | if (key != null) 1264 | { 1265 | string[] preferredLanguages = key.GetValue("PreferredUILanguages") as string[]; 1266 | if (preferredLanguages != null && preferredLanguages.Length > 0) 1267 | { 1268 | lang = preferredLanguages[0]; 1269 | } 1270 | key.Close(); 1271 | } 1272 | } 1273 | catch { } 1274 | 1275 | return lang.Substring(0, 2).ToLower(); 1276 | } 1277 | 1278 | static void InstallRemove() 1279 | { 1280 | AnyInstall = true; 1281 | 1282 | if (Win11) 1283 | { 1284 | Win11Install = true; 1285 | using (RegistryKey key = Registry.CurrentUser.OpenSubKey(CCMB)) 1286 | { 1287 | Win10ContextMenu = key != null; 1288 | } 1289 | } 1290 | 1291 | DialogResult result = TwoChoiceBox.Show(sSetup, sMain, sInstall, sRemove); 1292 | 1293 | if (result == DialogResult.Yes) 1294 | { 1295 | Install(true); 1296 | } 1297 | if (result == DialogResult.No) 1298 | { 1299 | Remove(true); 1300 | } 1301 | } 1302 | 1303 | static void ContextMenuInstall(bool HKCU) 1304 | { 1305 | RemoveContextMenuEntries(HKCU); 1306 | RemoveContextMenuEntriesCCM(HKCU); 1307 | InstallContextMenuEntries(@"Drive", HKCU); 1308 | InstallContextMenuEntries(@"Directory", HKCU); 1309 | InstallContextMenuEntries(@"Directory\Background", HKCU); 1310 | InstallContextMenuEntriesCCM(HKCU); 1311 | if (HKCU) SetWin11ContextMenu(); 1312 | } 1313 | static void ContextMenuRemove(bool HKCU) 1314 | { 1315 | RemoveContextMenuEntries(HKCU); 1316 | RemoveContextMenuEntriesCCM(HKCU); 1317 | if (HKCU) SetWin11ContextMenu(); 1318 | } 1319 | 1320 | static void Install(bool interactive) 1321 | { 1322 | ContextMenuInstall(true); 1323 | 1324 | if (!isAdmin) 1325 | { 1326 | if (interactive) CustomMessageBox.Show(sDone, sMain); 1327 | return; 1328 | } 1329 | 1330 | if (interactive) addTask = checkboxTask.Checked; 1331 | 1332 | if (addTask) 1333 | { 1334 | CommandLine = "/TaskInstallQuiet"; 1335 | if (interactive) CommandLine = "/TaskInstall"; 1336 | RunUAC(myExe); 1337 | } 1338 | else 1339 | { 1340 | if (interactive) CustomMessageBox.Show(sDone, sMain); 1341 | } 1342 | } 1343 | 1344 | static void Remove(bool interactive) 1345 | { 1346 | ContextMenuRemove(true); 1347 | 1348 | if (!isAdmin) 1349 | { 1350 | if (interactive) CustomMessageBox.Show(sDone, sMain); 1351 | return; 1352 | } 1353 | 1354 | if (removeTask && TaskExists()) 1355 | { 1356 | CommandLine = "/TaskRemoveQuiet"; 1357 | if (interactive) CommandLine = "/TaskRemove"; 1358 | RunUAC(myExe); 1359 | } 1360 | else 1361 | { 1362 | if (interactive) CustomMessageBox.Show(sDone, sMain); 1363 | } 1364 | 1365 | } 1366 | 1367 | static void HKUInstall() 1368 | { 1369 | CCMfolder = FindCustomCommandsFolder(false); 1370 | ContextMenuInstall(false); 1371 | if (addTask) TaskInstall(false); 1372 | } 1373 | 1374 | static void HKURemove() 1375 | { 1376 | CCMfolder = FindCustomCommandsFolder(false); 1377 | ContextMenuRemove(false); 1378 | TaskRemove(false); 1379 | } 1380 | 1381 | static void SetWin11ContextMenu() 1382 | { 1383 | if (!Win11) return; 1384 | 1385 | string H = @"HKEY_CURRENT_USER\"; 1386 | 1387 | if (checkboxCCM.Checked && !Win10ContextMenu) 1388 | { 1389 | try 1390 | { 1391 | Registry.SetValue($@"{H}{CCMB}", "", "", RegistryValueKind.String); 1392 | StartDirectory = myPath; 1393 | RestartExplorer(); 1394 | } 1395 | catch 1396 | { 1397 | } 1398 | } 1399 | 1400 | if (!checkboxCCM.Checked && Win10ContextMenu) 1401 | { 1402 | try 1403 | { 1404 | Registry.CurrentUser.DeleteSubKeyTree(CCMA, false); 1405 | } 1406 | catch 1407 | { 1408 | } 1409 | } 1410 | } 1411 | 1412 | static void TaskInstall(bool interactive) 1413 | { 1414 | Process p = new Process(); 1415 | p.StartInfo.FileName = SchTasksExe; 1416 | p.StartInfo.Arguments = $"/delete /f /tn \"{TaskName}\""; 1417 | p.StartInfo.UseShellExecute = false; 1418 | p.StartInfo.CreateNoWindow = true; 1419 | p.Start(); 1420 | p.WaitForExit(); 1421 | 1422 | string XMLFile = $@"{TempPath}Task.xml"; 1423 | string XMLData = File.ReadAllText($@"{appParts}\Task.cfg"); 1424 | XMLData = XMLData.Replace("{myPath}", myPath); 1425 | XMLData = XMLData.Replace("{bitPath}", bitPath); 1426 | File.WriteAllText(XMLFile, XMLData, Encoding.Unicode); 1427 | 1428 | p = new Process(); 1429 | p.StartInfo.FileName = SchTasksExe; 1430 | p.StartInfo.Arguments = $"/create /f /xml \"{XMLFile}\" /tn \"{TaskName}\""; 1431 | p.StartInfo.UseShellExecute = false; 1432 | p.StartInfo.CreateNoWindow = true; 1433 | p.Start(); 1434 | p.WaitForExit(); 1435 | 1436 | File.Delete(XMLFile); 1437 | 1438 | if (interactive) CustomMessageBox.Show(sDone, sMain); 1439 | } 1440 | 1441 | static void TaskRemove(bool interactive) 1442 | { 1443 | Process p = new Process(); 1444 | p.StartInfo.FileName = SchTasksExe; 1445 | p.StartInfo.Arguments = $"/delete /f /tn \"{TaskName}\""; 1446 | p.StartInfo.UseShellExecute = false; 1447 | p.StartInfo.CreateNoWindow = true; 1448 | p.Start(); 1449 | p.WaitForExit(); 1450 | 1451 | if (interactive) CustomMessageBox.Show(sDone, sMain); 1452 | } 1453 | 1454 | static void InstallContextMenuEntries(string thiskey, bool HKCU) 1455 | { 1456 | RegistryKey baseKey = Registry.CurrentUser; 1457 | 1458 | if (!HKCU) 1459 | { 1460 | if (userSID == "") return; 1461 | baseKey = Registry.Users.OpenSubKey(userSID, true); 1462 | } 1463 | 1464 | string MyKey = $@"Software\Classes\{thiskey}\shell\{myName}"; 1465 | 1466 | using (RegistryKey key = baseKey.CreateSubKey(MyKey)) 1467 | { 1468 | key.SetValue("SubCommands", ""); 1469 | key.SetValue("", ""); 1470 | key.SetValue("MUIVerb", sMain); 1471 | key.SetValue("Icon", myExe); 1472 | } 1473 | 1474 | for (int i = 0; i < CmdKeys.Length; i++) 1475 | { 1476 | using (RegistryKey key = baseKey.CreateSubKey($@"{MyKey}\shell\{i:D2}-{CmdKeys[i]}")) 1477 | { 1478 | key.SetValue("", CmdLabels[i]); 1479 | key.SetValue("Icon", $@"{appParts}\Icons\{CmdKeys[i]}.ico"); 1480 | 1481 | using (RegistryKey commandKey = key.CreateSubKey("command")) 1482 | { 1483 | string CmdLine = $"\"{myExe}\" /{CmdKeys[i]}"; 1484 | if (CmdKeys[i].Substring(CmdKeys[i].Length - 4) == "Here") CmdLine += " \"%v|\""; 1485 | commandKey.SetValue("", CmdLine); 1486 | } 1487 | } 1488 | } 1489 | } 1490 | 1491 | static void InstallContextMenuEntriesCCM(bool HKCU) 1492 | { 1493 | if (CCMfolder == null) return; 1494 | string exe = myExe.Replace(@"\", @"\\"); 1495 | 1496 | for (int i = 0; i < CmdKeys.Length; i++) 1497 | { 1498 | string icon = $@"{appParts}\Icons\{CmdKeys[i]}.ico"; 1499 | icon = icon.Replace(@"\", @"\\"); 1500 | string JSONFile = $@"{CCMfolder}\{CmdLabels[i]}.JSON"; 1501 | string JSONData = File.ReadAllText($@"{appParts}\JSON.cfg"); 1502 | JSONData = JSONData.Replace("{i}", $"{i+100}"); 1503 | JSONData = JSONData.Replace("{label}", CmdLabels[i]); 1504 | JSONData = JSONData.Replace("{exe}", exe); 1505 | JSONData = JSONData.Replace("{cmdline}", $@"/{CmdKeys[i]}"); 1506 | JSONData = JSONData.Replace("{icon}", icon); 1507 | File.WriteAllText(JSONFile, JSONData); 1508 | } 1509 | } 1510 | 1511 | static void RemoveContextMenuEntriesCCM(bool HKCU) 1512 | { 1513 | if (CCMfolder == null) return; 1514 | 1515 | DirectoryInfo directory = new DirectoryInfo(CCMfolder); 1516 | 1517 | foreach (FileInfo file in directory.GetFiles("*.JSON")) 1518 | { 1519 | if (File.ReadAllText(file.FullName).Contains(myName)) 1520 | { 1521 | file.Delete(); 1522 | } 1523 | } 1524 | } 1525 | 1526 | static void RemoveContextMenuEntries(bool HKCU) 1527 | { 1528 | RegistryKey baseKey = Registry.CurrentUser; 1529 | if (!HKCU) baseKey = Registry.Users.OpenSubKey(userSID, true); 1530 | 1531 | using (RegistryKey key = baseKey.OpenSubKey(@"Software\Classes\Drive\shell", true)) 1532 | { 1533 | try { key.DeleteSubKeyTree(myName, false); } 1534 | catch { } 1535 | } 1536 | using (RegistryKey key = baseKey.OpenSubKey(@"Software\Classes\Directory\shell", true)) 1537 | { 1538 | try { key.DeleteSubKeyTree(myName, false); } 1539 | catch { } 1540 | } 1541 | using (RegistryKey key = baseKey.OpenSubKey(@"Software\Classes\Directory\Background\shell", true)) 1542 | { 1543 | try { key.DeleteSubKeyTree(myName, false); } 1544 | catch { } 1545 | } 1546 | 1547 | } 1548 | 1549 | static string FindCustomCommandsFolder(bool HKCU) 1550 | { 1551 | string packagesFolderPath = $@"{Environment.GetEnvironmentVariable("LocalAppData")}\Packages"; 1552 | 1553 | if (!HKCU) 1554 | { 1555 | string keyPath = $@"HKEY_USERS\{userSID}\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders"; 1556 | packagesFolderPath = $@"{(string)Registry.GetValue(keyPath, @"Local AppData", "")}\Packages"; 1557 | } 1558 | 1559 | if (!Directory.Exists(packagesFolderPath)) return null; 1560 | 1561 | string[] packageFolders = Directory.GetDirectories(packagesFolderPath); 1562 | 1563 | foreach (string packageFolder in packageFolders) 1564 | { 1565 | string customCommandsPath = Path.Combine(packageFolder, @"LocalState\custom_commands"); 1566 | if (Directory.Exists(customCommandsPath)) return customCommandsPath; 1567 | } 1568 | return null; 1569 | } 1570 | 1571 | 1572 | // Dialog for simple OK messages 1573 | public class CustomMessageBox : Form 1574 | { 1575 | private Label messageLabel; 1576 | private Label buttonHelp; 1577 | private Button buttonOK; 1578 | 1579 | public CustomMessageBox(string message, string caption) 1580 | { 1581 | message = $"\n{message}"; 1582 | 1583 | Icon = new Icon(myIcon); 1584 | StartPosition = FormStartPosition.Manual; 1585 | FormBorderStyle = FormBorderStyle.FixedDialog; 1586 | Text = caption; 1587 | Width = (int)(300 * ScaleFactor); 1588 | Height = (int)(150 * ScaleFactor); 1589 | MaximizeBox = false; 1590 | MinimizeBox = false; 1591 | 1592 | messageLabel = new Label(); 1593 | messageLabel.Text = message; 1594 | messageLabel.Font = new Font("Segoe UI", 10); 1595 | messageLabel.TextAlign = ContentAlignment.TopCenter; 1596 | messageLabel.Dock = DockStyle.Fill; 1597 | 1598 | using (Graphics g = CreateGraphics()) 1599 | { 1600 | SizeF size = g.MeasureString(message, new Font("Segoe UI", 10), Width); 1601 | Height = Math.Max(Height, (int)(size.Height + (int)(100 * ScaleFactor))); 1602 | } 1603 | 1604 | buttonHelp = new Label(); 1605 | Image image = Image.FromFile($@"{appParts}\Icons\Question.png"); 1606 | Bitmap scaledImage = new Bitmap((int)(26 * ScaleFactor), (int)(26 * ScaleFactor)); 1607 | using (Graphics g = Graphics.FromImage(scaledImage)) 1608 | { 1609 | g.InterpolationMode = InterpolationMode.HighQualityBicubic; 1610 | g.DrawImage(image, 0, 0, (int)(26 * ScaleFactor), (int)(26 * ScaleFactor)); 1611 | } 1612 | buttonHelp.BackgroundImage = scaledImage; 1613 | buttonHelp.BackgroundImageLayout = ImageLayout.Stretch; 1614 | buttonHelp.Size = new Size((int)(26 * ScaleFactor), (int)(26 * ScaleFactor)); 1615 | buttonHelp.FlatStyle = FlatStyle.Flat; 1616 | buttonHelp.Left = ClientSize.Width - (int)(30 * ScaleFactor); 1617 | buttonHelp.Top = (int)(4 * ScaleFactor); 1618 | buttonHelp.Click += ButtonHelp_Click; 1619 | 1620 | messageLabel.Padding = new Padding(0, 0, (int)(26 * ScaleFactor), 0); 1621 | 1622 | buttonOK = new Button(); 1623 | buttonOK.Text = sOK; 1624 | buttonOK.DialogResult = DialogResult.OK; 1625 | buttonOK.Font = new Font("Segoe UI", 9); 1626 | buttonOK.Width = (int)(75 * ScaleFactor); 1627 | buttonOK.Height = (int)(26 * ScaleFactor); 1628 | buttonOK.Left = (ClientSize.Width - buttonOK.Width) / 2; 1629 | buttonOK.Top = ClientSize.Height - buttonOK.Height - (int)(10 * ScaleFactor); 1630 | if (Dark) 1631 | { 1632 | buttonOK.FlatStyle = FlatStyle.Flat; 1633 | buttonOK.FlatAppearance.BorderColor = SystemColors.Highlight; 1634 | buttonOK.FlatAppearance.BorderSize = 1; 1635 | buttonOK.BackColor = Color.FromArgb(60, 60, 60); 1636 | buttonOK.FlatAppearance.MouseOverBackColor = Color.Black; 1637 | DarkTitleBar(Handle); 1638 | BackColor = Color.FromArgb(32, 32, 32); 1639 | ForeColor = Color.White; 1640 | } 1641 | Controls.Add(buttonHelp); 1642 | Controls.Add(buttonOK); 1643 | Controls.Add(messageLabel); 1644 | 1645 | Point cursorPosition = Cursor.Position; 1646 | int dialogX = Cursor.Position.X - Width / 2; 1647 | int dialogY = Cursor.Position.Y - Height / 2 - (int)(50 * ScaleFactor); 1648 | Screen screen = Screen.FromPoint(cursorPosition); 1649 | int screenWidth = screen.WorkingArea.Width; 1650 | int screenHeight = screen.WorkingArea.Height; 1651 | int baseX = screen.Bounds.X; 1652 | int baseY = screen.Bounds.Y; 1653 | dialogX = Math.Max(baseX, Math.Min(baseX + screenWidth - Width, dialogX)); 1654 | dialogY = Math.Max(baseY, Math.Min(baseY + screenHeight - Height, dialogY)); 1655 | Location = new Point(dialogX, dialogY); 1656 | } 1657 | public static DialogResult Show(string message, string caption) 1658 | { 1659 | using (var customMessageBox = new CustomMessageBox(message, caption)) 1660 | { 1661 | return customMessageBox.ShowDialog(); 1662 | } 1663 | } 1664 | 1665 | } 1666 | 1667 | static void GetCheckboxChoice() 1668 | { 1669 | fLatCB = ReadString(myIniFile, "General", "AlternateCheckbox", "1") == "1"; 1670 | } 1671 | 1672 | // Dialog for install/Remove and Yes/No 1673 | public class TwoChoiceBox : Form 1674 | { 1675 | private Label messageLabel; 1676 | private Label buttonHelp; 1677 | private Button buttonYes; 1678 | private Button buttonNo; 1679 | 1680 | public TwoChoiceBox(string message, string caption, string button1, string button2) 1681 | { 1682 | GetCheckboxChoice(); 1683 | int b2Width = (int)(bwidth * ScaleFactor); 1684 | using (Graphics g = CreateGraphics()) 1685 | { 1686 | SizeF size = g.MeasureString(button2, new Font("Segoe UI", 9)); 1687 | b2Width = Math.Max((int)size.Width, b2Width); 1688 | } 1689 | message = $"\n{message}"; 1690 | 1691 | Icon = new Icon(myIcon); 1692 | StartPosition = FormStartPosition.Manual; 1693 | Text = caption; 1694 | Width = (int)(300 * ScaleFactor); 1695 | int h = 150; if (AnyInstall) h = 174; if (Win11Install) h = 194; 1696 | Height = (int)(h * ScaleFactor); 1697 | FormBorderStyle = FormBorderStyle.FixedDialog; 1698 | MaximizeBox = false; 1699 | MinimizeBox = false; 1700 | 1701 | messageLabel = new Label(); 1702 | messageLabel.Text = message; 1703 | messageLabel.Font = new Font("Segoe UI", 10); 1704 | messageLabel.TextAlign = ContentAlignment.TopCenter; 1705 | messageLabel.Dock = DockStyle.Fill; 1706 | 1707 | using (Graphics g = CreateGraphics()) 1708 | { 1709 | SizeF size = g.MeasureString(message, new Font("Segoe UI", 10), Width); 1710 | Height = Math.Max(Height, (int)(size.Height + (int)(100 * ScaleFactor))); 1711 | } 1712 | 1713 | buttonHelp = new Label(); 1714 | Image image = Image.FromFile($@"{appParts}\Icons\Question.png"); 1715 | Bitmap scaledImage = new Bitmap((int)(26 * ScaleFactor), (int)(26 * ScaleFactor)); 1716 | using (Graphics g = Graphics.FromImage(scaledImage)) 1717 | { 1718 | g.InterpolationMode = InterpolationMode.HighQualityBicubic; 1719 | g.DrawImage(image, 0, 0, (int)(26 * ScaleFactor), (int)(26 * ScaleFactor)); 1720 | } 1721 | buttonHelp.BackgroundImage = scaledImage; 1722 | buttonHelp.BackgroundImageLayout = ImageLayout.Stretch; 1723 | buttonHelp.Size = new Size((int)(26 * ScaleFactor), (int)(26 * ScaleFactor)); 1724 | buttonHelp.FlatStyle = FlatStyle.Flat; 1725 | buttonHelp.Left = ClientSize.Width - (int)(30 * ScaleFactor); 1726 | buttonHelp.Top = (int)(4 * ScaleFactor); 1727 | buttonHelp.Click += ButtonHelp_Click; 1728 | 1729 | messageLabel.Padding = new Padding(0, 0, (int)(26 * ScaleFactor), 0); 1730 | 1731 | checkboxTask = new CheckBox(); 1732 | checkboxTask.Font = new Font("Segoe UI", 10); 1733 | checkboxTask.Text = sInstallTask; 1734 | checkboxTask.Checked = true; 1735 | checkboxTask.AutoSize = true; 1736 | checkboxTask.Location = new Point((int)(12 * ScaleFactor), (int)(60 * ScaleFactor)); 1737 | if (fLatCB) checkboxTask.FlatStyle = FlatStyle.Flat; 1738 | 1739 | checkboxCCM = new CheckBox(); 1740 | checkboxCCM.Font = new Font("Segoe UI", 10); 1741 | checkboxCCM.Text = sCCM; 1742 | checkboxCCM.Checked = Win10ContextMenu; 1743 | checkboxCCM.AutoSize = true; 1744 | checkboxCCM.Location = new Point((int)(12 * ScaleFactor), (int)(86 * ScaleFactor)); 1745 | if (fLatCB) checkboxCCM.FlatStyle = FlatStyle.Flat; 1746 | 1747 | buttonYes = new Button(); 1748 | buttonYes.Text = button1; 1749 | buttonYes.Font = new Font("Segoe UI", 9); 1750 | buttonYes.MinimumSize = new Size((int)(bwidth * ScaleFactor), (int)(26 * ScaleFactor)); 1751 | buttonYes.Left = (int)(10 * ScaleFactor); 1752 | buttonYes.Top = ClientSize.Height - buttonYes.Height - (int)(12 * ScaleFactor); 1753 | buttonYes.DialogResult = DialogResult.Yes; 1754 | 1755 | buttonNo = new Button(); 1756 | buttonNo.Text = button2; 1757 | buttonNo.Font = new Font("Segoe UI", 9); 1758 | buttonNo.MinimumSize = new Size((int)(bwidth * ScaleFactor), (int)(26 * ScaleFactor)); 1759 | buttonNo.Left = ClientSize.Width - b2Width - (int)(16 * ScaleFactor); 1760 | buttonNo.Top = ClientSize.Height - buttonNo.Height - (int)(12 * ScaleFactor); 1761 | buttonNo.DialogResult = DialogResult.No; 1762 | 1763 | if (Dark) 1764 | { 1765 | buttonYes.FlatStyle = FlatStyle.Flat; 1766 | buttonYes.FlatAppearance.BorderColor = SystemColors.Highlight; 1767 | buttonYes.FlatAppearance.BorderSize = 1; 1768 | buttonYes.BackColor = Color.FromArgb(60, 60, 60); 1769 | buttonYes.FlatAppearance.MouseOverBackColor = Color.Black; 1770 | buttonNo.FlatStyle = FlatStyle.Flat; 1771 | buttonNo.FlatAppearance.BorderColor = SystemColors.Highlight; 1772 | buttonNo.FlatAppearance.BorderSize = 1; 1773 | buttonNo.BackColor = Color.FromArgb(60, 60, 60); 1774 | buttonNo.FlatAppearance.MouseOverBackColor = Color.Black; 1775 | DarkTitleBar(Handle); 1776 | BackColor = Color.FromArgb(32, 32, 32); 1777 | ForeColor = Color.White; 1778 | } 1779 | 1780 | if (AnyInstall) Controls.Add(checkboxTask); 1781 | if (Win11Install) Controls.Add(checkboxCCM); 1782 | Controls.Add(buttonHelp); 1783 | Controls.Add(buttonYes); 1784 | Controls.Add(buttonNo); 1785 | Controls.Add(messageLabel); 1786 | 1787 | Point cursorPosition = Cursor.Position; 1788 | int dialogX = Cursor.Position.X - Width / 2; 1789 | int x = 50; if (Win11Install) x = 40; 1790 | int dialogY = Cursor.Position.Y - Height / 2 - (int)(x * ScaleFactor); 1791 | Screen screen = Screen.FromPoint(cursorPosition); 1792 | int screenWidth = screen.WorkingArea.Width; 1793 | int screenHeight = screen.WorkingArea.Height; 1794 | int baseX = screen.Bounds.X; 1795 | int baseY = screen.Bounds.Y; 1796 | dialogX = Math.Max(baseX, Math.Min(baseX + screenWidth - Width, dialogX)); 1797 | dialogY = Math.Max(baseY, Math.Min(baseY + screenHeight - Height, dialogY)); 1798 | Location = new Point(dialogX, dialogY); 1799 | } 1800 | 1801 | public static DialogResult Show(string message, string caption, string button1, string button2) 1802 | { 1803 | using (var TwoChoiceBox = new TwoChoiceBox(message, caption, button1, button2)) 1804 | { 1805 | return TwoChoiceBox.ShowDialog(); 1806 | } 1807 | } 1808 | 1809 | } 1810 | 1811 | static void ButtonHelp_Click(object sender, EventArgs e) 1812 | { 1813 | Process.Start("https://lesferch.github.io/RightClickTools#" + helpPage); 1814 | } 1815 | 1816 | // Dialog for Add-Del Path 1817 | public class AddDelPathDialog : Form 1818 | { 1819 | private Label messageLabel; 1820 | private Label buttonHelp; 1821 | private Button buttonOK; 1822 | 1823 | public AddDelPathDialog(string message, string caption) 1824 | { 1825 | GetCheckboxChoice(); 1826 | message = $"\n\n\n\n{message}"; 1827 | 1828 | Icon = new Icon(myIcon); 1829 | StartPosition = FormStartPosition.Manual; 1830 | FormBorderStyle = FormBorderStyle.FixedDialog; 1831 | Text = caption; 1832 | Width = (int)(300 * ScaleFactor); 1833 | Height = (int)(150 * ScaleFactor); 1834 | MaximizeBox = false; 1835 | MinimizeBox = false; 1836 | 1837 | messageLabel = new Label(); 1838 | messageLabel.Text = message; 1839 | messageLabel.Font = new Font("Segoe UI", 10); 1840 | messageLabel.TextAlign = ContentAlignment.TopCenter; 1841 | messageLabel.Dock = DockStyle.Fill; 1842 | 1843 | using (Graphics g = CreateGraphics()) 1844 | { 1845 | SizeF size = g.MeasureString(message, new Font("Segoe UI", 10), Width); 1846 | Height = Math.Max(Height, (int)(size.Height + (int)(100 * ScaleFactor))); 1847 | } 1848 | 1849 | buttonHelp = new Label(); 1850 | Image image = Image.FromFile($@"{appParts}\Icons\Question.png"); 1851 | Bitmap scaledImage = new Bitmap((int)(26 * ScaleFactor), (int)(26 * ScaleFactor)); 1852 | using (Graphics g = Graphics.FromImage(scaledImage)) 1853 | { 1854 | g.InterpolationMode = InterpolationMode.HighQualityBicubic; 1855 | g.DrawImage(image, 0, 0, (int)(26 * ScaleFactor), (int)(26 * ScaleFactor)); 1856 | } 1857 | buttonHelp.BackgroundImage = scaledImage; 1858 | buttonHelp.BackgroundImageLayout = ImageLayout.Stretch; 1859 | buttonHelp.Size = new Size((int)(26 * ScaleFactor), (int)(26 * ScaleFactor)); 1860 | buttonHelp.FlatStyle = FlatStyle.Flat; 1861 | buttonHelp.Left = ClientSize.Width - (int)(30 * ScaleFactor); 1862 | buttonHelp.Top = (int)(4 * ScaleFactor); 1863 | buttonHelp.Click += ButtonHelp_Click; 1864 | helpPage = "add-or-remove-folder-in-path-variable"; 1865 | 1866 | buttonOK = new Button(); 1867 | buttonOK.Text = sOK; 1868 | buttonOK.DialogResult = DialogResult.OK; 1869 | buttonOK.Font = new Font("Segoe UI", 9); 1870 | buttonOK.Width = (int)(75 * ScaleFactor); 1871 | buttonOK.Height = (int)(26 * ScaleFactor); 1872 | buttonOK.Left = (ClientSize.Width - buttonOK.Width) / 2; 1873 | buttonOK.Top = ClientSize.Height - buttonOK.Height - (int)(10 * ScaleFactor); 1874 | 1875 | userPathCheckbox = new CheckBox(); 1876 | userPathCheckbox.Font = new Font("Segoe UI", 10); 1877 | userPathCheckbox.Text = sUserPath; 1878 | userPathCheckbox.Checked = InUserPath; 1879 | userPathCheckbox.AutoSize = true; 1880 | userPathCheckbox.Location = new Point((int)(8 * ScaleFactor), (int)(16 * ScaleFactor)); 1881 | if (fLatCB) userPathCheckbox.FlatStyle = FlatStyle.Flat; 1882 | 1883 | systemPathCheckbox = new CheckBox(); 1884 | systemPathCheckbox.Font = new Font("Segoe UI", 10); 1885 | systemPathCheckbox.Text = sSystemPath; 1886 | systemPathCheckbox.Checked = InSystemPath; 1887 | systemPathCheckbox.AutoSize = true; 1888 | systemPathCheckbox.Location = new Point((int)(8 * ScaleFactor), (int)(40 * ScaleFactor)); 1889 | if (fLatCB) systemPathCheckbox.FlatStyle = FlatStyle.Flat; 1890 | 1891 | if (Dark) 1892 | { 1893 | buttonOK.FlatStyle = FlatStyle.Flat; 1894 | buttonOK.FlatAppearance.BorderColor = SystemColors.Highlight; 1895 | buttonOK.FlatAppearance.BorderSize = 1; 1896 | buttonOK.BackColor = Color.FromArgb(60, 60, 60); 1897 | buttonOK.FlatAppearance.MouseOverBackColor = Color.Black; 1898 | DarkTitleBar(Handle); 1899 | BackColor = Color.FromArgb(32, 32, 32); 1900 | ForeColor = Color.White; 1901 | } 1902 | 1903 | Controls.Add(buttonHelp); 1904 | Controls.Add(userPathCheckbox); 1905 | Controls.Add(systemPathCheckbox); 1906 | Controls.Add(buttonOK); 1907 | Controls.Add(messageLabel); 1908 | 1909 | Point cursorPosition = Cursor.Position; 1910 | int dialogX = Cursor.Position.X - Width / 2; 1911 | int dialogY = Cursor.Position.Y - Height / 2 - (int)(50 * ScaleFactor); 1912 | Screen screen = Screen.FromPoint(cursorPosition); 1913 | int screenWidth = screen.WorkingArea.Width; 1914 | int screenHeight = screen.WorkingArea.Height; 1915 | int baseX = screen.Bounds.X; 1916 | int baseY = screen.Bounds.Y; 1917 | dialogX = Math.Max(baseX, Math.Min(baseX + screenWidth - Width, dialogX)); 1918 | dialogY = Math.Max(baseY, Math.Min(baseY + screenHeight - Height, dialogY)); 1919 | Location = new Point(dialogX, dialogY); 1920 | } 1921 | 1922 | public static DialogResult Show(string message, string caption) 1923 | { 1924 | using (var AddDelPathDialog = new AddDelPathDialog(message, caption)) 1925 | { 1926 | return AddDelPathDialog.ShowDialog(); 1927 | } 1928 | } 1929 | } 1930 | 1931 | // Dialog for Shell Refresh 1932 | public class ShellRefreshDialog : Form 1933 | { 1934 | private Label messageLabel; 1935 | private Label buttonHelp; 1936 | private Button buttonOK; 1937 | 1938 | public ShellRefreshDialog(string message, string caption) 1939 | { 1940 | GetCheckboxChoice(); 1941 | message = $"\n\n\n\n{message}"; 1942 | 1943 | Icon = new Icon(myIcon); 1944 | StartPosition = FormStartPosition.Manual; 1945 | FormBorderStyle = FormBorderStyle.FixedDialog; 1946 | Text = caption; 1947 | Width = (int)(300 * ScaleFactor); 1948 | Height = (int)(150 * ScaleFactor); 1949 | MaximizeBox = false; 1950 | MinimizeBox = false; 1951 | 1952 | messageLabel = new Label(); 1953 | messageLabel.Text = message; 1954 | messageLabel.Font = new Font("Segoe UI", 10); 1955 | messageLabel.TextAlign = ContentAlignment.TopCenter; 1956 | messageLabel.Dock = DockStyle.Fill; 1957 | 1958 | using (Graphics g = CreateGraphics()) 1959 | { 1960 | SizeF size = g.MeasureString(message, new Font("Segoe UI", 10), Width); 1961 | Height = Math.Max(Height, (int)(size.Height + (int)(100 * ScaleFactor))); 1962 | } 1963 | 1964 | buttonHelp = new Label(); 1965 | Image image1 = Image.FromFile($@"{appParts}\Icons\Question.png"); 1966 | Bitmap scaledImage1 = new Bitmap((int)(26 * ScaleFactor), (int)(26 * ScaleFactor)); 1967 | using (Graphics g = Graphics.FromImage(scaledImage1)) 1968 | { 1969 | g.InterpolationMode = InterpolationMode.HighQualityBicubic; 1970 | g.DrawImage(image1, 0, 0, (int)(26 * ScaleFactor), (int)(26 * ScaleFactor)); 1971 | } 1972 | Image image2 = Image.FromFile($@"{appParts}\Icons\Question.png"); 1973 | Bitmap scaledImage2 = new Bitmap((int)(26 * ScaleFactor), (int)(26 * ScaleFactor)); 1974 | using (Graphics g = Graphics.FromImage(scaledImage2)) 1975 | { 1976 | g.InterpolationMode = InterpolationMode.HighQualityBicubic; 1977 | g.DrawImage(image2, 0, 0, (int)(26 * ScaleFactor), (int)(26 * ScaleFactor)); 1978 | } 1979 | buttonHelp.BackgroundImage = scaledImage1; 1980 | buttonHelp.BackgroundImageLayout = ImageLayout.Stretch; 1981 | buttonHelp.Size = new Size((int)(26 * ScaleFactor), (int)(26 * ScaleFactor)); 1982 | buttonHelp.FlatStyle = FlatStyle.Flat; 1983 | buttonHelp.Left = ClientSize.Width - (int)(30 * ScaleFactor); 1984 | buttonHelp.Top = (int)(4 * ScaleFactor); 1985 | buttonHelp.Click += ButtonHelp_Click; 1986 | helpPage = "refresh-shell"; 1987 | 1988 | buttonOK = new Button(); 1989 | buttonOK.Text = sOK; 1990 | buttonOK.DialogResult = DialogResult.OK; 1991 | buttonOK.Font = new Font("Segoe UI", 9); 1992 | buttonOK.Width = (int)(75 * ScaleFactor); 1993 | buttonOK.Height = (int)(26 * ScaleFactor); 1994 | buttonOK.Left = (ClientSize.Width - buttonOK.Width) / 2; 1995 | buttonOK.Top = ClientSize.Height - buttonOK.Height - (int)(10 * ScaleFactor); 1996 | 1997 | ShellRefreshCheckbox = new CheckBox(); 1998 | ShellRefreshCheckbox.Font = new Font("Segoe UI", 10); 1999 | ShellRefreshCheckbox.Text = sShellRefresh; 2000 | ShellRefreshCheckbox.AutoSize = true; 2001 | ShellRefreshCheckbox.Location = new Point((int)(8 * ScaleFactor), (int)(16 * ScaleFactor)); 2002 | ShellRefreshCheckbox.Checked = true; 2003 | ShellRefreshCheckbox.CheckedChanged += new EventHandler(CB1); 2004 | if (fLatCB) ShellRefreshCheckbox.FlatStyle = FlatStyle.Flat; 2005 | 2006 | iconCacheCheckbox = new CheckBox(); 2007 | iconCacheCheckbox.Font = new Font("Segoe UI", 10); 2008 | iconCacheCheckbox.Text = sResetIcons; 2009 | iconCacheCheckbox.AutoSize = true; 2010 | iconCacheCheckbox.Location = new Point((int)(8 * ScaleFactor), (int)(40 * ScaleFactor)); 2011 | iconCacheCheckbox.CheckedChanged += new EventHandler(CB2); 2012 | if (fLatCB) iconCacheCheckbox.FlatStyle = FlatStyle.Flat; 2013 | 2014 | thumbCacheCheckbox = new CheckBox(); 2015 | thumbCacheCheckbox.Font = new Font("Segoe UI", 10); 2016 | thumbCacheCheckbox.Text = sResetThumbs; 2017 | thumbCacheCheckbox.AutoSize = true; 2018 | thumbCacheCheckbox.Location = new Point((int)(8 * ScaleFactor), (int)(64 * ScaleFactor)); 2019 | thumbCacheCheckbox.CheckedChanged += new EventHandler(CB2); 2020 | if (fLatCB) thumbCacheCheckbox.FlatStyle = FlatStyle.Flat; 2021 | 2022 | if (Dark) 2023 | { 2024 | buttonOK.FlatStyle = FlatStyle.Flat; 2025 | buttonOK.FlatAppearance.BorderColor = SystemColors.Highlight; 2026 | buttonOK.FlatAppearance.BorderSize = 1; 2027 | buttonOK.BackColor = Color.FromArgb(60, 60, 60); 2028 | buttonOK.FlatAppearance.MouseOverBackColor = Color.Black; 2029 | DarkTitleBar(Handle); 2030 | BackColor = Color.FromArgb(32, 32, 32); 2031 | ForeColor = Color.White; 2032 | } 2033 | 2034 | Controls.Add(buttonHelp); 2035 | Controls.Add(ShellRefreshCheckbox); 2036 | Controls.Add(iconCacheCheckbox); 2037 | Controls.Add(thumbCacheCheckbox); 2038 | Controls.Add(buttonOK); 2039 | Controls.Add(messageLabel); 2040 | 2041 | Point cursorPosition = Cursor.Position; 2042 | int dialogX = Cursor.Position.X - Width / 2; 2043 | int dialogY = Cursor.Position.Y - Height / 2 - (int)(50 * ScaleFactor); 2044 | Screen screen = Screen.FromPoint(cursorPosition); 2045 | int screenWidth = screen.WorkingArea.Width; 2046 | int screenHeight = screen.WorkingArea.Height; 2047 | int baseX = screen.Bounds.X; 2048 | int baseY = screen.Bounds.Y; 2049 | dialogX = Math.Max(baseX, Math.Min(baseX + screenWidth - Width, dialogX)); 2050 | dialogY = Math.Max(baseY, Math.Min(baseY + screenHeight - Height, dialogY)); 2051 | Location = new Point(dialogX, dialogY); 2052 | } 2053 | 2054 | private void CB1(object sender, EventArgs e) 2055 | { 2056 | if (ShellRefreshCheckbox.Checked) 2057 | { 2058 | iconCacheCheckbox.Checked = false; 2059 | thumbCacheCheckbox.Checked = false; 2060 | } 2061 | if (!iconCacheCheckbox.Checked && !thumbCacheCheckbox.Checked) 2062 | { 2063 | ShellRefreshCheckbox.Checked = true; 2064 | } 2065 | 2066 | } 2067 | private void CB2(object sender, EventArgs e) 2068 | { 2069 | if (iconCacheCheckbox.Checked || thumbCacheCheckbox.Checked) 2070 | { 2071 | ShellRefreshCheckbox.Checked = false; 2072 | } 2073 | else 2074 | { 2075 | ShellRefreshCheckbox.Checked = true; 2076 | } 2077 | } 2078 | 2079 | 2080 | public static DialogResult Show(string message, string caption) 2081 | { 2082 | using (var ShellRefreshDialog = new ShellRefreshDialog(message, caption)) 2083 | { 2084 | return ShellRefreshDialog.ShowDialog(); 2085 | } 2086 | } 2087 | } 2088 | 2089 | // Dialog for Clear History 2090 | public class ClearHistoryDialog : Form 2091 | { 2092 | private Label messageLabel; 2093 | private Button buttonOK; 2094 | private Label buttonHelp; 2095 | 2096 | public ClearHistoryDialog(string message, string caption) 2097 | { 2098 | GetCheckboxChoice(); 2099 | message = $"\n\n\n\n\n\n\n{message}?"; 2100 | 2101 | Icon = new Icon(myIcon); 2102 | StartPosition = FormStartPosition.Manual; 2103 | FormBorderStyle = FormBorderStyle.FixedDialog; 2104 | Text = caption; 2105 | Width = (int)(300 * ScaleFactor); 2106 | Height = (int)(150 * ScaleFactor); 2107 | MaximizeBox = false; 2108 | MinimizeBox = false; 2109 | 2110 | messageLabel = new Label(); 2111 | messageLabel.Text = message; 2112 | messageLabel.Font = new Font("Segoe UI", 10); 2113 | messageLabel.TextAlign = ContentAlignment.TopCenter; 2114 | messageLabel.Dock = DockStyle.Fill; 2115 | 2116 | using (Graphics g = CreateGraphics()) 2117 | { 2118 | SizeF size = g.MeasureString(message, new Font("Segoe UI", 10), Width); 2119 | Height = Math.Max(Height, (int)(size.Height + (int)(100 * ScaleFactor))); 2120 | } 2121 | 2122 | buttonHelp = new Label(); 2123 | Image image = Image.FromFile($@"{appParts}\Icons\Question.png"); 2124 | Bitmap scaledImage = new Bitmap((int)(26 * ScaleFactor), (int)(26 * ScaleFactor)); 2125 | using (Graphics g = Graphics.FromImage(scaledImage)) 2126 | { 2127 | g.InterpolationMode = InterpolationMode.HighQualityBicubic; 2128 | g.DrawImage(image, 0, 0, (int)(26 * ScaleFactor), (int)(26 * ScaleFactor)); 2129 | } 2130 | buttonHelp.BackgroundImage = scaledImage; 2131 | buttonHelp.BackgroundImageLayout = ImageLayout.Stretch; 2132 | buttonHelp.Size = new Size((int)(26 * ScaleFactor), (int)(26 * ScaleFactor)); 2133 | buttonHelp.FlatStyle = FlatStyle.Flat; 2134 | buttonHelp.Left = ClientSize.Width - (int)(30 * ScaleFactor); 2135 | buttonHelp.Top = (int)(4 * ScaleFactor); 2136 | buttonHelp.Click += ButtonHelp_Click; 2137 | helpPage = "clear-history"; 2138 | 2139 | buttonOK = new Button(); 2140 | buttonOK.Text = sOK; 2141 | buttonOK.DialogResult = DialogResult.OK; 2142 | buttonOK.Font = new Font("Segoe UI", 9); 2143 | buttonOK.Width = (int)(75 * ScaleFactor); 2144 | buttonOK.Height = (int)(26 * ScaleFactor); 2145 | buttonOK.Left = (ClientSize.Width - buttonOK.Width) / 2; 2146 | buttonOK.Top = ClientSize.Height - buttonOK.Height - (int)(10 * ScaleFactor); 2147 | if (Dark) 2148 | { 2149 | buttonOK.FlatStyle = FlatStyle.Flat; 2150 | buttonOK.FlatAppearance.BorderColor = SystemColors.Highlight; 2151 | buttonOK.FlatAppearance.BorderSize = 1; 2152 | buttonOK.BackColor = Color.FromArgb(60, 60, 60); 2153 | buttonOK.FlatAppearance.MouseOverBackColor = Color.Black; 2154 | DarkTitleBar(Handle); 2155 | BackColor = Color.FromArgb(32, 32, 32); 2156 | ForeColor = Color.White; 2157 | } 2158 | 2159 | RecentItemsCheckbox = new CheckBox(); 2160 | RecentItemsCheckbox.Font = new Font("Segoe UI", 10); 2161 | RecentItemsCheckbox.Text = sRecent; 2162 | RecentItemsCheckbox.Checked = false; 2163 | RecentItemsCheckbox.AutoSize = true; 2164 | RecentItemsCheckbox.Location = new Point((int)(8 * ScaleFactor), (int)(16 * ScaleFactor)); 2165 | if (fLatCB) RecentItemsCheckbox.FlatStyle = FlatStyle.Flat; 2166 | 2167 | AutoSuggestCheckbox = new CheckBox(); 2168 | AutoSuggestCheckbox.Font = new Font("Segoe UI", 10); 2169 | AutoSuggestCheckbox.Text = sAutoSuggest; 2170 | AutoSuggestCheckbox.Checked = false; 2171 | AutoSuggestCheckbox.AutoSize = true; 2172 | AutoSuggestCheckbox.Location = new Point((int)(8 * ScaleFactor), (int)(40 * ScaleFactor)); 2173 | if (fLatCB) AutoSuggestCheckbox.FlatStyle = FlatStyle.Flat; 2174 | 2175 | TempFilesCheckbox = new CheckBox(); 2176 | TempFilesCheckbox.Font = new Font("Segoe UI", 10); 2177 | TempFilesCheckbox.Text = sTemp; 2178 | TempFilesCheckbox.Checked = false; 2179 | TempFilesCheckbox.AutoSize = true; 2180 | TempFilesCheckbox.Location = new Point((int)(8 * ScaleFactor), (int)(64 * ScaleFactor)); 2181 | if (fLatCB) TempFilesCheckbox.FlatStyle = FlatStyle.Flat; 2182 | 2183 | DefenderCheckbox = new CheckBox(); 2184 | DefenderCheckbox.Font = new Font("Segoe UI", 10); 2185 | DefenderCheckbox.Text = sDefender; 2186 | DefenderCheckbox.Checked = false; 2187 | DefenderCheckbox.AutoSize = true; 2188 | DefenderCheckbox.Location = new Point((int)(8 * ScaleFactor), (int)(88 * ScaleFactor)); 2189 | if (fLatCB) DefenderCheckbox.FlatStyle = FlatStyle.Flat; 2190 | 2191 | Controls.Add(buttonHelp); 2192 | Controls.Add(RecentItemsCheckbox); 2193 | Controls.Add(AutoSuggestCheckbox); 2194 | Controls.Add(TempFilesCheckbox); 2195 | Controls.Add(DefenderCheckbox); 2196 | Controls.Add(buttonOK); 2197 | Controls.Add(messageLabel); 2198 | 2199 | Point cursorPosition = Cursor.Position; 2200 | int dialogX = Cursor.Position.X - Width / 2; 2201 | int dialogY = Cursor.Position.Y - Height / 2 - (int)(50 * ScaleFactor); 2202 | Screen screen = Screen.FromPoint(cursorPosition); 2203 | int screenWidth = screen.WorkingArea.Width; 2204 | int screenHeight = screen.WorkingArea.Height; 2205 | int baseX = screen.Bounds.X; 2206 | int baseY = screen.Bounds.Y; 2207 | dialogX = Math.Max(baseX, Math.Min(baseX + screenWidth - Width, dialogX)); 2208 | dialogY = Math.Max(baseY, Math.Min(baseY + screenHeight - Height, dialogY)); 2209 | Location = new Point(dialogX, dialogY); 2210 | } 2211 | 2212 | public static DialogResult Show(string message, string caption) 2213 | { 2214 | using (var ClearHistoryDialog = new ClearHistoryDialog(message, caption)) 2215 | { 2216 | return ClearHistoryDialog.ShowDialog(); 2217 | } 2218 | } 2219 | } 2220 | } 2221 | 2222 | 2223 | //Credit for the following TrustedInstaller code: https://github.com/rara64/GetTrustedInstaller 2224 | class TrustedInstaller 2225 | { 2226 | [DllImport("kernel32.dll")] 2227 | [return: MarshalAs(UnmanagedType.Bool)] 2228 | static extern bool CreateProcess(string lpApplicationName, string lpCommandLine, ref SECURITY_ATTRIBUTES lpProcessAttributes, ref SECURITY_ATTRIBUTES lpThreadAttributes, bool bInheritHandles, uint dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory, [In] ref STARTUPINFOEX lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation); 2229 | 2230 | [DllImport("kernel32.dll", SetLastError = true)] 2231 | public static extern IntPtr OpenProcess(ProcessAccessFlags processAccess, bool bInheritHandle, int processId); 2232 | 2233 | [DllImport("kernel32.dll", SetLastError = true)] 2234 | public static extern UInt32 WaitForSingleObject(IntPtr handle, UInt32 milliseconds); 2235 | 2236 | [DllImport("kernel32.dll", SetLastError = true)] 2237 | [return: MarshalAs(UnmanagedType.Bool)] 2238 | private static extern bool UpdateProcThreadAttribute(IntPtr lpAttributeList, uint dwFlags, IntPtr Attribute, IntPtr lpValue, IntPtr cbSize, IntPtr lpPreviousValue, IntPtr lpReturnSize); 2239 | 2240 | [DllImport("kernel32.dll", SetLastError = true)] 2241 | [return: MarshalAs(UnmanagedType.Bool)] 2242 | private static extern bool InitializeProcThreadAttributeList(IntPtr lpAttributeList, int dwAttributeCount, int dwFlags, ref IntPtr lpSize); 2243 | 2244 | [DllImport("kernel32.dll", SetLastError = true)] 2245 | static extern bool SetHandleInformation(IntPtr hObject, HANDLE_FLAGS dwMask, HANDLE_FLAGS dwFlags); 2246 | 2247 | [DllImport("kernel32.dll", SetLastError = true)] 2248 | static extern bool CloseHandle(IntPtr hObject); 2249 | 2250 | [DllImport("kernel32.dll", SetLastError = true)] 2251 | [return: MarshalAs(UnmanagedType.Bool)] 2252 | static extern bool DuplicateHandle(IntPtr hSourceProcessHandle, IntPtr hSourceHandle, IntPtr hTargetProcessHandle, ref IntPtr lpTargetHandle, uint dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, uint dwOptions); 2253 | 2254 | public static void Run(int parentProcessId, string binaryPath) 2255 | { 2256 | const int PROC_THREAD_ATTRIBUTE_PARENT_PROCESS = 0x00020000; 2257 | 2258 | const uint EXTENDED_STARTUPINFO_PRESENT = 0x00080000; 2259 | const uint CREATE_NEW_CONSOLE = 0x00000010; 2260 | 2261 | var pInfo = new PROCESS_INFORMATION(); 2262 | var siEx = new STARTUPINFOEX(); 2263 | 2264 | IntPtr lpValueProc = IntPtr.Zero; 2265 | IntPtr hSourceProcessHandle = IntPtr.Zero; 2266 | var lpSize = IntPtr.Zero; 2267 | 2268 | InitializeProcThreadAttributeList(IntPtr.Zero, 1, 0, ref lpSize); 2269 | siEx.lpAttributeList = Marshal.AllocHGlobal(lpSize); 2270 | InitializeProcThreadAttributeList(siEx.lpAttributeList, 1, 0, ref lpSize); 2271 | 2272 | IntPtr parentHandle = OpenProcess(ProcessAccessFlags.CreateProcess | ProcessAccessFlags.DuplicateHandle, false, parentProcessId); 2273 | 2274 | lpValueProc = Marshal.AllocHGlobal(IntPtr.Size); 2275 | Marshal.WriteIntPtr(lpValueProc, parentHandle); 2276 | 2277 | UpdateProcThreadAttribute(siEx.lpAttributeList, 0, (IntPtr)PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, lpValueProc, (IntPtr)IntPtr.Size, IntPtr.Zero, IntPtr.Zero); 2278 | 2279 | var ps = new SECURITY_ATTRIBUTES(); 2280 | var ts = new SECURITY_ATTRIBUTES(); 2281 | ps.nLength = Marshal.SizeOf(ps); 2282 | ts.nLength = Marshal.SizeOf(ts); 2283 | 2284 | // lpCommandLine was used instead of lpApplicationName to allow for arguments to be passed 2285 | bool ret = CreateProcess(null, binaryPath, ref ps, ref ts, true, EXTENDED_STARTUPINFO_PRESENT | CREATE_NEW_CONSOLE, IntPtr.Zero, null, ref siEx, out pInfo); 2286 | 2287 | String stringPid = pInfo.dwProcessId.ToString(); 2288 | 2289 | } 2290 | 2291 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 2292 | struct STARTUPINFOEX 2293 | { 2294 | public STARTUPINFO StartupInfo; 2295 | public IntPtr lpAttributeList; 2296 | } 2297 | 2298 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 2299 | struct STARTUPINFO 2300 | { 2301 | public Int32 cb; 2302 | public string lpReserved; 2303 | public string lpDesktop; 2304 | public string lpTitle; 2305 | public Int32 dwX; 2306 | public Int32 dwY; 2307 | public Int32 dwXSize; 2308 | public Int32 dwYSize; 2309 | public Int32 dwXCountChars; 2310 | public Int32 dwYCountChars; 2311 | public Int32 dwFillAttribute; 2312 | public Int32 dwFlags; 2313 | public Int16 wShowWindow; 2314 | public Int16 cbReserved2; 2315 | public IntPtr lpReserved2; 2316 | public IntPtr hStdInput; 2317 | public IntPtr hStdOutput; 2318 | public IntPtr hStdError; 2319 | } 2320 | 2321 | [StructLayout(LayoutKind.Sequential)] 2322 | internal struct PROCESS_INFORMATION 2323 | { 2324 | public IntPtr hProcess; 2325 | public IntPtr hThread; 2326 | public int dwProcessId; 2327 | public int dwThreadId; 2328 | } 2329 | 2330 | [StructLayout(LayoutKind.Sequential)] 2331 | public struct SECURITY_ATTRIBUTES 2332 | { 2333 | public int nLength; 2334 | public IntPtr lpSecurityDescriptor; 2335 | [MarshalAs(UnmanagedType.Bool)] 2336 | public bool bInheritHandle; 2337 | } 2338 | 2339 | [Flags] 2340 | public enum ProcessAccessFlags : uint 2341 | { 2342 | All = 0x001F0FFF, 2343 | Terminate = 0x00000001, 2344 | CreateThread = 0x00000002, 2345 | VirtualMemoryOperation = 0x00000008, 2346 | VirtualMemoryRead = 0x00000010, 2347 | VirtualMemoryWrite = 0x00000020, 2348 | DuplicateHandle = 0x00000040, 2349 | CreateProcess = 0x000000080, 2350 | SetQuota = 0x00000100, 2351 | SetInformation = 0x00000200, 2352 | QueryInformation = 0x00000400, 2353 | QueryLimitedInformation = 0x00001000, 2354 | Synchronize = 0x00100000 2355 | } 2356 | 2357 | [Flags] 2358 | enum HANDLE_FLAGS : uint 2359 | { 2360 | None = 0, 2361 | INHERIT = 1, 2362 | PROTECT_FROM_CLOSE = 2 2363 | } 2364 | } 2365 | 2366 | } 2367 | -------------------------------------------------------------------------------- /Properties/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("RightClickTools")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("RightClickTools")] 13 | [assembly: AssemblyCopyright("lesferch@gmail.com")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("a2c1801a-cb6b-45b7-8dc5-22b0e2e3abf9")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.2.0.0")] 36 | [assembly: AssemblyFileVersion("1.2.0.0")] 37 | -------------------------------------------------------------------------------- /RightClickTools.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {A2C1801A-CB6B-45B7-8DC5-22B0E2E3ABF9} 8 | WinExe 9 | RightClickTools 10 | RightClickTools 11 | v4.8 12 | 512 13 | true 14 | true 15 | 16 | 17 | AnyCPU 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | false 26 | 27 | 28 | AnyCPU 29 | pdbonly 30 | true 31 | bin\Release\ 32 | TRACE 33 | prompt 34 | 4 35 | false 36 | 37 | 38 | RightClickTools.ico 39 | 40 | 41 | app.manifest 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | {EAB22AC0-30C1-11CF-A7EB-0000C05BAE0B} 72 | 1 73 | 1 74 | 0 75 | tlbimp 76 | False 77 | True 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /RightClickTools.csproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /RightClickTools.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LesFerch/RightClickTools/7ebc7dd162a23d13ad896bd887a19d1b049a36ae/RightClickTools.ico -------------------------------------------------------------------------------- /RightClickTools.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.8.34511.84 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RightClickTools", "RightClickTools.csproj", "{A2C1801A-CB6B-45B7-8DC5-22B0E2E3ABF9}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {A2C1801A-CB6B-45B7-8DC5-22B0E2E3ABF9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {A2C1801A-CB6B-45B7-8DC5-22B0E2E3ABF9}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {A2C1801A-CB6B-45B7-8DC5-22B0E2E3ABF9}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {A2C1801A-CB6B-45B7-8DC5-22B0E2E3ABF9}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {EA115A65-21FC-4DB9-A603-C297BEDE73BA} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /app.manifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 54 | 55 | 56 | 57 | true 58 | true 59 | 60 | 61 | 62 | 63 | 77 | 78 | 79 | --------------------------------------------------------------------------------