-
-
Notifications
You must be signed in to change notification settings - Fork 117
/
Super_God_Mode.ps1
4331 lines (3782 loc) · 205 KB
/
Super_God_Mode.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
# Get All Shell Folder Shortcuts Script (Aka "Super God Mode")
#
# Author: ThioJoe
# GitHub Repo: https://github.com/ThioJoe/Windows-Super-God-Mode
#
# This PowerShell script is designed to find and create shortcuts for all special shell folders in Windows.
# These folders can be identified through their unique Class Identifiers (CLSIDs) or by their names.
# The script also generates CSV files listing these folders and associated tasks/links.
# How to Use:
# 1. Open PowerShell and navigate to the path containing this script using the 'cd' command.
# 2. Run the following command to allow running scripts for the current session:
# Set-ExecutionPolicy -ExecutionPolicy unrestricted -Scope Process
# 3. Without closing the PowerShell window, run the script by typing the name of the script file starting with .\ for example:
# .\Super_God_Mode.ps1
# 4. Wait for it to finish, then check the "Super God Mode" folder for the generated shortcuts.
# ======================================================================================================
# =================================== ARGUMENTS (ALL ARE OPTIONAL) ===================================
# ======================================================================================================
#
# --------------------------------- Alternative Options Arguments ----------------------------------
#
# -DontGroupTasks
# • Switch (Takes no values)
# Prevent grouping task shortcuts, meaning the application name won't be prepended to the task name in the shortcut file
#
# -UseAlternativeCategoryNames
# • Switch (Takes no values)
# Looks up alternative category names for task links to prepend to the task names
#
# -AllURLProtocols
# • Switch (Takes no values)
# Include third party URL protocols from installed software in the URL Protocols section. By default, only protocols detected to be from Microsoft or system protocols are included.
#
# -DeepScanHiddenLinks
# • Switch (Takes no values)
# Scans all files in the installation directory of non-appx-package apps for hidden links. Otherwise, only the primary binary file will be searched. Note: This will be MUCH slower.
#
# -CollectExtraURLProtocolInfo
# • Switch (Takes no values)
# Collects extra information about URL protocols that goes into the CSV spreadsheet. Optional because it is not used in the shortcuts and takes slightly longer.
#
# -AllowDuplicateDeepLinks
# • Switch (Takes no values)
# Allow the creation of Deep Links that are the same as an existing Task Link. By default, such duplicates are not included in the Deep Links folder.
#
# ------------------------------------------ Control Output ------------------------------------------
#
# -Output
# • String Type
# Specify a custom output folder path (relative or absolute) to save the generated shortcuts. If not provided, a folder named "Super God Mode" will be created in the script's directory.
#
# -KeepPreviousOutputFolders
# • Switch (Takes no values)
# Doesn't delete existing output folders before running the script. Any existing shortcuts will still be overwritten if being created again.
#
# ------------------------------- Arguments to Limit Outputs -------------------------------
#
# -NoStatistics
# • Switch (Takes no values)
# Skip creating the statistics folder and files containing CSV data about the shell folders and tasks and XML files with other collected data
#
# -NoReadMe
# • Switch (Takes no values)
# Skip creating the ReadMe text file in the main folder
#
#
# -SkipCLSID
# • Switch (Takes no values)
# Skip creating shortcuts for shell folders based on CLSIDs
#
# -SkipNamedFolders
# • Switch (Takes no values)
# Skip creating shortcuts for named special folders
#
# -SkipTaskLinks
# • Switch (Takes no values)
# Skip creating shortcuts for task links (sub-pages within shell folders and control panel menus)
#
# -SkipMSSettings
# • Switch (Takes no values)
# Skip creating shortcuts for ms-settings: links (system settings pages)
#
# -SkipDeepLinks
# • Switch (Takes no values)
# Skip creating shortcuts for deep links (direct links to various settings menus across Windows)
#
# -SkipURLProtocols
# • Switch (Takes no values)
# Skip creating shortcuts for URL protocols (e.g., mailto:, ms-settings:, etc.)
#
# -SkipHiddenAppLinks
# • Switch (Takes no values)
# Skip creating shortcuts for hidden sub-page links for app protocols (e.g., ms-clock://pausefocustimer, etc.)
#
# -------------------------------------------- Debugging ---------------------------------------------
#
# -Verbose
# • Switch (Takes no values)
# Enable verbose output for more detailed information during script execution
#
# -Debug
# • Switch (Takes no values)
# Enable debug output for maximum information during script execution. This will also enable verbose output.
#
# -timing
# • Switch (Takes no values)
# Enable timing output to show how long each section of the script takes to run. Or timing will be enabled automatically if in verbose or debug mode
#
# -debugSkipAppxSearch
# • Switch (Takes no values)
# Skip searching for hidden links in AppX packages. This is useful for debugging and testing searching of third party apps without having to wait for the AppX search to complete.
#
# -debugSearchOnlyProtocolList
# • String Type
# Specify a comma-separated list of URL protocols (surrounded by quotes) to search for in the debug mode. This is useful for testing the URL protocol search without having to wait for the full search to complete.
#
# -uniqueOutputFolder
# • Switch (Takes no values)
# Append a unique identifier to the output folder name to prevent overwriting existing folders, even if using manual output folder name. Useful to compare different runs without having to manually set a new output folder each time.
#
# ---------------------------------------- Advanced Arguments ----------------------------------------
#
# -NoGUI
# • Switch (Takes no values)
# Skip the GUI dialog when running the script. If no other arguments are provided, the script will run with default settings. If other arguments are provided, they will be used without the GUI.
#
# -CustomDLLPath
# • String Type
# Specify a custom DLL file path to load the shell32.dll content from. If not provided, the default shell32.dll will be used.
# NOTE: Because of how Windows works behind the scenes, DLLs reference resources in corresponding .mui and .mun files.
# The XML data (resource ID 21) that is required in this script is actually located in shell32.dll.mun, which is located at "C:\Windows\SystemResources\shell32.dll.mun"
# This means if you want to reference the data from a DLL that is NOT at C:\Windows\System32\shell32.dll, you should directly reference the .mun file instead. It will auto redirect if it's at that exact path, but not otherwise.
# > This is especially important if wanting to reference the data from a different computer, you need to be sure to copy the .mun file
# See: https://stackoverflow.com/questions/68389730/windows-dll-function-behaviour-is-different-if-dll-is-moved-to-different-locatio
#
# -CustomLanguageFolderPath
# • String Type
# Specify a path to a folder containing language-specific MUI files to use for localized string references, and it will prefer any mui files from there if available instead of the system default.
# For example, to use your own language file for shell32.dll, you could specify a path to a folder containing a file named "shell32.dll.mui" in the desired language, and any other such files.
# For another example, if you have multiple language packs installed on your system, you could specify the entire language directory in system32 such as "C:\Windows\System32\en-US" to use English strings, or "C:\Windows\System32\de-DE" for German strings.
#
# -CustomSystemSettingsDLLPath
# • String Type
# Specify a custom path to the SystemSettings.dll file to load the system settings (ms-settings: links) content from. If not provided, the default SystemSettings.dll will be used.
#
# -CustomAllSystemSettingsXMLPath
# • String Type
# Specify a custom path to the AllSystemSettings XML file to load deep links from. If not provided, the default AllSystemSettings XML file will be used.
# The default path is "C:\Windows\ImmersiveControlPanel\Settings\AllSystemSettings\ and versions may vary depending on Windows 11 or Windows 10.
#
# ------------------------------------------------------------------------------------------------------
#
# EXAMPLE USAGE FROM COMMAND LINE:
# .\Super_God_Mode.ps1 -NoStatistics -CollectExtraURLProtocolInfo -Output "C:\Users\Username\Desktop\My Shortcuts"
#
# ------------------------------------------------------------------------------------------------------
param(
# Alternative Options Arguments
[switch]$DontGroupTasks,
[switch]$UseAlternativeCategoryNames,
[switch]$AllURLProtocols,
[switch]$CollectExtraURLProtocolInfo,
[switch]$AllowDuplicateDeepLinks,
[switch]$DeepScanHiddenLinks,
# Control Output
[string]$Output,
[switch]$KeepPreviousOutputFolders,
# Arguments to Limit Outputs
[switch]$NoStatistics,
[switch]$NoReadMe,
[switch]$SkipCLSID,
[switch]$SkipNamedFolders,
[switch]$SkipTaskLinks,
[switch]$SkipMSSettings,
[switch]$SkipDeepLinks,
[switch]$SkipURLProtocols,
[switch]$SkipHiddenAppLinks,
# Debugging
[switch]$Verbose,
[switch]$Debug,
[switch]$timing,
[switch]$debugSkipAppxSearch,
[string]$debugSearchOnlyProtocolList,
[switch]$uniqueOutputFolder,
# Advanced Arguments
[switch]$NoGUI,
[string]$CustomDLLPath,
[string]$CustomLanguageFolderPath,
[string]$CustomSystemSettingsDLLPath,
[string]$CustomAllSystemSettingsXMLPath
)
# Note: Arguments that are command line only and not used in the GUI:
# -NoGUI
# -NoReadMe
# -CustomDLLPath
# -CustomLanguageFolderPath
# -CustomSystemSettingsDLLPath
# -CustomAllSystemSettingsXMLPath
# -debugSkipAppxSearch
# -debugSearchOnlyProtocolList
# -uniqueOutputFolder
$VERSION = "1.2.3"
# ==============================================================================================================================
# ================================================== GUI FUNCTION ============================================================
# ==============================================================================================================================
# Function to show a GUI dialog for selecting script options
function Show-SuperGodModeDialog {
# Add param for output folder default name
param(
[string]$defaultOutputFolderName,
[switch]$initialDebug,
[switch]$initialVerbose
)
# Define tooltips here for easy editing
$tooltips = @{
# Use 
 for line breaks in the tooltip text
DontGroupTasks = "Prevent grouping task shortcuts, meaning the application name won't be 
prepended to the task name in the shortcut file"
UseAlternativeCategoryNames = "Looks up alternative category names for task links to prepend to the task names"
AllURLProtocols = "When creating shortcuts to URL protocols like 'ms-settings://', include third party 
URL protocols from installed software, not just Microsoft or system protocols"
CollectExtraURLProtocolInfo = "Collects extra information about URL protocols that goes into the CSV spreadsheet. 
Optional because it is not used in the shortcuts and takes slightly longer."
KeepPreviousOutputFolders = "Doesn't delete existing output folders before running the script. 
It will still overwrite any existing shortcuts if being created again."
CollectStatistics = "Create the statistics folder and files containing CSV data about the shell folders 
and tasks and XML files with other collected data"
AllowDuplicateDeepLinks = "Allow the creation of Deep Links that are the same as an existing Task Link. 
By default, such duplicates are not included in the Deep Links folder."
CollectCLSID = "Create shortcuts for shell folders based on CLSIDs"
CollectNamedFolders = "Create shortcuts for named special folders"
CollectTaskLinks = "Create shortcuts for task links (sub-pages within shell folders and control panel menus)"
CollectMSSettings = "Create shortcuts for ms-settings: links (system settings pages)"
CollectDeepLinks = "Create shortcuts for deep links (direct links to various settings menus across Windows)"
CollectURLProtocols = "Create shortcuts for URL protocols (e.g., ms-settings:, etc.)"
CollectAppxLinks = "Create shortcuts for hidden sub-page URL links for apps (e.g., ms-clock://pausefocustimer, etc.) 
Note: Requires collecting URL Protocol Links"
DeepScanHiddenLinks = "Scans all files in the installation directory of non-appx-package apps for hidden links. 
Otherwise only the primary binary file will be searched. 

Note: This wll be MUCH slower. 
Also Note: Not to be confused with "Deep Links"."
LoggingLevel = "Select the level of detail shown in the console window during runtime:
 - Standard: Normal logging
 - Verbose: More detailed logging
 - Debug: Maximum detail, also creates some log files."
}
Add-Type -AssemblyName PresentationFramework
Add-Type -AssemblyName System.Windows.Forms
[xml]$xaml = @"
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Super God Mode Options" Height="715" Width="800">
<Window.Resources>
<Color x:Key="BackgroundColor">#1E1E1E</Color>
<Color x:Key="ForegroundColor">#CCCCCC</Color>
<Color x:Key="AccentColor">#0078D4</Color>
<Color x:Key="SecondaryBackgroundColor">#2D2D2D</Color>
<Color x:Key="BorderColor">#3F3F3F</Color>
<Color x:Key="WarningColor">#FF6B68</Color>
<Color x:Key="VersionColor">#888888</Color>
<Color x:Key="ButtonHoverColor">#1b99fa</Color>
<Color x:Key="HighlightedTextColor">#69d2ff</Color>
<SolidColorBrush x:Key="BackgroundBrush" Color="{StaticResource BackgroundColor}"/>
<SolidColorBrush x:Key="ForegroundBrush" Color="{StaticResource ForegroundColor}"/>
<SolidColorBrush x:Key="AccentBrush" Color="{StaticResource AccentColor}"/>
<SolidColorBrush x:Key="SecondaryBackgroundBrush" Color="{StaticResource SecondaryBackgroundColor}"/>
<SolidColorBrush x:Key="BorderBrush" Color="{StaticResource BorderColor}"/>
<SolidColorBrush x:Key="WarningBrush" Color="{StaticResource WarningColor}"/>
<SolidColorBrush x:Key="VersionBrush" Color="{StaticResource VersionColor}"/>
<SolidColorBrush x:Key="ButtonHoverBrush" Color="{StaticResource ButtonHoverColor}"/>
<SolidColorBrush x:Key="HighlightedTextBrush" Color="{StaticResource HighlightedTextColor}"/>
<Thickness x:Key="BorderThickness">1</Thickness>
<Thickness x:Key="GroupBoxPadding">5</Thickness>
<Style x:Key="DarkModeGroupBoxStyle" TargetType="GroupBox">
<Setter Property="BorderBrush" Value="{StaticResource BorderBrush}"/>
<Setter Property="BorderThickness" Value="{StaticResource BorderThickness}"/>
<Setter Property="Padding" Value="{StaticResource GroupBoxPadding}"/>
<Setter Property="Margin" Value="0,10,0,10"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="GroupBox">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Grid.Row="0" Grid.RowSpan="2"/>
<Border Background="{TemplateBinding Background}" BorderBrush="Transparent" BorderThickness="{TemplateBinding BorderThickness}" Grid.Row="1">
<ContentPresenter Margin="{TemplateBinding Padding}"/>
</Border>
<TextBlock Margin="5,0,0,0" Padding="3,0,3,0" Background="{StaticResource BackgroundBrush}" HorizontalAlignment="Left" VerticalAlignment="Top" TextElement.Foreground="{StaticResource ForegroundBrush}" Text="{TemplateBinding Header}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="SubtleButtonStyle" TargetType="Button">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Foreground" Value="{StaticResource ForegroundBrush}"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="FontSize" Value="12"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Padding" Value="10,5"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{StaticResource ButtonHoverBrush}"/>
</Trigger>
</Style.Triggers>
</Style>
<Style x:Key="CustomCheckBoxStyle" TargetType="CheckBox" BasedOn="{StaticResource {x:Type CheckBox}}">
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value="0.5"/>
</Trigger>
</Style.Triggers>
</Style>
<Style x:Key="HighlightedCheckBoxStyle" TargetType="CheckBox" BasedOn="{StaticResource {x:Type CheckBox}}">
<Setter Property="Foreground" Value="{StaticResource HighlightedTextBrush}"/>
<Setter Property="FontWeight" Value="Semibold"/>
</Style>
</Window.Resources>
<Grid Background="{StaticResource BackgroundBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Border Background="{StaticResource AccentBrush}" Grid.Row="0">
<Grid>
<StackPanel>
<TextBlock Text=""Super God Mode" Script" FontSize="24" Foreground="White" HorizontalAlignment="Center" Margin="0,10,0,0"/>
<TextBlock Text="For Windows" FontSize="16" Foreground="White" HorizontalAlignment="Center" Margin="0,0,0,10"/>
</StackPanel>
<Button x:Name="btnAbout" Content="About" Style="{StaticResource SubtleButtonStyle}"
HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0,10,10,0"/>
</Grid>
</Border>
<ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto">
<Grid Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Text="Hover over settings for details" FontStyle="Italic" HorizontalAlignment="Right" Margin="0,0,0,10" Grid.Row="0" Foreground="{StaticResource ForegroundBrush}"/>
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<GroupBox Header="Alternative Options" Grid.Column="0" Style="{StaticResource DarkModeGroupBoxStyle}">
<StackPanel Margin="5">
<CheckBox x:Name="chkDontGroupTasks" Content="Task Links: Don't Group Task Links" Margin="0,5,0,0" Foreground="{StaticResource ForegroundBrush}">
<CheckBox.ToolTip>
<ToolTip Content="$($tooltips.DontGroupTasks)" />
</CheckBox.ToolTip>
</CheckBox>
<CheckBox x:Name="chkUseAlternativeCategoryNames" Content="Task Links: Use Alternative Category Names" Margin="0,5,0,0" Foreground="{StaticResource ForegroundBrush}">
<CheckBox.ToolTip>
<ToolTip Content="$($tooltips.UseAlternativeCategoryNames)" />
</CheckBox.ToolTip>
</CheckBox>
<CheckBox x:Name="chkAllowDuplicateDeepLinks" Content="Deep Links: Allow Duplicate Deep Links" Margin="0,5,0,0" Foreground="{StaticResource ForegroundBrush}">
<CheckBox.ToolTip>
<ToolTip Content="$($tooltips.AllowDuplicateDeepLinks)" />
</CheckBox.ToolTip>
</CheckBox>
<CheckBox x:Name="chkAllURLProtocols" Content="Protocols: Include third-party app URL Protocols" Margin="0,5,0,0" Foreground="{StaticResource ForegroundBrush}">
<CheckBox.ToolTip>
<ToolTip Content="$($tooltips.AllURLProtocols)" />
</CheckBox.ToolTip>
</CheckBox>
<CheckBox x:Name="chkCollectExtraURLProtocolInfo" Content="Protocols: Collect Extra URL Protocol Info" Margin="0,5,0,0" Foreground="{StaticResource ForegroundBrush}">
<CheckBox.ToolTip>
<ToolTip Content="$($tooltips.CollectExtraURLProtocolInfo)" />
</CheckBox.ToolTip>
</CheckBox>
<CheckBox x:Name="chkDeepScanHiddenLinks" Content="Protocols: Deeper Scan For Hidden Links (Slow)" Margin="0,5,0,0" Foreground="{StaticResource ForegroundBrush}">
<CheckBox.ToolTip>
<ToolTip Content="$($tooltips.DeepScanHiddenLinks)" />
</CheckBox.ToolTip>
</CheckBox>
</StackPanel>
</GroupBox>
<GroupBox Header="Control Outputs" Grid.Column="1" Style="{StaticResource DarkModeGroupBoxStyle}">
<Grid Margin="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<CheckBox x:Name="chkCollectStatistics" Content="Collect Statistics 📊" IsChecked="True" Margin="0,5,5,5" Grid.Column="0" Grid.Row="0" Style="{StaticResource HighlightedCheckBoxStyle}">
<CheckBox.ToolTip>
<ToolTip Content="$($tooltips.CollectStatistics)" />
</CheckBox.ToolTip>
</CheckBox>
<CheckBox x:Name="chkCollectCLSID" Content="CLSID Links" IsChecked="True" Margin="5,5,0,5" Grid.Column="1" Grid.Row="0" Foreground="{StaticResource ForegroundBrush}">
<CheckBox.ToolTip>
<ToolTip Content="$($tooltips.CollectCLSID)" />
</CheckBox.ToolTip>
</CheckBox>
<CheckBox x:Name="chkCollectNamedFolders" Content="Named Folders Links" IsChecked="True" Margin="0,5,5,5" Grid.Column="0" Grid.Row="1" Foreground="{StaticResource ForegroundBrush}">
<CheckBox.ToolTip>
<ToolTip Content="$($tooltips.CollectNamedFolders)" />
</CheckBox.ToolTip>
</CheckBox>
<CheckBox x:Name="chkCollectTaskLinks" Content="Task Links" IsChecked="True" Margin="5,5,0,5" Grid.Column="1" Grid.Row="1" Foreground="{StaticResource ForegroundBrush}">
<CheckBox.ToolTip>
<ToolTip Content="$($tooltips.CollectTaskLinks)" />
</CheckBox.ToolTip>
</CheckBox>
<CheckBox x:Name="chkCollectMSSettings" Content="MS-Settings Links" IsChecked="True" Margin="0,5,5,5" Grid.Column="0" Grid.Row="2" Foreground="{StaticResource ForegroundBrush}">
<CheckBox.ToolTip>
<ToolTip Content="$($tooltips.CollectMSSettings)" />
</CheckBox.ToolTip>
</CheckBox>
<CheckBox x:Name="chkCollectDeepLinks" Content="Deep Links" IsChecked="True" Margin="5,5,0,5" Grid.Column="1" Grid.Row="2" Foreground="{StaticResource ForegroundBrush}">
<CheckBox.ToolTip>
<ToolTip Content="$($tooltips.CollectDeepLinks)" />
</CheckBox.ToolTip>
</CheckBox>
<CheckBox x:Name="chkCollectURLProtocols" Content="URL Protocols Links" IsChecked="True" Margin="0,5,5,5" Grid.Column="0" Grid.Row="3" Foreground="{StaticResource ForegroundBrush}">
<CheckBox.ToolTip>
<ToolTip Content="$($tooltips.CollectURLProtocols)" />
</CheckBox.ToolTip>
</CheckBox>
<CheckBox x:Name="chkCollectAppxLinks" Content="Hidden App Links" IsChecked="True" Margin="5,5,0,5" Grid.Column="1" Grid.Row="3" Foreground="{StaticResource ForegroundBrush}" Style="{StaticResource CustomCheckBoxStyle}" ToolTipService.ShowOnDisabled="True">
<CheckBox.ToolTip>
<ToolTip Content="$($tooltips.CollectAppxLinks)" />
</CheckBox.ToolTip>
</CheckBox>
</Grid>
</GroupBox>
</Grid>
<GroupBox Header="Output Location" Grid.Row="2" Style="{StaticResource DarkModeGroupBoxStyle}">
<StackPanel Margin="5">
<CheckBox x:Name="chkKeepPreviousOutputFolders" Content="Don't Auto-Delete Existing Output Folders" Margin="0,5,0,0" Foreground="{StaticResource ForegroundBrush}">
<CheckBox.ToolTip>
<ToolTip Content="$($tooltips.KeepPreviousOutputFolders)" />
</CheckBox.ToolTip>
</CheckBox>
<TextBlock Text="Output Directory:" Margin="0,10,0,5" Foreground="{StaticResource ForegroundBrush}"/>
<DockPanel LastChildFill="True" Margin="0,0,0,5">
<Button x:Name="btnBrowse" Content="Browse" DockPanel.Dock="Right" Margin="5,0,0,0" Padding="10,5" FontSize="14" MinWidth="100" Background="{StaticResource SecondaryBackgroundBrush}" Foreground="{StaticResource ForegroundBrush}"/>
<TextBox x:Name="txtOutputPath" IsReadOnly="True" Padding="5,0,0,0" VerticalContentAlignment="Center" FontSize="14" Height="30" Background="{StaticResource SecondaryBackgroundBrush}" Foreground="{StaticResource ForegroundBrush}"/>
</DockPanel>
<TextBlock Text="Output Folder Name:" Margin="0,5,0,5" Foreground="{StaticResource ForegroundBrush}"/>
<TextBox x:Name="txtOutputFolderName" Margin="0,0,0,5" Padding="5,0,0,0" VerticalContentAlignment="Center" FontSize="14" Height="30" Background="{StaticResource SecondaryBackgroundBrush}" Foreground="{StaticResource ForegroundBrush}"/>
<Separator Margin="0,10,0,10" Background="{StaticResource BorderBrush}"/>
<TextBlock Text="Final Output Path:" Margin="0,5,0,5" FontWeight="Bold" Foreground="{StaticResource ForegroundBrush}"/>
<TextBlock x:Name="txtCurrentPath" Text="" Margin="0,0,0,10" TextWrapping="Wrap" FontWeight="Bold" Foreground="{StaticResource ForegroundBrush}"/>
</StackPanel>
</GroupBox>
<StackPanel Grid.Row="3">
<Button x:Name="btnOK" Content="Run Script" Width="Auto" Height="Auto" FontSize="14" HorizontalAlignment="Center" Margin="0,10,0,10" Padding="10,5" Background="{StaticResource AccentBrush}" Foreground="White"/>
<TextBlock Text="All settings are optional - Leave them alone to use defaults" FontWeight="Bold" Foreground="{StaticResource WarningBrush}" HorizontalAlignment="Center" Margin="0,0,0,10"/>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Orientation="Horizontal" HorizontalAlignment="Left" VerticalAlignment="Center">
<TextBlock Text="Logging:" Margin="0,0,10,0" VerticalAlignment="Center" Foreground="{StaticResource ForegroundBrush}">
<TextBlock.ToolTip>
<ToolTip Content="$($tooltips.LoggingLevel)" />
</TextBlock.ToolTip>
</TextBlock>
<ComboBox x:Name="cmbLoggingLevel" Width="Auto" MinWidth="65" SelectedIndex="0">
<ComboBoxItem Content="Standard"/>
<ComboBoxItem Content="Verbose"/>
<ComboBoxItem Content="Debug"/>
<ComboBox.ToolTip>
<ToolTip Content="$($tooltips.LoggingLevel)" />
</ComboBox.ToolTip>
</ComboBox>
</StackPanel>
</Grid>
</StackPanel>
</Grid>
</ScrollViewer>
<TextBlock x:Name="txtVersion" Text="Version: $VERSION" Grid.Row="1" HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="0,0,10,5" FontSize="12" Foreground="{StaticResource VersionBrush}"/>
</Grid>
</Window>
"@
$reader = New-Object System.Xml.XmlNodeReader $xaml
$window = [Windows.Markup.XamlReader]::Load($reader)
# Alternate Settings Check Boxes
$chkDontGroupTasks = $window.FindName("chkDontGroupTasks")
$chkUseAlternativeCategoryNames = $window.FindName("chkUseAlternativeCategoryNames")
$chkAllURLProtocols = $window.FindName("chkAllURLProtocols")
$chkCollectExtraURLProtocolInfo = $window.FindName("chkCollectExtraURLProtocolInfo")
$chkKeepPreviousOutputFolders = $window.FindName("chkKeepPreviousOutputFolders")
$chkAllowDuplicateDeepLinks = $window.FindName("chkAllowDuplicateDeepLinks")
$chkDeepScanHiddenLinks = $window.FindName("chkDeepScanHiddenLinks")
# Control Outputs Check Boxes
$chkCollectStatistics = $window.FindName("chkCollectStatistics")
$chkCollectCLSID = $window.FindName("chkCollectCLSID")
$chkCollectNamedFolders = $window.FindName("chkCollectNamedFolders")
$chkCollectTaskLinks = $window.FindName("chkCollectTaskLinks")
$chkCollectMSSettings = $window.FindName("chkCollectMSSettings")
$chkCollectDeepLinks = $window.FindName("chkCollectDeepLinks")
$chkCollectURLProtocols = $window.FindName("chkCollectURLProtocols")
$chkCollectAppxLinks = $window.FindName("chkCollectAppxLinks")
# Output Location Controls
$txtOutputPath = $window.FindName("txtOutputPath")
$txtCurrentPath = $window.FindName("txtCurrentPath")
$txtOutputFolderName = $window.FindName("txtOutputFolderName")
$btnBrowse = $window.FindName("btnBrowse")
$btnOK = $window.FindName("btnOK")
# Other controls
$cmbLoggingLevel = $window.FindName("cmbLoggingLevel")
# Set initial logging level based on the initialDebug and initialVerbose switches
if ($initialDebug) {
$cmbLoggingLevel.SelectedIndex = 2
} elseif ($initialVerbose) {
$cmbLoggingLevel.SelectedIndex = 1
} else {
$cmbLoggingLevel.SelectedIndex = 0
}
# Set default values
$defaultOutputPath = $PSScriptRoot
$txtOutputPath.Text = $defaultOutputPath
$txtOutputFolderName.Text = $defaultOutputFolderName
$txtCurrentPath.Text = [System.IO.Path]::Combine($defaultOutputPath, $defaultOutputFolderName)
# Add event handlers like browse button and text change
$btnBrowse.Add_Click({
$folderBrowser = New-Object System.Windows.Forms.OpenFileDialog
$folderBrowser.ValidateNames = $false
$folderBrowser.CheckFileExists = $false
$folderBrowser.CheckPathExists = $true
$folderBrowser.FileName = "Folder Selection"
$folderBrowser.Title = "Select Output Directory"
$folderBrowser.InitialDirectory = $txtOutputPath.Text
if ($folderBrowser.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) {
$selectedPath = Split-Path $folderBrowser.FileName
$txtOutputPath.Text = $selectedPath
UpdateCurrentPath
}
})
# Add event handler for URL Protocols checkbox
$chkCollectURLProtocols.Add_Checked({
$chkCollectAppxLinks.IsEnabled = $true
})
$chkCollectURLProtocols.Add_Unchecked({
$chkCollectAppxLinks.IsChecked = $false
$chkCollectAppxLinks.IsEnabled = $false
})
# Initialize the state of chkCollectAppxLinks based on chkCollectURLProtocols
$chkCollectAppxLinks.IsEnabled = $chkCollectURLProtocols.IsChecked
$txtOutputPath.Add_TextChanged({ UpdateCurrentPath })
$txtOutputFolderName.Add_TextChanged({ UpdateCurrentPath })
# After loading the XAML and before showing the window
$btnAbout = $window.FindName("btnAbout")
$btnAbout.Add_Click({
[System.Windows.MessageBox]::Show(" `"Super God Mode`" Script For Windows
Version: $VERSION
Author: ThioJoe
Source Code:
https://github.com/ThioJoe/Windows-Super-God-Mode
",
"About Super God Mode Script",
[System.Windows.MessageBoxButton]::OK,
[System.Windows.MessageBoxImage]::None
)
})
function UpdateCurrentPath {
$outputPath = $txtOutputPath.Text
$folderName = $txtOutputFolderName.Text.Trim()
if ([string]::IsNullOrWhiteSpace($folderName)) {
$txtCurrentPath.Text = $outputPath
} else {
$txtCurrentPath.Text = [System.IO.Path]::Combine($outputPath, $folderName)
}
}
$btnOK.Add_Click({
$window.DialogResult = $true
$window.Close()
})
$result = $window.ShowDialog()
if (-not $result) {
return $null
}
# Return script parameters based on GUI selections
return @{
# Alternative Options
DontGroupTasks = $chkDontGroupTasks.IsChecked
UseAlternativeCategoryNames = $chkUseAlternativeCategoryNames.IsChecked
AllURLProtocols = $chkAllURLProtocols.IsChecked
CollectExtraURLProtocolInfo = $chkCollectExtraURLProtocolInfo.IsChecked
KeepPreviousOutputFolders = $chkKeepPreviousOutputFolders.IsChecked
NoStatistics = !$chkCollectStatistics.IsChecked
AllowDuplicateDeepLinks = $chkAllowDuplicateDeepLinks.IsChecked
DeepScanHiddenLinks = $chkDeepScanHiddenLinks.IsChecked
# Inverse of the Skip options
SkipCLSID = !$chkCollectCLSID.IsChecked
SkipNamedFolders = !$chkCollectNamedFolders.IsChecked
SkipTaskLinks = !$chkCollectTaskLinks.IsChecked
SkipMSSettings = !$chkCollectMSSettings.IsChecked
SkipDeepLinks = !$chkCollectDeepLinks.IsChecked
SkipURLProtocols = !$chkCollectURLProtocols.IsChecked
SkipHiddenAppLinks = !$chkCollectAppxLinks.IsChecked
# Output folder path
Output = $txtCurrentPath.Text
# Logging level
Verbose = $cmbLoggingLevel.SelectedIndex -eq 1
Debug = $cmbLoggingLevel.SelectedIndex -eq 2
}
}
# Setting the default folder name up here so it can be used in the GUI dialog
$timestamp = Get-Date -Format "yyyyMMdd-HHmmss"
$defaultOutputFolderName = "Super God Mode"
if ($uniqueOutputFolder) { $defaultOutputFolderName += "-$timestamp" }
# Start the GUI dialog unless -NoGUI is used
if (-not $NoGUI) {
Write-Host "`nUse the GUI window that just appeared to select any options and run the script.`n(Do not close this window)"
$params = Show-SuperGodModeDialog -defaultOutputFolderName $defaultOutputFolderName -initialDebug:$Debug -initialVerbose:$Verbose
if ($null -eq $params) {
Write-host "Script GUI window appears to have been closed. Exiting script.`n" -ForegroundColor Yellow
exit
}
# Use $params here to set your script variables
$DontGroupTasks = $params.DontGroupTasks
$UseAlternativeCategoryNames = $params.UseAlternativeCategoryNames
$AllURLProtocols = $params.AllURLProtocols
$CollectExtraURLProtocolInfo = $params.CollectExtraURLProtocolInfo
$KeepPreviousOutputFolders = $params.KeepPreviousOutputFolders
$NoStatistics = $params.NoStatistics
$AllowDuplicateDeepLinks = $params.AllowDuplicateDeepLinks
$DeepScanHiddenLinks = $params.DeepScanHiddenLinks
$SkipCLSID = $params.SkipCLSID
$SkipNamedFolders = $params.SkipNamedFolders
$SkipTaskLinks = $params.SkipTaskLinks
$SkipMSSettings = $params.SkipMSSettings
$SkipDeepLinks = $params.SkipDeepLinks
$SkipURLProtocols = $params.SkipURLProtocols
$SkipHiddenAppLinks = $params.SkipHiddenAppLinks
$Output = $params.Output
$Verbose = $params.Verbose
$Debug = $params.Debug
}
# If -Debug or -Verbose is used, set $DebugPreference and $VerbosePreference to Continue, otherwise set to SilentlyContinue.
# This way it will show messages without stopping if -Debug is used and not otherwise
if ($Verbose) {
$Verbose = $true # Setting it as $true instead of letting it be a switch to avoid confusion with 'IsPresent' property
$VerbosePreference = 'Continue'
} else { $VerbosePreference = 'SilentlyContinue' }
if ($Debug) {
$Debug = $true # Setting it as $true instead of letting it be a switch to avoid confusion with 'IsPresent' property
$DebugPreference = 'Continue'
$VerbosePreference = 'Continue' # If Debug is used, also enable Verbose
$Verbose = $true # Set Verbose to true if Debug is used
} else { $DebugPreference = 'SilentlyContinue' }
Write-Host "Beginning script execution..." -ForegroundColor Green
# ====================================================================================================================================
# ================================================== SCRIPT PREPARATION ============================================================
# ====================================================================================================================================
# Set the output folder path for the generated shortcuts based on the provided argument or default location. Convert to full path if necessary
if ($Output) {
# Remove any trailing backslashes from the output path
$Output = $Output.TrimEnd("\")
# Append timestamp if unique output folder is requested
if ($uniqueOutputFolder) { $Output += "-$timestamp" }
# Convert to full path only if necessary, otherwise use as is
if (-not [System.IO.Path]::IsPathRooted($Output)) {
$mainShortcutsFolder = Join-Path $PSScriptRoot $Output
} else { $mainShortcutsFolder = $Output }
} else {
# Default output folder path is a subfolder named "Super God Mode" in the script's directory
$mainShortcutsFolder = Join-Path $PSScriptRoot $defaultOutputFolderName
}
# If Debug mode enabled, create debug logs folder and start transcript
$debugLogsFolderName = "__Debug Logs"
$debugLogFolderPath = Join-Path $mainShortcutsFolder $debugLogsFolderName
if ($Debug) {
if (-not (Test-Path $debugLogFolderPath)) { New-Item -Path $debugLogFolderPath -ItemType Directory -Force | Out-Null }
$debugTranscriptFileName = "DebugTranscript-$timestamp.log"
$debugTranscriptFilePath = Join-Path $debugLogFolderPath $debugTranscriptFileName
Start-Transcript -Path $debugTranscriptFilePath
}
# Print the script parameters to the console
if ($Debug) {
Write-Debug "************** Initial Script Parameters **************"
Write-Debug ("DontGroupTasks: $DontGroupTasks`nUseAlternativeCategoryNames: $UseAlternativeCategoryNames`n" +
"AllURLProtocols: $AllURLProtocols`nCollectExtraURLProtocolInfo: $CollectExtraURLProtocolInfo`n" +
"AllowDuplicateDeepLinks: $AllowDuplicateDeepLinks`nDeepScanHiddenLinks: $DeepScanHiddenLinks`n" +
"Output: $Output`nKeepPreviousOutputFolders: $KeepPreviousOutputFolders`nNoStatistics: $NoStatistics`n" +
"NoReadMe: $NoReadMe`nSkipCLSID: $SkipCLSID`nSkipNamedFolders: $SkipNamedFolders`n" +
"SkipTaskLinks: $SkipTaskLinks`nSkipMSSettings: $SkipMSSettings`nSkipDeepLinks: $SkipDeepLinks`n" +
"SkipURLProtocols: $SkipURLProtocols`nSkipHiddenAppLinks: $SkipHiddenAppLinks`nVerbose: $Verbose`n" +
"Debug: $Debug`ntiming: $timing`ndebugSkipAppxSearch: $debugSkipAppxSearch`n" +
"debugSearchOnlyProtocolList: $debugSearchOnlyProtocolList`nuniqueOutputFolder: $uniqueOutputFolder`n" +
"NoGUI: $NoGUI`nCustomDLLPath: $CustomDLLPath`nCustomLanguageFolderPath: $CustomLanguageFolderPath`n" +
"CustomSystemSettingsDLLPath: $CustomSystemSettingsDLLPath`nCustomAllSystemSettingsXMLPath: $CustomAllSystemSettingsXMLPath")
}
# Define folder names
$clsidFolderName = "CLSID Shell Folder Shortcuts"
$namedFolderName = "Special Named Folders"
$taskLinksFolderName = "All Task Links"
$msSettingsFolderName = "System Settings"
$deepLinksFolderName = "Deep Links"
$urlProtocolsFolderName = "URL Protocols"
$URLProtocolPageLinksFolderName = "Hidden App Links"
$statisticsFolderName = "__Script Result Statistics"
# Construct paths for subfolders
$CLSIDshortcutsOutputFolder = Join-Path $mainShortcutsFolder $clsidFolderName
$namedShortcutsOutputFolder = Join-Path $mainShortcutsFolder $namedFolderName
$taskLinksOutputFolder = Join-Path $mainShortcutsFolder $taskLinksFolderName
$msSettingsOutputFolder = Join-Path $mainShortcutsFolder $msSettingsFolderName
$deepLinksOutputFolder = Join-Path $mainShortcutsFolder $deepLinksFolderName
$URLProtocolLinksOutputFolder = Join-Path $mainShortcutsFolder $urlProtocolsFolderName
$URLProtocolPageLinksOutputFolder = Join-Path $mainShortcutsFolder $URLProtocolPageLinksFolderName
$statisticsOutputFolder = Join-Path $mainShortcutsFolder $statisticsFolderName
# Define hashtables for CSV and XML files
$csvFiles = @{
CLSID = @{ Value = "CLSID_Shell_Folders.csv"; Skip = $SkipCLSID }
NamedFolders = @{ Value = "Named_Shell_Folders.csv"; Skip = $SkipNamedFolders }
TaskLinks = @{ Value = "Task_Links.csv"; Skip = $SkipTaskLinks }
MSSettings = @{ Value = "MS_Settings.csv"; Skip = $SkipMSSettings }
DeepLinks = @{ Value = "Deep_Links.csv"; Skip = $SkipDeepLinks }
URLProtocols = @{ Value = "URL_Protocols.csv"; Skip = $SkipURLProtocols }
URLProtocolPages = @{ Value = "Hidden_App_Links.csv"; Skip = $SkipHiddenAppLinks }
}
$xmlFiles = @{
Shell32Content = @{ Value = "Shell32_Tasks.xml"; Skip = $SkipTaskLinks }
Shell32ResolvedContent = @{ Value = "Shell32_Tasks_Resolved.xml"; Skip = $SkipTaskLinks }
ResolvedSettings = @{ Value = "Settings_XML_Resolved.xml"; Skip = $SkipDeepLinks }
}
# Set filenames for various output files (CSV and XML)
$clsidCsvPath = Join-Path $statisticsOutputFolder $csvFiles.CLSID.Value
$namedFoldersCsvPath = Join-Path $statisticsOutputFolder $csvFiles.NamedFolders.Value
$taskLinksCsvPath = Join-Path $statisticsOutputFolder $csvFiles.TaskLinks.Value
$msSettingsCsvPath = Join-Path $statisticsOutputFolder $csvFiles.MSSettings.Value
$deepLinksCsvPath = Join-Path $statisticsOutputFolder $csvFiles.DeepLinks.Value
$URLProtocolLinksCsvPath = Join-Path $statisticsOutputFolder $csvFiles.URLProtocols.Value
$URLProtocolPageLinksCsvPath = Join-Path $statisticsOutputFolder $csvFiles.URLProtocolPages.Value
# XML content file paths
$xmlContentFilePath = Join-Path $statisticsOutputFolder $xmlFiles.Shell32Content.Value
$resolvedXmlContentFilePath = Join-Path $statisticsOutputFolder $xmlFiles.Shell32ResolvedContent.Value
$resolvedSettingsXmlContentFilePath = Join-Path $statisticsOutputFolder $xmlFiles.ResolvedSettings.Value
# Other constants / known paths.
# Available AllSystemSettings XML files may differ depending on Windows 11 or Windows 10, so will try them in order:
$allSettingsXmlPath1 = "$Env:windir\ImmersiveControlPanel\Settings\AllSystemSettings_{D6E2A6C6-627C-44F2-8A5C-4959AC0C2B2D}.xml"
$allSettingsXmlPath2 = "$Env:windir\ImmersiveControlPanel\Settings\AllSystemSettings_{FDB289F3-FCFC-4702-8015-18926E996EC1}.xml"
$allSettingsXmlPath3 = "$Env:windir\ImmersiveControlPanel\Settings\AllSystemSettings_{253E530E-387D-4BC2-959D-E6F86122E5F2}.xml"
$systemSettingsDllPath = "$Env:windir\ImmersiveControlPanel\SystemSettings.dll"
# URI Protocols deemed "permanent" and not to be included in the URL Protocols section because they aren't special
# See: https://www.iana.org/assignments/uri-schemes/uri-schemes.xhtml
$permanentURIProtocols = @(
'bb','drop','fax','filesystem','grd','mailserver','modem','p1','pack','payment','prospero','snews','upt','videotex','wais','wpid','z39.50',
'aaa','aaas','about','acap','acct','cap','cid','coap','coap+tcp','coap+ws','coaps','coaps+tcp','coaps+ws','crid','data','dav','dict','dns',
'dtn','example','file','ftp','geo','go','gopher','h323','http','https','iax','icap','im','imap','info','ipn','ipp','ipps','iris','iris.beep',
'iris.lwz','iris.xpc','iris.xpcs','jabber','ldap','leaptofrogans','mailto','mid','msrp','msrps','mt','mtqp','mupdate','news','nfs','ni','nih',
'nntp','opaquelocktoken','pkcs11','pop','pres','reload','rtsp','rtsps','rtspu','service','session','shttp','sieve','sip','sips','sms','snmp',
'soap.beep','soap.beeps','stun','stuns','tag','tel','telnet','tftp','thismessage','tip','tn3270','turn','turns','tv','urn','vemmi','vnc','ws',
'wss','xcon','xcon-userid','xmlrpc.beep','xmlrpc.beeps','xmpp','z39.50r','z39.50s'
)
# Tests if a file exists at a path without throwing a huge exception if it doesn't
function Test-Path-Safe {
param (
[Parameter(Mandatory=$true)]
[string]$Path
)
try {
$testPathResult = Test-Path -LiteralPath $Path -PathType Leaf -ErrorAction Stop
if ($testPathResult -ne $true) {
Write-Debug "Test-Path-Safe Result for $Path`: $testPathResult"
}
return $testPathResult
}
catch {
Write-Debug "Test-Path-Safe: Error checking path - $Path : $_"
return $false
}
}
# Check which AllSystemSettings XML file to use
if ($CustomAllSystemSettingsXMLPath) {
if (-not (Test-Path-Safe $CustomAllSystemSettingsXMLPath)) {
Write-Error "The specified AllSystemSettings XML path does not exist: $CustomAllSystemSettingsXMLPath"
return
} else {
$allSettingsXmlPath = $CustomAllSystemSettingsXMLPath
}
} elseif (Test-Path-Safe $allSettingsXmlPath1) {
$allSettingsXmlPath = $allSettingsXmlPath1
} elseif (Test-Path-Safe $allSettingsXmlPath2) {
$allSettingsXmlPath = $allSettingsXmlPath2
} elseif (Test-Path-Safe $allSettingsXmlPath3) {
$allSettingsXmlPath = $allSettingsXmlPath3
} else {
Write-Error "No AllSystemSettings XML file found in expected directory `"$Env:windir\ImmersiveControlPanel\Settings`" - Deep Link shortcuts will not be created."
$allSettingsXmlPath = $null
}
# Check if main folder already exists
if (-not (Test-Path $mainShortcutsFolder)) {
$mainFolderWasCreatedThisRun = $true
} else {
$mainFolderWasCreatedThisRun = $false
}
# Creates the main directory if it does not exist; `-Force` ensures it is created without errors if it already exists. It won't overwrite any files within even if the folder already exists
try {
New-Item -Path $mainShortcutsFolder -ItemType Directory -Force -ErrorAction Stop | Out-Null
# If creating the folder failed and it doesn't already exist, throw an error and exit the script. Give suggestions for some specific cases
} catch [System.UnauthorizedAccessException] {
Write-Error "Failed to create output folder: $_"
# If the default path is used
if (-not $Output) {
Write-Host "This may be due to a permissions issue. Ensure you have permissions to create a folder in the script's directory." -ForegroundColor Yellow
} else {
Write-Host "This may be due to a permissions issue. Ensure you have permissions to create a folder at the specified path." -ForegroundColor Yellow
}
return
} catch {
if (-not (Test-Path $mainShortcutsFolder)) {
Write-Host "Failed to create output folder: $_" -ForegroundColor Yellow
return
}
}
# If the -KeepPreviousOutputFolders switch is not used, go into the set main folder and delete each set subfolder using above variable names
# Doing this instead of just deleting the entire main folder in case the user wants to put the output into a directory in use for other things
if (-not $KeepPreviousOutputFolders) {
try {
if (Test-Path $mainShortcutsFolder) {
# Remove folders
if (Test-Path $CLSIDshortcutsOutputFolder){
Remove-Item -Path $mainShortcutsFolder -Recurse -Force
}
if (Test-Path $namedShortcutsOutputFolder){
Remove-Item -Path $namedShortcutsOutputFolder -Recurse -Force
}
if (Test-Path $taskLinksOutputFolder){
Remove-Item -Path $taskLinksOutputFolder -Recurse -Force
}
if (Test-Path $statisticsOutputFolder) {
Remove-Item -Path $statisticsOutputFolder -Recurse -Force
}
if (Test-Path $msSettingsOutputFolder){
Remove-Item -Path $msSettingsOutputFolder -Recurse -Force
}
if (Test-Path $deepLinksOutputFolder){
Remove-Item -Path $deepLinksOutputFolder -Recurse -Force
}
if (Test-Path $URLProtocolLinksOutputFolder){
Remove-Item -Path $URLProtocolLinksOutputFolder -Recurse -Force
}
if (Test-Path $URLProtocolPageLinksOutputFolder){
Remove-Item -Path $URLProtocolPageLinksOutputFolder -Recurse -Force
}
}
} catch {
Write-Error "Failed to delete contents of previous output folder: $_"
}
}
# Validate the custom dll path if provided
if ($CustomDLLPath) {
if (-not (Test-Path-Safe $CustomDLLPath)) {
Write-Error "The specified DLL path does not exist: $CustomDLLPath"
return
}
}
# Validate the custom language folder path if provided. Ensure it is a folder
if ($CustomLanguageFolderPath) {
if (-not (Test-Path $CustomLanguageFolderPath -PathType Container)) {
Write-Error "The specified custom language folder path is not a valid folder: $CustomLanguageFolderPath"
# Check if they insetad provided a file path, and if so, suggest they provide the folder containing the file
if (Test-Path $CustomLanguageFolderPath -PathType Leaf) {
Write-Host "If you are trying to specify a file, please provide the folder containing the file instead, and name it to correspond with whatever DLL file it is for." -ForegroundColor Yellow
}
return
}
else {
Write-Host "Using custom language folder path: $CustomLanguageFolderPath"
}
}
# Validate the custom system settings DLL path if provided
if ($CustomSystemSettingsDLLPath) {
if (-not (Test-Path-Safe $CustomSystemSettingsDLLPath)) {
Write-Error "The specified SystemSettings.dll path does not exist: $CustomSystemSettingsDLLPath"
return
} else {
$systemSettingsDllPath = $CustomSystemSettingsDLLPath
}
}
# Validate or set appropriate incompatible or dependent switches
if ($SkipURLProtocols) {
$SkipHiddenAppLinks = $true
}
# Function to create a folder with a custom icon and set Details view
function New-FolderWithIcon {
param (
[string]$FolderPath,
[string]$IconFile,
[string]$IconIndex,
[string]$IconFileWin10,
[string]$IconIndexWin10,
[switch]$DetailsView,
[switch]$desktopIniOnly
)
# Create the folder
if (-not $desktopIniOnly) {
New-Item -Path $FolderPath -ItemType Directory -Force | Out-Null
}
# Check current build of windows to determine which icon to use
$windowsBuildNum = [System.Environment]::OSVersion.Version.Build
if ($windowsBuildNum -lt 22000) {
# Update the icon index if a different one is specified for Windows 10 and earlier
if ($IconIndexWin10) {
$IconIndex = $IconIndexWin10
}
if ($IconFileWin10) {
$IconFile = $IconFileWin10
}
}
# If there's not a negative sign at the beginning of the index, add one
if ($IconIndex -notmatch '^-') {
$IconIndex = "-$IconIndex"
}
# Create desktop.ini content
if ($DetailsView) {