Mick's IT Blogs

Mick's IT Blogs

Latest Updates

21 April 2016

NIC Advanced Properties

Posted By: Mick Pletcher - 6:59 PM










Recently, we started having issues with our new Dell Latitude E7450 laptops. They would be put to sleep and then they could not restore the network connection once the laptop was docked again. The problem came from the Energy Efficient Ethernet setting in the advanced properties of the NIC. That is what lead me to writing this script so that we could set it during the build process. With the help of Sapien Technology's PowerShell Studio, this was pretty easy to write and it made writing the code very thorough.

I wrote the script so that all entries are there, at least for the Dell models we use. You may need to manually add or delete some values if the systems you have differ, which they likely will. I set the script up so that unless there are values that need to be entered, everything can be done from command line. If you do not define a parameter, then it is skipped over. I entered the exact values from the drop-down menus for each value. The script translates that into the required value to enter into the registry. I also put the possible values within the comments of each parameter.

You can download the script from here.


1:  <#  
2:       .SYNOPSIS  
3:            NIC Advanced Properties  
4:         
5:       .DESCRIPTION  
6:            Configure NIC Advanced Properties by modifying the values in the HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4d36e972-e325-11ce-bfc1-08002be10318} registry key.  
7:         
8:       .PARAMETER ConsoleTitle  
9:            Title displayed in the PowerShell Console  
10:         
11:       .PARAMETER EnergyEfficientEthernet  
12:            RegValue: EEELinkAdvertisement  
13:            0 - Off  
14:            1 - On  
15:         
16:       .PARAMETER FlowControl  
17:            RegValue: *FlowControl  
18:            0 - Disabled  
19:            1 - Tx Enabled  
20:            2 - Rx Enabled  
21:            3 - Rx & Tx Enabled  
22:         
23:       .PARAMETER JumboPacket  
24:            RegValue: *JumboPacket  
25:            1514 - Disabled  
26:            4088 - 4088 Bytes  
27:            9014 - 9014 Bytes  
28:         
29:       .PARAMETER LegacySwitchCompatibilityMode  
30:            RegValue: LinkNegotiationProcess  
31:            1 - Disabled  
32:            2 - Enabled  
33:         
34:       .PARAMETER LinkSpeedBatterySaver  
35:            RegValue: AutoPowerSaveModeEnabled  
36:            0 - Disabled  
37:            1 - Enabled  
38:         
39:       .PARAMETER PriorityVLAN  
40:            RegValue: *PriorityVLANTag  
41:            0 - Priority & VLAN Disabled  
42:            1 - Priority Enabled  
43:            2 - VLAN Enabled  
44:            3 - Priority & VLAN Enabled  
45:         
46:       .PARAMETER ProtocolARPOffload  
47:            RegValue: *PMARPOffload  
48:            0x00000000 - Enabled  
49:            0x00000001 - Disabled  
50:         
51:       .PARAMETER ProtocolNSOffload  
52:            RegValue: *PMNSOffload  
53:            0x00000000 - Enabled  
54:            0x00000001 - Disabled  
55:         
56:       .PARAMETER SpeedDuplex  
57:            RegValue: *SpeedDuplex  
58:            0 - Auto Negotiation  
59:            1 - 10 Mbps Half Duplex  
60:            2 - 10 Mbps Full Duplex  
61:            3 - 100 Mbps Half Duplex  
62:            4 - 100 Mbps Full Duplex  
63:            6 - 1.0 Gbps Full Duplex  
64:         
65:       .PARAMETER SystemIdlePowerSaver  
66:            RegValue: SipsEnabled  
67:            0 - Disabled  
68:            1 - Enabled  
69:         
70:       .PARAMETER WakeOnMagicPacket  
71:            RegValue: *WakeOnMagicPacket  
72:            0x00000000 - Enabled  
73:            0x00000001 - Disabled  
74:         
75:       .PARAMETER WakeOnPatternMatch  
76:            RegValue: *WakeOnPattern  
77:            0x00000000 - Enabled  
78:            0x00000001 - Disabled  
79:         
80:       .NOTES  
81:            ===========================================================================  
82:            Created with:      SAPIEN Technologies, Inc., PowerShell Studio 2016 v5.2.119  
83:            Created on:       4/20/2016 11:20 AM  
84:            Created by:          Mick Pletcher  
85:            Organization:  
86:            Filename:          NICAdvancedProperties  
87:            ===========================================================================  
88:  #>  
89:  [CmdletBinding()]  
90:  param  
91:  (  
92:            [string]$ConsoleTitle = 'NIC Advanced Properties',  
93:            [ValidateSet('Off', 'On')][string]$EnergyEfficientEthernet,  
94:            [ValidateSet('Disabled', 'Tx Enabled', 'Rx Enabled', 'Rx & Tx Enabled')][string]$FlowControl,  
95:            [ValidateSet('Disabled', '4088 Bytes', '9014 Bytes')][string]$JumboPacket,  
96:            [ValidateSet('Disabled', 'Enabled')][string]$LegacySwitchCompatibilityMode,  
97:            [ValidateSet('Disabled', 'Enabled')][string]$LinkSpeedBatterySaver,  
98:            [ValidateSet('Priority & VLAN Disabled', 'Priority Enabled', 'VLAN Enabled', 'Priority & VLAN Enabled')][string]$PriorityVLAN,  
99:            [ValidateSet('Disabled', 'Enabled')][string]$ProtocolARPOffload,  
100:            [ValidateSet('Disabled', 'Enabled')][string]$ProtocolNSOffload,  
101:            [ValidateSet('Auto Negotiation', '10 Mbps Half Duplex', '10 Mbps Full Duplex', '100 Mbps Half Duplex', '100 Mbps Full Duplex', '1.0 Gbps Full Duplex')][string]$SpeedDuplex,  
102:            [ValidateSet('Disabled', 'Enabled')][string]$SystemIdlePowerSaver,  
103:            [ValidateSet('Disabled', 'Enabled')][string]$WakeOnMagicPacket,  
104:            [ValidateSet('Disabled', 'Enabled')][string]$WakeOnPatternMatch  
105:  )  
106:    
107:  function Get-PhysicalNICs {  
108:  <#  
109:       .SYNOPSIS  
110:            Retrieve the Physical NICs  
111:         
112:       .DESCRIPTION  
113:            Find the physical NICs that are currently being used and return the information from the function  
114:         
115:       .EXAMPLE  
116:            PS C:\> Get-PhysicalNICs  
117:         
118:       .NOTES  
119:            Additional information about the function.  
120:  #>  
121:         
122:       [CmdletBinding()]  
123:       param ()  
124:         
125:       # Get all physical ethernet adaptors  
126:       $NICs = Get-WmiObject Win32_NetworkAdapter -filter "AdapterTypeID = '0' `  
127:       AND PhysicalAdapter = 'true' `  
128:       AND NOT Description LIKE '%Centrino%' `  
129:       AND NOT Description LIKE '%wireless%' `  
130:       AND NOT Description LIKE '%virtual%' `  
131:       AND NOT Description LIKE '%WiFi%' `  
132:       AND NOT Description LIKE '%Bluetooth%'"  
133:       Return $NICs  
134:  }  
135:    
136:  function Get-Platform {  
137:  <#  
138:       .SYNOPSIS  
139:            Determine Platform  
140:         
141:       .DESCRIPTION  
142:            Test if system is a desktop or laptop  
143:         
144:       .NOTES  
145:            Additional information about the function.  
146:  #>  
147:         
148:       [CmdletBinding()][OutputType([string])]  
149:       param ()  
150:         
151:       if (Get-WmiObject -Class win32_battery -ComputerName "localhost") {  
152:            $Platform = "Laptop"  
153:       } else {  
154:            $Platform = "Desktop"  
155:       }  
156:       Return $Platform  
157:  }  
158:    
159:  function Set-NICRegistryKey {  
160:  <#  
161:       .SYNOPSIS  
162:            Get registry key of NIC  
163:         
164:       .DESCRIPTION  
165:            Find the registry key of the physical NIC  
166:         
167:       .PARAMETER NetworkAdapters  
168:            List of physical NIC cards  
169:         
170:       .EXAMPLE  
171:            PS C:\> Set-NICRegistryKey  
172:         
173:       .NOTES  
174:            Additional information about the function.  
175:  #>  
176:         
177:       [CmdletBinding()]  
178:       param  
179:       (  
180:                 $NetworkAdapters  
181:       )  
182:         
183:       $NetworkAdapterKey = "HKLM:\system\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}"  
184:       foreach ($NetworkAdapter in $NetworkAdapters) {  
185:            If ([int]$NetworkAdapter.DeviceID -lt 10) {  
186:                 $NetworkAdapterSubKey = $NetworkAdapterKey + "\" + "000" + $NetworkAdapter.DeviceID  
187:            } else {  
188:                 $NetworkAdapterSubKey = $NetworkAdapterKey + "\" + "00" + $NetworkAdapter.DeviceID  
189:            }  
190:            $AdapterProperties = Get-ItemProperty $NetworkAdapterSubKey  
191:            #Energy Efficient Ethernet  
192:            If ($EnergyEfficientEthernet -ne "") {  
193:                 $AdaptorProperty = 'EEELinkAdvertisement'  
194:                 Write-Host "Energy Efficient Ethernet....." -NoNewline  
195:                 If ($EnergyEfficientEthernet -eq "On") {  
196:                      $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
197:                      Set-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty -Value 1  
198:                      $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
199:                      If ($Value.$AdaptorProperty -eq 1) {  
200:                           Write-Host $EnergyEfficientEthernet -ForegroundColor Yellow  
201:                      } else {  
202:                           Write-Host "Failed" -ForegroundColor Red  
203:                      }  
204:                 } else {  
205:                      $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
206:                      Set-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty -Value 0  
207:                      $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
208:                      If ($Value.$AdaptorProperty -eq 0) {  
209:                           Write-Host $EnergyEfficientEthernet -ForegroundColor Yellow  
210:                      } else {  
211:                           Write-Host "Failed" -ForegroundColor Red  
212:                      }  
213:                 }  
214:            }  
215:            #Flow Control  
216:            If ($FlowControl -ne "") {  
217:                 $AdaptorProperty = '*FlowControl'  
218:                 Write-Host "Flow Control....." -NoNewline  
219:                 switch ($FlowControl) {  
220:                      "Disabled" {  
221:                           $AdapterPropertyValue = 0  
222:                           $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
223:                           Set-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty -Value $AdapterPropertyValue  
224:                           $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
225:                           If ($Value.$AdaptorProperty -eq $AdapterPropertyValue) {  
226:                                Write-Host $FlowControl -ForegroundColor Yellow  
227:                           } else {  
228:                                Write-Host "Failed" -ForegroundColor Red  
229:                           }  
230:                      }  
231:                      "Tx Enabled" {  
232:                           $AdapterPropertyValue = 1  
233:                           $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
234:                           Set-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty -Value $AdapterPropertyValue  
235:                           $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
236:                           If ($Value.$AdaptorProperty -eq $AdapterPropertyValue) {  
237:                                Write-Host $FlowControl -ForegroundColor Yellow  
238:                           } else {  
239:                                Write-Host "Failed" -ForegroundColor Red  
240:                           }  
241:                      }  
242:                      "Rx Enabled" {  
243:                           $AdapterPropertyValue = 2  
244:                           $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
245:                           Set-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty -Value $AdapterPropertyValue  
246:                           $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
247:                           If ($Value.$AdaptorProperty -eq $AdapterPropertyValue) {  
248:                                Write-Host $FlowControl -ForegroundColor Yellow  
249:                           } else {  
250:                                Write-Host "Failed" -ForegroundColor Red  
251:                           }  
252:                      }  
253:                      "Rx & Tx Enabled" {  
254:                           $AdapterPropertyValue = 3  
255:                           $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
256:                           Set-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty -Value $AdapterPropertyValue  
257:                           $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
258:                           If ($Value.$AdaptorProperty -eq $AdapterPropertyValue) {  
259:                                Write-Host $FlowControl -ForegroundColor Yellow  
260:                           } else {  
261:                                Write-Host "Failed" -ForegroundColor Red  
262:                           }  
263:                      }  
264:                 }  
265:            }  
266:            #Jumbo Packet  
267:            If ($JumboPacket -ne "") {  
268:                 $AdaptorProperty = '*JumboPacket'  
269:                 Write-Host "Jumbo Packet....." -NoNewline  
270:                 switch ($JumboPacket) {  
271:                      "Disabled" {  
272:                           $AdapterPropertyValue = 1514  
273:                           $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
274:                           Set-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty -Value $AdapterPropertyValue  
275:                           $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
276:                           If ($Value.$AdaptorProperty -eq $AdapterPropertyValue) {  
277:                                Write-Host $JumboPacket -ForegroundColor Yellow  
278:                           } else {  
279:                                Write-Host "Failed" -ForegroundColor Red  
280:                           }  
281:                      }  
282:                      "4088 Bytes" {  
283:                           $AdapterPropertyValue = 4088  
284:                           $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
285:                           Set-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty -Value $AdapterPropertyValue  
286:                           $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
287:                           If ($Value.$AdaptorProperty -eq $AdapterPropertyValue) {  
288:                                Write-Host $JumboPacket -ForegroundColor Yellow  
289:                           } else {  
290:                                Write-Host "Failed" -ForegroundColor Red  
291:                           }  
292:                      }  
293:                      "9014 Bytes" {  
294:                           $AdapterPropertyValue = 9014  
295:                           $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
296:                           Set-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty -Value $AdapterPropertyValue  
297:                           $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
298:                           If ($Value.$AdaptorProperty -eq $AdapterPropertyValue) {  
299:                                Write-Host $JumboPacket -ForegroundColor Yellow  
300:                           } else {  
301:                                Write-Host "Failed" -ForegroundColor Red  
302:                           }  
303:                      }  
304:                 }  
305:            }  
306:            #Legacy Switch Compatibility Mode  
307:            If ($LegacySwitchCompatibilityMode -ne "") {  
308:                 $AdaptorProperty = 'LinkNegotiationProcess'  
309:                 Write-Host "Legacy Switch Compatibility Mode....." -NoNewline  
310:                 If ($LegacySwitchCompatibilityMode -eq "Disabled") {  
311:                      $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
312:                      Set-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty -Value 1  
313:                      $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
314:                      If ($Value.$AdaptorProperty -eq 1) {  
315:                           Write-Host $LegacySwitchCompatibilityMode -ForegroundColor Yellow  
316:                      } else {  
317:                           Write-Host "Failed" -ForegroundColor Red  
318:                      }  
319:                 } else {  
320:                      $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
321:                      Set-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty -Value 2  
322:                      $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
323:                      If ($Value.$AdaptorProperty -eq 2) {  
324:                           Write-Host $LegacySwitchCompatibilityMode -ForegroundColor Yellow  
325:                      } else {  
326:                           Write-Host "Failed" -ForegroundColor Red  
327:                      }  
328:                 }  
329:            }  
330:            #Link Speed Battery Saver  
331:            If ($LinkSpeedBatterySaver -ne "") {  
332:                 $Platform = Get-Platform  
333:                 If ($Platform -eq "Laptop") {  
334:                      $AdaptorProperty = 'AutoPowerSaveModeEnabled'  
335:                      Write-Host "Link Speed Battery Saver....." -NoNewline  
336:                      If ($LinkSpeedBatterySaver -eq "Disabled") {  
337:                           $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
338:                           Set-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty -Value 0  
339:                           $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
340:                           If ($Value.$AdaptorProperty -eq 0) {  
341:                                Write-Host $LinkSpeedBatterySaver -ForegroundColor Yellow  
342:                           } else {  
343:                                Write-Host "Failed" -ForegroundColor Red  
344:                           }  
345:                      } else {  
346:                           $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
347:                           Set-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty -Value 1  
348:                           $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
349:                           If ($Value.$AdaptorProperty -eq 1) {  
350:                                Write-Host $LinkSpeedBatterySaver -ForegroundColor Yellow  
351:                           } else {  
352:                                Write-Host "Failed" -ForegroundColor Red  
353:                           }  
354:                      }  
355:                 }  
356:            }  
357:            #Priority VLAN  
358:            If ($PriorityVLAN -ne "") {  
359:                 $AdaptorProperty = '*PriorityVLANTag'  
360:                 Write-Host "Priority VLAN....." -NoNewline  
361:                 switch ($PriorityVLAN) {  
362:                      "Priority & VLAN Disabled" {  
363:                           $AdapterPropertyValue = 0  
364:                           $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
365:                           Set-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty -Value $AdapterPropertyValue  
366:                           $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
367:                           If ($Value.$AdaptorProperty -eq $AdapterPropertyValue) {  
368:                                Write-Host $PriorityVLAN -ForegroundColor Yellow  
369:                           } else {  
370:                                Write-Host "Failed" -ForegroundColor Red  
371:                           }  
372:                      }  
373:                      "Priority Enabled" {  
374:                           $AdapterPropertyValue = 1  
375:                           $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
376:                           Set-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty -Value $AdapterPropertyValue  
377:                           $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
378:                           If ($Value.$AdaptorProperty -eq $AdapterPropertyValue) {  
379:                                Write-Host $PriorityVLAN -ForegroundColor Yellow  
380:                           } else {  
381:                                Write-Host "Failed" -ForegroundColor Red  
382:                           }  
383:                      }  
384:                      "VLAN Enabled" {  
385:                           $AdapterPropertyValue = 2  
386:                           $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
387:                           Set-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty -Value $AdapterPropertyValue  
388:                           $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
389:                           If ($Value.$AdaptorProperty -eq $AdapterPropertyValue) {  
390:                                Write-Host $PriorityVLAN -ForegroundColor Yellow  
391:                           } else {  
392:                                Write-Host "Failed" -ForegroundColor Red  
393:                           }  
394:                      }  
395:                      "Priority & VLAN Enabled" {  
396:                           $AdapterPropertyValue = 3  
397:                           $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
398:                           Set-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty -Value $AdapterPropertyValue  
399:                           $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
400:                           If ($Value.$AdaptorProperty -eq $AdapterPropertyValue) {  
401:                                Write-Host $PriorityVLAN -ForegroundColor Yellow  
402:                           } else {  
403:                                Write-Host "Failed" -ForegroundColor Red  
404:                           }  
405:                      }  
406:                 }  
407:            }  
408:            #Protocol ARP Offload  
409:            If ($ProtocolARPOffload -ne "") {  
410:                 $AdaptorProperty = '*PMARPOffload'  
411:                 Write-Host "Protocol ARP Offload....." -NoNewline  
412:                 If ($ProtocolARPOffload -eq "Disabled") {  
413:                      $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
414:                      Set-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty -Value 0x00000001  
415:                      $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
416:                      If ($Value.$AdaptorProperty -eq 0x00000001) {  
417:                           Write-Host $ProtocolARPOffload -ForegroundColor Yellow  
418:                      } else {  
419:                           Write-Host "Failed" -ForegroundColor Red  
420:                      }  
421:                 } else {  
422:                      $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
423:                      Set-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty -Value 0x00000000  
424:                      $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
425:                      If ($Value.$AdaptorProperty -eq 0x00000000) {  
426:                           Write-Host $ProtocolARPOffload -ForegroundColor Yellow  
427:                      } else {  
428:                           Write-Host "Failed" -ForegroundColor Red  
429:                      }  
430:                 }  
431:            }  
432:            #Protocol NS Offload  
433:            If ($ProtocolNSOffload -ne "") {  
434:                 $AdaptorProperty = '*PMNSOffload'  
435:                 Write-Host "Protocol NS Offload....." -NoNewline  
436:                 If ($ProtocolNSOffload -eq "Disabled") {  
437:                      $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
438:                      Set-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty -Value 0x00000001  
439:                      $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
440:                      If ($Value.$AdaptorProperty -eq 0x00000001) {  
441:                           Write-Host $ProtocolNSOffload -ForegroundColor Yellow  
442:                      } else {  
443:                           Write-Host "Failed" -ForegroundColor Red  
444:                      }  
445:                 } else {  
446:                      $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
447:                      Set-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty -Value 0x00000000  
448:                      $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
449:                      If ($Value.$AdaptorProperty -eq 0x00000000) {  
450:                           Write-Host $ProtocolNSOffload -ForegroundColor Yellow  
451:                      } else {  
452:                           Write-Host "Failed" -ForegroundColor Red  
453:                      }  
454:                 }  
455:            }  
456:            #Speed Duplex  
457:            if ($SpeedDuplex -ne "") {  
458:                 $AdaptorProperty = '*SpeedDuplex'  
459:                 $AdapterProperties.$AdaptorProperty = $SpeedDuplex  
460:            }  
461:            If ($SpeedDuplex -ne "") {  
462:                 $AdaptorProperty = '*SpeedDuplex'  
463:                 Write-Host "Speed Duplex....." -NoNewline  
464:                 switch ($SpeedDuplex) {  
465:                      "Auto Negotiation" {  
466:                           $AdapterPropertyValue = 0  
467:                           $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
468:                           Set-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty -Value $AdapterPropertyValue  
469:                           $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
470:                           If ($Value.$AdaptorProperty -eq $AdapterPropertyValue) {  
471:                                Write-Host $SpeedDuplex -ForegroundColor Yellow  
472:                           } else {  
473:                                Write-Host "Failed" -ForegroundColor Red  
474:                           }  
475:                      }  
476:                      "10 Mbps Half Duplex" {  
477:                           $AdapterPropertyValue = 1  
478:                           $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
479:                           Set-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty -Value $AdapterPropertyValue  
480:                           $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
481:                           If ($Value.$AdaptorProperty -eq $AdapterPropertyValue) {  
482:                                Write-Host $SpeedDuplex -ForegroundColor Yellow  
483:                           } else {  
484:                                Write-Host "Failed" -ForegroundColor Red  
485:                           }  
486:                      }  
487:                      "10 Mbps Full Duplex" {  
488:                           $AdapterPropertyValue = 2  
489:                           $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
490:                           Set-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty -Value $AdapterPropertyValue  
491:                           $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
492:                           If ($Value.$AdaptorProperty -eq $AdapterPropertyValue) {  
493:                                Write-Host $SpeedDuplex -ForegroundColor Yellow  
494:                           } else {  
495:                                Write-Host "Failed" -ForegroundColor Red  
496:                           }  
497:                      }  
498:                      "100 Mbps Half Duplex" {  
499:                           $AdapterPropertyValue = 3  
500:                           $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
501:                           Set-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty -Value $AdapterPropertyValue  
502:                           $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
503:                           If ($Value.$AdaptorProperty -eq $AdapterPropertyValue) {  
504:                                Write-Host $SpeedDuplex -ForegroundColor Yellow  
505:                           } else {  
506:                                Write-Host "Failed" -ForegroundColor Red  
507:                           }  
508:                      }  
509:                      "100 Mbps Full Duplex" {  
510:                           $AdapterPropertyValue = 4  
511:                           $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
512:                           Set-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty -Value $AdapterPropertyValue  
513:                           $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
514:                           If ($Value.$AdaptorProperty -eq $AdapterPropertyValue) {  
515:                                Write-Host $SpeedDuplex -ForegroundColor Yellow  
516:                           } else {  
517:                                Write-Host "Failed" -ForegroundColor Red  
518:                           }  
519:                      }  
520:                      "1.0 Gbps Full Duplex" {  
521:                           $AdapterPropertyValue = 6  
522:                           $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
523:                           Set-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty -Value $AdapterPropertyValue  
524:                           $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
525:                           If ($Value.$AdaptorProperty -eq $AdapterPropertyValue) {  
526:                                Write-Host $SpeedDuplex -ForegroundColor Yellow  
527:                           } else {  
528:                                Write-Host "Failed" -ForegroundColor Red  
529:                           }  
530:                      }  
531:                 }  
532:            }  
533:            #System Idle Power Saver  
534:            If ($SystemIdlePowerSaver -ne "") {  
535:                 $AdaptorProperty = 'SipsEnabled'  
536:                 Write-Host "System Idle Power Saver....." -NoNewline  
537:                 If ($SystemIdlePowerSaver -eq "Enabled") {  
538:                      $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
539:                      Set-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty -Value 1  
540:                      $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
541:                      If ($Value.$AdaptorProperty -eq 1) {  
542:                           Write-Host $SystemIdlePowerSaver -ForegroundColor Yellow  
543:                      } else {  
544:                           Write-Host "Failed" -ForegroundColor Red  
545:                      }  
546:                 } else {  
547:                      $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
548:                      Set-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty -Value 0  
549:                      $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
550:                      If ($Value.$AdaptorProperty -eq 0) {  
551:                           Write-Host $SystemIdlePowerSaver -ForegroundColor Yellow  
552:                      } else {  
553:                           Write-Host "Failed" -ForegroundColor Red  
554:                      }  
555:                 }  
556:            }  
557:            #Wake On Magic Packet  
558:            If ($WakeOnMagicPacket -ne "") {  
559:                 $AdaptorProperty = '*WakeOnMagicPacket'  
560:                 Write-Host "Wake On Magic Packet....." -NoNewline  
561:                 If ($WakeOnMagicPacket -eq "Disabled") {  
562:                      $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
563:                      Set-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty -Value 0x00000001  
564:                      $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
565:                      If ($Value.$AdaptorProperty -eq 0x00000001) {  
566:                           Write-Host $WakeOnMagicPacket -ForegroundColor Yellow  
567:                      } else {  
568:                           Write-Host "Failed" -ForegroundColor Red  
569:                      }  
570:                 } else {  
571:                      $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
572:                      Set-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty -Value 0x00000000  
573:                      $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
574:                      If ($Value.$AdaptorProperty -eq 0x00000000) {  
575:                           Write-Host $WakeOnMagicPacket -ForegroundColor Yellow  
576:                      } else {  
577:                           Write-Host "Failed" -ForegroundColor Red  
578:                      }  
579:                 }  
580:            }  
581:            #Wake On Pattern Match  
582:            If ($WakeOnPatternMatch -ne "") {  
583:                 $AdaptorProperty = '*WakeOnPattern'  
584:                 Write-Host "Wake On Pattern Match....." -NoNewline  
585:                 If ($WakeOnPatternMatch -eq "Disabled") {  
586:                      $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
587:                      Set-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty -Value 0x00000001  
588:                      $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
589:                      If ($Value.$AdaptorProperty -eq 0x00000001) {  
590:                           Write-Host $WakeOnPatternMatch -ForegroundColor Yellow  
591:                      } else {  
592:                           Write-Host "Failed" -ForegroundColor Red  
593:                      }  
594:                 } else {  
595:                      $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
596:                      Set-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty -Value 0x00000000  
597:                      $Value = Get-ItemProperty -Path $NetworkAdapterSubKey -Name $AdaptorProperty  
598:                      If ($Value.$AdaptorProperty -eq 0x00000000) {  
599:                           Write-Host $WakeOnPatternMatch -ForegroundColor Yellow  
600:                      } else {  
601:                           Write-Host "Failed" -ForegroundColor Red  
602:                      }  
603:                 }  
604:            }  
605:       }  
606:  }  
607:    
608:  function Set-ConsoleTitle {  
609:  <#  
610:       .SYNOPSIS  
611:            Console Title  
612:         
613:       .DESCRIPTION  
614:            Sets the title of the PowerShell Console  
615:         
616:       .PARAMETER ConsoleTitle  
617:            Title of the PowerShell Console  
618:         
619:       .NOTES  
620:            Additional information about the function.  
621:  #>  
622:         
623:       [CmdletBinding()]  
624:       param  
625:       (  
626:                 [Parameter(Mandatory = $true)][String]$ConsoleTitle  
627:       )  
628:         
629:       $host.ui.RawUI.WindowTitle = $ConsoleTitle  
630:  }  
631:    
632:  Clear-Host  
633:  Set-ConsoleTitle $ConsoleTitle  
634:  $NICs = Get-PhysicalNICs  
635:  Set-NICRegistryKey -NetworkAdapters $NICs  
636:    

20 April 2016

NIC Power Management Properties

Posted By: Mick Pletcher - 12:36 PM












I wrote and published a script that enabled wake on lan two years ago. Since then, I have needed to write new scripts to modify the advanced tab of the NIC properties. I began by looking at my old script to see about adding the new settings to it and I decided to update the old one and republish it here. Thanks to Sapien Technology's PowerShell Studio, I have updated the script with much documentation.

This script will check or uncheck the three boxes in the screenshot below:


To use the script, I have set four parameters which I have set defaults to, which you can easily change:

  • ConsoleTitle - Title displayed in the PowerShell Console
  • TurnOffDeviceAllow the computer to turn off this device to save power. Select true to check this or false to uncheck it
  • WakeComputer - Allow this device to wake the computer. Select true to check this or false to uncheck it
  • AllowMagicPacketsOnly - Only allow a magic packet to wake the computer. Select true to check this or false to uncheck it
You can download the script from here.

Here is the script:


1:  <#  
2:       .SYNOPSIS  
3:            NIC Power Management  
4:         
5:       .DESCRIPTION  
6:            Configure NIC Power Management settings  
7:         
8:       .PARAMETER ConsoleTitle  
9:            Title displayed in the PowerShell Console  
10:         
11:       .PARAMETER TurnOffDevice  
12:            Allow the computer to turn off this device to save power. Select true to check this or false to uncheck it.  
13:         
14:       .PARAMETER WakeComputer  
15:            Allow this device to wake the computer. Select true to check this or false to uncheck it.  
16:         
17:       .PARAMETER AllowMagicPacketsOnly  
18:            Only allow a magic packet to wake the computer. Select true to check this or false to uncheck it.  
19:         
20:       .EXAMPLE  
21:            powershell.exe -executionpolicy bypass -file NICPowerManagement.ps1 -ConsoleTitle "NIC Power Management" -TurnOffDevice $true -WakeComputer $true -AllowMagicPacketsOnly $true  
22:         
23:       .NOTES  
24:            ===========================================================================  
25:            Created with:      SAPIEN Technologies, Inc., PowerShell Studio 2016 v5.2.119  
26:            Created on:       4/20/2016 11:20 AM  
27:            Created by:       Mick Pletcher  
28:            Organization:  
29:            Filename:        NICPowerManagement.ps1  
30:            ===========================================================================  
31:  #>  
32:  [CmdletBinding()]  
33:  param  
34:  (  
35:            [Parameter(Mandatory = $false)][string]$ConsoleTitle = 'NIC Power Management',  
36:            [bool]$TurnOffDevice = $true,  
37:            [bool]$WakeComputer = $true,  
38:            [bool]$AllowMagicPacketsOnly = $true  
39:  )  
40:    
41:  function Exit-PowerShell {  
42:  <#  
43:       .SYNOPSIS  
44:            Exit PowerShell  
45:         
46:       .DESCRIPTION  
47:            Exit out of the PowerShell script and return an error code 1 if errors were encountered  
48:         
49:       .PARAMETER Errors  
50:            True or false if errors were encountered  
51:         
52:       .NOTES  
53:            Additional information about the function.  
54:  #>  
55:         
56:       [CmdletBinding()]  
57:       param  
58:       (  
59:                 [bool]$Errors  
60:       )  
61:         
62:       If ($Errors -eq $true) {  
63:            Exit 1  
64:       }  
65:  }  
66:    
67:  function Get-RelativePath {  
68:  <#  
69:       .SYNOPSIS  
70:            Get the relative path  
71:         
72:       .DESCRIPTION  
73:            Returns the location of the currently running PowerShell script  
74:         
75:       .NOTES  
76:            Additional information about the function.  
77:  #>  
78:         
79:       [CmdletBinding()][OutputType([string])]  
80:       param ()  
81:         
82:       $Path = (split-path $SCRIPT:MyInvocation.MyCommand.Path -parent) + "\"  
83:       Return $Path  
84:  }  
85:    
86:  function Get-PhysicalNICs {  
87:  <#  
88:       .SYNOPSIS  
89:            Retrieve the Physical NICs  
90:         
91:       .DESCRIPTION  
92:            Find the physical NICs that are currently being used and return the information from the function  
93:         
94:       .EXAMPLE  
95:            PS C:\> Get-PhysicalNICs  
96:         
97:       .NOTES  
98:            Additional information about the function.  
99:  #>  
100:         
101:       [CmdletBinding()]  
102:       param ()  
103:         
104:       # Get all physical ethernet adaptors  
105:       $NICs = Get-WmiObject Win32_NetworkAdapter -filter "AdapterTypeID = '0' `  
106:       AND PhysicalAdapter = 'true' `  
107:       AND NOT Description LIKE '%Centrino%' `  
108:       AND NOT Description LIKE '%wireless%' `  
109:       AND NOT Description LIKE '%virtual%' `  
110:       AND NOT Description LIKE '%WiFi%' `  
111:       AND NOT Description LIKE '%Bluetooth%'"  
112:       Return $NICs  
113:  }  
114:    
115:  function Set-ConsoleTitle {  
116:  <#  
117:       .SYNOPSIS  
118:            Console Title  
119:         
120:       .DESCRIPTION  
121:            Sets the title of the PowerShell Console  
122:         
123:       .NOTES  
124:            Additional information about the function.  
125:  #>  
126:         
127:       [CmdletBinding()]  
128:       param ()  
129:         
130:       $host.ui.RawUI.WindowTitle = $ConsoleTitle  
131:  }  
132:    
133:  function Set-NICPowerManagement {  
134:  <#  
135:       .SYNOPSIS  
136:            Enable NIC Power Management  
137:         
138:       .DESCRIPTION  
139:            A detailed description of the Set-NICPowerManagement function.  
140:         
141:       .PARAMETER NICs  
142:            Physical NICs  
143:         
144:       .NOTES  
145:            Additional information about the function.  
146:  #>  
147:         
148:       [CmdletBinding()][OutputType([bool])]  
149:       param  
150:       (  
151:                 $NICs  
152:       )  
153:         
154:       foreach ($NIC in $NICs) {  
155:            $Errors = $false  
156:            Write-Host "NIC:"$NIC.Name  
157:            #Allow the computer to turn off this device  
158:            Write-Host "Allow the computer to turn off this device....." -NoNewline  
159:            $NICPowerManage = Get-WmiObject MSPower_DeviceEnable -Namespace root\wmi | Where-Object { $_.instancename -match [regex]::escape($nic.PNPDeviceID) }  
160:            If ($NICPowerManage.Enable -ne $TurnOffDevice) {  
161:                 $NICPowerManage.Enable = $TurnOffDevice  
162:                 $HideOutput = $NICPowerManage.psbase.Put()  
163:            }  
164:            If ($NICPowerManage.Enable -eq $TurnOffDevice) {  
165:                 Write-Host "Success" -ForegroundColor Yellow  
166:            } else {  
167:                 Write-Host "Failed" -ForegroundColor Red  
168:                 $Errors = $true  
169:            }  
170:            # Allow this device to wake the computer  
171:            Write-Host "Allow this device to wake the computer....." -NoNewline  
172:            $NICPowerManage = Get-WmiObject MSPower_DeviceWakeEnable -Namespace root\wmi | Where-Object { $_.instancename -match [regex]::escape($nic.PNPDeviceID) }  
173:            If ($NICPowerManage.Enable -ne $WakeComputer) {  
174:                 $NICPowerManage.Enable = $WakeComputer  
175:                 $HideOutput = $NICPowerManage.psbase.Put()  
176:            }  
177:            If ($NICPowerManage.Enable -eq $WakeComputer) {  
178:                 Write-Host "Success" -ForegroundColor Yellow  
179:            } else {  
180:                 Write-Host "Failed" -ForegroundColor Red  
181:                 $Errors = $true  
182:            }  
183:            # Only allow a magic packet to wake the computer  
184:            Write-Host "Only allow a magic packet to wake the computer....." -NoNewline  
185:            $NICPowerManage = Get-WmiObject MSNdis_DeviceWakeOnMagicPacketOnly -Namespace root\wmi | Where-Object { $_.instancename -match [regex]::escape($nic.PNPDeviceID) }  
186:            If ($NICPowerManage.EnableWakeOnMagicPacketOnly -ne $AllowMagicPacketsOnly) {  
187:                 $NICPowerManage.EnableWakeOnMagicPacketOnly = $AllowMagicPacketsOnly  
188:                 $HideOutput = $NICPowerManage.psbase.Put()  
189:            }  
190:            If ($NICPowerManage.EnableWakeOnMagicPacketOnly -eq $AllowMagicPacketsOnly) {  
191:                 Write-Host "Success" -ForegroundColor Yellow  
192:            } else {  
193:                 Write-Host "Failed" -ForegroundColor Red  
194:                 $Errors = $true  
195:            }  
196:       }  
197:       Return $Errors  
198:  }  
199:    
200:  Clear-Host  
201:  Set-ConsoleTitle  
202:  $PhysicalNICs = Get-PhysicalNICs  
203:  $Errors = Set-NICPowerManagement -NICs $PhysicalNICs  
204:  Start-Sleep -Seconds 5  
205:  Exit-PowerShell -Errors $Errors  
206:    

18 April 2016

Apple QuickTime Uninstaller

Posted By: Mick Pletcher - 2:55 PM










As we have all seen recently, it is time we get rid of Apple QuickTime from PCs as they are no longer going to update the software. I had a few ask me to publish a blanket uninstaller for QuickTime. With the help of Sapien's PowerShell Studio, I wrote this script to uninstall it from all of the machines in my firm. This uninstaller will query the Add/Remove programs for any applications named quicktime. It will uninstall any version of QuickTime. I have pre-configured the script parameters to search for apps name 'QuickTime' and use the msi switches '/qb- /norestart'.

You can download the script from here.


1:  <#  
2:       .SYNOPSIS  
3:            Apple Quicktime  
4:         
5:       .DESCRIPTION  
6:            Uninstall Apple Quicktime  
7:         
8:       .PARAMETER ApplicationName  
9:            A description of the ApplicationName parameter.  
10:         
11:       .PARAMETER WindowTitle  
12:            Title of the PowerShell window  
13:         
14:       .PARAMETER MSI_Switches  
15:            The switches used when executing the uninstallation of the MSI  
16:         
17:       .EXAMPLE  
18:            powershell.exe -executionpolicy bypass -file uninstall.ps1  
19:         
20:       .NOTES  
21:            ===========================================================================  
22:            Created with:     SAPIEN Technologies, Inc., PowerShell Studio 2016 v5.2.119  
23:            Created on:       4/18/2016 1:44 PM  
24:            Created by:       Mick Pletcher  
25:            Organization:  
26:            Filename:         UninstallQuicktime.ps1  
27:            ===========================================================================  
28:  #>  
29:  param  
30:  (  
31:            [string]$ApplicationName = 'quicktime',  
32:            [string]$WindowTitle = 'Uninstall Apple Quicktime',  
33:            [string]$MSI_Switches = '/qb- /norestart'  
34:  )  
35:    
36:  function Set-ConsoleTitle {  
37:  <#  
38:       .SYNOPSIS  
39:            Console Title  
40:         
41:       .DESCRIPTION  
42:            Sets the title of the PowerShell Console  
43:         
44:       .PARAMETER Title  
45:            Title of the PowerShell console  
46:         
47:       .NOTES  
48:            Additional information about the function.  
49:  #>  
50:         
51:       [CmdletBinding()]  
52:       param  
53:       (  
54:                 [Parameter(Mandatory = $true)][String]$Title  
55:       )  
56:         
57:       $host.ui.RawUI.WindowTitle = $Title  
58:  }  
59:    
60:    
61:  Function InitializeVariables {  
62:       $Global:BuildLog = $Env:windir + "\Waller\Logs\BuildLogs\Build.csv"  
63:       $Global:Errors = $null  
64:       $Global:LogFile = $Env:windir + "\Waller\Logs\BuildLogs\AppleQuicktime.log"  
65:       $Global:Phase = "Software Deployment"  
66:       $Global:RelativePath = (split-path $SCRIPT:MyInvocation.MyCommand.Path -parent) + "\"  
67:  }  
68:    
69:  function Uninstall-MSIByName {  
70:  <#  
71:       .SYNOPSIS  
72:            Uninstall-MSIByName  
73:         
74:       .DESCRIPTION  
75:            Uninstalls an application that was installed using the MSI installer. This function will query the 32-bit and 64-bit add/remove programs entries to match a what is defined in the ApplicationName parameter. You do not have to enter the entire name. This allows you to uninstall multiple versions of an application by entering just a portion of the name that is displayed amoung all versions.  
76:         
77:       .EXAMPLE  
78:            Uninstall-MSIByName "Adobe Reader" "/qb- /norestart"  
79:         
80:       .NOTES  
81:            Additional information about the function.  
82:  #>  
83:         
84:       [CmdletBinding()]  
85:       param ()  
86:         
87:       $Uninstall = Get-ChildItem HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall -Recurse -ErrorAction SilentlyContinue  
88:       $Uninstall += Get-ChildItem HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall -Recurse -ErrorAction SilentlyContinue  
89:       $SearchName = "*" + $ApplicationName + "*"  
90:       $Executable = $Env:windir + "\system32\msiexec.exe"  
91:       Foreach ($Key in $Uninstall) {  
92:            $TempKey = $Key.Name -split "\\"  
93:            If ($TempKey[002] -eq "Microsoft") {  
94:                 $Key = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\" + $Key.PSChildName  
95:            } else {  
96:                 $Key = "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\" + $Key.PSChildName  
97:            }  
98:            If ((Test-Path $Key) -eq $true) {  
99:                 $KeyName = Get-ItemProperty -Path $Key  
100:                 If ($KeyName.DisplayName -like $SearchName) {  
101:                      $TempKey = $KeyName.UninstallString -split " "  
102:                      If ($TempKey[0] -eq "MsiExec.exe") {  
103:                           Write-Host "Uninstall"$KeyName.DisplayName"....." -NoNewline  
104:                           $Parameters = "/x " + $KeyName.PSChildName + [char]32 + $MSI_Switches  
105:                           $ErrCode = (Start-Process -FilePath $Executable -ArgumentList $Parameters -Wait -Passthru).ExitCode  
106:                           If (($ErrCode -eq 0) -or ($ErrCode -eq 3010) -or ($ErrCode -eq 1605)) {  
107:                                Write-Host "Success" -ForegroundColor Yellow  
108:                           } else {  
109:                                Write-Host "Failed with error code "$ErrCode -ForegroundColor Red  
110:                           }  
111:                      }  
112:                 }  
113:            }  
114:       }  
115:  }  
116:    
117:  Clear-Host  
118:  Set-ConsoleTitle -Title $WindowTitle  
119:  Uninstall-MSIByName  
120:  Exit-PowerShell  
121:    

15 April 2016

Using PowerShell to control Dell Command | Update for drivers and BIOS updates

Posted By: Mick Pletcher - 1:38 PM
The Dell Command | Update is a great tool to use, but it also lacks some features that I have implemented in the following script. During system builds, I have the application to update all drivers and the BIOS. The features I have included are:
  1. Ability to disable the BIOS password
  2. Ability to either run the dcu-cli.exe on either a 32-bit or 64-bit machine
  3. Ability to apply XML policies
For features 1 and 3, if the parameters are not populated, they are skipped over. If option 3 is left blank, it runs the dcu-cli.exe to update all Dell applications, BIOS, and drivers. I know that if you are going to flash the BIOS, the BIOS password is then cleared, but I figured I would add this feature just if you wanted to make sure it was done.

Here is an example of how it is integrated in MDT:



You can download the script from here.

Update.ps1
1:  <#  
2:       .SYNOPSIS  
3:            Update Dell drivers, Dell Applications, and Dell BIOS via Dell Command | Update  
4:         
5:       .DESCRIPTION  
6:            Uses Dell Command | Update to update all drivers, BIOS, and Dell applications. Everything can be entered through the parameters without the need to modify the code.  
7:         
8:       .PARAMETER BIOSPassword  
9:            If no BIOS Password is submitted, then the script will skip over clearing disabling the BIOS Password.  
10:         
11:       .PARAMETER Policy  
12:            Name of the custom policy file that configures what updates to install.  
13:         
14:       .PARAMETER ConsoleTitle  
15:            Title of the PowerShell Window  
16:    
17:       .EXAMPLE  
18:            powershell.exe -file Update.ps1 -ConsoleTitle "Dell Command | Update" -Policy "BIOS.xml" -BIOSPassword "Pwd"  
19:            powershell.exe -file Update.ps1 -ConsoleTitle "Dell Command | Update" -Policy "BIOS.xml"  
20:            powershell.exe -file Update.ps1 -ConsoleTitle "Dell Command | Update" -BIOSPassword "Pwd"  
21:            powershell.exe -file Update.ps1 -ConsoleTitle "Dell Command | Update"  
22:         
23:       .NOTES  
24:            ===========================================================================  
25:            Created with:      SAPIEN Technologies, Inc., PowerShell Studio 2015 v4.2.99  
26:            Created on:       1/29/2016 2:59 PM  
27:            Created by:       Mick Pletcher  
28:            Organization:  
29:            Filename:        Update.ps1  
30:            ===========================================================================  
31:  #>  
32:  [CmdletBinding()]  
33:  param  
34:  (  
35:            [string]$BIOSPassword,  
36:            [string]$Policy,  
37:            [string]$ConsoleTitle = " "  
38:  )  
39:    
40:  function Get-RelativePath {  
41:  <#  
42:       .SYNOPSIS  
43:            Get the relative path  
44:         
45:       .DESCRIPTION  
46:            Returns the location of the currently running PowerShell script  
47:         
48:       .NOTES  
49:            Additional information about the function.  
50:  #>  
51:         
52:       [CmdletBinding()][OutputType([string])]  
53:       param ()  
54:         
55:       $Path = (split-path $SCRIPT:MyInvocation.MyCommand.Path -parent) + "\"  
56:       Return $Path  
57:  }  
58:    
59:  function Set-ConsoleTitle {  
60:  <#  
61:       .SYNOPSIS  
62:            Console Title  
63:         
64:       .DESCRIPTION  
65:            Sets the title of the PowerShell Console  
66:         
67:       .PARAMETER Title  
68:            Title of the PowerShell console  
69:         
70:       .NOTES  
71:            Additional information about the function.  
72:  #>  
73:         
74:       [CmdletBinding()]  
75:       param  
76:       (  
77:            [Parameter(Mandatory = $true)][String]  
78:            $Title  
79:       )  
80:         
81:       $host.ui.RawUI.WindowTitle = $Title  
82:  }  
83:    
84:  function Get-Architecture {  
85:  <#  
86:       .SYNOPSIS  
87:            System Architecture  
88:         
89:       .DESCRIPTION  
90:            Determine if the system is x86 or x64. It will then return "32-bit" or "64-bit"  
91:         
92:       .NOTES  
93:            Additional information about the function.  
94:  #>  
95:         
96:       [CmdletBinding()]  
97:       param ()  
98:         
99:       $Architecture = Get-WmiObject -Class Win32_OperatingSystem | Select-Object OSArchitecture  
100:       $Architecture = $Architecture.OSArchitecture  
101:       #Returns 32-bit or 64-bit  
102:       Return $Architecture  
103:  }  
104:    
105:  function Install-Updates {  
106:  <#  
107:       .SYNOPSIS  
108:            Install Dell Updates  
109:         
110:       .DESCRIPTION  
111:            This will install the Dell drivers, applications, and BIOS updates.  
112:         
113:       .PARAMETER DisplayName  
114:            Title to display in the PowerShell Output Console  
115:         
116:       .PARAMETER Executable  
117:            32-bit or 64-bit dcu-cli executable to execute  
118:         
119:       .PARAMETER Switches  
120:            Switches when executing the DCU-CLI executable  
121:         
122:       .NOTES  
123:            Additional information about the function.  
124:  #>  
125:         
126:       [CmdletBinding()]  
127:       param  
128:       (  
129:            [String]  
130:            $DisplayName,  
131:            [String]  
132:            $Executable,  
133:            [String]  
134:            $Switches  
135:       )  
136:         
137:       Write-Host "Install"$DisplayName"....." -NoNewline  
138:       If ((Test-Path $Executable) -eq $true) {  
139:            $ErrCode = (Start-Process -FilePath $Executable -ArgumentList $Switches -Wait -Passthru).ExitCode  
140:       } else {  
141:            $ErrCode = 1  
142:       }  
143:       If (($ErrCode -eq 0) -or ($ErrCode -eq 1) -or ($ErrCode -eq 3010)) {  
144:            Write-Host "Success" -ForegroundColor Yellow  
145:       } else {  
146:            Write-Host "Failed with error code "$ErrCode -ForegroundColor Red  
147:       }  
148:         
149:  }  
150:    
151:  function Set-BIOSSetting {  
152:  <#  
153:       .SYNOPSIS  
154:            Configure BIOS Settings  
155:         
156:       .DESCRIPTION  
157:            Uses the CCTK.exe to configure Dell BIOS settings  
158:         
159:       .PARAMETER Name  
160:            Display name of the BIOS setting  
161:         
162:       .PARAMETER Option  
163:            Technical name of the BIOS setting  
164:         
165:       .PARAMETER Setting  
166:            Switches for the Option parameter  
167:         
168:       .PARAMETER Drives  
169:            Populated if the Set-BIOSSetting is being used to configure the drive boot sequences  
170:         
171:       .PARAMETER Architecture  
172:            Designates if the OS is x86 or x64  
173:         
174:       .NOTES  
175:            Additional information about the function.  
176:  #>  
177:         
178:       [CmdletBinding()]  
179:       param  
180:       (  
181:            [string]  
182:            $Name,  
183:            [string]  
184:            $Option,  
185:            [string]  
186:            $Setting,  
187:            [string]  
188:            $Drives,  
189:            [string]  
190:            $Architecture  
191:       )  
192:         
193:       If ($Architecture -eq "32-bit") {  
194:            $EXE = $Env:PROGRAMFILES + "\Dell\Command Configure\X86\cctk.exe"  
195:       } else {  
196:            $EXE = ${env:ProgramFiles(x86)} + "\Dell\Command Configure\X86_64\cctk.exe"  
197:       }  
198:       $Argument = "--" + $Option + "=" + $Setting  
199:       Write-Host $Name"....." -NoNewline  
200:       If ((Test-Path $EXE) -eq $true) {  
201:            $ErrCode = (Start-Process -FilePath $EXE -ArgumentList $Argument -Wait -Passthru).ExitCode  
202:       } else {  
203:            $ErrCode = 1  
204:       }  
205:       If (($ErrCode -eq 0) -or ($ErrCode -eq 240) -or ($ErrCode -eq 241)) {  
206:            Write-Host "Success" -ForegroundColor Yellow  
207:       } elseIf ($ErrCode -eq 119) {  
208:            Write-Host "Unavailable" -ForegroundColor Green  
209:       } else {  
210:            Write-Host "Failed with error code "$ErrCode -ForegroundColor Red  
211:       }  
212:  }  
213:    
214:  cls  
215:  Set-ConsoleTitle -Title $ConsoleTitle  
216:  $Architecture = Get-Architecture  
217:  If ($BIOSPassword -ne "") {  
218:       Set-BIOSSetting -Name "Disable BIOS Password" -Option "valsetuppwd" -Setting $BIOSPassword" --setuppwd=" -Drives "" -Architecture $Architecture  
219:  }  
220:  If ($Architecture -eq "32-bit") {  
221:       $EXE = $Env:PROGRAMFILES + "\Dell\CommandUpdate\dcu-cli.exe"  
222:  } else {  
223:       $EXE = ${env:ProgramFiles(x86)} + "\Dell\CommandUpdate\dcu-cli.exe"  
224:  }  
225:  If ($Policy -eq "") {  
226:       $Parameters = " "  
227:  } else {  
228:       $RelativePath = Get-RelativePath  
229:       $Parameters = "/policy " + [char]34 + $RelativePath + $Policy + [char]34  
230:  }  
231:  If ((Test-Path $EXE) -eq $true) {  
232:       Install-Updates -DisplayName "Update Dell Components" -Executable $EXE -Switches $Parameters  
233:  } else {  
234:       Exit 1  
235:  }  

14 April 2016

Query Event Logs to a Central Log File

Posted By: Mick Pletcher - 10:19 AM









Recently, we have had sporadic issues with Outlook and needed to see who all was experiencing the problem. We knew it was logged in the event viewer logs. I decided to write a PowerShell script, with the help of Sapien Technology's PowerShell Studio, that would be able to be deployed to machines, query the event viewer logs, and then write the machine name to a centralized log file if it met the criteria. That is what this script will do. I wrote the script so that it can be used in any instance where the need arises to get a report of systems with a specific event viewer log.

To use the script, the following parameters need to be populated:
  • -LogFileLocation -- the location where the centralized log file is to be written to
  • -LogFileName -- the name of the centralized log file
  • -EventLogName -- the name of the event viewer log for the script to query
  • -LogMessage -- the specific message you are looking for in the logs
All that needs to be done to use this is to deploy it through SCCM as a package so that it runs one time. You maybe wondering what happens if multiple systems try to write to the log file at the same time. I included a do-while/try-catch loop in it so that as long as it cannot write to the file it will continue trying until the file is free for it to write its entry.

You can download the script from here.


1:  <#  
2:       .SYNOPSIS  
3:            Query Event Viewer Logs  
4:         
5:       .DESCRIPTION  
6:            This script will query the event viewer logs and write the computer name to a designated, centralized log file, thereby indicating the system met the query specifications.  
7:         
8:       .PARAMETER LogFileLocation  
9:            The network location of where the log file resides.  
10:         
11:       .PARAMETER LogFileName  
12:            The name of the centralized log file  
13:         
14:       .PARAMETER EventLogName  
15:            Name of the event viewer log  
16:         
17:       .PARAMETER LogMessage  
18:            The message to filter the log files for.  
19:         
20:       .NOTES  
21:            ===========================================================================  
22:            Created with:     SAPIEN Technologies, Inc., PowerShell Studio 2016 v5.2.119  
23:            Created on:       4/13/2016 1:54 PM  
24:            Created by:       Mick Pletcher  
25:            Organization:  
26:            Filename:         OutlookLogs.ps1  
27:            ===========================================================================  
28:  #>  
29:  [CmdletBinding()]  
30:  param  
31:  (  
32:            [string]$LogFileLocation,  
33:            [string]$LogFileName,  
34:            [string]$EventLogName,  
35:            [string]$LogMessage  
36:  )  
37:    
38:  #Declare Variable  
39:  Set-Variable -Name Logs -Value $null -Scope Local -Force  
40:    
41:  cls  
42:  $ReportFile = $LogFileLocation + $LogFileName  
43:  $LogMessage = [char]42 + $LogMessage + [char]42  
44:  $Logs = Get-EventLog -LogName $EventLogName | where { $_.Message -like $LogMessage }  
45:  If ($Logs -ne $null) {  
46:       $Logs  
47:       Do {  
48:            Try {  
49:                 $Written = $true  
50:                 Out-File -FilePath $ReportFile -InputObject $env:COMPUTERNAME -Append -Encoding UTF8 -ErrorAction SilentlyContinue  
51:            } Catch {  
52:                 Start-Sleep -Seconds 1  
53:                 $Written = $false  
54:            }  
55:       } while ($Written -eq $false)  
56:  }  
57:    

12 April 2016

Import Active Directory Module into Windows PE

Posted By: Mick Pletcher - 3:38 PM
One thing I have been wanting to have is access to active directory in a WinPE environment. The main reason I want it is to be able to delete systems from active directory during a build. When I first started researching, I found this blog that guided me on writing this script. The blog tells how to inject the AD module into the WIM file. That is fine, but do you really want to do that every time you generate a new WIM file? I don't. I started testing to see if the directories could be copied into the WinPE environment while it was running without the need of a reboot. It worked. Currently, this script only makes the Active Directory module available in the WinPE environment. I am going to write more scripts to take advantage of the AD module.

To use this script, you will need to place it on a network share, or if you are using WinPE, you can place it within the scripts folder of the DeploymentShare so the image will have access to it. I wrote this with four parameters so that you can use the domain username and password within a task sequence without putting it inside the script to possibly expose it. The username and password give the script access to map to the NetworkPath. The NetworkPath points to the location where the Active Directory components reside to copy over to the WinPE environment. The DriveLetter pertains to the drive letter you wish for the script to use when mapping to the NetworkPath. If you want, you could enter default values for the parameters if you want.

The next thing you will need to do is to create the source folders on the NetworkPath, which will contain all of the files.

For 32-Bit WinPE, create the following directories on your NetworkPath. This is what my source directory looks like:

NOTE: The last two directories will have different names as the module is updated by Microsoft. You will have to search for the first part of the name to find them if it changes. That is why in the script I have it to search for the name of the directory knowing that it might change.

For 32-bit WinPE, copy the following directories from a Windows 10 machine to the appropriate directories created above. Make sure you copy all subdirectories along with the full contents:

  • %windir%\System32\WindowsPowerShell\v1.0\Modules\ActiveDirectory
  • %windir%\Microsoft.NET\assembly\GAC_32\Microsoft.ActiveDirectory.Management
  • %windir%\Microsoft.NET\assembly\GAC_32\Microsoft.ActiveDirectory.Management.Resources
  • %windir%\WinSxS\x86_microsoft.activedirectory.management_31bf3856ad364e35_6.3.9431.0_none_b85eb2e785c286ef
  • %windir%\WinSxS\msil_microsoft-windows-d..ivecenter.resources_31bf3856ad364e35_6.3.9431.0_en-us_38f21d039944539f
For 64-Bit WinPE, I have included an If statement, but it has not been tested, so I can't guarantee it will work. I am not sure if you still need to copy the 32-bit folders also, or if they can be removed and just the 64-bit folders installed. Here is the list of folders to copy from a Windows 10 x64 system:
  • %windir%\SysWOW64\WindowsPowerShell\v1.0\Modules\ActiveDirectory 
  • %windir%\Microsoft.NET\assembly\GAC_64\Microsoft.ActiveDirectory.Management
  • %windir%\Microsoft.NET\assembly\GAC_64\Microsoft.ActiveDirectory.Management.Resources
  • %windir%\WinSxS\amd64_microsoft.activedir..anagement.resources_31bf3856ad364e35_6.3.9431.0_en-us_fb186ae865900ae8
As for the last 64-bit entry above, I have included a variable in the script to grab the name of the directory as the last part will likely change upon future updates to the PowerShell AD module.


Below is how I put the script into the task sequence build. I first map a T: drive to the location of where the directories above exist. I then execute the powershell script and finally unmap the T: drive.



After you get these source files copied to a network location, you can now use the script below to run during the WinPE environment. You can see the pop-up windows in the background as it robocopies the directories over to WinPE. Here is a video of the script in action:

video


One thing you will encounter when executing the script is that it will give you the following warning when you import the module:


I racked my brain last week trying to get this to go away. I was trying to use the new-psdrive to open a connection to the active directory server and I just couldn't get it to work. I finally posted to the Facebook PowerShell group and one advised me to ignore the message and use the -server parameter for each cmdlet. That works. You can ignore this message. I ran the Get-ADComputer cmdlet and specificed the AD server in the -server parameter. It worked perfectly.

You can download the script from here.

InstallActiveDirectoryModule.ps1



1:  <#  
2:       .SYNOPSIS  
3:            Install PowerShell Active Directory Module  
4:         
5:       .DESCRIPTION  
6:            Copies the PowerShell Active Directory Module to the WinPE environment. This allows the use of the PowerShell module without having to mount, inject the directories, and dismount a WIM everytime a new WIM is generated.  
7:         
8:       .PARAMETER DomainUserName  
9:            Username with domain access used to map drives  
10:         
11:       .PARAMETER DomainPassword  
12:            Domain password used to map network drives  
13:         
14:       .PARAMETER NetworkPath  
15:            Network path to map where the Active Directory PowerShell module exists  
16:         
17:       .PARAMETER DriveLetter  
18:            Drive letter mapping where the PowerShell Active Directory module files exists  
19:         
20:       .NOTES  
21:            ===========================================================================  
22:            Created with: SAPIEN Technologies, Inc., PowerShell Studio 2016 v5.2.119  
23:            Created on:   4/8/2016 12:41 PM  
24:            Created by:   Mick Pletcher  
25:            Organization:  
26:            Filename:     InstallActiveDirectoryModule.ps1  
27:            ===========================================================================  
28:  #>  
29:  [CmdletBinding()]  
30:  param  
31:  (  
32:       [string]  
33:       $DomainUserName,  
34:       [string]  
35:       $DomainPassword,  
36:       [string]  
37:       $NetworkPath,  
38:       [string]  
39:       $DriveLetter  
40:  )  
41:    
42:  function Copy-Folder {  
43:  <#  
44:       .SYNOPSIS  
45:            Copy Folder  
46:         
47:       .DESCRIPTION  
48:            Copy folder to destination  
49:         
50:       .PARAMETER SourceFolder  
51:            A description of the SourceFolder parameter.  
52:         
53:       .PARAMETER DestinationFolder  
54:            A description of the DestinationFolder parameter.  
55:         
56:       .EXAMPLE  
57:                      PS C:\> Copy-Folder -SourceFolder 'Value1' -DestinationFolder 'Value2'  
58:         
59:       .NOTES  
60:            Additional information about the function.  
61:  #>  
62:         
63:       [CmdletBinding()]  
64:       param  
65:       (  
66:            [string]  
67:            $SourceFolder,  
68:            [string]  
69:            $DestinationFolder  
70:       )  
71:         
72:       $Executable = $env:windir + "\system32\Robocopy.exe"  
73:       $Switches = $SourceFolder + [char]32 + $DestinationFolder + [char]32 + "/e /eta /mir"  
74:       Write-Host "Copying "$SourceFolder"....." -NoNewline  
75:       $ErrCode = (Start-Process -FilePath $Executable -ArgumentList $Switches -Wait -Passthru).ExitCode  
76:       If (($ErrCode -eq 0) -or ($ErrCode -eq 1)) {  
77:            Write-Host "Success" -ForegroundColor Yellow  
78:       } else {  
79:            Write-Host "Failed with error code"$ErrCode -ForegroundColor Red  
80:       }  
81:  }  
82:    
83:  function Get-Architecture {  
84:  <#  
85:       .SYNOPSIS  
86:            Get-Architecture  
87:         
88:       .DESCRIPTION  
89:            Returns whether the system architecture is 32-bit or 64-bit  
90:         
91:       .EXAMPLE  
92:            Get-Architecture  
93:         
94:       .NOTES  
95:            Additional information about the function.  
96:  #>  
97:         
98:       [CmdletBinding()][OutputType([string])]  
99:       param ()  
100:         
101:       $OSArchitecture = Get-WmiObject -Class Win32_OperatingSystem | Select-Object OSArchitecture  
102:       $OSArchitecture = $OSArchitecture.OSArchitecture  
103:       Return $OSArchitecture  
104:       #Returns 32-bit or 64-bit  
105:  }  
106:    
107:    
108:  function New-NetworkDrive {  
109:  <#  
110:       .SYNOPSIS  
111:            Map network drive  
112:         
113:       .DESCRIPTION  
114:            Map the network drive for copying down the PowerShell Active Directory files to the WinPE environment  
115:         
116:       .EXAMPLE  
117:            PS C:\> New-NetworkDrive  
118:         
119:       .NOTES  
120:            Additional information about the function.  
121:  #>  
122:         
123:       [CmdletBinding()]  
124:       param ()  
125:         
126:       $Executable = $env:windir + "\system32\net.exe"  
127:       $Switches = "use" + [char]32 + $DriveLetter + ":" + [char]32 + $NetworkPath + [char]32 + "/user:" + $DomainUserName + [char]32 + $DomainPassword  
128:       Write-Host "Mapping"$DriveLetter":\ drive....." -NoNewline  
129:       $ErrCode = (Start-Process -FilePath $Executable -ArgumentList $Switches -Wait -Passthru).ExitCode  
130:       If ((Test-Path $DriveLetter":\") -eq $true) {  
131:            Write-Host "Success" -ForegroundColor Yellow  
132:       } else {  
133:            Write-Host "Failed" -ForegroundColor Yellow  
134:       }  
135:  }  
136:    
137:  function Remove-NetworkDrive {  
138:  <#  
139:       .SYNOPSIS  
140:            Delete the mapped network drive  
141:         
142:       .DESCRIPTION  
143:            Delete the mapped network drive  
144:         
145:       .EXAMPLE  
146:                      PS C:\> Remove-NetworkDrive  
147:         
148:       .NOTES  
149:            Additional information about the function.  
150:  #>  
151:         
152:       [CmdletBinding()]  
153:       param ()  
154:         
155:       $Executable = $env:windir + "\system32\net.exe"  
156:       $Switches = "use" + [char]32 + $DriveLetter + ":" + [char]32 + "/delete"  
157:       Write-Host "Deleting"$DriveLetter":\ drive....." -NoNewline  
158:       $ErrCode = (Start-Process -FilePath $Executable -ArgumentList $Switches -Wait -Passthru).ExitCode  
159:       If ((Test-Path $DriveLetter":\") -eq $true) {  
160:            Write-Host "Failed" -ForegroundColor Yellow  
161:       } else {  
162:            Write-Host "Success" -ForegroundColor Yellow  
163:       }  
164:  }  
165:    
166:  cls  
167:  #Get WinPE Architecture  
168:  $Architecture = Get-Architecture  
169:  #Map network drive to PowerShell active directory module  
170:  New-NetworkDrive  
171:  #Get msil_microsoft-windows-d..ivecenter.resources Directory Name  
172:  $MicrosoftWindowsIvecenterResources = Get-ChildItem $DriveLetter":\" | where { $_.Attributes -eq 'Directory' } | Where-Object { $_.FullName -like "*msil_microsoft-windows-d..ivecenter.resources*" }  
173:  #Get WinSxS x86_microsoft.activedirectory.management Name  
174:  $WinSxSMicrosoftActiveDirectoryManagementResources = Get-ChildItem $DriveLetter":\" | where { $_.Attributes -eq 'Directory' } | Where-Object { $_.FullName -like "*x86_microsoft.activedirectory.management*" }  
175:  #Get WinSxS amd64_microsoft.activedir..anagement.resources Name  
176:  $WinSxSMicrosoftActiveDirectoryManagementResources_x64 = Get-ChildItem $DriveLetter":\" | where { $_.Attributes -eq 'Directory' } | Where-Object { $_.FullName -like "*amd64_microsoft.activedir..anagement.resources*" }  
177:    
178:  #Copy ActiveDirectory Folder  
179:  Copy-Folder -SourceFolder $NetworkPath"\ActiveDirectory" -DestinationFolder $env:windir"\System32\WindowsPowerShell\v1.0\Modules\ActiveDirectory"  
180:  #Copy Microsoft.ActiveDirectory.Management Folder  
181:  Copy-Folder -SourceFolder $NetworkPath"\Microsoft.ActiveDirectory.Management" -DestinationFolder $env:windir"\Microsoft.NET\assembly\GAC_32\Microsoft.ActiveDirectory.Management"  
182:  #Copy Microsoft.ActiveDirectory.Management.Resources Folder  
183:  Copy-Folder -SourceFolder $NetworkPath"\Microsoft.ActiveDirectory.Management.Resources" -DestinationFolder $env:windir"\Microsoft.NET\assembly\GAC_32\Microsoft.ActiveDirectory.Management.Resources"  
184:  #Copy msil_microsoft-windows-d..ivecenter.resources Folder  
185:  Copy-Folder -SourceFolder $NetworkPath"\"$MicrosoftWindowsIvecenterResources -DestinationFolder $env:windir"\WinSxS\"$MicrosoftWindowsIvecenterResources  
186:  #Copy x86_microsoft.activedirectory.management Folder  
187:  Copy-Folder -SourceFolder $NetworkPath"\"$WinSxSMicrosoftActiveDirectoryManagementResources -DestinationFolder $env:windir"WinSxS\"$WinSxSMicrosoftActiveDirectoryManagementResources  
188:    
189:  If ($Architecture -eq "64-bit") {  
190:       #Copy ActiveDirectory x64 Folder  
191:       Copy-Folder -SourceFolder $NetworkPath"\ActiveDirectory" -DestinationFolder $env:SystemDrive"\"  
192:       #Copy Microsoft.ActiveDirectory.Management x64 Folder  
193:       Copy-Folder -SourceFolder $NetworkPath"\Microsoft.ActiveDirectory.Management" -DestinationFolder $env:windir"\Microsoft.NET\assembly\GAC_64\Microsoft.ActiveDirectory.Management"  
194:       #Copy Microsoft.ActiveDirectory.Management.Resources x64 Folder  
195:       Copy-Folder -SourceFolder $NetworkPath"\Microsoft.ActiveDirectory.Management.Resources" -DestinationFolder $env:windir"\Microsoft.NET\assembly\GAC_64\Microsoft.ActiveDirectory.Management.Resources"  
196:       #Copy amd64_microsoft.activedir..anagement.resources x64 Folder  
197:       Copy-Folder -SourceFolder $NetworkPath"\"$WinSxSMicrosoftActiveDirectoryManagementResources_x64 -DestinationFolder $env:windir"\WinSxS\"$WinSxSMicrosoftActiveDirectoryManagementResources_x64  
198:  }  
199:    
200:  #Unmap Network Drive  
201:  Remove-NetworkDrive  
202:    

01 April 2016

Optiplex 9010 Blue Screen during driver installation

Posted By: Mick Pletcher - 10:58 AM
Recently, I went through and updated the drivers for the Optiplex 9010 from Dell's enterprise driver site. I then imported the drivers into MDT and imaged a 9010. When the system started to install the devices, it crashed. After combing through the drivers and disabling sets of them upon each build, I located the bad driver. It is:

Intel(R) Corporation USB iusb3xhc.inf 1.0.245

Once I disabled this driver, the system imaged successfully. 

04 March 2016

Bitlocker Access is Denied

Posted By: Mick Pletcher - 3:33 PM









We recently started getting access is denied when trying to enable bitlocker on our Dell Latitude E7440 models. At first we thought it was a problem with the laptop itself upon the first occurrence of it. We were able to image all other models with no problems. We contacted Dell Premiere support and they concurred. They said that replacing the motherboard should rectify the issue since the issue seemed to be with the TPM chip. Dell replaced the motherboard and this issue persisted. We imaged other E7440 laptops and got the same error. Actually, the access is denied appeared when we went to manually encrypt the laptops. We would get Error code: 0x80070005 when trying to enable bitlocker via the control panel. The build would fail when it tried to enable the bitlocker. When I looked at the event viewer logs, I found the following errors:




At this point, we thought the issue might have been with the build process. We started combing through the build trying to find out what might be wrong. The problem was that all other model systems worked, except for this one. We did the following steps in troubleshooting:

  1. Verified all other model laptops enable bitlocker with no issues
  2. The same task sequence is used on all laptops. The only differences are drivers and bios.
  3. We followed the procedure from this blog that fixed this issue for some users. It did not fix it for our systems.
  4. We verified the BIOS is updated to the latest version
  5. Dell replaced the motherboard and HDD
  6. Windows 7 32-Bit installs and bitlockering on this model had no issues
  7. We verified that the system will bitlocker if we move it to the computers container in active directory
  8. We noticed two problems with the BIOS. The first is that it will not activate the TPM on the first try. When you click activate, apply, and exit, the system reboots, but it goes back to deactivate. It takes two times to activate it. The second problem is pxe booting. When we select to boot from the NIC, the system reboots on the first try. These problems are happening to all of our E7440 laptops.
  9. I laid down a base windows 7 image with no drivers or windows updates. The only driver I installed was the NIC for network connectivity. When I joined it to the domain, it still gave access denied.
  10. I downgraded the BIOS
  11. We disabled the Cisco Anywhere Connect VPN software from being installed during the build. I ran across troubleshooting post for the access is denied where they recommended uninstall any VPN software. This did not fix the issue.
  12. I gave the SELF account full control of the specific computer in active directory with no success
  13. One more suggestion we found that some said worked was upgrading the firmware to the latest version for the HDD. We were not able to get the firmware to upgrade on our flash HDD.
  14. We were able to get systems to bitlocker if we joined the system to a local workgroup, changed the name of the system to one that had never been used before, and then joined the domain.
  15. We were able to get systems to bitlocker if we moved the system in active directory to the computers container where it gets no GPOs.
  16. We also noticed other problems with the E7440. When you go into the BIOS to turn on, clear, and activate the TPM, it does not behave correctly. Once you have completed the clear process, the TPM is automatically put into deactivated mode. You must then reboot the system for it to take effect. Next, you click to activate the TPM, it shows it is activated, but when you reboot and go back into the BIOS, the TPM is showing as deactivated. The activation step must be done twice. The second issue we found was with PXE booting. Sometimes when we hit F12, select Onboard NIC, the system will reboot when it begins the initializing step of the PXE process.
By this time, we had spent almost 70 hours troubleshooting this, including Dell support trying to help. Finally I decided to find out exactly what the Bitlocker GPO changed on system. I found it pushed two registry keys: HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\FVE and HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\TPM. I deleted those registry keys out and then tried to enable bitlocker through the control panel. It worked. I knew at this point, it had to be with the system and not the GPO, especially since it worked with all other systems. The next thing that needed to be done was to make sure the recovery key got to active directory. I ran a GPUPDATE.EXE to force the registry keys back down to the system. I then ran manage-bde -protectors -get c: to get the numerical password ID. Finally, I ran manage-bde -protectors -adbackup c: -id {Numerical ID} to push the key to active directory and it worked! My next step was to make sure this same process would work on other model systems so that we could have a single process to work on all instead of having more than one. It does successfully work on the other models. 

I have written two PowerShell scripts, with the help of PowerShell Studio by Sapien Technologies, that bitlocker the systems. The first script uses BitlockerSAK to make sure the TPM is ready to be used. Once it verifies the TPM is turned on, cleared, and activated, the script deletes the FVE and TPM registry keys. The next step is does is to take ownership of the TPM. To take ownership of the TPM, it needs the BIOS password, which is a mandatory parameter upon the execution of the script. The next step is to enable bitlocker. A group policy update is now necessary to repopulate the registry keys the script deleted earlier. Next, the script gets the Bitlocker ID using the function provided by PowerShell District. This is necessary for the next step that pushes the recovery key to active directory. At this point, the script is finished and the system must be rebooted in order for bitlocker to begin encrypting the drive. 

There is a second script for the actual encryption process. This script is executed as the next task sequence. It first waits for the fvenotify.exe to begin. The script waits 5 minutes for this to begin. If it does not begin within 5 minutes, the script exits with an error code 1. Once the fvenotify.exe is a process, the script waits until it disappears. This is intended to delay a build until the encryption process is completed. 

You can download the scripts from the following links:


BitlockerSystem.ps1
 <#       
      .NOTES  
      ===========================================================================  
       Created with:      SAPIEN Technologies, Inc., PowerShell Studio 2015 v4.2.99  
       Created on:       2/25/2016 4:29 PM  
       Created by:       Mick Pletcher  
       Organization:         
       Filename:        BitlockerSystem.ps1  
      ===========================================================================  
      .DESCRIPTION  
           This script waits for the bitlocker process to begin. If the bitlocker  
           process does not begin within 5 minutes, the script exits with an error  
           code 1. If the process does begin, then the script waits until   
           bitlocker is complete with encrypting the system.  
 #>  
   
   
 #Declare Variables  
 Set-Variable -Name CurrentTime -Scope Local -Force  
 Set-Variable -Name Difference -Scope Local -Force  
 Set-Variable -Name Output1 -Scope Local -Force  
 Set-Variable -Name Output2 -Scope Local -Force  
 Set-Variable -Name Output3 -Scope Local -Force  
 Set-Variable -Name Process -Value $null -Scope Local -Force  
 Set-Variable -Name StartTime -Scope Local -Force  
   
 Clear-Host  
 $StartTime = Get-Date  
 $Output1 = "Waiting for Bitlocker Encryption to begin....."  
 $Output1  
 While ($Process -eq $null) {  
      Start-Sleep -Seconds 5  
      $Process = Get-Process -Name fvenotify -ErrorAction SilentlyContinue  
      $CurrentTime = Get-Date  
      $Difference = (New-TimeSpan -Start $StartTime -End $CurrentTime).minutes  
      If ($Difference -eq 5) {  
           Exit 1  
      }  
 }  
 $Output1 = $Output1 + "Completed"  
 Clear-Host  
 $Output1  
 $Output2 = "Bitlockering System....."  
 $Output2  
 while ($Process -ne $null) {  
      $Process = $null  
      $Process = Get-Process -Name fvenotify -ErrorAction SilentlyContinue  
      $Output3 = manage-bde -status $env:HOMEDRIVE  
      Clear-Host  
      $Output1  
      $Output2  
      Write-Host  
      $Output3[9].TRIM()  
      Start-Sleep -Seconds 60  
 }  
 Write-Host "Complete" -ForegroundColor Yellow  
   
 #Cleanup Variables  
 Remove-Variable -Name CurrentTime -Scope Local -Force  
 Remove-Variable -Name Difference -Scope Local -Force  
 Remove-Variable -Name Output1 -Scope Local -Force  
 Remove-Variable -Name Output2 -Scope Local -Force  
 Remove-Variable -Name Output3 -Scope Local -Force  
 Remove-Variable -Name Process -Scope Local -Force  
 Remove-Variable -Name StartTime -Scope Local -Force  
   


EnableBitlocker.ps1
 <#  
      ===========================================================================  
      Created with:     SAPIEN Technologies, Inc., PowerShell Studio 2015 v4.2.99  
      Created on:       2/26/2016 2:02 PM  
      Created by:       Mick Pletcher  
      Organization:  
      Filename:         EnableBitlocker.ps1  
      ===========================================================================  
      .DESCRIPTION  
           This script will enable bitlocker on a system. It first tests the   
           system to make sure the TPM is ready for bitlocker. If it passes  
           the test, then it does the following:  
           1) Deletes the FVE and TPM registry keys  
           2) Takes ownership of the TPM  
           3) Enables bitlocker  
           4) Performs a gpupdate  
           5) Gets the bitlocker recovery key ID  
           6) Backs up the recovery key to active directory  
 #>  
   
 param  
 (  
      [Parameter(Mandatory = $true)][string]$BIOSPassword  
 )  
   
 Function BitLockerSAK {  
 <#  
 .SYNOPSIS  
      Get and set Bitlocker related information.  
     
 .DESCRIPTION  
      Based on WMI classes, this function can achiev the following tasks :  
   
   --TPM operations---  
     -TPM activation state.  
     -If the TPM is enabled or not.  
     -If a TPM OwnerShip is Allowed.  
     -If the TPM is currently owned.  
     -The possibility to take the ownerShip  
   
   --Encryption possibilities ---  
     - Retrieves the current encryption method.  
     - Get the current protection status.  
     - The current protection state.  
     - The possibility to encrypt a Drive.  
     - The possibility to Resume an encryption that has been paused.  
     - Possibility to return the current protector ID's.  
     - Possibility to return the current protector type(s).  
     - Retrieves the Volume key protector Passwords  
     
   
 .PARAMETER isTPMActivated  
      Returns activation state of the TPM:  
   Returns true if activated and false if not.  
   
 .PARAMETER isTPMEnabled  
      Returns the enabled state of the TPM:  
   Returns true if activated and false if not.  
   
 .PARAMETER IsTPMOwnerShipAllowed  
   Returns if the TPM ownership is allowed.  
   Returns true if allowed, false if not.  
   
 .PARAMETER ResumeEncryption  
   Will resume an paused encryption.  
   
 .PARAMETER GetEncryptionState  
   Returns the current encurrent state in an object as wolled :   
   
 .PARAMETER GetProtectionStatus  
   Returns the current protection status. It will return "Protected" if the drive is 100% encrypted, and "Unprotected" if anything else then "100% encrypted".  
   
 .PARAMETER Encrypt  
   Will encrypt a drive.  
   
 .PARAMETER TakeTPMOwnerShip  
   Returns true if allowed, false if not  
   
 .PARAMETER pin  
   Is needed in order to take the ownership and to encrypt the drive.  
   
 .PARAMETER IsTPMOwned  
   Returns true if owned, false if not  
   
 .PARAMETER GetKeyProtectorIds  
   Returns all the protector id's available on the machine.  
   
 .PARAMETER GetKeyProtectorType  
   Returns the type of protector that is currently in use.  
   
 .PARAMETER GetEncryptionMethod  
   REturns the current encryption method that is in use.  
   
 .PARAMETER GetKeyProtectorNumericalPassword  
   Returns a given numerical password based on a Protector ID value.  
   The ProtectorID value is mandatory, and must be passed using the parameter VolumeKeyProtectorID.   
   
 .PARAMETER VolumeKeyProtectorID  
   This parameter will work only in conjunction with GetKeyProtectorNumericalPassword switch.  
   It must contain the ProtectorID from which the desired Numerical Password will be returned.  
             
 .PARAMETER GetKeyProtectorTypeAndID  
   The GetKeyProtectorTypeAndID switch will return all the existing key protector ID's and their type of the Keys existing on the machine.  
   
   
 .PARAMETER Whatif  
      Permits to launch this script in "draft" mode. This means it will only show the results without really making generating the files.  
   
 .PARAMETER Verbose  
      Allow to run the script in verbose mode for debbuging purposes.  
     
 .EXAMPLE  
   
 BitLockerSAK  
   
 Returns the current status of the drives.  
   
 IsTPMOwned         : True  
 EncryptionMethod      : AES_128  
 IsTPMOwnerShipAllowed    : True  
 IsTPMActivated       : True  
 IsTPMEnabled        : True  
 CurrentEncryptionPercentage : 100  
 EncryptionState       : FullyEncrypted  
 ProtectorIds        : {{FFC19381-6E75-4D1E-94E9-D6E0D3E681FA}, {65AF5A93-9846-47AC-B3B1-D8DE6F06B780}}  
 KeyProtectorType      : {Numerical password, Trusted Platform Module (TPM)}  
   
 .EXAMPLE  
    
 BitLockerSAK -GetProtectionStatus  
   
 Returns the current protection status : Protected or unprotected  
   
 .EXAMPLE  
    
 BitLockerSAK -GetEncryptionState  
   
 CurrentEncryptionProgress is express in percentage.   
   
 CurrentEncryptionProgress EncryptionState                                             
 ------------------------- ---------------                                             
            100 FullyEncrypted  
     
 .EXAMPLE  
   
 Get all the key protectors and their respective ID's and protector types from the current machine.  
   
 BitLockerSAK -GetKeyProtectorTypeAndID  
   
 KeyProtectorID                                           KeyProtectorType                                            
 --------------                                           ----------------                                            
 {AB1535D4-ECB3-49D6-8AB1-E334A4F60579}                               Numerical password                                           
 {B1BDF8CD-55F2-4532-A93F-4B1AF4F22B55}                               Trusted Platform Module (TPM)  
   
 .EXAMPLE  
   
 Get the numerical password from a specefic Key using the ID.  
   
 BitLockerSAK -GetKeyProtectorNumericalPassword -VolumeKeyProtectorID "{AB1535D4-ECB3-49D6-8AB1-E334A4F60579}"  
   
 Message                              KeyProtectorNumericalPassword                   VolumeKeyProtectorID                         
 -------                              -----------------------------                   --------------------                         
 The method was successful.                     242968-693319-295251-477840-704451-214225-550055-383229      {AB1535D4-ECB3-49D6-8AB1-E334A4F60579}   
   
 .NOTES  
      -Author: Stephane van Gulick  
      -Email :   
      -CreationDate: 13-01-2014  
      -LastModifiedDate: 11.06.2015  
      -Version: 1.5  
      -History:  
   #0.1 : Created function  
   #1.1 : 20140901 Added GetProtectorIds  
   #1.2 : 20140909 Rewrote function  
           Added GetKeyprotectorType  
           Added EncryptionMethod  
      #1.3 : 20141003 Added TPM conditions.  
   #1.4 : Possiblity to select drive letter, added RemoveKeyProtectors.  
     --> GetKeyProtectorTypeAndID,  
     --> DeleteKeyProtectors,  
     --> ProtectorIDs,  
     --> DeleteKeyProtector,  
     --> PauseEncryption,  
     --> PauseDecryption,  
     --> Decrytp  
   #1.4.1 --> updated help with GetKeyPRotectedID instead of KeyProtectedID parameter  
   #1.5 Added GetKeyProtectorNumericalPassword and VolumeKeyProtectorID parameters.  
   
 .LINK  
   www.PowerShellDistrict.com  
   
 #>  
      [cmdletBinding()]  
      Param (  
           [Switch]$IsTPMActivated,  
           [Switch]$IsTPMEnabled,  
           [Switch]$IsTPMOwnerShipAllowed,  
           [Switch]$ResumeEncryption,  
           [Switch]$GetEncryptionState,  
           [Switch]$GetProtectionStatus,  
           [switch]$Encrypt,  
           [Parameter(ParameterSetName = 'OwnerShip')][switch]$TakeTPMOwnerShip,  
           [Parameter(ParameterSetName = 'OwnerShip')][int]$pin,  
           [switch]$IsTPMOwned,  
           [Switch]$GetKeyProtectorIds,  
           [switch]$GetEncryptionMethod,  
           [ValidateScript({  
                if ($_ -match '^[A-Z]{1}[:]') {  
                     return $true  
                } else {  
                     Write-Warning 'The drive letter parameter has to respect the following case: DriverLetter+Colomn EG: --> C: --> D: --> E: '  
                     return $false  
                }  
           })][string]$DriveLetter = 'C:',  
           [switch]$GetKeyProtectorTypeAndID,  
           [switch]$DeleteKeyProtectors,  
           #Acceptvaluefrompipelinebyname  
           [String[]]$ProtectorIDs,  
           [switch]$DeleteKeyProtector,  
           [switch]$PauseEncryption,  
           [switch]$PauseDecryption,  
           [switch]$Decrytp,  
           [Parameter(ParameterSetName = 'NumericalPassword')][Switch]$GetKeyProtectorNumericalPassword,  
           [Parameter(ParameterSetName = 'NumericalPassword', Mandatory = $true)][String]$VolumeKeyProtectorID  
             
      )  
      Begin {  
           try {  
                $Tpm = Get-WmiObject -Namespace ROOT\CIMV2\Security\MicrosoftTpm -Class Win32_Tpm -ErrorAction Stop  
           } catch [System.Management.ManagementException]{  
                  
                write-warning 'Could not access the WMI methods. Verify that you run the script with elevated rights and try again.'  
                continue  
                  
                  
           }  
      }  
      Process {  
           ##Add switch to verify if enough place is present on HD (6gig are need, 10 recommended).  
             
             
           switch ($PSBoundParameters.keys) {  
                  
                'IsTPMActivated'{ $return = if ($Tpm) { $tpm.IsActivated().isactivated }; break }  
                'IsTPMEnabled'{ $return = if ($Tpm) { $tpm.IsEnabled().isenabled }; break }  
                'IsTPMOwnerShipAllowed'{ $return = if ($Tpm) { $tpm.IsOwnerShipAllowed().IsOwnerShipAllowed }; break }  
                'IsTPMOwned'{ $return = if ($Tpm) { $Tpm.isowned().isowned }; break }  
                'GetEncryptionState'{  
                     write-verbose "Getting the encryptionstate of drive $($driveletter)"  
                     #http://msdn.microsoft.com/en-us/library/aa376433(VS.85).aspx  
                     #We only want to work on the C: drive.  
                     $EncryptionData = Get-WmiObject -Namespace ROOT\CIMV2\Security\Microsoftvolumeencryption -Class Win32_encryptablevolume -Filter "DriveLetter = '$DriveLetter'"  
                     $protectionState = $EncryptionData.GetConversionStatus()  
                     $CurrentEncryptionProgress = $protectionState.EncryptionPercentage  
                       
                     switch ($ProtectionState.Conversionstatus) {  
                            
                          '0' {  
                                 
                               $Properties = @{ 'EncryptionState' = 'FullyDecrypted'; 'CurrentEncryptionProgress' = $CurrentEncryptionProgress }  
                               $Return = New-Object psobject -Property $Properties  
                                 
                          }  
                            
                          '1' {  
                                 
                               $Properties = @{ 'EncryptionState' = 'FullyEncrypted'; 'CurrentEncryptionProgress' = $CurrentEncryptionProgress }  
                               $Return = New-Object psobject -Property $Properties  
                                 
                          }  
                          '2' {  
                                 
                               $Properties = @{ 'EncryptionState' = 'EncryptionInProgress'; 'CurrentEncryptionProgress' = $CurrentEncryptionProgress }  
                               $Return = New-Object psobject -Property $Properties  
                          }  
                          '3' {  
                                 
                               $Properties = @{ 'EncryptionState' = 'DecryptionInProgress'; 'CurrentEncryptionProgress' = $CurrentEncryptionProgress }  
                               $Return = New-Object psobject -Property $Properties  
                          }  
                          '4' {  
                                 
                               $Properties = @{ 'EncryptionState' = 'EncryptionPaused'; 'CurrentEncryptionProgress' = $CurrentEncryptionProgress }  
                               $Return = New-Object psobject -Property $Properties  
                          }  
                          '5' {  
                                 
                               $Properties = @{ 'EncryptionState' = 'DecryptionPaused'; 'CurrentEncryptionProgress' = $CurrentEncryptionProgress }  
                               $Return = New-Object psobject -Property $Properties  
                          }  
                          default {  
                               write-verbose "Couldn't retrieve an encryption state."  
                               $Properties = @{ 'EncryptionState' = $false; 'CurrentEncryptionProgress' = $false }  
                               $Return = New-Object psobject -Property $Properties  
                          }  
                     }  
                }  
                'ResumeEncryption'{  
                     write-verbose 'Resuming encryption'  
                     $ProtectionState = Get-WmiObject -Namespace ROOT\CIMV2\Security\Microsoftvolumeencryption -Class Win32_encryptablevolume -Filter "DriveLetter = '$DriveLetter'"  
                       
                     $Ret = $protectionState.ResumeConversion()  
                     $ReturnCode = $ret.ReturnValue  
                       
                     switch ($ReturnCode) {  
                            
                          ('0') { $Message = 'The Method Resume Conversion was called succesfully.' }  
                          ('2150694912') { $message = 'The volume is locked' }  
                          default { $message = 'The resume operation failed with an uknowned return code.' }  
                     }  
                       
                     $Properties = @{ 'ReturnCode' = $ReturnCode; 'ErrorMessage' = $message }  
                     $Return = New-Object psobject -Property $Properties  
                } #EndResumeEncryption    
                'GetProtectionStatus'{  
                     #http://msdn.microsoft.com/en-us/library/windows/desktop/aa376448(v=vs.85).aspx  
                     $ProtectionState = Get-WmiObject -Namespace ROOT\CIMV2\Security\Microsoftvolumeencryption -Class Win32_encryptablevolume -Filter "DriveLetter = '$DriveLetter'"  
                     write-verbose 'Gathering BitLocker protection status infos.'  
                       
                     switch ($ProtectionState.GetProtectionStatus().protectionStatus) {  
                            
                          ('0') { $return = 'Unprotected' }  
                          ('1') { $return = 'Protected' }  
                          ('2') { $return = 'Uknowned' }  
                          default { $return = 'NoReturn' }  
                     } #EndSwitch  
                } #EndGetProtection  
                'Encrypt'{  
                     #http://msdn.microsoft.com/en-us/library/windows/desktop/aa376432(v=vs.85).aspx  
                     $ProtectionState = Get-WmiObject -Namespace ROOT\CIMV2\Security\Microsoftvolumeencryption -Class Win32_encryptablevolume -Filter "DriveLetter = '$DriveLetter'"  
                     write-verbose 'Launching drive encryption.'  
                       
                     $ProtectorKey = $protectionState.ProtectKeyWithTPMAndPIN('ProtectKeyWithTPMAndPin', '', $pin)  
                     Start-Sleep -Seconds 3  
                     $NumericalPasswordReturn = $protectionState.ProtectKeyWithNumericalPassword()  
                       
                     $Return = $protectionState.Encrypt()  
                     $returnCode = $return.returnvalue  
                     switch ($ReturnCode) {  
                            
                          ('0') { $message = 'Operation successfully started.' }  
                          ('2147942487') { $message = 'The EncryptionMethod parameter is provided but is not within the known range or does not match the current Group Policy setting.' }  
                          ('2150694958') { $message = 'No encryption key exists for the volume' }  
                          ('2150694957') { $message = 'The provided encryption method does not match that of the partially or fully encrypted volume.' }  
                          ('2150694942') { $message = 'The volume cannot be encrypted because this computer is configured to be part of a server cluster.' }  
                          ('2150694956') { $message = 'No key protectors of the type Numerical Password are specified. The Group Policy requires a backup of recovery information to Active Directory Domain Services' }  
                          default {  
                               $message = 'An unknown status was returned by the Encryption action.'  
                                 
                          }  
                     }  
                       
                     $Properties = @{ 'ReturnCode' = $ReturnCode; 'ErrorMessage' = $message }  
                     $Return = New-Object psobject -Property $Properties  
                }  
                'GetKeyProtectorIds'{  
                     $BitLocker = Get-WmiObject -Namespace 'Root\cimv2\Security\MicrosoftVolumeEncryption' -Class 'Win32_EncryptableVolume' -Filter "DriveLetter = '$DriveLetter'"  
                     $return = $BitLocker.GetKeyProtectors('0').VolumeKeyProtectorID  
                }  
                'GetEncryptionMethod'{  
                     $BitLocker = Get-WmiObject -Namespace 'Root\cimv2\Security\MicrosoftVolumeEncryption' -Class 'Win32_EncryptableVolume' -Filter "DriveLetter = '$DriveLetter'"  
                     $EncryptMethod = $BitLocker.GetEncryptionMethod().encryptionmethod  
                     switch ($EncryptMethod) {  
                          '0'{ $Return = 'None'; break }  
                          '1'{ $Return = 'AES_128_WITH_DIFFUSER'; break }  
                          '2'{ $Return = 'AES_256_WITH_DIFFUSER'; break }  
                          '3'{ $Return = 'AES_128'; break }  
                          '4'{ $Return = 'AES_256'; break }  
                          '5'{ $Return = 'HARDWARE_ENCRYPTION'; break }  
                          default { $Return = 'UNKNOWN'; break }  
                     }  
                       
                }  
                'GetKeyProtectorTypeAndID'{  
                       
                     $BitLocker = Get-WmiObject -Namespace 'Root\cimv2\Security\MicrosoftVolumeEncryption' -Class 'Win32_EncryptableVolume' -Filter "DriveLetter = '$DriveLetter'"  
                     $ProtectorIds = $BitLocker.GetKeyProtectors('0').volumekeyprotectorID  
                       
                     $return = @()  
                       
                     foreach ($ProtectorID in $ProtectorIds) {  
                            
                          $KeyProtectorType = $BitLocker.GetKeyProtectorType($ProtectorID).KeyProtectorType  
                          $keyType = ''  
                          switch ($KeyProtectorType) {  
                                 
                               '0'{ $Keytype = 'Unknown or other protector type'; break }  
                               '1'{ $Keytype = 'Trusted Platform Module (TPM)'; break }  
                               '2'{ $Keytype = 'External key'; break }  
                               '3'{ $Keytype = 'Numerical password'; break }  
                               '4'{ $Keytype = 'TPM And PIN'; break }  
                               '5'{ $Keytype = 'TPM And Startup Key'; break }  
                               '6'{ $Keytype = 'TPM And PIN And Startup Key'; break }  
                               '7'{ $Keytype = 'Public Key'; break }  
                               '8'{ $Keytype = 'Passphrase'; break }  
                               '9'{ $Keytype = 'TPM Certificate'; break }  
                               '10'{ $Keytype = 'CryptoAPI Next Generation (CNG) Protector'; break }  
                                 
                          } #endSwitch  
                            
                          $Properties = @{ 'KeyProtectorID' = $ProtectorID; 'KeyProtectorType' = $Keytype }  
                          $Return += New-Object -TypeName psobject -Property $Properties  
                     } #EndForeach  
                       
                } #EndGetKeyProtectorType  
                'DeleteKeyProtectors'{  
                     $BitLocker = Get-WmiObject -Namespace 'Root\cimv2\Security\MicrosoftVolumeEncryption' -Class 'Win32_EncryptableVolume' -Filter "DriveLetter = '$DriveLetter'"  
                     $Return = $BitLocker.DeleteKeyProtectors()  
                       
                }  
                'TakeTPMOwnerShip'{  
                     $Tpm.takeOwnership()  
                }  
                'DeleteKeyProtector'{  
                       
                     if ($PSBoundParameters.ContainsKey('ProtectorIDs')) {  
                          $Return = @()  
                          $BitLocker = Get-WmiObject -Namespace 'Root\cimv2\Security\MicrosoftVolumeEncryption' -Class 'Win32_EncryptableVolume' -Filter "DriveLetter = '$DriveLetter'"  
                            
                          foreach ($ProtID in $ProtectorIDs) {  
                               $Return += $BitLocker.DeleteKeyProtector($ProtID)  
                          }  
                     } else {  
                          write-warning 'Could not delete the key protector. Missing ProtectorID parameter.'  
                          $Return = 'Could not delete the key protector. Missing ProtectorID parameter.'  
                            
                     }  
                }  
                'PauseEncryption'{  
                     $BitLocker = Get-WmiObject -Namespace 'Root\cimv2\Security\MicrosoftVolumeEncryption' -Class 'Win32_EncryptableVolume' -Filter "DriveLetter = '$DriveLetter'"  
                     $ReturnCode = $BitLocker.PauseConversion()  
                       
                     switch ($ReturnCode.ReturnValue) {  
                          '0'{ $Return = 'Paused sucessfully.'; break }  
                          '2150694912'{ $Return = 'The volume is locked.'; Break }  
                          default { $Return = 'Uknown return code.'; break }  
                     }  
                }  
                'PauseDecryption'{  
                     $BitLocker = Get-WmiObject -Namespace 'Root\cimv2\Security\MicrosoftVolumeEncryption' -Class 'Win32_EncryptableVolume' -Filter "DriveLetter = '$DriveLetter'"  
                     $ReturnCode = $BitLocker.PauseConversion()  
                       
                     switch ($ReturnCode.ReturnValue) {  
                          '0'{ $Return = 'Paused sucessfully.'; break }  
                          '2150694912'{ $Return = 'The volume is locked.'; Break }  
                          default { $Return = 'Uknown return code.'; break }  
                     }  
                }  
                'Decrytp'{  
                     $BitLocker = Get-WmiObject -Namespace 'Root\cimv2\Security\MicrosoftVolumeEncryption' -Class 'Win32_EncryptableVolume' -Filter "DriveLetter = '$DriveLetter'"  
                     $ReturnCode = $BitLocker.Decrypt()  
                       
                     switch ($ReturnCode.ReturnValue) {  
                          '0'{ $Return = 'Uncryption started successfully.'; break }  
                          '2150694912'{ $Return = 'The volume is locked.'; Break }  
                          '2150694953' { $Return = 'This volume cannot be decrypted because keys used to automatically unlock data volumes are available.'; Break }  
                          default { $Return = 'Uknown return code.'; break }  
                     }  
                       
                }  
                'GetKeyProtectorNumericalPassword'{  
                     $BitLocker = Get-WmiObject -Namespace 'Root\cimv2\Security\MicrosoftVolumeEncryption' -Class 'Win32_EncryptableVolume' -Filter "DriveLetter = '$DriveLetter'"  
                     $Return = @()  
                       
                       
                     $KeyProtectorReturn = $BitLocker.GetKeyProtectorNumericalPassword($VolumeKeyProtectorID)  
                       
                     switch ($KeyProtectorReturn.ReturnValue) {  
                          '0' { $msg = 'The method was successful.' }  
                          '2150694912' { $msg = 'The volume is locked.'; Break }  
                          '2147942487' { $msg = "The VolumeKeyProtectorID parameter does not refer to a key protector of the type 'Numerical Password'."; Break }  
                          '2150694920' { $msg = 'BitLocker is not enabled on the volume. Add a key protector to enable BitLocker.'; Break }  
                          default { $msg = "Unknown return value: $($KeyProtectorReturn.ReturnValue)" }  
                     } #EndSwitch  
                       
                     $Properties = @{ 'KeyProtectorNumericalPassword' = $KeyProtectorReturn.NumericalPassword; 'VolumeKeyProtectorID' = $VolumeKeyProtectorID; 'Message' = $msg }  
                     $Return += New-Object -TypeName psobject -Property $Properties  
                       
                       
                }  
           } #endSwitch  
             
             
           if ($PSBoundParameters.Keys.Count -eq 0) {  
                #Returning info on all drives.  
                write-verbose 'Returning bitlocker main status'  
                $Tpm = Get-WmiObject -Namespace ROOT\CIMV2\Security\MicrosoftTpm -Class Win32_Tpm  
                $BitLocker = Get-WmiObject -Namespace 'Root\cimv2\Security\MicrosoftVolumeEncryption' -Class 'Win32_EncryptableVolume' -Filter "DriveLetter = '$DriveLetter'"  
                  
                #If no TPM module is present  
                if ($tpm) {  
                     $TpmActivated = $tpm.IsActivated().isactivated  
                     $TPMEnabled = $tpm.IsEnabled().isenabled  
                     $TPMOwnerShipAllowed = $Tpm.IsOwnershipAllowed().IsOwnerShipAllowed  
                     $TPMOwned = $Tpm.isowned().isowned  
                       
                }  
                  
                $ProtectorIds = $BitLocker.GetKeyProtectors('0').volumekeyprotectorID  
                $CurrentEncryptionState = BitLockerSAK -GetEncryptionState  
                $EncryptionMethod = BitLockerSAK -GetEncryptionMethod  
                $KeyProtectorTypeAndID = BitLockerSAK -GetKeyProtectorTypeAndID  
                  
                $properties = @{  
                     'IsTPMActivated' = $TpmActivated;`  
                     'IsTPMEnabled' = $TPMEnabled;`  
                     'IsTPMOwnerShipAllowed' = $TPMOwnerShipAllowed;`  
                     'IsTPMOwned' = $TPMOwned;`  
                     'CurrentEncryptionPercentage' = $CurrentEncryptionState.CurrentEncryptionProgress;`  
                     'EncryptionState' = $CurrentEncryptionState.encryptionState; `  
                     'EncryptionMethod' = $EncryptionMethod;`  
                     'KeyProtectorTypesAndIDs' = $KeyProtectorTypeAndID  
                }  
                  
                $Return = New-Object psobject -Property $Properties  
           }  
             
      }  
      End {  
           return $return  
      }  
        
 }  
   
 Function Get-Architecture {  
      #Define Local Variables  
      Set-Variable -Name Architecture -Scope Local -Force  
        
      $Architecture = Get-WmiObject -Class Win32_OperatingSystem | Select-Object OSArchitecture  
      $Architecture = $Architecture.OSArchitecture  
      Return $Architecture  
      #Returns 32-bit or 64-bit  
        
      #Cleanup Local Variables  
      Remove-Variable -Name Architecture -Scope Local -Force  
 }  
   
 function Get-BiosStatus {  
      param ([String]$Option)  
        
      #Declare Local Variables  
      Set-Variable -Name Architecture -Scope Local -Force  
      Set-Variable -Name Argument -Scope Local -Force  
      Set-Variable -Name CCTK -Scope Local -Force  
      Set-Variable -Name Output -Scope Local -Force  
        
      $Architecture = Get-Architecture  
      If ($Architecture -eq "32-bit") {  
           $CCTK = $env:ProgramFiles + "\Dell\Command Configure\X86\cctk.exe"  
      } else {  
           $CCTK = ${env:ProgramFiles(x86)} + "\Dell\Command Configure\X86_64\cctk.exe"  
      }  
      $Argument = "--" + $Option  
      $Output = [string] (& $CCTK $Argument)  
      $Output = $Output.Split('=')  
      Return $Output[1]  
        
      #Cleanup Local Variables  
      Remove-Variable -Name Architecture -Scope Local -Force  
      Remove-Variable -Name Argument -Scope Local -Force  
      Remove-Variable -Name CCTK -Scope Local -Force  
      Remove-Variable -Name Output -Scope Local -Force  
 }  
   
 Function Install-EXE {  
      Param ([String]$DisplayName,  
           [String]$Executable,  
           [String]$Switches)  
        
      #Declare Local Variables  
      Set-Variable -Name ErrCode -Scope Local -Force  
        
      Write-Host "Install"$DisplayName"....." -NoNewline  
      If ((Test-Path $Executable) -eq $true) {  
           $ErrCode = (Start-Process -FilePath $Executable -ArgumentList $Switches -Wait -Passthru).ExitCode  
      } else {  
           $ErrCode = 1  
      }  
      If (($ErrCode -eq 0) -or ($ErrCode -eq 3010)) {  
           Write-Host "Success" -ForegroundColor Yellow  
      } else {  
           Write-Host "Failed with error code "$ErrCode -ForegroundColor Red  
      }  
        
      #Cleanup Local Variables  
      Remove-Variable -Name ErrCode -Scope Local -Force  
 }  
   
 Function Get-BitLockerRecoveryKeyId {  
        
      <#  
      .SYNOPSIS  
      This returns the Bitlocker key protector id.  
        
      .DESCRIPTION  
      The key protectorID is retrived either according to the protector type, or simply all of them.  
        
      .PARAMETER KeyProtectorType  
        
      The key protector type can have one of the following values :  
      *TPM  
      *ExternalKey  
      *NumericPassword  
      *TPMAndPin  
      *TPMAndStartUpdKey  
      *TPMAndPinAndStartUpKey  
      *PublicKey  
      *PassPhrase  
      *TpmCertificate  
      *SID  
        
        
      .EXAMPLE  
        
      Get-BitLockerRecoveryKeyId  
      Returns all the ID's available from all the different protectors.  
   
   .EXAMPLE  
   
     Get-BitLockerRecoveryKeyId -KeyProtectorType NumericPassword  
     Returns the ID(s) of type NumericPassword  
   
   
      .NOTES  
           Version: 1.0  
     Author: Stephane van Gulick  
     Creation date:12.08.2014  
     Last modification date: 12.08.2014  
   
      .LINK  
           www.powershellDistrict.com  
   
      .LINK  
           http://social.technet.microsoft.com/profile/st%C3%A9phane%20vg/  
   
   .LINK  
     #http://msdn.microsoft.com/en-us/library/windows/desktop/aa376441(v=vs.85).aspx  
 #>       
        
      [cmdletBinding()]  
      Param (  
           [Parameter(Mandatory = $false, ValueFromPipeLine = $false)][ValidateSet("Alltypes", "TPM", "ExternalKey", "NumericPassword", "TPMAndPin", "TPMAndStartUpdKey", "TPMAndPinAndStartUpKey", "PublicKey", "PassPhrase", "TpmCertificate", "SID")]$KeyProtectorType  
      )  
        
      $BitLocker = Get-WmiObject -Namespace "Root\cimv2\Security\MicrosoftVolumeEncryption" -Class "Win32_EncryptableVolume"  
        
      switch ($KeyProtectorType) {  
           ("Alltypes") { $Value = "0" }  
           ("TPM") { $Value = "1" }  
           ("ExternalKey") { $Value = "2" }  
           ("NumericPassword") { $Value = "3" }  
           ("TPMAndPin") { $Value = "4" }  
           ("TPMAndStartUpdKey") { $Value = "5" }  
           ("TPMAndPinAndStartUpKey") { $Value = "6" }  
           ("PublicKey") { $Value = "7" }  
           ("PassPhrase") { $Value = "8" }  
           ("TpmCertificate") { $Value = "9" }  
           ("SID") { $Value = "10" }  
           default { $Value = "0" }  
      }  
      $Ids = $BitLocker.GetKeyProtectors($Value).volumekeyprotectorID  
      return $ids  
 }  
   
 Function Remove-RegistryKey {  
      Param ([String]$RegistryKey,  
           [Boolean]$Recurse)  
        
      #Declare Local Variables  
      Set-Variable -Name i -Scope Local -Force  
      Set-Variable -Name RegKey -Scope Local -Force  
      Set-Variable -Name RegistryKey1 -Scope Local -Force  
      Set-Variable -Name tempdrive -Scope Local -Force  
        
      $tempdrive = New-PSDrive -Name HKCR -PSProvider Registry -Root HKEY_CLASSES_ROOT  
      $RegistryKey1 = $RegistryKey.split("\")  
      switch ($RegistryKey1[0]) {  
           "HKEY_CLASSES_ROOT" { $RegistryKey1[0] = "HKCR" }  
           "HKEY_CURRENT_USER" { $RegistryKey1[0] = "HKCU" }  
           "HKEY_LOCAL_MACHINE" { $RegistryKey1[0] = "HKLM" }  
           "HKEY_USERS" { $RegistryKey1[0] = "HKU" }  
           "HKEY_CURRENT_CONFIG" { $RegistryKey1[0] = "HKCC" }  
      }  
      For ($i = 0; $i -lt $RegistryKey1.Count; $i++) {  
           $RegKey = $RegKey + $RegistryKey1[$i]  
           If ($i -eq 0) {  
                $RegKey = $RegKey + ":\"  
           } elseif ($i -ne $RegistryKey1.Count - 1) {  
                $RegKey = $RegKey + "\"  
           } else {  
                $RegKey = $RegKey  
           }  
      }  
      Write-Host "Delete"$RegKey"....." -NoNewline  
      If (Test-Path $RegKey) {  
           If (($Recurse -eq $false) -or ($Recurse -eq $null)) {  
                Remove-Item -Path $RegKey -Force  
           } elseIf ($Recurse -eq $true) {  
                Remove-Item -Path $RegKey -Recurse -Force  
           }  
           if ((Test-Path $RegKey) -eq $false) {  
                Write-Host "Success" -ForegroundColor Yellow  
           } else {  
                Write-Host "Failed" -ForegroundColor Yellow  
           }  
      } else {  
           Write-Host "Not Present" -ForegroundColor Green  
      }  
        
      #Cleanup Local Variables  
      Remove-Variable -Name i -Scope Local -Force  
      Remove-Variable -Name RegKey -Scope Local -Force  
      Remove-Variable -Name RegistryKey1 -Scope Local -Force  
      Remove-Variable -Name tempdrive -Scope Local -Force  
 }  
   
 #Declare Local Variables  
 Set-Variable -Name BitlockerID -Scope Local -Force  
 Set-Variable -Name ManageBDE -Value $env:windir"\System32\manage-bde.exe" -Scope Local -Force  
 Set-Variable -Name Switches -Scope Local -Force  
 Set-Variable -Name TPMActivated -Scope Local -Force  
 Set-Variable -Name TPMEnabled -Scope Local -Force  
 Set-Variable -Name TPMOwnershipAllowed -Scope Local -Force  
   
 cls  
 #Check if TPM is enabled  
 $TPMEnabled = Get-BiosStatus -Option "tpm"  
 Write-Host "TPM Enabled:"$TPMEnabled  
 #Check if TPM is activated  
 $TPMActivated = Get-BiosStatus -Option "tpmactivation"  
 Write-Host "TPM Activated:"$TPMActivated  
 #Check if TPM Ownership is allowed  
 $TPMOwnershipAllowed = BitLockerSAK -IsTPMOwnerShipAllowed  
 Write-Host "TPM Ownership Allowed:"$TPMOwnershipAllowed  
 #Check if TPM is owned  
 $TPMOwned = BitLockerSAK -IsTPMOwned  
 Write-Host "TPM Owned:"$TPMOwned  
 If (($TPMEnabled -eq "on") -and ($TPMActivated -eq "activate") -and ($TPMOwnershipAllowed -eq $true) -and ($TPMOwned -eq $false)) {  
      #Delete Bitlocker GPO registry keys  
      Remove-RegistryKey -RegistryKey "HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\FVE" -Recurse $true  
      Remove-RegistryKey -RegistryKey "HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\TPM" -Recurse $true  
      #Take ownership of TPM  
      $Switches = "-tpm -takeownership" + [char]32 + $BIOSPassword  
      Install-EXE -DisplayName "Take TPM Ownership" -Executable $ManageBDE -Switches $Switches  
      #Enable Bitlocker  
      $Switches = "-on" + [char]32 + $env:HOMEDRIVE + [char]32 + "-recoverypassword"  
      Install-EXE -DisplayName "Enable Bitlocker" -Executable $ManageBDE -Switches $Switches  
      #Execute GPUpdate to re-apply registry keys  
      Install-EXE -DisplayName "GPUpdate" -Executable $env:windir"\System32\gpupdate.exe" -Switches " "  
      #Retrieve numerical password ID  
      $BitlockerID = Get-BitLockerRecoveryKeyId -KeyProtectorType NumericPassword  
      #Backup recovery key to active directory  
      $Switches = "-protectors -adbackup" + [char]32 + $env:HOMEDRIVE + [char]32 + "-id" + [char]32 + $BitlockerID  
      Install-EXE -DisplayName "Backup Recovery Key to AD" -Executable $ManageBDE -Switches $Switches  
 }  
 #Cleanup Local Variables  
 Remove-Variable -Name BitlockerID -Scope Local -Force  
 Remove-Variable -Name ManageBDE -Scope Local -Force  
 Remove-Variable -Name Switches -Scope Local -Force  
 Remove-Variable -Name TPMActivated -Scope Local -Force  
 Remove-Variable -Name TPMEnabled -Scope Local -Force  
 Remove-Variable -Name TPMOwnershipAllowed -Scope Local -Force  
   

Copyright © 2013 Mick's IT Blogs™ is a registered trademark.