Set-OSInstallData.ps1
<#PSScriptInfo
.GUID d572020a-7583-4867-a845-bb9737b1ecd8 .VERSION 1.0.0.2 .AUTHOR Michael Haken .COMPANYNAME BAMCIS .COPYRIGHT (c) 2016 BAMCIS. All rights reserved. .TAGS WMI InstallData Version .LICENSEURI https://www.bamcisnetworks.net/license .PROJECTURI .ICONURI .EXTERNALMODULEDEPENDENCIES .REQUIREDSCRIPTS .EXTERNALSCRIPTDEPENDENCIES .RELEASENOTES Updated script to use CIM instead of WMI for compatibility with Nano server. #> <# .SYNOPSIS Creates the Win32_OSInstallData WMI class on the local computer or a remote computer. .DESCRIPTION The cmdlet creates a custom WMI class for enumerating information about when an OS image was deployed. It creates a temporary mof file on the SystemDrive and calls mofcomp.exe to add the WMI class. .PARAMETER Increment The sequential increment number for the version during the current quarter. Valid range is 0 to 999. .PARAMETER ComputerName The computer to create the custom WMI classes on. This defaults to localhost. If the target is a remote computer, Invoke-Command is used to execute the underlying function. .PARAMETER TempFilePath Where the temporary mof file is stored, this defaults to %SYSTEMDRIVE%\osinstalldata.mof. .PARAMETER Credential The credential to use to connect to a remote computer. This parameter is ignored if the ComputerName is localhost, ".", or 127.0.0.1. .EXAMPLE Set-OSInstallData Creates the custom WMI class on the local computer with an increment number of 0 which results in 16.1.000 if it was the first quarter of 2016. .EXAMPLE Set-OSInstallData -Increment 12 Creates the custom WMI class on the local computer with an increment number of 12 which results in 16.1.012 if it was the first quarter of 2016. .EXAMPLE Set-OSInstallData -ComputerName server1.contoso.com -Credential (Get-Credential) Creates the custom WMI class on server1.contoso.com with an increment number of 0 which results in 16.1.000 if it was the first quarter of 2016.. .INPUTS System.Int32, System.String, System.String .OUTPUTS None .NOTES AUTHOR: Michael Haken LAST UPDATE: 3/24/2016 #> Param ( [Parameter(Position=0,ValueFromPipeline=$true)] [ValidateScript({$_ -ge 0 -and $_ -le 999})] [int]$Increment = 0, [Parameter(Position=1,ValueFromPipelineByPropertyName=$true)] [string]$ComputerName = "localhost", [Parameter(Position=2,ValueFromPipelineByPropertyName=$true)] [string]$TempFilePath = "$env:SYSTEMDRIVE\OSInstallData.mof", [Parameter(Position=3)] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty ) Function Set-OSInstallDataWMIClass { Param ( [Parameter(Position=0,ValueFromPipeline=$true)] [ValidateScript({$_ -ge 0 -and $_ -le 999})] [int]$Increment = 0, [Parameter(Position=1,ValueFromPipelineByPropertyName=$true)] [string]$RegistryKeyName = "OSInstallData", [Parameter(Position=2,ValueFromPipelineByPropertyName=$true)] [string]$TempFilePath = "$env:SYSTEMDRIVE\OSInstallData.mof" ) Begin { if (!([System.Security.Principal.WindowsPrincipal][System.Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)) { throw "Script must be run with administrator privileges." } if ([System.String]::IsNullOrEmpty($RegistryKeyName)) { $RegistryKeyName = "OSInstallData" } if ([System.String]::IsNullOrEmpty($TempFilePath)) { $TempFilePath = "$env:SYSTEMDRIVE\OSInstallData.mof" } $Path = "HKLM:\SOFTWARE\$RegistryKeyName" $WmiClass = "Win32_OSInstallData" $FileContent = @" #pragma namespace("\\\\.\\root\\cimv2") #PRAGMA AUTORECOVER [DYNPROPS] Class $WmiClass { [key] string KeyName; Uint32 InstallDate; Uint32 VersionMajor; Uint32 VersionMinor; Uint32 VersionIncrement; String DisplayVersion; String DisplayInstallDate; }; [DYNPROPS] Instance of $WmiClass { KeyName="OS Install Data"; [PropertyContext("Local|HKEY_LOCAL_MACHINE\\SOFTWARE\\$RegistryKeyName|InstallDate"),Dynamic,Provider("RegPropProv")] InstallDate; [PropertyContext("Local|HKEY_LOCAL_MACHINE\\SOFTWARE\\$RegistryKeyName|VersionMajor"),Dynamic,Provider("RegPropProv")] VersionMajor; [PropertyContext("Local|HKEY_LOCAL_MACHINE\\SOFTWARE\\$RegistryKeyName|VersionMinor"),Dynamic,Provider("RegPropProv")] VersionMinor; [PropertyContext("Local|HKEY_LOCAL_MACHINE\\SOFTWARE\\$RegistryKeyName|VersionIncrement"),Dynamic,Provider("RegPropProv")] VersionIncrement; [PropertyContext("Local|HKEY_LOCAL_MACHINE\\SOFTWARE\\$RegistryKeyName|DisplayVersion"),Dynamic,Provider("RegPropProv")] DisplayVersion; [PropertyContext("Local|HKEY_LOCAL_MACHINE\\SOFTWARE\\$RegistryKeyName|DisplayInstallDate"),Dynamic,Provider("RegPropProv")] DisplayInstallDate; }; "@ } Process { New-Item -Path $Path -Force | Out-Null [DateTime]$Date = (Get-Date).ToUniversalTime() New-ItemProperty -Path $Path -Name "InstallDate" -Value (Get-Date -Date $Date -UFormat "%s") -PropertyType ([Microsoft.Win32.RegistryValueKind]::DWord) -Force | Out-Null New-ItemProperty -Path $Path -Name "DisplayInstallDate" -Value (Get-Date).ToShortDateString() -PropertyType ([Microsoft.Win32.RegistryValueKind]::String) -Force | Out-Null switch ($Date.Month) { default {$Quarter = 1} 1 {$Quarter = 1} 2 {$Quarter = 1} 3 {$Quarter = 1} 4 {$Quarter = 2} 5 {$Quarter = 2} 6 {$Quarter = 2} 7 {$Quarter = 3} 8 {$Quarter = 3} 9 {$Quarter = 3} 10 {$Quarter = 4} 11 {$Quarter = 4} 12 {$Quarter = 4} } New-ItemProperty -Path $Path -Name "VersionMajor" -Value $Date.Year.ToString().Substring(2) -PropertyType ([Microsoft.Win32.RegistryValueKind]::DWord) -Force | Out-Null New-ItemProperty -Path $Path -Name "VersionMinor" -Value $Quarter -PropertyType ([Microsoft.Win32.RegistryValueKind]::DWord) -Force | Out-Null New-ItemProperty -Path $Path -Name "VersionIncrement" -Value $Increment -PropertyType ([Microsoft.Win32.RegistryValueKind]::DWord) -Force | Out-Null $IncrementString = $Increment.ToString() while ($IncrementString.Length -lt 3) { $IncrementString = "0" + $IncrementString } New-ItemProperty -Path $Path -Name "DisplayVersion" -Value ($Date.Year.ToString().Substring(2) + "." + $Quarter + "." + $IncrementString) -Force | Out-Null Set-Content -Path $TempFilePath -Value $FileContent $Wmi = Get-CimInstance -ClassName $WmiClass -Namespace "root\cimv2" -ErrorAction SilentlyContinue if ($Wmi -ne $null) { Remove-CimInstance -InputObject $Wmi } $InstallType = Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' -Name InstallationType | Select-Object -ExpandProperty InstallationType if ($InstallType -eq "Nano Server") { Start-Process -FilePath ($env:SystemRoot + "\system32\wbem\mofcomp.exe") -ArgumentList @($TempFilePath) -Wait | Out-Null } else { Start-Process -FilePath ($env:SystemRoot + "\system32\wbem\mofcomp.exe") -ArgumentList @($TempFilePath) -WindowStyle Hidden -Wait | Out-Null } $Counter = 0 while ($true) { try { Remove-Item -Path $TempFilePath -ErrorAction Stop -Force | Out-Null break } catch [Exception] { if ($Counter -gt 30) { Write-Warning "Timeout waiting to delete the temporary mof file, delete manually." break } Start-Sleep -Seconds 1 $Counter++ } } } End { Write-Host "WMI class creation complete." } } if ([System.String]::IsNullOrEmpty($TempFilePath)) { $TempFilePath = "$env:SYSTEMDRIVE\OSInstallData.mof" } if (![System.String]::IsNullOrEmpty($ComputerName) -and ($ComputerName.ToLower() -ne "localhost") -and ($ComputerName -ne ".") -and ($ComputerName -ne "127.0.0.1")) { Invoke-Command -ComputerName $ComputerName -ScriptBlock ${function:Set-OSInstallDataWMIClass} -ArgumentList @($Increment,$TempFilePath) -Credential $Credential } else { Set-OSInstallDataWMIClass -Increment $Increment -TempFilePath $TempFilePath } |