├── Configure Script.lnk
├── README.md
├── input
└── configfilegoeshere.txt
├── output
└── outputgoeshere.txt
└── script.ps1
/Configure Script.lnk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gngrninja/psconfigui/5d1ee18248f6d1a75087d8a9965967813519f236/Configure Script.lnk
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # psconfigui
2 | PowerShell GUI for Script Configuration
3 |
4 | For an overview on using this code, please read this article:
5 | http://www.gngrninja.com/script-ninja/2016/12/23/powershell-configure-your-scripts-with-a-gui
6 |
--------------------------------------------------------------------------------
/input/configfilegoeshere.txt:
--------------------------------------------------------------------------------
1 | Your config file will be stored in this directory!
2 |
--------------------------------------------------------------------------------
/output/outputgoeshere.txt:
--------------------------------------------------------------------------------
1 | Script output will be placed in this directory
2 |
--------------------------------------------------------------------------------
/script.ps1:
--------------------------------------------------------------------------------
1 | [cmdletbinding()]
2 | param(
3 | [Parameter(
4 | Mandatory = $false
5 | )]
6 | [Switch]
7 | $ConfigScript = $false,
8 | [Parameter(
9 | Mandatory = $false
10 | )]
11 | [ValidateSet('XML','JSON')]
12 | [String]
13 | $ImportAs = 'XML'
14 | )
15 |
16 | #Setup paths
17 | $scriptPath = Split-Path -parent $MyInvocation.MyCommand.Definition
18 | $inputDir = "$scriptPath\Input"
19 | $outputDir = "$scriptPath\Output"
20 |
21 | #Set the correct file extension
22 | Switch ($ImportAs) {
23 |
24 | 'JSON' {
25 |
26 | $importExtension = '.json'
27 |
28 | }
29 |
30 | 'XML' {
31 |
32 | $importExtension = '.xml'
33 |
34 | }
35 |
36 | }
37 |
38 | #Set config file correctly
39 | $configFile = "$inputDir\config$($importExtension)"
40 |
41 | function Import-Config { #Begin function Import-Config
42 | [cmdletbinding()]
43 | param()
44 |
45 | Switch ($ImportAs) {
46 |
47 | 'JSON' {
48 |
49 | $script:configData = Get-Content -Path $configFile | ConvertFrom-Json
50 |
51 | }
52 |
53 | 'XML' {
54 |
55 | $script:configData = Import-Clixml -Path $configFile
56 |
57 | }
58 |
59 | }
60 |
61 | } #End function Import-Config
62 |
63 | function Export-Config { #Begin function Export-Config
64 | [cmdletbinding()]
65 | param(
66 | [Parameter(
67 | Mandatory
68 | )]
69 | [ValidateSet('JSON','XML')]
70 | $ExportAs,
71 | [Parameter(
72 | Mandatory
73 | )]
74 | $ConfigurationOptions
75 | )
76 |
77 | #If there's a file, we're gonna back it up!
78 | if (Test-Path -Path $configFile) {
79 |
80 | $backup = $true
81 |
82 | }
83 |
84 | Switch ($ExportAs) { #Begin config type switch
85 |
86 | 'JSON' {
87 |
88 | if ($backup) {
89 |
90 | Get-Content $configFile | Out-File -FilePath $configFile.Replace('.json','.json.bak')
91 |
92 | Write-Verbose "Backed up existing configuration to $($configFile.Replace('.json','.json.bak'))!"
93 | Write-Verbose ""
94 |
95 | }
96 |
97 | $ConfigurationOptions | ConvertTo-Json | Out-File -FilePath $configFile
98 |
99 | }
100 |
101 | 'XML' {
102 |
103 | if ($backup) {
104 |
105 | Get-Content $configFile | Out-File -FilePath $configFile.Replace('.xml','.xml.bak')
106 |
107 | Write-Verbose "Backed up existing configuration to $($configFile.Replace('.xml','.xml.bak'))!"
108 | Write-Verbose ""
109 |
110 | }
111 |
112 | $ConfigurationOptions | Export-Clixml -Path $configFile
113 |
114 | }
115 |
116 | } #End config type switch
117 |
118 | } #End function Export-Config
119 |
120 | function Invoke-UserAction { #Begin function Invoke-UserAction
121 | [cmdletbinding()]
122 | param(
123 | [Parameter(
124 | Mandatory,
125 | ValueFromPipeline
126 | )]
127 | $usersToProcess
128 | )
129 |
130 | Begin { #Begin begin block for Invoke-UserAction
131 |
132 | #Create array to store results in
133 | [System.Collections.ArrayList]$processedArray = @()
134 |
135 | Write-Verbose "User processing started!"
136 | Write-Verbose ""
137 |
138 | } #End begin block for Invoke-UserAction
139 |
140 | Process { #Begin process block for function Invoke-UserAction
141 |
142 | foreach ($user in $usersToProcess) { #Begin user foreach loop
143 |
144 | #Set variables to null so they are not set by the last iteration
145 | $lastLogonDays = $null
146 | $userAction = $null
147 |
148 | $notes = 'N/A'
149 |
150 | #Some error handling for getting the last logon days
151 | Try {
152 |
153 | #Set value based on calculation using the LastLogon value of the user
154 | $lastLogonDays = ((Get-Date) - $user.LastLogon).Days
155 |
156 | }
157 |
158 | Catch {
159 |
160 | #Capture message into variable $errorMessage, and set other variables accordingly
161 | $errorMessage = $_.Exception.Message
162 | $lastLogonDays = $null
163 | $notes = $errorMessage
164 |
165 | Write-Warning "Issue encountered while calculating last logon days [$errorMessage]"
166 | Write-Warning ""
167 |
168 | }
169 |
170 | Write-Verbose "Checking on [$($user.DisplayName)], who last logged on [$lastLogonDays] days ago..."
171 | Write-Verbose ""
172 |
173 | #Switch statement to switch out the value of $lastLogonDays
174 | Switch ($lastLogonDays) { #Begin action switch
175 |
176 | #This expression compares the value of $lastLogondays to the script scoped variable for warning days, set with the configuration data file
177 | {$_ -lt $script:configData.DisableDays -and $_ -ge $script:configData.WarnDays} { #Begin actions for warning
178 |
179 | $userAction = 'Warn'
180 |
181 | Write-Verbose "Warning, [$($user.DisplayName)] will be disabled in [$($script:configData.DisableDays - $lastLogonDays)] days!"
182 | Write-Verbose ""
183 |
184 | Break
185 |
186 | } #End actions for warning
187 |
188 | #This expression compares the value of $lastLogondays to the script scoped variable for disable days, set with the configuration data file
189 | {$_ -ge $script:configData.DisableDays} { #Begin actions for disable
190 |
191 | $userAction = 'Disable'
192 |
193 | Write-Verbose "[$($user.DisplayName)] is going to be disabled, and is [$($lastLogonDays - $script:ConfigData.DisableDays)] days past the threshold!"
194 | Write-Verbose ""
195 |
196 | Break
197 |
198 | } #End actions for disable
199 |
200 | {$_ -eq $null} { #Begin actions for a null value
201 |
202 | $userAction = 'Error'
203 |
204 | Write-Verbose "Something went wrong, no value specified for last logon days!"
205 | Write-Verbose ""
206 |
207 | Break
208 |
209 | } #End actions for a null value
210 |
211 | #Adding a default to catch other values
212 | default { #Begin default actions
213 |
214 | $userAction = 'None'
215 | Write-Verbose "$($user.DisplayName) is good to go, they last logged on [$($lastLogonDays)] days ago!"
216 | Write-Verbose ""
217 |
218 | } #Begin default actions
219 |
220 | } #End action switch
221 |
222 | #Create object to store in array
223 | $processedObject = [PSCustomObject]@{
224 |
225 | DisplayName = $user.DisplayName
226 | UserName = $user.UserName
227 | OU = $user.OU
228 | LastLogon = $user.LastLogon
229 | LastLogonDays = $lastLogonDays
230 | Action = $userAction
231 | Notes = $notes
232 |
233 | }
234 |
235 | #Add object to array of processed users
236 | $processedArray.Add($processedObject) | Out-Null
237 |
238 | } #End user foreach loop
239 |
240 | } #End process block for function Invoke-UserAction
241 |
242 | End { #Begin end block for Invoke-UserAction
243 |
244 | Write-Verbose "User processing ended!"
245 | Write-Verbose ""
246 |
247 | #Return array
248 | Return $processedArray
249 |
250 | } #End end block for Invoke-UserAction
251 |
252 | } #End function Invoke-UserAction
253 |
254 | function Invoke-ConfigurationGeneration { #Begin function Invoke-ConfigurationGeneration
255 | [cmdletbinding()]
256 | param(
257 | [Parameter(
258 | Mandatory = $false
259 | )]
260 | [ValidateSet('XML','JSON')]
261 | [String]
262 | $ExportAs = $ImportAs,
263 | [Parameter(
264 | Mandatory = $false
265 | )]
266 | $ConfigurationOptions
267 | )
268 |
269 | if (!$configurationOptions) { #Actions if we don't pass in any options to the function
270 |
271 | #The OU list will be an array
272 | [System.Collections.ArrayList]$ouList = @()
273 |
274 | #These variables will be used to evaluate last logon dates of users
275 | [int]$warnDays = 23
276 | [int]$disableDays = 30
277 |
278 | #Add some fake OUs for testing purposes
279 | $ouList.Add('OU=Marketing,DC=FakeDomain,DC=COM') | Out-Null
280 | $ouList.Add('OU=Sales,DC=FakeDomain,DC=COM') | Out-Null
281 |
282 | #Create a custom object to store things in
283 | $configurationOptions = [PSCustomObject]@{
284 |
285 | WarnDays = $warnDays
286 | DisableDays = $disableDays
287 | OUList = $ouList
288 |
289 | }
290 |
291 | #Handle different types
292 | #Export the object we created as the current configuration
293 | Export-Config -configurationOptions $ConfigurationOptions -ExportAs $ExportAs
294 |
295 | Write-Verbose "Exporting generated configuration file to [$configFile]!"
296 |
297 | } else { #End actions for no options passed in, begin actions for if they are
298 |
299 | Export-Config -configurationOptions $ConfigurationOptions -ExportAs $ExportAs
300 |
301 | Write-Verbose "Exporting passed in options as configuration file to [$configFile]!"
302 |
303 | } #End if for options passed into function
304 |
305 | } #End function Invoke-ConfigurationGeneration
306 |
307 | function Invoke-UserDiscovery { #Begin function Invoke-UserDiscovery
308 | [cmdletbinding()]
309 | param()
310 |
311 | #Create empty arrayList object
312 | [System.Collections.ArrayList]$userList = @()
313 |
314 | #Create users and add them to array
315 | $testUser2 = [PSCustomObject]@{
316 |
317 | DisplayName = 'Mike Jones'
318 | UserName = 'jonesm'
319 | LastLogon = (Get-Date).AddDays(-35)
320 | OU = Get-Random -inputObject $script:configData.OUList
321 |
322 | }
323 |
324 | $testUser1 = [PSCustomObject]@{
325 |
326 | DisplayName = 'John Doe'
327 | UserName = 'doej'
328 | LastLogon = (Get-Date).AddDays(-24)
329 | OU = Get-Random -inputObject $script:configData.OUList
330 |
331 | }
332 |
333 | $testUser3 = [PSCustomObject]@{
334 |
335 | DisplayName = 'Jim Doe'
336 | UserName = 'doeji'
337 | LastLogon = (Get-Date).AddDays(-10)
338 | OU = Get-Random -inputObject $script:configData.OUList
339 |
340 | }
341 |
342 |
343 | $testUser4 = [PSCustomObject]@{
344 |
345 | DisplayName = 'This WontWork'
346 | UserName = 'wontworkt'
347 | LastLogon = $null
348 | OU = Get-Random -inputObject $script:configData.OUList
349 |
350 | }
351 |
352 | $testUser5 = [PSCustomObject]@{
353 |
354 | DisplayName = 'This AlsoWontWork'
355 | UserName = 'alsowontworkt'
356 | LastLogon = 'this many!'
357 | OU = Get-Random -inputObject $script:configData.OUList
358 |
359 | }
360 |
361 | $testUser6 = [PSCustomObject]@{
362 |
363 | DisplayName = 'Sally Smith'
364 | UserName = 'smiths'
365 | LastLogon = (Get-Date).AddDays(-30)
366 | OU = Get-Random -inputObject $script:configData.OUList
367 |
368 | }
369 |
370 | #Add users to arraylist
371 | $userList.Add($testUser1) | Out-Null
372 | $userList.Add($testUser2) | Out-Null
373 | $userList.Add($testUser3) | Out-Null
374 | $userList.Add($testUser4) | Out-Null
375 | $userList.Add($testUser5) | Out-Null
376 | $userList.Add($testUser6) | Out-Null
377 |
378 | #Return list
379 | Return $userList
380 |
381 | } #End function Invoke-UserDiscovery
382 |
383 | function Invoke-GUI { #Begin function Invoke-GUI
384 | [cmdletbinding()]
385 | Param()
386 |
387 | #We technically don't need these, but they may come in handy later if you want to pop up message boxes, etc
388 | [void][System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
389 | [void][System.Reflection.Assembly]::LoadWithPartialName('presentationframework')
390 |
391 | #Input XAML here
392 | $inputXML = @"
393 |
403 |
404 |
405 |
406 |
407 |
408 |
409 |
410 |
411 |
412 |
413 |
414 |
415 | "@
416 |
417 | [xml]$XAML = $inputXML -replace 'mc:Ignorable="d"','' -replace "x:N",'N' -replace '^