Bookmark and Share 

 

Hey, Scripting Guy! Question

Hey, Scripting Guy! I need to be able to create several registry keys, but only if the computer meets certain hardware requirements. I was thinking I could query a bunch of WMI classes and then use a transaction, but I am not sure which hardware WMI classes I should use. Do you have any ideas?

-- NB

 

Hey, Scripting Guy! AnswerHello NB,

Microsoft Scripting Guy Ed Wilson here. I have spent quite a bit of time today tweeting with a member of the Sydney Windows PowerShell users group. The other day, Don Jones was going to be speaking to them while visiting Australia on vacation. The entire experience brought back some excellent memories. Also, Brett, the Microsoft Technical Account Manager (TAM) in Sydney who is my ANZAC biscuit connection, is coming to Seattle for the Microsoft TechReady session. I unfortunately will not be able to attend; I am still unable to fly because of recent ear surgery. Therefore, I spent my spare time finding a co-worker in Charlotte who can pick up my ANZAC biscuits. Therefore, it was a busy day, and mostly centered on Australia. That got me looking through some pictures I took during my last trip down under. Here is one I particularly like of the opera house.

Photo of Sydney Opera House

 

When I was not trying to support my ANZAC biscuit addiction, I did get some time to check the scripter@microsoft.com inbox. NB, if it were me and I did not need specific hardware performance specifications, I would use the WinSAT scores. One thing to keep in mind about WinSAT scores is they are generally created when Windows 7 or Windows Vista are installed (these are the only two platforms that have WinSat). New drivers, such as video drivers, can either enhance or degrade performance, and therefore you should run the WinSAT utility again. The Win32_WinSAT WMI class can be used to retrieve the most recent WinSAT scores for a particular platform. The Win32_WinSAT WMI class is documented on MSDN. Unfortunately, the Win32_WinSAT WMI class does not have an update method—in fact it has no methods at all. There is a command line WinSAT utility, that can be used to update the WinSAT scores—it must be run with administrative permissions. Winsat.exe is documented in the command-line reference on TechNet.

The WriteWinSatToRegistryUseTransaction.ps1 script is similar to the script used in yesterday’s Hey, Scripting Guy! Blog post. The big difference is that in this script, we need to create a new registry key, but we are unable to do so with the Set-Item cmdlet. If the HKCU:\Software\ScriptingGuys\Hardware registry key exists, an error will be generated. It is best to use the Test-Path cmdlet to check to see if the registry key exists. If it does not exist, create it. The syntax is seen here:

if(-not (test-path -Path HKCU:\Software\ScriptingGuys\Hardware))
{
 New-Item -Path HKCU:\Software\ScriptingGuys\Hardware
}

After creating the registry key, if it needs to be created, the remainder of the script is similar to yesterdays. I use several Set-ItemProperty cmdlets to store the WinSat information in the registry. This is seen here.

   Set-ItemProperty -Name CPUScore -Path HKCU:\Software\ScriptingGuys\Hardware `
   -Value ($a.CPUScore).ToString() -useTransaction | out-null
   Set-ItemProperty -Name D3dScore -Path HKCU:\Software\ScriptingGuys\Hardware `
   -Value ($a.D3DScore).ToString() -useTransaction | out-null  
   Set-ItemProperty -Name DiskScore -Path HKCU:\Software\ScriptingGuys\Hardware `
   -Value ($a.DiskScore).ToString() -useTransaction | out-null
   Set-ItemProperty -Name GraphicsScore -Path HKCU:\Software\ScriptingGuys\Hardware `
   -Value ($a.GraphicsScore).ToString() -useTransaction | out-null
   Set-ItemProperty -Name MemoryScore -Path HKCU:\Software\ScriptingGuys\Hardware `
   -Value ($a.MemoryScore).ToString() -useTransaction | out-null
   Set-ItemProperty -Name TimeTaken -Path HKCU:\Software\ScriptingGuys\Hardware `
   -Value ($a.TimeTaken).ToString() -useTransaction | out-null
   Set-ItemProperty -Name WinSPRLevel -Path HKCU:\Software\ScriptingGuys\Hardware `
   -Value ($a.WinSPRLevel).ToString() -useTransaction | out-null

When I was writing the script, I copied the first line and pasted it six times. I then went down the code, one line at a time, changing the registry key names and the WMI property names. I had a Windows PowerShell console open with the results of the following command on the screen so that I could easily make my changes.

PS C:\> gwmi win32_winsat


__GENUS               : 2
__CLASS               : Win32_WinSAT
__SUPERCLASS          :
__DYNASTY             : Win32_WinSAT
__RELPATH             : Win32_WinSAT.TimeTaken="MostRecentAssessment"
__PROPERTY_COUNT      : 8
__DERIVATION          : {}
__SERVER              : MRED1
__NAMESPACE           : root\cimv2
__PATH                : \\MRED1\root\cimv2:Win32_WinSAT.TimeTaken="MostRecentAssessment"
CPUScore              : 7.2
D3DScore              : 4
DiskScore             : 7.1
GraphicsScore         : 4
MemoryScore           : 7.2
TimeTaken             : MostRecentAssessment
WinSATAssessmentState : 1
WinSPRLevel           : 4



PS C:\>

We now need to complete the transaction, and display a status message:


   Complete-Transaction
   "registry Key updated"

The complete WriteWinSatToRegistryUseTransaction.ps1 script is seen here.

WriteWinSatToRegistryUseTransaction.ps1

#requires -version 2.0
Function New-HardwareKey ($computer)
{
 $t = {Start-Transaction}
 &($t)
 Try
  {
   $a = Get-WmiObject -Class win32_WinSat -ComputerName $computer -ErrorAction silentlyContinue
   if(-not (test-path -Path HKCU:\Software\ScriptingGuys\Hardware))
    {
     New-Item -Path HKCU:\Software\ScriptingGuys\Hardware -UseTransaction `
      -ErrorAction stop | out-null
    }
   Set-ItemProperty -Name CPUScore -Path HKCU:\Software\ScriptingGuys\Hardware `
   -Value ($a.CPUScore).ToString() -useTransaction | out-null
   Set-ItemProperty -Name D3dScore -Path HKCU:\Software\ScriptingGuys\Hardware `
   -Value ($a.D3DScore).ToString() -useTransaction | out-null  
   Set-ItemProperty -Name DiskScore -Path HKCU:\Software\ScriptingGuys\Hardware `
   -Value ($a.DiskScore).ToString() -useTransaction | out-null
   Set-ItemProperty -Name GraphicsScore -Path HKCU:\Software\ScriptingGuys\Hardware `
   -Value ($a.GraphicsScore).ToString() -useTransaction | out-null
   Set-ItemProperty -Name MemoryScore -Path HKCU:\Software\ScriptingGuys\Hardware `
   -Value ($a.MemoryScore).ToString() -useTransaction | out-null
   Set-ItemProperty -Name TimeTaken -Path HKCU:\Software\ScriptingGuys\Hardware `
   -Value ($a.TimeTaken).ToString() -useTransaction | out-null
   Set-ItemProperty -Name WinSPRLevel -Path HKCU:\Software\ScriptingGuys\Hardware `
   -Value ($a.WinSPRLevel).ToString() -useTransaction | out-null
   Complete-Transaction
   "registry Key updated"
  }
 Catch [System.Exception]
  {
    Undo-Transaction
    "roll back transaction"
  }
 Finally { "done" }
} #end function New-HardwareKey

New-HardwareKey localHost

When the WriteWinSatToRegistryUseTransaction.ps1 script is run, the registry is modified. This is seen in the following image.

Image of registry modified

 

NB, that is all there is to using transactions to write WMI information to the registry. This concludes our look at using transactions with the registry provider. Tomorrow it is once again time for Quick-Hits Friday.

If you want to know exactly what we will be looking at tomorrow, follow us on Twitter or Facebook. If you have any questions, send e-mail to us at scripter@microsoft.com or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
 

Ed Wilson and Craig Liebendorfer, Scripting Guys