forked from Hoorge/WIM-Witch
-
Notifications
You must be signed in to change notification settings - Fork 2
/
WIMWitch.ps1
2267 lines (1964 loc) · 110 KB
/
WIMWitch.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
#===========================================================================
# WIM Witch
#===========================================================================
#
# Written and maintained by: Donna Ryan
# Twitter: @TheNotoriousDRR
# www.TheNotoriousDRR.com
# www.SCConfigMgr.com
#
#===========================================================================
#
# WIM Witch is a GUI driven tool used to update and customize Windows
# Image (WIM) files. It can also create WIM configuration templates and
# apply them either with the GUI or programatically for bulk creation.
#
# It currently supports the following functions:
#
# -Selecting the individual index to import
# -Autopilot for existing devices
# -Retrieve Autopilot deployment profiles from Intune
# -Multi path driver importation
# -Injection of updates from a self maintained local update cache
# -Save and Load Configuration Templates
# -Removal of AppX Modern Apps
# -Create batch jobs for image catalog updating
# -importing WIM and .Net binaries from an ISO file
# -injecting .Net 3.5 binaries into image
#
#===========================================================================
# Version 1.1.1
#
# -Fixed a typo that caused the skype app to not be uninstalled on 1903
# Credit @AndyUpperton for finding the bug :)
#===========================================================================
# Version 1.1
#
# -Fixed OSDSUS upgrade issue by having separate OSDSUS upgrade
# -Fixed a fat-fingering
#
#===========================================================================
# Version 1.0
#
# -Minor bug fixes
# -Removed useless logging tab
# -added color scheme
# -Removed step to update OSDSUS as OSDUpdate updats OSDSUS as a dependent package
# -Removed requirement to check enable updates to perfrom update maintenance.
#
#===========================================================================
# Version 0.9.9
#
# -Added import from ISO function for install.wim and .net binaries
# -Added function to inject .net 3.5 binaries into image, has file existsential check feature
# -minor bug fixes
# -add version detection for OSDSUS module
#
#===========================================================================
# Version 0.9.8
#
# -Added installation check and remdiation
# -Added variable path installation
#
#===========================================================================
# Version 0.9.7
#
# -Added function to check and repair mount point folder
# -Added check to validate existance of Autopilot json file (preflight in MIS)
# -Preflight for MIS stops if target wim already exists (GUI)
# -Added appending target wim file name with last write date to prevent conflict (commandline)
# -Added appending target log file name with last write date to prevent conflict (commandline)
# -Name and file extenstion validation for Source wim selections
# -Catch cancelling the grid view of the indexes for the source WIM
#
#
#===========================================================================
# Version 0.9.6
#
# -Added commandline support for the following:
#
# -handle superseded update deletion
# -downloading of new updates
# -update OSDUpdate module
#
#===========================================================================
# Version 0.9.5
#
# -Added opening and closing notifications
# -Cleaned up opening displays
#===========================================================================
#
# Version 0.9.4
#
# -Added ability to run configs from commandline
# -Added ability to run batch jobs from a single folder where all configs get run
#
#===========================================================================
#
# Version 0.9.3
#
# -Added Save and load from XML
# -Separated Source WIM and JSON function to two parts each. One for select, one for import
# -Started development of a function to refresh the confirmation text boxes on the MIS tab. Doesn't work yet.
#
#
#============================================================================================================
Param(
[parameter(mandatory = $false, HelpMessage = "enable auto")]
[ValidateSet("yes")]
$auto,
[parameter(mandatory = $false, HelpMessage = "config file")]
$autofile,
[parameter(mandatory = $false, HelpMessage = "config path")]
#[ValidateSet("$PSScriptRoot\configs")]
$autopath,
[parameter(mandatory = $false, HelpMessage = "Superseded updates")]
[ValidateSet("audit", "delete")]
$Superseded,
[parameter(mandatory = $false, HelpMessage = "Superseded updates")]
[ValidateSet("update")]
$OSDSUS,
#[parameter(mandatory=$false,HelpMessage="Superseded updates")]
#[ValidateSet("download")]
#$newupdates,
[parameter(mandatory = $false, HelpMessage = "Superseded updates")]
[ValidateSet("all", "1709", "1803", "1809", "1903")]
$DownUpdates,
[parameter(mandatory = $false, HelpMessage = "Superseded updates")]
[ValidateSet("yes")]
$updates
)
#Your XAML goes here :)
$inputXML = @"
<Window x:Class="WIM_Witch_Tabbed.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WIM_Witch_Tabbed"
mc:Ignorable="d"
Title="WIM Witch - v1.1.1" Height="500" Width="825" Background="#FF610536">
<Grid>
<TabControl Margin="0,0,0.2,-0.2" Background="#FFACACAC" BorderBrush="#FF610536" >
<TabItem Header="Import" Height="20" Width="100">
<Grid>
<TextBox x:Name="ImportISOTextBox" HorizontalAlignment="Left" Height="25" Margin="26,85,0,0" TextWrapping="Wrap" Text="ISO to import from..." VerticalAlignment="Top" Width="500" IsEnabled="False"/>
<TextBlock HorizontalAlignment="Left" Margin="26,56,0,0" TextWrapping="Wrap" Text="Select a Windows 10 ISO:" VerticalAlignment="Top" Height="26" Width="353"/>
<Button x:Name="ImportImportSelectButton" Content="Select" HorizontalAlignment="Left" Margin="451,127,0,0" VerticalAlignment="Top" Width="75"/>
<TextBlock HorizontalAlignment="Left" Margin="26,159,0,0" TextWrapping="Wrap" Text="Select the item(s) to import:" VerticalAlignment="Top" Width="263"/>
<CheckBox x:Name="ImportWIMCheckBox" Content="Install.wim" HorizontalAlignment="Left" Margin="44,191,0,0" VerticalAlignment="Top"/>
<CheckBox x:Name="ImportDotNetCheckBox" Content=".Net Binaries" HorizontalAlignment="Left" Margin="44,211,0,0" VerticalAlignment="Top"/>
<TextBlock HorizontalAlignment="Left" Margin="26,268,0,0" TextWrapping="Wrap" Text="New name for the imported WIM:" VerticalAlignment="Top" Width="311"/>
<TextBox x:Name="ImportNewNameTextBox" HorizontalAlignment="Left" Height="23" Margin="26,289,0,0" TextWrapping="Wrap" Text="Name for the imported WIM" VerticalAlignment="Top" Width="500" IsEnabled="False"/>
<Button x:Name="ImportImportButton" Content="Import" HorizontalAlignment="Left" Margin="451,354,0,0" VerticalAlignment="Top" Width="75" IsEnabled="False"/>
</Grid>
</TabItem>
<TabItem Header="Source WIM" Margin="0" Width="100">
<Grid>
<TextBox x:Name="SourceWIMSelectWIMTextBox" HorizontalAlignment="Left" Height="25" Margin="26,98,0,0" TextWrapping="Wrap" Text="Select WIM File" VerticalAlignment="Top" Width="500" IsEnabled="False" Grid.ColumnSpan="2"/>
<Label Content="Source Wim " HorizontalAlignment="Left" Height="25" Margin="26,70,0,0" VerticalAlignment="Top" Width="100"/>
<TextBlock HorizontalAlignment="Left" Margin="26,20,0,0" TextWrapping="Wrap" Text="Select the WIM file, and then Edition, that will serve as the base for the custom WIM." VerticalAlignment="Top" Height="42" Width="353" Grid.ColumnSpan="2"/>
<Button x:Name="SourceWIMSelectButton" Content="Select" HorizontalAlignment="Left" Height="25" Margin="450,142,0,0" VerticalAlignment="Top" Width="75"/>
<TextBox x:Name="SourceWIMImgDesTextBox" HorizontalAlignment="Left" Height="23" Margin="94,155,0,0" TextWrapping="Wrap" Text="ImageDescription" VerticalAlignment="Top" Width="225" IsEnabled="False"/>
<TextBox x:Name="SourceWimArchTextBox" HorizontalAlignment="Left" Height="23" Margin="94,183,0,0" TextWrapping="Wrap" Text="Architecture" VerticalAlignment="Top" Width="225" IsEnabled="False"/>
<TextBox x:Name="SourceWimVerTextBox" HorizontalAlignment="Left" Height="23" Margin="94,211,0,0" TextWrapping="Wrap" Text="Version" VerticalAlignment="Top" Width="225" IsEnabled="False"/>
<TextBox x:Name="SourceWimSPBuildTextBox" HorizontalAlignment="Left" Height="23" Margin="94,239,0,0" TextWrapping="Wrap" Text="SPBuild" VerticalAlignment="Top" Width="225" IsEnabled="False"/>
<TextBox x:Name="SourceWimLangTextBox" HorizontalAlignment="Left" Height="23" Margin="94,267,0,0" TextWrapping="Wrap" Text="Languages" VerticalAlignment="Top" Width="225" IsEnabled="False"/>
<Label Content="Edition" HorizontalAlignment="Left" Height="30" Margin="22,151,0,0" VerticalAlignment="Top" Width="68"/>
<Label Content="Arch" HorizontalAlignment="Left" Height="30" Margin="22,183,0,0" VerticalAlignment="Top" Width="68"/>
<Label Content="Version" HorizontalAlignment="Left" Height="30" Margin="22,211,0,0" VerticalAlignment="Top" Width="68"/>
<Label Content="Patch Level" HorizontalAlignment="Left" Height="30" Margin="22,239,0,0" VerticalAlignment="Top" Width="68"/>
<Label Content="Languages" HorizontalAlignment="Left" Height="30" Margin="22,267,0,0" VerticalAlignment="Top" Width="68"/>
<TextBox x:Name="SourceWimIndexTextBox" HorizontalAlignment="Left" Height="23" Margin="94,297,0,0" TextWrapping="Wrap" Text="Index" VerticalAlignment="Top" Width="225" IsEnabled="False"/>
<Label Content="Index" HorizontalAlignment="Left" Height="30" Margin="22,297,0,0" VerticalAlignment="Top" Width="68"/>
</Grid>
</TabItem>
<TabItem Header="Updates" Height="20" Width="100">
<Grid>
<TextBlock HorizontalAlignment="Left" Margin="91,194,0,0" TextWrapping="Wrap" Text="Installed version " VerticalAlignment="Top"/>
<TextBox x:Name="UpdatesOSDBVersion" HorizontalAlignment="Left" Height="23" Margin="91,217,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120" IsEnabled="False"/>
<Button x:Name="UpdateOSDBUpdateButton" Content="Install / Update" HorizontalAlignment="Left" Margin="218,290,0,0" VerticalAlignment="Top" Width="120"/>
<TextBlock HorizontalAlignment="Left" Height="42" Margin="435,131,0,0" TextWrapping="Wrap" Text="Select which version(s) of Windows 10 to download current patches for. Downloading will also purge superseded updates." VerticalAlignment="Top" Width="335"/>
<TextBlock HorizontalAlignment="Left" Height="23" Margin="471,178,0,0" TextWrapping="Wrap" Text="1903" VerticalAlignment="Top" Width="35"/>
<TextBlock HorizontalAlignment="Left" Height="23" Margin="549,178,0,0" TextWrapping="Wrap" Text="1809" VerticalAlignment="Top" Width="35"/>
<TextBlock HorizontalAlignment="Left" Height="23" Margin="621,178,0,0" TextWrapping="Wrap" Text="1803" VerticalAlignment="Top" Width="35"/>
<TextBlock HorizontalAlignment="Left" Height="23" Margin="690,178,0,0" TextWrapping="Wrap" Text="1709" VerticalAlignment="Top" Width="35"/>
<TextBlock HorizontalAlignment="Left" Margin="20,28,0,0" TextWrapping="Wrap" Text="Click the check box to enable updates for the selected WIM file. WIM Witch will automatically determine the correct version to apply. Updates must have been downloaded prior to making it so." VerticalAlignment="Top" Height="47" Width="353"/>
<CheckBox x:Name="UpdatesEnableCheckBox" Content="Enable Updates" HorizontalAlignment="Left" Margin="26,90,0,0" VerticalAlignment="Top" ClickMode="Press"/>
<CheckBox x:Name="Updates1903CheckBox" Content="" HorizontalAlignment="Left" Margin="446,180,0,0" VerticalAlignment="Top"/>
<CheckBox x:Name="Updates1809CheckBox" Content="" HorizontalAlignment="Left" Margin="524,180,0,0" VerticalAlignment="Top"/>
<CheckBox x:Name="Updates1803CheckBox" Content="" HorizontalAlignment="Left" Margin="596,180,0,0" VerticalAlignment="Top"/>
<CheckBox x:Name="Updates1709CheckBox" Content="" HorizontalAlignment="Left" Margin="665,180,0,0" VerticalAlignment="Top"/>
<Button x:Name="UpdatesDownloadNewButton" Content="Download" HorizontalAlignment="Left" Margin="688,232,0,0" VerticalAlignment="Top" Width="75"/>
<TextBlock HorizontalAlignment="Left" Margin="20,136,0,0" TextWrapping="Wrap" Text="Update OSDeploy modules by using the button below. Updating the modules will require PowerShell to be restarted" VerticalAlignment="Top" Height="34" Width="321"/>
<TextBox x:Name="UpdatesOSDBCurrentVerTextBox" HorizontalAlignment="Left" Height="23" Margin="218,216,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120" IsEnabled="False"/>
<TextBlock HorizontalAlignment="Left" Margin="218,194,0,0" TextWrapping="Wrap" Text="Current Version" VerticalAlignment="Top"/>
<TextBlock x:Name="UpdatesOSDBOutOfDateTextBlock" HorizontalAlignment="Left" Margin="20,315,0,0" TextWrapping="Wrap" Text="A software update module is out of date. Please click the "Install / Update" button to update it." VerticalAlignment="Top" RenderTransformOrigin="0.493,0.524" FontSize="20" Width="321" Visibility="Hidden" />
<TextBlock x:Name="UpdatesOSDBSupercededExistTextBlock" HorizontalAlignment="Left" Margin="417,283,0,0" TextWrapping="Wrap" Text="Superceded updates discovered. Please select the versions of Windows 10 you are supporting and click "Update"" VerticalAlignment="Top" FontSize="20" Width="375" Visibility="Hidden"/>
<TextBlock x:Name="UpdatesOSDBClosePowerShellTextBlock" HorizontalAlignment="Left" Margin="435,28,0,0" TextWrapping="Wrap" Text="Please close all PowerShell windows, including WIM Witch, then relaunch app to continue" VerticalAlignment="Top" RenderTransformOrigin="0.493,0.524" FontSize="20" Width="321" Visibility="Hidden"/>
<TextBlock HorizontalAlignment="Left" Margin="24,217,0,0" TextWrapping="Wrap" Text="OSDUpdate" VerticalAlignment="Top"/>
<TextBlock HorizontalAlignment="Left" Margin="26,254,0,0" TextWrapping="Wrap" Text="OSDSUS" VerticalAlignment="Top"/>
<TextBox x:Name="UpdatesOSDSUSVersion" HorizontalAlignment="Left" Height="23" Margin="91,250,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120" IsEnabled="False"/>
<TextBox x:Name="UpdatesOSDSUSCurrentVerTextBox" HorizontalAlignment="Left" Height="23" Margin="218,250,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120" IsEnabled="False"/>
</Grid>
</TabItem>
<TabItem Header="Autopilot" Width="100">
<Grid>
<TextBox x:Name="JSONTextBox" HorizontalAlignment="Left" Height="25" Margin="26,130,0,0" TextWrapping="Wrap" Text="Select JSON File" VerticalAlignment="Top" Width="500" IsEnabled="False"/>
<Label x:Name="JSONLabel" Content="Source JSON" HorizontalAlignment="Left" Height="25" Margin="26,104,0,0" VerticalAlignment="Top" Width="100"/>
<Button x:Name="JSONButton" Content="Select" HorizontalAlignment="Left" Height="25" Margin="451,165,0,0" VerticalAlignment="Top" Width="75" IsEnabled="False"/>
<TextBlock HorizontalAlignment="Left" Margin="26,20,0,0" TextWrapping="Wrap" Text="Select a JSON file for use in deploying Autopilot systems. The file will be copied to processing folder during the build" VerticalAlignment="Top" Height="42" Width="353"/>
<CheckBox x:Name="JSONEnableCheckBox" Content="Enable Autopilot " HorizontalAlignment="Left" Margin="26,80,0,0" VerticalAlignment="Top" ClickMode="Press"/>
<TextBox x:Name="ZtdCorrelationId" HorizontalAlignment="Left" Height="23" Margin="129,176,0,0" TextWrapping="Wrap" Text="Select JSON File..." VerticalAlignment="Top" Width="236" IsEnabled="False"/>
<TextBox x:Name="CloudAssignedTenantDomain" HorizontalAlignment="Left" Height="23" Margin="129,204,0,0" TextWrapping="Wrap" Text="Select JSON File..." VerticalAlignment="Top" Width="236" IsEnabled="False"/>
<TextBox x:Name="Comment_File" HorizontalAlignment="Left" Height="23" Margin="129,232,0,0" TextWrapping="Wrap" Text="Select JSON File..." VerticalAlignment="Top" Width="236" IsEnabled="False"/>
<TextBlock HorizontalAlignment="Left" Margin="24,178,0,0" TextWrapping="Wrap" Text="ZTD ID#" VerticalAlignment="Top"/>
<TextBlock HorizontalAlignment="Left" Margin="24,204,0,0" TextWrapping="Wrap" Text="Tenant Name" VerticalAlignment="Top"/>
<TextBlock HorizontalAlignment="Left" Margin="24,233,0,0" TextWrapping="Wrap" Text="Deployment Profile" VerticalAlignment="Top"/>
<TextBox x:Name="JSONTextBoxSavePath" HorizontalAlignment="Left" Height="23" Margin="26,375,0,0" TextWrapping="Wrap" Text="$PSScriptRoot\Autopilot" VerticalAlignment="Top" Width="499" IsEnabled="False"/>
<TextBox x:Name="JSONTextBoxAADID" HorizontalAlignment="Left" Height="23" Margin="27,331,0,0" TextWrapping="Wrap" Text="User ID for Intune authentication" VerticalAlignment="Top" Width="499"/>
<TextBlock HorizontalAlignment="Left" Margin="26,275,0,0" TextWrapping="Wrap" Text="To download a new Autopilot profile from Intune, provide an AAD user name and a path to save the file" VerticalAlignment="Top" Height="36" Width="331"/>
<TextBlock HorizontalAlignment="Left" Margin="27,312,0,0" TextWrapping="Wrap" Text="User ID:" VerticalAlignment="Top"/>
<TextBlock HorizontalAlignment="Left" Margin="27,358,0,0" TextWrapping="Wrap" Text="Path to save file:" VerticalAlignment="Top"/>
<Button x:Name="JSONButtonSavePath" Content="Select" HorizontalAlignment="Left" Margin="450,403,0,0" VerticalAlignment="Top" Width="75"/>
<Button x:Name="JSONButtonRetrieve" Content="Retrieve Profile" HorizontalAlignment="Left" Margin="382,275,0,0" VerticalAlignment="Top" Width="130"/>
</Grid>
</TabItem>
<TabItem Header="Drivers" Height="20" Width="100">
<Grid>
<TextBox x:Name="DriverDir1TextBox" HorizontalAlignment="Left" Height="25" Margin="26,144,0,0" TextWrapping="Wrap" Text="Select Driver Source Folder" VerticalAlignment="Top" Width="500" IsEnabled="False"/>
<Label x:Name="DirverDirLabel" Content="Driver Source" HorizontalAlignment="Left" Height="25" Margin="26,114,0,0" VerticalAlignment="Top" Width="100"/>
<Button x:Name="DriverDir1Button" Content="Select" HorizontalAlignment="Left" Height="25" Margin="562,144,0,0" VerticalAlignment="Top" Width="75" IsEnabled="False"/>
<TextBlock HorizontalAlignment="Left" Margin="26,20,0,0" TextWrapping="Wrap" Text="Select the path to the driver source(s) that contains the drivers that will be injected." VerticalAlignment="Top" Height="42" Width="353"/>
<CheckBox x:Name="DriverCheckBox" Content="Enable Driver Injection" HorizontalAlignment="Left" Margin="26,80,0,0" VerticalAlignment="Top"/>
<TextBox x:Name="DriverDir2TextBox" HorizontalAlignment="Left" Height="25" Margin="26,189,0,0" TextWrapping="Wrap" Text="Select Driver Source Folder" VerticalAlignment="Top" Width="500" IsEnabled="False"/>
<Button x:Name="DriverDir2Button" Content="Select" HorizontalAlignment="Left" Height="25" Margin="562,189,0,0" VerticalAlignment="Top" Width="75" IsEnabled="False"/>
<TextBox x:Name="DriverDir3TextBox" HorizontalAlignment="Left" Height="25" Margin="26,234,0,0" TextWrapping="Wrap" Text="Select Driver Source Folder" VerticalAlignment="Top" Width="500" IsEnabled="False"/>
<Button x:Name="DriverDir3Button" Content="Select" HorizontalAlignment="Left" Height="25" Margin="562,234,0,0" VerticalAlignment="Top" Width="75" IsEnabled="False"/>
<TextBox x:Name="DriverDir4TextBox" HorizontalAlignment="Left" Height="25" Margin="26,281,0,0" TextWrapping="Wrap" Text="Select Driver Source Folder" VerticalAlignment="Top" Width="500" IsEnabled="False"/>
<Button x:Name="DriverDir4Button" Content="Select" HorizontalAlignment="Left" Height="25" Margin="562,281,0,0" VerticalAlignment="Top" Width="75" IsEnabled="False"/>
<TextBox x:Name="DriverDir5TextBox" HorizontalAlignment="Left" Height="25" Margin="26,328,0,0" TextWrapping="Wrap" Text="Select Driver Source Folder" VerticalAlignment="Top" Width="500" IsEnabled="False"/>
<Button x:Name="DriverDir5Button" Content="Select" HorizontalAlignment="Left" Height="25" Margin="562,328,0,0" VerticalAlignment="Top" Width="75" IsEnabled="False"/>
</Grid>
</TabItem>
<TabItem Header ="App Removal" Height="20" Width="100">
<Grid>
<TextBox x:Name="AppxTextBox" TextWrapping="Wrap" Text="Select the apps to remove..." Margin="21,85,252.2,22.8" VerticalScrollBarVisibility="Visible"/>
<TextBlock HorizontalAlignment="Left" Margin="21,65,0,0" TextWrapping="Wrap" Text="Selected app packages to remove:" VerticalAlignment="Top" Height="15" Width="194"/>
<CheckBox x:Name="AppxCheckBox" Content="Enable app removal" HorizontalAlignment="Left" Margin="21,33,0,0" VerticalAlignment="Top"/>
<Button x:Name="AppxButton" Content="Select" HorizontalAlignment="Left" Margin="202,33,0,0" VerticalAlignment="Top" Width="75"/>
</Grid>
</TabItem>
<TabItem Header="Make It So" Height="20" Width="100">
<Grid>
<Button x:Name="MISFolderButton" Content="Select" HorizontalAlignment="Left" Margin="444,155,0,0" VerticalAlignment="Top" Width="75" RenderTransformOrigin="0.39,-2.647"/>
<TextBox x:Name="MISWimNameTextBox" HorizontalAlignment="Left" Height="25" Margin="20,85,0,0" TextWrapping="Wrap" Text="Enter Target WIM Name" VerticalAlignment="Top" Width="500"/>
<TextBox x:Name="MISDriverTextBox" HorizontalAlignment="Left" Height="23" Margin="136,345,0,0" TextWrapping="Wrap" Text="Driver Y/N" VerticalAlignment="Top" Width="120" IsEnabled="False"/>
<Label Content="Driver injection?" HorizontalAlignment="Left" Height="30" Margin="29,343,0,0" VerticalAlignment="Top" Width="101"/>
<TextBox x:Name="MISJSONTextBox" HorizontalAlignment="Left" Height="23" Margin="136,374,0,0" TextWrapping="Wrap" Text="JSON Select Y/N" VerticalAlignment="Top" Width="120" IsEnabled="False"/>
<Label Content="JSON injection?" HorizontalAlignment="Left" Margin="29,372,0,0" VerticalAlignment="Top" Width="102"/>
<TextBox x:Name="MISWimFolderTextBox" HorizontalAlignment="Left" Height="23" Margin="20,119,0,0" TextWrapping="Wrap" Text="$PSScriptRoot\CompletedWIMs" VerticalAlignment="Top" Width="500" IsEnabled="False"/>
<TextBlock HorizontalAlignment="Left" Margin="20,20,0,0" TextWrapping="Wrap" Text="Enter a name, and select a destination forlder, for the image to be created. Once complete, and build parameters verified, click "Make it so!" to start the build." VerticalAlignment="Top" Height="60" Width="353"/>
<Button x:Name="MISMakeItSoButton" Content="Make it so!" HorizontalAlignment="Left" Margin="400,20,0,0" VerticalAlignment="Top" Width="120" Height="29" FontSize="16"/>
<TextBox x:Name="MISMountTextBox" HorizontalAlignment="Left" Height="25" Margin="19,219,0,0" TextWrapping="Wrap" Text="$PSScriptRoot\Mount" VerticalAlignment="Top" Width="500" IsEnabled="False"/>
<Label Content="Mount Path" HorizontalAlignment="Left" Margin="19,194,0,0" VerticalAlignment="Top" Height="25" Width="100"/>
<Button x:Name="MISMountSelectButton" Content="Select" HorizontalAlignment="Left" Margin="444,255,0,0" VerticalAlignment="Top" Width="75" Height="25"/>
<Label Content="Update injection?" HorizontalAlignment="Left" Margin="29,311,0,0" VerticalAlignment="Top" Width="109"/>
<TextBox x:Name="MISUpdatesTextBox" HorizontalAlignment="Left" Height="23" Margin="136,314,0,0" TextWrapping="Wrap" Text="Updates Y/N" VerticalAlignment="Top" Width="120" RenderTransformOrigin="0.171,0.142" IsEnabled="False"/>
<Label Content="App removal?" HorizontalAlignment="Left" Margin="29,280,0,0" VerticalAlignment="Top" Width="109"/>
<TextBox x:Name="MISAppxTextBox" HorizontalAlignment="Left" Height="23" Margin="136,283,0,0" TextWrapping="Wrap" Text="Updates Y/N" VerticalAlignment="Top" Width="120" RenderTransformOrigin="0.171,0.142" IsEnabled="False"/>
<CheckBox x:Name="MISDotNetCheckBox" Content="Inject .Net 3.5" HorizontalAlignment="Left" Margin="306,349,0,0" VerticalAlignment="Top" FontSize="16" FontWeight="Bold"/>
<TextBlock HorizontalAlignment="Left" Margin="306,293,0,0" TextWrapping="Wrap" Text="To inject .Net 3.5, check the box below. Binaries must be imported from an ISO. WIM Witch cannot download them directly from Microsoft." VerticalAlignment="Top" Height="56" Width="260"/>
</Grid>
</TabItem>
<TabItem Header="Save/Load" Height="20" Width="100">
<Grid>
<TextBox x:Name="SLSaveFileName" HorizontalAlignment="Left" Height="25" Margin="26,85,0,0" TextWrapping="Wrap" Text="Name for saved configuration..." VerticalAlignment="Top" Width="500"/>
<TextBlock HorizontalAlignment="Left" Margin="26,38,0,0" TextWrapping="Wrap" Text="Provide a name for the saved configuration" VerticalAlignment="Top" Height="42" Width="353"/>
<Button x:Name="SLSaveButton" Content="Save" HorizontalAlignment="Left" Margin="451,127,0,0" VerticalAlignment="Top" Width="75"/>
<Border BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Left" Height="1" Margin="0,216,0,0" VerticalAlignment="Top" Width="785"/>
<TextBox x:Name="SLLoadTextBox" HorizontalAlignment="Left" Height="23" Margin="26,308,0,0" TextWrapping="Wrap" Text="Select configuration file to load" VerticalAlignment="Top" Width="500"/>
<Button x:Name="SLLoadButton" Content="Load" HorizontalAlignment="Left" Margin="451,351,0,0" VerticalAlignment="Top" Width="75"/>
<TextBlock HorizontalAlignment="Left" Margin="26,279,0,0" TextWrapping="Wrap" Text="Select configuration file to load" VerticalAlignment="Top" Width="353"/>
</Grid>
</TabItem>
</TabControl>
</Grid>
</Window>
"@
$inputXML = $inputXML -replace 'mc:Ignorable="d"', '' -replace "x:N", 'N' -replace '^<Win.*', '<Window'
[void][System.Reflection.Assembly]::LoadWithPartialName('presentationframework')
[void][System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[xml]$XAML = $inputXML
#Read XAML
$reader = (New-Object System.Xml.XmlNodeReader $xaml)
try {
$Form = [Windows.Markup.XamlReader]::Load( $reader )
}
catch {
Write-Warning "Unable to parse XML, with error: $($Error[0])`n Ensure that there are NO SelectionChanged or TextChanged properties in your textboxes (PowerShell cannot process them)"
throw
}
#===========================================================================
# Load XAML Objects In PowerShell
#===========================================================================
$xaml.SelectNodes("//*[@Name]") | % { "trying item $($_.Name)" | out-null;
try { Set-Variable -Name "WPF$($_.Name)" -Value $Form.FindName($_.Name) -ErrorAction Stop }
catch { throw }
}
Function Get-FormVariables {
if ($global:ReadmeDisplay -ne $true) { Write-host "If you need to reference this display again, run Get-FormVariables" -ForegroundColor Yellow; $global:ReadmeDisplay = $true }
#write-host "Found the following interactable elements from our form" -ForegroundColor Cyan
get-variable WPF*
}
#Get-FormVariables
#===========================================================================
# Functions for Controls
#===========================================================================
#Funtion to select mounting directory
Function SelectMountDir {
Add-Type -AssemblyName System.Windows.Forms
$browser = New-Object System.Windows.Forms.FolderBrowserDialog
$browser.Description = "Select the mount folder"
$null = $browser.ShowDialog()
$MountDir = $browser.SelectedPath
$WPFMISMountTextBox.text = $MountDir
check-mountpath -path $WPFMISMountTextBox.text
update-log -Data "Mount directory selected" -Class Information
}
#Function to select Source WIM
Function SelectSourceWIM {
$SourceWIM = New-Object System.Windows.Forms.OpenFileDialog -Property @{
#InitialDirectory = [Environment]::GetFolderPath('Desktop')
InitialDirectory = "$PSScriptRoot\imports\wim"
Filter = 'WIM (*.wim)|'
}
$null = $SourceWIM.ShowDialog()
$WPFSourceWIMSelectWIMTextBox.text = $SourceWIM.FileName
if ($SourceWIM.FileName -notlike "*.wim") {
update-log -Data "A WIM file not selected. Please select a valid file to continue." -Class Warning
return
}
#Select the index
$ImageFull = @(get-windowsimage -ImagePath $WPFSourceWIMSelectWIMTextBox.text)
$a = $ImageFull | Out-GridView -Title "Choose an Image Index" -Passthru
$IndexNumber = $a.ImageIndex
#write-host $IndexNumber
if ($indexnumber -eq $null) {
update-log -Data "Index not selected. Reselect the WIM file to select an index" -Class Warning
return
}
import-wiminfo -IndexNumber $IndexNumber
}
function import-wiminfo($IndexNumber) {
Update-Log -Data "Importing Source WIM Info" -Class Information
try {
#Gets WIM metadata to populate fields on the Source tab.
$ImageInfo = get-windowsimage -ImagePath $WPFSourceWIMSelectWIMTextBox.text -index $IndexNumber -ErrorAction Stop
}
catch {
Update-Log -data $_.Exception.Message -class Error
Update-Log -data "The WIM file selected may be borked. Try a different one" -Class Warning
Return
}
$text = "WIM file selected: " + $SourceWIM.FileName
Update-Log -data $text -Class Information
$text = "Edition selected: " + $ImageInfo.ImageDescription
Update-Log -data $text -Class Information
$ImageIndex = $IndexNumber
$WPFSourceWIMImgDesTextBox.text = $ImageInfo.ImageDescription
$WPFSourceWimVerTextBox.Text = $ImageInfo.Version
$WPFSourceWimSPBuildTextBox.text = $ImageInfo.SPBuild
$WPFSourceWimLangTextBox.text = $ImageInfo.Languages
$WPFSourceWimIndexTextBox.text = $ImageIndex
if ($ImageInfo.Architecture -eq 9) {
$WPFSourceWimArchTextBox.text = 'x64'
}
Else {
$WPFSourceWimArchTextBox.text = 'x86'
}
}
#Function to Select JSON File
Function SelectJSONFile {
$JSON = New-Object System.Windows.Forms.OpenFileDialog -Property @{
InitialDirectory = [Environment]::GetFolderPath('Desktop')
Filter = 'JSON (*.JSON)|'
}
$null = $JSON.ShowDialog()
$WPFJSONTextBox.Text = $JSON.FileName
$text = "JSON file selected: " + $JSON.FileName
update-log -Data $text -Class Information
Parse-JSON -file $JSON.FileName
}
#Function to parse the JSON file for user valuable info
Function Parse-JSON($file) {
try {
Update-Log -Data "Attempting to parse JSON file..." -Class Information
$autopilotinfo = Get-Content $WPFJSONTextBox.Text | ConvertFrom-Json
Update-Log -Data "Successfully parsed JSON file" -Class Information
$WPFZtdCorrelationId.Text = $autopilotinfo.ZtdCorrelationId
$WPFCloudAssignedTenantDomain.Text = $autopilotinfo.CloudAssignedTenantDomain
$WPFComment_File.text = $autopilotinfo.Comment_File
}
catch {
$WPFZtdCorrelationId.Text = "Bad file. Try Again."
$WPFCloudAssignedTenantDomain.Text = "Bad file. Try Again."
$WPFComment_File.text = "Bad file. Try Again."
Update-Log -Data "Failed to parse JSON file. Try another"
return
}
}
#Function to select the paths for the driver fields
Function SelectDriverSource($DriverTextBoxNumber) {
#write-host $DriverTextBoxNumber
Add-Type -AssemblyName System.Windows.Forms
$browser = New-Object System.Windows.Forms.FolderBrowserDialog
$browser.Description = "Select the Driver Source folder"
$null = $browser.ShowDialog()
$DriverDir = $browser.SelectedPath
$DriverTextBoxNumber.Text = $DriverDir
update-log -Data "Driver path selected: $DriverDir" -Class Information
}
#Function for the Make it So button
Function MakeItSo ($appx) {
#Check if new file name is valid, also append file extension if neccessary
###Starting MIS Preflight###
check-mountpath -path $WPFMISMountTextBox.Text -clean True
if (($WPFMISWimNameTextBox.Text -eq "") -or ($WPFMISWimNameTextBox.Text -eq "Enter Target WIM Name")) {
update-log -Data "Enter a valid file name and then try again" -Class Error
return
}
if ($auto -ne "yes") {
$checkresult = (check-name)
if ($checkresult -eq "stop") { return }
}
if ($auto -eq "yes") {
$checkresult = (check-name -conflict append)
if ($checkresult -eq "stop") { return }
}
#check for working directory, make if does not exist, delete files if they exist
$FolderExist = Test-Path $PSScriptRoot\Staging -PathType Any
update-log -Data "Checking to see if the staging path exists..." -Class Information
try {
if ($FolderExist = $False) {
New-Item -ItemType Directory -Force -Path $PSScriptRoot\Staging -ErrorAction Stop
update-log -Data "Path did not exist, but it does now :)" -Class Information -ErrorAction Stop
}
Else {
Remove-Item –path $PSScriptRoot\Staging\* -Recurse -ErrorAction Stop
update-log -Data "The path existed, and it has been purged." -Class Information -ErrorAction Stop
}
}
catch {
Update-Log -data $_.Exception.Message -class Error
Update-Log -data "Something is wrong with folder $PSScriptRoot\Staging. Try deleting manually if it exists" -Class Error
return
}
if ($WPFJSONEnableCheckBox.IsChecked -eq $true) {
Update-Log -Data "Validating existance of JSON file..." -Class Information
$APJSONExists = (Test-Path $WPFJSONTextBox.Text)
if ($APJSONExists -eq $true) { Update-Log -Data "JSON exists. Continuing..." -Class Information }
else {
Update-Log -Data "The Autopilot file could not be verified. Check it and try again." -Class Error
return
}
}
if ($WPFMISDotNetCheckBox.IsChecked -eq $true) {
if ((check-dotnetexists) -eq $False) { return }
}
#####End of MIS Preflight###################################################################
#Copy source WIM
update-log -Data "Copying source WIM to the staging folder" -Class Information
try {
Copy-Item $WPFSourceWIMSelectWIMTextBox.Text -Destination "$PSScriptRoot\Staging" -ErrorAction Stop
}
catch {
Update-Log -data $_.Exception.Message -class Error
Update-Log -Data "The file couldn't be copied. No idea what happened" -class Error
return
}
update-log -Data "Source WIM has been copied to the source folder" -Class Information
#Rename copied source WiM
try {
$wimname = Get-Item -Path $PSScriptRoot\Staging\*.wim -ErrorAction Stop
Rename-Item -Path $wimname -NewName $WPFMISWimNameTextBox.Text -ErrorAction Stop
update-log -Data "Copied source WIM has been renamed" -Class Information
}
catch {
Update-Log -data $_.Exception.Message -class Error
Update-Log -data "The copied source file couldn't be renamed. This shouldn't have happened." -Class Error
Update-Log -data "Go delete the WIM from $PSScriptRoot\Staging\, then try again" -Class Error
return
}
#Remove the unwanted indexes
remove-indexes
#Mount the WIM File
$wimname = Get-Item -Path $PSScriptRoot\Staging\*.wim
update-log -Data "Mounting source WIM $wimname" -Class Information
update-log -Data "to mount point:" -Class Information
update-log -data $WPFMISMountTextBox.Text -Class Information
try {
#write-host $IndexNumber
Mount-WindowsImage -Path $WPFMISMountTextBox.Text -ImagePath $wimname -Index 1 -ErrorAction Stop | Out-Null
}
catch {
Update-Log -data $_.Exception.Message -class Error
Update-Log -data "The WIM couldn't be mounted. Make sure the mount directory is empty" -Class Error
Update-Log -Data "and that it isn't an active mount point" -Class Error
return
}
#Inject .Net Binaries
if ($WPFMISDotNetCheckBox.IsChecked -eq $true) { inject-dotnet }
#Inject Autopilot JSON file
if ($WPFJSONEnableCheckBox.IsChecked -eq $true) {
update-log -Data "Injecting JSON file" -Class Information
try {
$autopilotdir = $WPFMISMountTextBox.Text + "\windows\Provisioning\Autopilot"
Copy-Item $WPFJSONTextBox.Text -Destination $autopilotdir -ErrorAction Stop
}
catch {
Update-Log -data $_.Exception.Message -class Error
Update-Log -data "JSON file couldn't be copied. Check to see if the correct SKU" -Class Error
Update-Log -Data "of Windows has been selected" -Class Error
Update-log -Data "The WIM is still mounted. You'll need to clean that up manually until" -Class Error
Update-Log -data "I get around to handling that error more betterer" -Class Error
Update-Log -data "- <3 Donna" -Class Error
return
}
}
else {
update-log -Data "JSON not selected. Skipping JSON Injection" -Class Information
}
#Inject Drivers
If ($WPFDriverCheckBox.IsChecked -eq $true) {
DriverInjection -Folder $WPFDriverDir1TextBox.text
DriverInjection -Folder $WPFDriverDir2TextBox.text
DriverInjection -Folder $WPFDriverDir3TextBox.text
DriverInjection -Folder $WPFDriverDir4TextBox.text
DriverInjection -Folder $WPFDriverDir5TextBox.text
}
Else {
update-log -Data "Drivers were not selected for injection. Skipping." -Class Information
}
#Apply Updates
If ($WPFUpdatesEnableCheckBox.IsChecked -eq $true) {
Apply-Updates -class "SSU"
Apply-Updates -class "LCU"
Apply-Updates -class "AdobeSU"
Apply-Updates -class "DotNet"
Apply-Updates -class "DotNetCU"
}
Else {
Update-Log -Data "Updates not enabled" -Class Information
}
#Remove AppX Packages
if ($WPFAppxCheckBox.IsChecked -eq $true) { remove-appx -array $appx }
Else {
Update-Log -Data "App removal not enabled" -Class Information
}
#Copy log to mounted WIM
try {
update-log -Data "Attempting to copy log to mounted image" -Class Information
$mountlogdir = $WPFMISMountTextBox.Text + "\windows\"
Copy-Item $PSScriptRoot\logging\WIMWitch.log -Destination $mountlogdir -ErrorAction Stop
$CopyLogExist = Test-Path $mountlogdir\WIMWitch.log -PathType Leaf
if ($CopyLogExist -eq $true) { update-log -Data "Log filed copied successfully" -Class Information }
}
catch {
Update-Log -data $_.Exception.Message -class Error
update-log -data "Coudn't copy the log file to the mounted image." -class Error
}
#Dismount, commit, and move WIM
update-log -Data "Dismounting WIM file, committing changes" -Class Information
try {
Dismount-WindowsImage -Path $WPFMISMountTextBox.Text -save -ErrorAction Stop | Out-Null
}
catch {
Update-Log -data $_.Exception.Message -class Error
Update-Log -data "The WIM couldn't save. You will have to manually discard the" -Class Error
Update-Log -data "mounted image manually" -Class Error
return
}
update-log -Data "WIM dismounted" -Class Information
try {
Move-Item -Path $wimname -Destination $WPFMISWimFolderTextBox.Text -ErrorAction Stop
}
catch {
Update-Log -data $_.Exception.Message -class Error
Update-Log -data "The WIM couldn't be copied. You can still retrieve it from staging path." -Class Error
Update-Log -data "The file will be deleted when the tool is rerun." -Class Error
return
}
update-log -Data "Moved saved WIM to target directory" -Class Information
#Copy log here
try {
update-log -Data "Copying build log to target folder" -Class Information
Copy-Item -Path $PSScriptRoot\logging\WIMWitch.log -Destination $WPFMISWimFolderTextBox.Text -ErrorAction Stop
$logold = $WPFMISWimFolderTextBox.Text + "\WIMWitch.log"
$lognew = $WPFMISWimFolderTextBox.Text + "\" + $WPFMISWimNameTextBox.Text + ".log"
#Put log detection code here
if ((test-path -Path $lognew) -eq $true) {
Update-Log -Data "A preexisting log file contains the same name. Renaming old log..." -Class Warning
replace-name -file $lognew -extension ".log"
}
#Put log detection code here
Rename-Item $logold -NewName $lognew -Force -ErrorAction Stop
Update-Log -Data "Log copied successfully" -Class Information
}
catch {
Update-Log -data $_.Exception.Message -class Error
Update-Log -data "The log file couldn't be copied and renamed. You can still snag it from the source." -Class Error
update-log -Data "Job's done." -Class Information
return
}
update-log -Data "Job's done." -Class Information
}
#Function to assign the target directory
Function SelectTargetDir {
Add-Type -AssemblyName System.Windows.Forms
$browser = New-Object System.Windows.Forms.FolderBrowserDialog
$browser.Description = "Select the target folder"
$null = $browser.ShowDialog()
$TargetDir = $browser.SelectedPath
$WPFMISWimFolderTextBox.text = $TargetDir #I SCREWED UP THIS VARIABLE
update-log -Data "Target directory selected" -Class Information
}
#Function to enable logging and folder check
Function Update-Log {
Param(
[Parameter(
Mandatory = $true,
ValueFromPipeline = $true,
ValueFromPipelineByPropertyName = $true,
Position = 0
)]
[string]$Data,
[Parameter(
Mandatory = $false,
ValueFromPipeline = $true,
ValueFromPipelineByPropertyName = $true,
Position = 0
)]
[string]$Solution = $Solution,
[Parameter(
Mandatory = $false,
ValueFromPipeline = $true,
ValueFromPipelineByPropertyName = $true,
Position = 1
)]
[validateset('Information', 'Warning', 'Error')]
[string]$Class = "Information"
)
$global:ScriptLogFilePath = $Log
$LogString = "$(Get-Date) $Class - $Data"
$HostString = "$(Get-Date) $Class - $Data"
Add-Content -Path $Log -Value $LogString
switch ($Class) {
'Information' {
Write-Host $HostString -ForegroundColor Gray
}
'Warning' {
Write-Host $HostString -ForegroundColor Yellow
}
'Error' {
Write-Host $HostString -ForegroundColor Red
}
Default { }
}
#The below line is for a logging tab that was removed. If it gets put back in, reenable the line
# $WPFLoggingTextBox.text = Get-Content -Path $Log -Delimiter "\n"
}
#Removes old log and creates all folders if does not exist
Function Set-Logging {
#logging folder
$FileExist = Test-Path -Path $PSScriptRoot\logging\WIMWitch.Log -PathType Leaf
if ($FileExist -eq $False) {
#update-log -data "Logging folder does not exist" -class Warning
New-Item -ItemType Directory -Force -Path $PSScriptRoot\Logging | Out-Null
New-Item -Path $PSScriptRoot\logging -Name "WIMWitch.log" -ItemType "file" -Value "***Logging Started***" | Out-Null
#update-log -data "Logging folder and log created successfully" -Class Information
}
Else {
Remove-Item -Path $PSScriptRoot\logging\WIMWitch.log
New-Item -Path $PSScriptRoot\logging -Name "WIMWitch.log" -ItemType "file" -Value "***Logging Started***" | Out-Null
#Update-Log -Data "Logging started successfully" -Class Information
}
#updates folder
$FileExist = Test-Path -Path $PSScriptRoot\updates #-PathType Leaf
if ($FileExist -eq $False) {
Update-Log -Data "Updates folder does not exist. Creating..." -Class Warning
New-Item -ItemType Directory -Force -Path $PSScriptRoot\updates | Out-Null
Update-Log -Data "Updates folder created" -Class Information
}
if ($FileExist -eq $True) { Update-Log -Data "Updates folder exists" -Class Information }
#staging folder
$FileExist = Test-Path -Path $PSScriptRoot\Staging #-PathType Leaf
if ($FileExist -eq $False) {
Update-Log -Data "Staging folder does not exist. Creating..." -Class Warning
New-Item -ItemType Directory -Force -Path $PSScriptRoot\Staging | Out-Null
Update-Log -Data "Staging folder created" -Class Information
}
if ($FileExist -eq $True) { Update-Log -Data "Staging folder exists" -Class Information }
#Mount folder
$FileExist = Test-Path -Path $PSScriptRoot\Mount #-PathType Leaf
if ($FileExist -eq $False) {
Update-Log -Data "Mount folder does not exist. Creating..." -Class Warning
New-Item -ItemType Directory -Force -Path $PSScriptRoot\Mount | Out-Null
Update-Log -Data "Mount folder created" -Class Information
}
if ($FileExist -eq $True) { Update-Log -Data "Mount folder exists" -Class Information }
#Completed WIMs folder
$FileExist = Test-Path -Path $PSScriptRoot\CompletedWIMs #-PathType Leaf
if ($FileExist -eq $False) {
Update-Log -Data "CompletedWIMs folder does not exist. Creating..." -Class Warning
New-Item -ItemType Directory -Force -Path $PSScriptRoot\CompletedWIMs | Out-Null
Update-Log -Data "CompletedWIMs folder created" -Class Information
}
if ($FileExist -eq $True) { Update-Log -Data "CompletedWIMs folder exists" -Class Information }
#Configurations XML folder
$FileExist = Test-Path -Path $PSScriptRoot\Configs #-PathType Leaf
if ($FileExist -eq $False) {
Update-Log -Data "Configs folder does not exist. Creating..." -Class Warning
New-Item -ItemType Directory -Force -Path $PSScriptRoot\Configs | Out-Null
Update-Log -Data "Configs folder created" -Class Information
}
if ($FileExist -eq $True) { Update-Log -Data "Configs folder exists" -Class Information }
}
#Function for injecting drivers into the mounted WIM
Function DriverInjection($Folder) {
Function ApplyDriver($drivertoapply) {
try {
add-windowsdriver -Path $WPFMISMountTextBox.Text -Driver $drivertoapply -ErrorAction Stop | Out-Null
Update-Log -Data "Applied $drivertoapply" -Class Information
}
catch {
update-log -Data "Couldn't apply $drivertoapply" -Class Warning
}
}
#This filters out invalid paths, such as the default value
$testpath = Test-Path $folder -PathType Container
If ($testpath -eq $false) { return }
If ($testpath -eq $true) {
update-log -data "Applying drivers from $folder" -class Information
Get-ChildItem $Folder -Recurse -Filter "*inf" | ForEach-Object { applydriver $_.FullName }
update-log -Data "Completed driver injection from $folder" -Class Information
}
}
#Function to retrieve OSDUpdate Version
Function Get-OSDBInstallation {
update-log -Data "Getting OSD Installation information" -Class Information
try {
Import-Module -name OSDUpdate -ErrorAction Stop
}
catch {
$WPFUpdatesOSDBVersion.Text = "Not Installed"
Update-Log -Data "OSD Update is not installed" -Class Warning
Return
}
try {
$OSDBVersion = get-module -name OSDUpdate -ErrorAction Stop
$WPFUpdatesOSDBVersion.Text = $OSDBVersion.Version
$text = $osdbversion.version
Update-Log -data "Installed version of OSD Update is $text" -Class Information
Return
}
catch {
Update-Log -Data "Whatever you were hoping for, you didn’t get :)" -Class Error
Return
}
}
#Function to retrieve OSDSUS Version
Function Get-OSDSUSInstallation {
update-log -Data "Getting OSDSUS Installation information" -Class Information
try {
Import-Module -name OSDSUS -ErrorAction Stop
}
catch {
$WPFUpdatesOSDSUSVersion.Text = "Not Installed"
Update-Log -Data "OSDSUS is not installed" -Class Warning
Return
}
try {
$OSDSUSVersion = get-module -name OSDSUS -ErrorAction Stop
$WPFUpdatesOSDSUSVersion.Text = $OSDSUSVersion.Version
$text = $osdsusversion.version
Update-Log -data "Installed version of OSDSUS is $text" -Class Information
Return
}
catch {
Update-Log -Data "Whatever you were hoping for, you didn’t get :)" -Class Error
Return
}
}
#Function to retrieve current OSDUpdate Version
Function Get-OSDBCurrentVer {
Update-Log -Data "Checking for the most current OSDUpdate version available" -Class Information
try {
$OSDBCurrentVer = find-module -name OSDUpdate -ErrorAction Stop
$WPFUpdatesOSDBCurrentVerTextBox.Text = $OSDBCurrentVer.version
$text = $OSDBCurrentVer.version
update-log -data "$text is the most current version" -class Information
Return
}
catch {
$WPFUpdatesOSDBCurrentVerTextBox.Text = "Network Error"
Return
}
}
#Function to retrieve current OSDUSUS Version
Function Get-OSDSUSCurrentVer {
Update-Log -Data "Checking for the most current OSDSUS version available" -Class Information
try {
$OSDSUSCurrentVer = find-module -name OSDSUS -ErrorAction Stop
$WPFUpdatesOSDSUSCurrentVerTextBox.Text = $OSDSUSCurrentVer.version
$text = $OSDSUSCurrentVer.version
update-log -data "$text is the most current version" -class Information
Return
}
catch {
$WPFUpdatesOSDSUSCurrentVerTextBox.Text = "Network Error"
Return
}
}
#Function to update or install OSDUpdate
Function update-OSDB {
if ($WPFUpdatesOSDBVersion.Text -eq "Not Installed") {
Update-Log -Data "Attempting to install and import OSD Update" -Class Information
try {
Install-Module OSDUpdate -Force -ErrorAction Stop
#Write-Host "Installed module"
Update-Log -data "OSD Update module has been installed" -Class Information
Import-Module -Name OSDUpdate -Force -ErrorAction Stop
#Write-Host "Imported module"
Update-Log -Data "OSD Update module has been imported" -Class Information
Update-Log -Data "****************************************************************************" -Class Warning
Update-Log -Data "Please close WIM Witch and all PowerShell windows, then rerun to continue..." -Class Warning
Update-Log -Data "****************************************************************************" -Class Warning
$WPFUpdatesOSDBClosePowerShellTextBlock.visibility = "Visible"
Return
}
catch {
$WPFUpdatesOSDBVersion.Text = "Inst Fail"
Update-Log -Data "Couldn't install OSD Update" -Class Error
Update-Log -data $_.Exception.Message -class Error
Return
}
}
If ($WPFUpdatesOSDBVersion.Text -gt "1.0.0") {
Update-Log -data "Attempting to update OSD Update" -class Information
try {
Update-ModuleOSDUpdate -ErrorAction Stop
Update-Log -Data "Updated OSD Update" -Class Information
Update-Log -Data "****************************************************************************" -Class Warning
Update-Log -Data "Please close WIM Witch and all PowerShell windows, then rerun to continue..." -Class Warning
Update-Log -Data "****************************************************************************" -Class Warning
$WPFUpdatesOSDBClosePowerShellTextBlock.visibility = "Visible"
get-OSDBInstallation
return
}
catch {
$WPFUpdatesOSDBCurrentVerTextBox.Text = "OSDB Err"
Return
}
}
}
#Function to update or install OSDSUS
Function update-OSDSUS {
if ($WPFUpdatesOSDSUSVersion.Text -eq "Not Installed") {
Update-Log -Data "Attempting to install and import OSDSUS" -Class Information
try {
Install-Module OSDUpdate -Force -ErrorAction Stop
#Write-Host "Installed module"
Update-Log -data "OSDSUS module has been installed" -Class Information
Import-Module -Name OSDUpdate -Force -ErrorAction Stop
#Write-Host "Imported module"
Update-Log -Data "OSDSUS module has been imported" -Class Information
Update-Log -Data "****************************************************************************" -Class Warning
Update-Log -Data "Please close WIM Witch and all PowerShell windows, then rerun to continue..." -Class Warning
Update-Log -Data "****************************************************************************" -Class Warning