forked from CodingWonders/SysprepPreparator
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMainForm.vb
More file actions
406 lines (357 loc) · 18.7 KB
/
MainForm.vb
File metadata and controls
406 lines (357 loc) · 18.7 KB
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
Imports SysprepPreparator.Helpers
Imports SysprepPreparator.Classes
Imports Microsoft.VisualBasic.ControlChars
Imports System.IO
Imports Microsoft.Win32
Public Class MainForm
''' <summary>
''' The current page in the wizard
''' </summary>
''' <remarks></remarks>
Dim CurrentWizardPage As New WizardPage()
''' <summary>
''' The pages in which the verification system should run checks
''' </summary>
''' <remarks></remarks>
Dim VerifyInPages As New List(Of WizardPage.Page) From {
WizardPage.Page.SysCheckPage
}
''' <summary>
''' Determines whether the CCPs have been run to avoid running them again
''' </summary>
''' <remarks></remarks>
Dim IsComputerChecked As Boolean = False
''' <summary>
''' The list of all the performed CCPs
''' </summary>
''' <remarks></remarks>
Dim PerformedChecks As New List(Of CompatibilityCheckerProviderStatus)
''' <summary>
''' The current Sysprep configuration
''' </summary>
''' <remarks></remarks>
Dim SysprepConfiguration As New SysprepConfig()
''' <summary>
''' This event is raised when a Preparation Task is about to start
''' </summary>
''' <param name="taskName">The name of the task</param>
''' <remarks></remarks>
Public Event TaskStarted(taskName As String)
''' <summary>
''' This event is raised when a Preparation Task has finished and reporting will occur
''' </summary>
''' <param name="Task">The reported item featuring the task name and whether the PT succeeded</param>
''' <remarks></remarks>
Public Event TaskReported(Task As Dictionary(Of String, Boolean))
''' <summary>
''' Handles the TaskStarted event
''' </summary>
''' <param name="taskName">The name of the task</param>
''' <remarks></remarks>
Private Sub OnTaskStarted(taskName As String) Handles Me.TaskStarted
SettingPreparationPage_ProgressLabel.Text = String.Format("Performing Task " & Quote & "{0}" & Quote & "...", taskName)
Refresh()
End Sub
''' <summary>
''' Handles the TaskReported event
''' </summary>
''' <param name="Task">The reported item featuring the task name and whether the PT succeeded</param>
''' <remarks></remarks>
Private Sub OnTaskReported(Task As Dictionary(Of String, Boolean)) Handles Me.TaskReported
Dim taskName As String = Task.Keys(0)
SettingPreparationPanel_TaskLv.Items.Add(New ListViewItem(New String() {taskName, Task(taskName)}))
Refresh()
End Sub
''' <summary>
''' A public method for the PT Helper to report task starts
''' </summary>
''' <param name="taskName">The name of the task</param>
''' <remarks></remarks>
Sub ReportTaskStart(taskName As String)
RaiseEvent TaskStarted(taskName)
End Sub
''' <summary>
''' A public method for the PT Helper to report task status
''' </summary>
''' <param name="task">The reported item featuring the task name and whether the PT succeeded</param>
''' <remarks></remarks>
Sub ReportTaskSuccess(task As Dictionary(Of String, Boolean))
RaiseEvent TaskReported(task)
End Sub
Dim OriginalWindowBounds As Rectangle ' Window bounds before full-screen
Dim OriginalWindowState As FormWindowState ' Window state before full-screen
Dim currentTheme As Theme
''' <summary>
''' Changes the wizard page
''' </summary>
''' <param name="NewPage">The new page to change to</param>
''' <remarks>Verification in a page may be done</remarks>
Sub ChangePage(NewPage As WizardPage.Page)
DynaLog.LogMessage("Changing current page of the wizard...")
DynaLog.LogMessage("New page to load: " & NewPage.ToString())
If NewPage > CurrentWizardPage.WizardPage AndAlso VerifyInPages.Contains(CurrentWizardPage.WizardPage) Then
If Not VerifyOptionsInPage(CurrentWizardPage.WizardPage) Then Exit Sub
End If
WelcomePage.Visible = (NewPage = WizardPage.Page.WelcomePage)
SystemCheckPanel.Visible = (NewPage = WizardPage.Page.SysCheckPage)
AdvSettingsPanel.Visible = (NewPage = WizardPage.Page.AdvSettingsPage)
SettingPreparationPanel.Visible = (NewPage = WizardPage.Page.SettingPreparationPage)
FinishPanel.Visible = (NewPage = WizardPage.Page.FinishPage)
CurrentWizardPage.WizardPage = NewPage
Select Case NewPage
Case WizardPage.Page.SysCheckPage
CheckComputer()
End Select
Next_Button.Enabled = (Not NewPage <> WizardPage.Page.FinishPage) OrElse (Not NewPage + 1 >= WizardPage.PageCount)
Cancel_Button.Enabled = Not (NewPage = WizardPage.Page.FinishPage)
Back_Button.Enabled = Not (NewPage = WizardPage.Page.WelcomePage) And Not (NewPage = WizardPage.Page.FinishPage)
Next_Button.Text = If(NewPage = WizardPage.Page.FinishPage, "Close", "Next")
ButtonPanel.Visible = Not (NewPage > WizardPage.Page.AdvSettingsPage)
If NewPage = WizardPage.Page.SettingPreparationPage Then
PrepareComputer()
ElseIf NewPage = WizardPage.Page.FinishPage Then
SysprepComputer()
End If
End Sub
Sub ChangeTheme()
ThemeHelper.LoadThemes()
Dim ColorModeRk As RegistryKey = Registry.CurrentUser.OpenSubKey("SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize", False)
Dim ColorModeVal As Integer = ColorModeRk.GetValue("AppsUseLightTheme", 1)
ColorModeRk.Close()
currentTheme = ThemeHelper.GetThemes().FirstOrDefault(Function(Theme) Theme.IsDark = (ColorModeVal = 0))
If currentTheme IsNot Nothing Then
BackColor = currentTheme.BackgroundColor
ForeColor = currentTheme.ForegroundColor
PageContainerPanel.BackColor = currentTheme.SectionBackgroundColor
ButtonPanel.BackColor = currentTheme.BackgroundColor
SysCheckPage_CheckDetailsGB.ForeColor = currentTheme.ForegroundColor
SysCheckPage_ChecksLv.BackColor = currentTheme.SectionBackgroundColor
SysCheckPage_ChecksLv.ForeColor = currentTheme.ForegroundColor
AdvSettingsPage_CleanupActionCBox.BackColor = currentTheme.SectionBackgroundColor
AdvSettingsPage_CleanupActionCBox.ForeColor = currentTheme.ForegroundColor
AdvSettingsPage_ShutdownOptionsCBox.BackColor = currentTheme.SectionBackgroundColor
AdvSettingsPage_ShutdownOptionsCBox.ForeColor = currentTheme.ForegroundColor
AdvSettingsPage_SysprepUnatt_AnswerFileText.BackColor = currentTheme.SectionBackgroundColor
AdvSettingsPage_SysprepUnatt_AnswerFileText.ForeColor = currentTheme.ForegroundColor
SettingPreparationPanel_TaskLv.BackColor = currentTheme.SectionBackgroundColor
SettingPreparationPanel_TaskLv.ForeColor = currentTheme.ForegroundColor
End If
End Sub
''' <summary>
''' Verifies user-specified settings in the specified wizard page
''' </summary>
''' <param name="WizardPage">The wizard page to check on</param>
''' <returns></returns>
''' <remarks></remarks>
Function VerifyOptionsInPage(WizardPage As WizardPage.Page) As Boolean
DynaLog.LogMessage("Verifying user options before moving on to next page...")
DynaLog.LogMessage("Page in which we need to verify user settings: " & WizardPage.ToString())
Select Case WizardPage
Case SysprepPreparator.WizardPage.Page.SysCheckPage
If Not Environment.GetCommandLineArgs().Contains("/test") AndAlso PerformedChecks.Any(Function(PerformedCheck) PerformedCheck.Compatible = False) Then
MessageBox.Show("Please resolve checks that failed and try again.")
Return False
End If
End Select
Return True
End Function
''' <summary>
''' Starts the CCP Helper and reports the events logged by each of the CCPs
''' </summary>
''' <remarks></remarks>
Sub CheckComputer()
If IsComputerChecked Then
Exit Sub
End If
SysCheckPage_ChecksLv.Items.Clear()
Refresh()
Cursor = Cursors.WaitCursor
PerformedChecks = CompatibilityCheckerHelper.RunChecks()
Cursor = Cursors.Arrow
For Each PerformedCheck In PerformedChecks
SysCheckPage_ChecksLv.Items.Add(New ListViewItem(New String() {PerformedCheck.StatusMessage.StatusTitle, PerformedCheck.Compatible, PerformedCheck.StatusMessage.SeverityToString(PerformedCheck.StatusMessage.StatusSeverity)}))
Next
IsComputerChecked = True
End Sub
''' <summary>
''' Starts the PT Helper
''' </summary>
''' <remarks></remarks>
Sub PrepareComputer()
Refresh()
Cursor = Cursors.WaitCursor
PreparationTaskHelper.RunTasks()
Cursor = Cursors.Arrow
ButtonPanel.Visible = True
Next_Button.PerformClick()
End Sub
''' <summary>
''' Runs the final Sysprep process with the user-specified Sysprep settings
''' </summary>
''' <remarks></remarks>
Sub SysprepComputer()
Dim CmdLine As String = ParseSysprepSettings()
If Environment.GetCommandLineArgs().Contains("/test") Then
MsgBox("Sysprep would be launched with flags " & Quote & CmdLine & Quote, vbOKOnly + vbInformation)
Else
Dim sysprepProcess As New Process() With {
.StartInfo = New ProcessStartInfo() With {
.FileName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), "system32", "sysprep", "sysprep.exe"),
.Arguments = CmdLine
}
}
sysprepProcess.Start()
sysprepProcess.WaitForExit()
MsgBox("Sysprep exited with code " & sysprepProcess.ExitCode, vbOKOnly + vbInformation)
End If
End Sub
''' <summary>
''' Parses the current sysprep settings into a command line
''' </summary>
''' <returns>A set of command line arguments that are passed to sysprep</returns>
''' <remarks></remarks>
Private Function ParseSysprepSettings() As String
Dim sysprepCommandLine As String = ""
If SysprepConfiguration.Generalize Then
sysprepCommandLine &= "/generalize "
End If
Select Case SysprepConfiguration.Cleanup
Case SysprepConfig.CleanupAction.EnterSystemAudit
sysprepCommandLine &= "/audit "
Case SysprepConfig.CleanupAction.EnterSystemOobe
sysprepCommandLine &= "/oobe "
End Select
Select Case SysprepConfiguration.Shutdown
Case SysprepConfig.ShutdownMode.Reboot
sysprepCommandLine &= "/reboot "
Case SysprepConfig.ShutdownMode.Shutdown
sysprepCommandLine &= "/shutdown "
Case SysprepConfig.ShutdownMode.Quit
sysprepCommandLine &= "/quit "
End Select
If SysprepConfiguration.AnswerFile <> "" AndAlso File.Exists(SysprepConfiguration.AnswerFile) Then
sysprepCommandLine &= String.Format("/unattend:{0} ", Quote & SysprepConfiguration.AnswerFile & Quote)
End If
If SysprepConfiguration.VMMode Then
sysprepCommandLine &= "/mode:vm"
End If
Return sysprepCommandLine.TrimEnd(" ")
End Function
''' <summary>
''' Initializes the default settings
''' </summary>
''' <remarks></remarks>
Sub InitializeSettings()
' Initialize Sysprep Process Configuration Settings
AdvSettingsPage_CleanupActionCBox.SelectedIndex = SysprepConfiguration.Cleanup
AdvSettingsPage_CleanupAction_Generalize.Checked = SysprepConfiguration.Generalize
AdvSettingsPage_ShutdownOptionsCBox.SelectedIndex = SysprepConfiguration.Shutdown
AdvSettingsPage_SysprepUnatt_AnswerFileText.Text = SysprepConfiguration.AnswerFile
AdvSettingsPage_VMMode.Checked = SysprepConfiguration.VMMode
End Sub
''' <summary>
''' Handles changes in the sysprep configuration
''' </summary>
''' <remarks></remarks>
Sub ChangeSysprepConfiguration()
SysprepConfiguration.Cleanup = AdvSettingsPage_CleanupActionCBox.SelectedIndex
SysprepConfiguration.Generalize = AdvSettingsPage_CleanupAction_Generalize.Checked
SysprepConfiguration.Shutdown = AdvSettingsPage_ShutdownOptionsCBox.SelectedIndex
SysprepConfiguration.AnswerFile = AdvSettingsPage_SysprepUnatt_AnswerFileText.Text
SysprepConfiguration.VMMode = AdvSettingsPage_VMMode.Checked
End Sub
Private Sub Back_Button_Click(sender As Object, e As EventArgs) Handles Back_Button.Click
ChangePage(CurrentWizardPage.WizardPage - 1)
End Sub
Private Sub Next_Button_Click(sender As Object, e As EventArgs) Handles Next_Button.Click
If CurrentWizardPage.WizardPage = WizardPage.Page.FinishPage Then
Close()
Else
ChangePage(CurrentWizardPage.WizardPage + 1)
End If
End Sub
Private Sub Cancel_Button_Click(sender As Object, e As EventArgs) Handles Cancel_Button.Click
Close()
End Sub
Private Sub SysCheckPage_CheckAgainBtn_Click(sender As Object, e As EventArgs) Handles SysCheckPage_CheckAgainBtn.Click
IsComputerChecked = False
CheckComputer()
End Sub
Private Sub MainForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
' Because of the DISM API, Windows 7 compatibility is out the window (no pun intended)
If Environment.OSVersion.Version.Major = 6 And Environment.OSVersion.Version.Minor < 2 Then
DynaLog.LogMessage("Windows 7 or an earlier version has been detected on this system. Program incompatible -- aborting any future procedures!")
MsgBox("This program is incompatible with Windows 7 and Server 2008 R2." & CrLf & "This program uses the DISM API, which requires files from the Assessment and Deployment Kit (ADK). However, support for Windows 7 is not included." & CrLf & CrLf & "The program will be closed.", vbOKOnly + vbCritical, "DISMTools")
Environment.Exit(1)
End If
' I once tested this on a computer which didn't require me to ask for admin privileges. This is a requirement of DISM. Check this
If Not My.User.IsInRole(ApplicationServices.BuiltInRole.Administrator) Then
DynaLog.LogMessage("This user is not part of the Administrators group/role -- aborting any future procedures!")
MsgBox("This program must be run as an administrator." & CrLf & "There are certain software configurations in which Windows will run this program without admin privileges, so you must ask for them manually." & CrLf & CrLf & "Right-click the executable, and select " & Quote & "Run as administrator" & Quote, vbOKOnly + vbCritical, "DISMTools")
Environment.Exit(1)
End If
OriginalWindowState = WindowState
OriginalWindowBounds = Bounds
FormBorderStyle = FormBorderStyle.None
WindowState = FormWindowState.Maximized
ChangePage(WizardPage.Page.WelcomePage)
InitializeSettings()
AddHandler AdvSettingsPage_CleanupActionCBox.SelectedIndexChanged, AddressOf ChangeSysprepConfiguration
AddHandler AdvSettingsPage_CleanupAction_Generalize.CheckedChanged, AddressOf ChangeSysprepConfiguration
AddHandler AdvSettingsPage_ShutdownOptionsCBox.SelectedIndexChanged, AddressOf ChangeSysprepConfiguration
AddHandler AdvSettingsPage_SysprepUnatt_AnswerFileText.TextChanged, AddressOf ChangeSysprepConfiguration
AddHandler AdvSettingsPage_VMMode.CheckedChanged, AddressOf ChangeSysprepConfiguration
ChangeTheme()
FinishPage_CloseBtn.Enabled = Environment.GetCommandLineArgs().Contains("/test")
End Sub
Private Sub SysCheckPage_ChecksLv_SelectedIndexChanged(sender As Object, e As EventArgs) Handles SysCheckPage_ChecksLv.SelectedIndexChanged
SysCheckPage_CheckDetailsTLP.Visible = (SysCheckPage_ChecksLv.SelectedItems.Count = 1)
If SysCheckPage_ChecksLv.SelectedItems.Count = 1 Then
Dim focusedIdx As Integer = SysCheckPage_ChecksLv.FocusedItem.Index
SysCheckPage_CheckDetails_Title.Text = PerformedChecks(focusedIdx).StatusMessage.StatusTitle
SysCheckPage_CheckDetails_DescriptionValue.Text = PerformedChecks(focusedIdx).StatusMessage.StatusDescription
SysCheckPage_CheckDetails_ResolutionValue.Text = PerformedChecks(focusedIdx).StatusMessage.StatusPossibleResolution
End If
End Sub
Private Sub AdvSettingsPage_ConfigSysprepSettings_CheckedChanged(sender As Object, e As EventArgs) Handles AdvSettingsPage_ConfigSysprepSettings.CheckedChanged
AdvSettingsPage_SysprepConfigPanel.Enabled = AdvSettingsPage_ConfigSysprepSettings.Checked
End Sub
Private Sub AdvSettingsPage_VMModeExplanationLink_LinkClicked(sender As Object, e As LinkLabelLinkClickedEventArgs) Handles AdvSettingsPage_VMModeExplanationLink.LinkClicked
Process.Start("https://learn.microsoft.com/en-us/windows-hardware/manufacture/desktop/sysprep-command-line-options?view=windows-11#modevm")
End Sub
Private Sub AdvSettingsPage_SysprepUnatt_Btn_Click(sender As Object, e As EventArgs) Handles AdvSettingsPage_SysprepUnatt_Btn.Click
AdvSettingsPage_SysprepUnatt_OFD.ShowDialog()
End Sub
Private Sub AdvSettingsPage_SysprepUnatt_OFD_FileOk(sender As Object, e As System.ComponentModel.CancelEventArgs) Handles AdvSettingsPage_SysprepUnatt_OFD.FileOk
AdvSettingsPage_SysprepUnatt_AnswerFileText.Text = AdvSettingsPage_SysprepUnatt_OFD.FileName
End Sub
Private Sub FinishPage_CloseBtn_Click(sender As Object, e As EventArgs) Handles FinishPage_CloseBtn.Click
Close()
End Sub
Private Sub FinishPage_ResysprepBtn_Click(sender As Object, e As EventArgs) Handles FinishPage_ResysprepBtn.Click
SysprepComputer()
End Sub
Private Sub FinishPage_RestartBtn_Click(sender As Object, e As EventArgs) Handles FinishPage_RestartBtn.Click
Process.Start("shutdown", "-r -t 00")
End Sub
Private Sub MainForm_KeyDown(sender As Object, e As KeyEventArgs) Handles MyBase.KeyDown
If e.KeyCode = Keys.F11 Then
ToggleFullScreenMode()
End If
End Sub
Sub ToggleFullScreenMode()
If FormBorderStyle = Windows.Forms.FormBorderStyle.None Then
DynaLog.LogMessage("Exiting full-screen mode...")
FormBorderStyle = Windows.Forms.FormBorderStyle.FixedSingle
Bounds = OriginalWindowBounds
WindowState = OriginalWindowState
Else
DynaLog.LogMessage("Entering full-screen mode...")
FormBorderStyle = Windows.Forms.FormBorderStyle.None
OriginalWindowState = WindowState
WindowState = FormWindowState.Normal
OriginalWindowBounds = Bounds
Bounds = Screen.FromControl(Me).Bounds
End If
End Sub
End Class