Created
February 4, 2026 06:47
-
-
Save scriptingstudio/0c380f4da6a1f251144f3802aabd25b7 to your computer and use it in GitHub Desktop.
SLMGR PowerShell workshop/framework to explore Windows activation management
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #Requires -Version 5 | |
| <# | |
| .SYNOPSIS | |
| Windows Software Licensing Management Tool | |
| .DESCRIPTION | |
| SLMGR PowerShell workshop/framework to explore Windows activation management. | |
| This is a ported slmgr.vbs script. | |
| .NOTES | |
| - Prerelease prototype | |
| - Known issues: | |
| - hidden VBS artifacts of any kind | |
| - error processing | |
| - output chaos | |
| .LINK | |
| - https://wutils.com/wmi/root/cimv2/softwarelicensingservice/#refreshlicensestatus_methods | |
| - https://wutils.com/wmi/root/cimv2/softwarelicensingproduct/#uninstallproductkey_methods | |
| - https://wutils.com/wmi/root/cimv2/softwarelicensingtokenactivationlicense/ | |
| - https://learn.microsoft.com/en-us/windows-server/get-started/activation-slmgr-vbs-options | |
| - https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-powershell-1.0/ee221101(v=msdn.10) | |
| #> | |
| [cmdletbinding(DefaultParameterSetName='LicenseInfo')] | |
| param ( | |
| # Connection options | |
| [parameter(Position=0)] | |
| [alias('computername')][Microsoft.Management.Infrastructure.CimSession] $CimSession, | |
| [PSCredential] $Credential, | |
| # Command options | |
| [alias('aid','appid')][string[]] $ActivationID, | |
| # Global/generic commands | |
| [alias('inpkey')][string] $ipk, | |
| [alias('act')][switch] $ato, | |
| [alias('dstatus')][switch] $dli, | |
| [alias('dstatusall')][switch] $dlv, | |
| [switch] $xpr, | |
| # Advanced commands | |
| [switch] $cpky, | |
| [alias('inslic')][string] $ilc, | |
| [switch] $rilc, | |
| [switch] $rearm, | |
| [string] $rearmapp, # rearm <app> | |
| [string] $rearmsku, # rearm <sku> | |
| [alias('unpkey')][switch] $upk, | |
| [alias('dinstid')][switch] $dti, | |
| [alias('actcid')][string[]] $atp, | |
| # Volume Licensing: Key Management Service (KMS) Client | |
| [alias('sethst')][string[]] $skms, | |
| [alias('remhst')][switch] $ckms, | |
| [string[]] $skmsdomain, | |
| [switch] $ckmsdomain, | |
| [alias('cachst')][switch] $skhc, | |
| [switch] $ckhc, | |
| # Volume Licensing: Token-based Activation | |
| [alias('dtokils')][switch] $lil, | |
| [alias('rtokil')][string[]] $ril, | |
| [alias('dtokcerts')][switch] $ltc, | |
| [alias('tokact')][string[]] $fta, | |
| # Volume Licensing: Key Management Service (KMS) | |
| [alias('setprt')][string] $sprt, | |
| [string] $sai, | |
| [string] $sri, | |
| [switch] $sdns, | |
| [switch] $cdns, | |
| [switch] $spri, | |
| [switch] $cpri, | |
| [alias('actype')][string[]] $acttype, | |
| # Volume Licensing: Active Directory (AD) Activation | |
| [alias('adaonline')][string[]] $adactivationonline, | |
| [alias('adaiid')][string] $adactivationgetiid, | |
| [alias('adacid')][string[]] $adactivationapplycid, | |
| [switch] $aolist, | |
| [string] $delao, | |
| [switch] $raw, # experimental | |
| [switch] $dsi, # experimental; display software info | |
| # Runtime options | |
| [switch] $noformat, # experimental | |
| [switch] $quiet, # experimental | |
| [switch] $whelp, # experimental | |
| [parameter(ParameterSetName='help')] | |
| [switch] $help | |
| ) # param block | |
| # Control panel | |
| $cp = @{ | |
| ComputerName = '.' | |
| IsRemoteComputer = $false | |
| winver = '' | |
| Error = 0 | |
| ConsoleLine = [System.Text.StringBuilder]::new() | |
| resourceDictionary = @{} # obsolete | |
| resourceLoaded = $false # obsolete | |
| output = [ordered]@{} | |
| tabalign = 24 # first column width | |
| # what is it???? | |
| DeterminedDisplayFlags = $false # orphan - from VBS | |
| ShowKmsInfo = $false # orphan - from VBS | |
| ShowKmsClientInfo = $false # orphan - from VBS | |
| ShowTBLInfo = $false # orphan - from VBS | |
| ShowPhoneInfo = $false # orphan - from VBS | |
| gvlk = @{ | |
| w11 = @{ | |
| pro = 'W269N-WFGWX-YVC9B-4J6C9-T83GX' | |
| ent = 'NPPR9-FWDCX-D2C8J-H872K-2YT43' | |
| ltsc = 'M7XTQ-FN8P6-TTKYV-9D4CC-J462D' | |
| } | |
| w8 = @{ | |
| pro = 'GCRJD-8NW9H-F2CDX-CCM8D-9D6T9' | |
| ent = 'MHF9N-XY6XB-WVXMC-BTDCT-MKKG7' | |
| } | |
| w7 = @{ | |
| pro = 'FJ82H-XT6CR-J8D7P-XQJJ2-GPDD4' | |
| ent = '33PXH-7Y6KF-2VJC9-XBBR8-HVTHH' | |
| } | |
| s16 = @{ | |
| std = 'WC2BQ-8NRM3-FDDYY-2BFGV-KHKQY' | |
| dc = 'CB7KF-BWN84-R7R2Y-793K2-8XDDG' | |
| } | |
| s19 = @{ | |
| std = 'N69G4-B89J2-4G8F4-WWYCC-J464C' | |
| dc = 'WMDGN-G9PQG-XVVXX-R3X43-63DFG' | |
| } | |
| s22 = @{ | |
| std = 'VDYBN-27WPP-V4HQT-9VMD4-VMK7H' | |
| dc = 'WX4NM-KYWYW-QJJR4-XV3QB-6VM33' | |
| } | |
| s25 = @{ | |
| std = {'TVRH6-WHNXV-R9WG3-9XRFY-MY832'} | |
| dc = {'D764K-2NDRG-47T6Q-P8T8W-YP6DF'} | |
| } | |
| } | |
| kmshost = @{} | |
| } # control panel | |
| if ($ErrorActionPreference -eq 2) {$ErrorActionPreference = 'Stop'} | |
| function main { | |
| if ($isMacos -or $islinux) {return} | |
| $scriptname = $script:MyInvocation.MyCommand.Name.ToLower() | |
| if ($credential) { | |
| $credential = Get-Credential $credential -ErrorAction Stop | |
| } | |
| $connCredential = if ($credential) {@{credential = $credential}} else {@{}} | |
| $ip = (Test-Connection $env:computername -count 1).IPV4Address.IPAddressToString | |
| $localhost = 'localhost', '.', '127.0.0.1',$ip, $env:COMPUTERNAME, ($env:COMPUTERNAME,$env:USERDNSDOMAIN -join '.') | |
| if ($CimSession.ComputerName -in $localhost) {$CimSession = $null} | |
| $erract = @{ErrorAction = 'Stop'} | |
| $connection = @{ErrorAction = 'Stop'} | |
| if ($ErrorActionPreference -ne 'Stop') { | |
| $erract['ErrorAction'] = $ErrorActionPreference | |
| $connection['ErrorAction'] = $ErrorActionPreference | |
| } | |
| $connection['CimSession'] = | |
| if ($CimSession.name) {$CimSession} | |
| elseif ($CimSession.ComputerName) { | |
| New-CimSession -ComputerName $_.ComputerName @connCredential -ErrorAction Stop | |
| $cp.Credential = $connCredential['credential'] | |
| $cp.ComputerName = $_.ComputerName | |
| } else { | |
| New-CimSession -Name slmlocal @connCredential -ErrorAction Stop | |
| $cp.ComputerName = $env:computername | |
| } | |
| # Update predefined strings | |
| $PartialProductKeyNonNullWhereClause = "ApplicationID='$WindowsAppId' AND PartialProductKey<>NULL" | |
| $error.clear() | |
| #try { | |
| Invoke-InputRouter | |
| #} catch {} | |
| #finally {} | |
| $error | |
| if ($connection['CimSession'] -is [CimSession]) { | |
| $null = Remove-CimSession $connection['CimSession'] | |
| } | |
| $null = Get-CimSession -Name slmlocal -ErrorAction 0 | Remove-CimSession | |
| if ($cp.output.count) { | |
| Write-Host "`nTo explore output data see variable `$slmgrdata" | |
| $global:slmgrdata = [pscustomobject]$cp.output | |
| } | |
| } # END main | |
| function Invoke-InputRouter { | |
| if ($help -or $script:MyInvocation.BoundParameters.count -eq 0) { | |
| Show-Help | |
| return | |
| } | |
| # Emulation of parameter sets | |
| if ($script:MyInvocation.BoundParameters.count -gt 2) { | |
| Write-Warning 'Parameter set cannot be resolved using the specified named parameters.' | |
| return | |
| } | |
| $computername1 = if ($cp.IsRemoteComputer) {$connection['cimsession'].ComputerName} else {$env:COMPUTERNAME} | |
| switch ($script:MyInvocation.BoundParameters.keys) { | |
| 'ilc' { # $L_optInstallLicense | |
| Install-License $script:PSBoundParameters[$_] | |
| break | |
| } | |
| 'ipk' { #$L_optInstallProductKey | |
| Install-ProductKey $script:PSBoundParameters[$_] | |
| break | |
| } | |
| 'upk' { #$L_optUninstallProductKey | |
| Uninstall-ProductKey $ActivationID | |
| break | |
| } | |
| 'dti' { # $L_optDisplayIID | |
| DisplayIID $ActivationID | |
| break | |
| } | |
| 'ato' { #$L_optActivateProduct | |
| ActivateProduct $ActivationID | |
| break | |
| } | |
| 'atp' { # $L_optPhoneActivateProduct | |
| PhoneActivateProduct $script:PSBoundParameters[$_] | |
| break | |
| } | |
| 'dli' { #$L_optDisplayInformation | |
| Get-LicenseInfo $ActivationID $false | |
| break | |
| } | |
| 'dlv' { #$L_optDisplayInformationVerbose | |
| Get-LicenseInfo $ActivationID $true | |
| break | |
| } | |
| 'cpky' { #$L_optClearPKeyFromRegistry | |
| if ($script:PSBoundParameters[$_]) {Clear-PKeyRegistry} | |
| break | |
| } | |
| 'rilc' { #$L_optReinstallLicenses | |
| if ($script:PSBoundParameters[$_]) {Reinstall-License} | |
| break | |
| } | |
| 'rearm' { #$L_optReArmWindows | |
| if ($script:PSBoundParameters[$_]) {ReArmWindows} | |
| break | |
| } | |
| 'rearmapp' { #$L_optReArmApplication | |
| ReArmApp $script:PSBoundParameters[$_] | |
| break | |
| } | |
| 'rearmsku' { #$L_optReArmSku | |
| ReArmSku $script:PSBoundParameters[$_] | |
| break | |
| } | |
| 'xpr' { #$L_optExpirationDatime | |
| Show-ExpirationDate $ActivationID | |
| break | |
| } | |
| 'skms' { #$L_optSetKmsName | |
| SetKmsMachineName $script:PSBoundParameters[$_] | |
| break | |
| } | |
| 'ckms' { #$L_optClearKmsName | |
| ClearKms $ActivationID | |
| break | |
| } | |
| $L_optSetKmsLookupDomain { # skmsdomain | |
| SetKmsLookupDomain $script:PSBoundParameters[$_] | |
| break | |
| } | |
| $L_optClearKmsLookupDomain { # ckmsdomain | |
| ClearKmsLookupDomain $ActivationID | |
| break | |
| } | |
| $L_optSetKmsHostCaching { # skhc | |
| SetHostCachingDisable $false | |
| break | |
| } | |
| $L_optClearKmsHostCaching { # ckhc | |
| SetHostCachingDisable $true | |
| break | |
| } | |
| $L_optSetActivationInterval { # sai | |
| SetActivationInterval $script:PSBoundParameters[$_] | |
| break | |
| } | |
| $L_optSetRenewalInterval { # sri | |
| SetRenewalInterval $script:PSBoundParameters[$_] | |
| break | |
| } | |
| $L_optSetKmsListenPort { # sprt | |
| SetKmsListenPort $script:PSBoundParameters[$_] | |
| break | |
| } | |
| $L_optSetDNS { # sdns | |
| SetDnsPublishingDisabled $false | |
| break | |
| } | |
| $L_optClearDNS { # cdns | |
| SetDnsPublishingDisabled $true | |
| break | |
| } | |
| $L_optSetNormalPriority { # spri | |
| SetDnsPublishingDisabled $true | |
| break | |
| } | |
| $L_optClearNormalPriority { # cpri | |
| SetKmsLowPriority $true | |
| break | |
| } | |
| $L_optSetVLActivationType { # acttype | |
| SetVLActivationType $script:PSBoundParameters[$_] | |
| break | |
| } | |
| $L_optListInstalledILs { # lil | |
| Get-TkaLicense | |
| break | |
| } | |
| $L_optRemoveInstalledIL { # ril | |
| Uninstall-TkaLicense $script:PSBoundParameters[$_] | |
| break | |
| } | |
| $L_optListTkaCerts { # ltc | |
| Get-TkaCertificate | |
| break | |
| } | |
| $L_optForceTkaActivation { # fta | |
| TkaActivate $script:PSBoundParameters[$_] | |
| break | |
| } | |
| $L_optADGetIID { # adactivationonline | |
| ADGetIID $script:PSBoundParameters[$_] | |
| break | |
| } | |
| $L_optADActivate { # adactivationgetiid | |
| ADActivateOnline $script:PSBoundParameters[$_] | |
| break | |
| } | |
| $L_optADApplyCID { # adactivationapplycid | |
| ADActivatePhone $script:PSBoundParameters[$_] | |
| break | |
| } | |
| $L_optADListAOs { # aolist | |
| if ($script:PSBoundParameters[$_]) {ADListActivationobjects} | |
| break | |
| } | |
| $L_optADDeleteAO { # delao | |
| ADDeleteActivationobjects $script:PSBoundParameters[$_] | |
| break | |
| } | |
| 'raw' { | |
| Show-LSClass | |
| break | |
| } | |
| 'dsi' { | |
| Get-SoftwareInfo | |
| break | |
| } | |
| default { | |
| if ($_ -eq 'activationId') { | |
| Write-Warning 'This parameter applies to -ato, -xpr, -upk, -dti, -ckms, or -ckmsdomain options' | |
| } | |
| } | |
| } # switch | |
| } # END Invoke-InputRouter | |
| #region GLOBAL OPTIONS | |
| # Display all information for /dlv and /dli | |
| # If you add need to access new properties through CIM you must add them to the | |
| # queries for service/object. Be sure to check that the object properties in Get-LicenseInfo | |
| # are requested for function/methods such as Test-PrimaryWindowsSKU and DisplayKMSClientInformation. | |
| #DisplayAllInformation | |
| function Get-LicenseInfo ([string]$cmdValue, $bVerbose) { | |
| $productKeyFound = $false | |
| if ($cmdValue -eq '*') {$cmdValue = 'all'} | |
| $ServiceSelectClause = | |
| "SubscriptionType, SubscriptionStatus, SubscriptionEdition, SubscriptionExpiry, KeyManagementServiceListeningPort, KeyManagementServiceDnsPublishing, RemainingWindowsReArmCount, KeyManagementServiceLowPriority, ClientMachineId, KeyManagementServiceHostCaching, Version" | |
| $ProductSelectClause = | |
| "$ProductIsPrimarySkuSelectClause, ProductKeyID, ProductKeyChannel, OfflineInstallationId, ProcessorURL, MachineURL, UseLicenseURL, ProductKeyURL, ValidationURL, GracePeriodRemaining, LicenseStatus, LicenseStatusReason, EvaluationEndDate, VLRenewalInterval, VLActivationInterval, KeyManagementServiceLookupDomain, KeyManagementServiceMachine, KeyManagementServicePort, DiscoveredKeyManagementServiceMachineName, DiscoveredKeyManagementServiceMachinePort, DiscoveredKeyManagementServiceMachineIpAddress, KeyManagementServiceProductKeyID, TokenActivationILID, TokenActivationILVID, TokenActivationGrantNumber, TokenActivationCertificateThumbprint, TokenActivationAdditionalInfo, TrustedTime, ADActivationobjectName, ADActivationobjectDN, ADActivationCsvlkPid, ADActivationCsvlkSkuId, VLActivationTypeEnabled, VLActivationType, IAID, AutomaticVMActivationHostMachineName, AutomaticVMActivationLastActivationTime, AutomaticVMActivationHostDigitalPid2" | |
| if ($bVerbose) { | |
| $ProductSelectClause = "RemainingAppReArmCount, RemainingSkuReArmCount, RemainingWindowsReArmCount, $ProductSelectClause" | |
| } | |
| $licService = Get-LicensingService $ServiceSelectClause | |
| if ($bVerbose) { # TODO: display different way | |
| Write-Host $L_MsgServiceVersion $licService.Version | |
| } else { | |
| $cp.tabalign = 20 | |
| } | |
| Write-Host | |
| $IterSelectClause,$filter = if ($cmdValue -eq 'all') { | |
| $ProductSelectClause | |
| $EmptyWhereClause | |
| } elseif (-not $cmdValue) { | |
| '*' #$ProductIsPrimarySkuSelectClause | |
| "ApplicationID='$WindowsAppId' AND PartialProductKey<>NULL" | |
| } else { | |
| $ProductIsPrimarySkuSelectClause | |
| "ApplicationID='$WindowsAppId' AND PartialProductKey<>NULL AND ID='$cmdValue'" | |
| } | |
| Get-ProductList $IterSelectClause $filter | Foreach-Object { | |
| if (-not $_) {return} | |
| Write-FormatLine 'Computer Name' $cp.ComputerName | |
| $product = $_ | |
| $SLActID = $product.ID | |
| # Display information if: | |
| # parm = "all" or | |
| # ActID = parm or | |
| # default to current ActID (parm = "" and IsPrimaryWindowsSKU is 1 or 2) | |
| $iIsPrimaryWindowsSku = Test-PrimaryWindowsSKU $product | |
| $pDescription = $product.Description | |
| $bUseDefault = $false | |
| $bShowSkuInformation = $false | |
| if (-not $cmdValue -and $iIsPrimaryWindowsSku -in 1,2) { | |
| $bUseDefault = $true | |
| $bShowSkuInformation = $true | |
| } | |
| if (-not $cmdValue -and ($product.LicenseIsAddon -and $product.PartialProductKey)) { | |
| $bShowSkuInformation = $true | |
| } | |
| if ($cmdValue -eq 'all' -or $cmdValue -eq $SLActID) { | |
| $bShowSkuInformation = $true | |
| } | |
| if ($bShowSkuInformation) { | |
| $productKeyFound = $true | |
| # If the user didn't specify anything and we are showing the default case, warn them if this can't be verified as the primary SKU | |
| if ($bUseDefault -and $iIsPrimaryWindowsSku -eq 2) { | |
| Write-UndeterminedOperationWarning $product | |
| } | |
| Write-FormatLine | |
| #Write-FormatLine 'Computer Name' $computername1 | |
| Write-FormatLine $L_MsgProductName $product.Name | |
| Write-FormatLine $L_MsgProductDesc $pDescription | |
| if ($product.TokenActivationAdditionalInfo) { | |
| Write-FormatLine $L_MsgTkaInfoAdditionalInfo.replace("%MOREINFO%",$product.TokenActivationAdditionalInfo) | |
| } | |
| $bKmsServer = IsKmsServer $pDescription | |
| $bKmsClient = IsKmsClient $pDescription | |
| $bTBL = IsTBL $pDescription | |
| $bAVMA = IsAVMA $pDescription | |
| if ($bVerbose) { | |
| Write-FormatLine $L_MsgActID $SLActID | |
| Write-FormatLine $L_MsgAppID $product.ApplicationID | |
| Write-FormatLine $L_MsgPID4 $product.ProductKeyID | |
| Write-FormatLine $L_MsgChannel $product.ProductKeyChannel | |
| Write-FormatLine $L_MsgInstallationID $product.OfflineInstallationId | |
| if (-not $bKmsClient -and -not $bAVMA) { | |
| # Note that we are re-using the UseLicenseURL for the Product Activation | |
| # URL for down-level compatibility reasons | |
| if ($product.ProductKeyURL) { | |
| Write-FormatLine $L_MsgPKeyCertUrl $product.ProductKeyURL | |
| } | |
| if ($product.ProcessorURL) { | |
| Write-FormatLine $L_MsgProcessorCertUrl $product.ProcessorURL | |
| } | |
| if ($product.MachineURL) { | |
| Write-FormatLine $L_MsgMachineCertUrl $product.MachineURL | |
| } | |
| if ($product.UseLicenseURL) { | |
| Write-FormatLine $L_MsgUseLicenseCertUrl $product.UseLicenseURL | |
| } | |
| if ($product.ValidationURL) { | |
| Write-FormatLine $L_MsgValidationUrl $product.ValidationURL | |
| } | |
| } | |
| } # verbose | |
| if ($product.PartialProductKey) { | |
| Write-FormatLine $L_MsgPartialPKey $product.PartialProductKey | |
| } else { | |
| Write-FormatLine $L_MsgErrorLicenseNotInUse | |
| } | |
| $ls = $product.LicenseStatus | |
| if ($ls -eq 0) { | |
| Write-FormatLine2 $L_MsgLicenseStatusUnlicensed_1 | |
| } | |
| elseif ($ls -eq 1) { | |
| Write-FormatLine2 $L_MsgLicenseStatusLicensed_1 | |
| $gpMin = $product.GracePeriodRemaining | |
| if ($gpMin -ne 0) { | |
| $gpDay = [int]([timespan]::FromMinutes($gpMin)).TotalDays | |
| $msgOutput = if ($bTBL) { | |
| $L_MsgLicenseStatusTBL_1.replace("%MINUTE%", $gpMin) | |
| } elseif ($bAVMA) { | |
| $L_MsgLicenseStatusAVMA_1.replace("%MINUTE%", $gpMin) | |
| } else { | |
| $L_MsgLicenseStatusVL_1.replace("%MINUTE%", $gpMin) | |
| } | |
| Write-FormatLine2 $msgOutput.replace("%DAY%", $gpDay) | |
| } | |
| } | |
| elseif ($ls -in 2,3,4,6) { | |
| Write-FormatLine2 $L_MsgLicenseStatusInitialGrace_1 | |
| $gpMin = $product.GracePeriodRemaining | |
| $gpDay = [int]([timespan]::FromMinutes($gpMin)).TotalDays | |
| Write-FormatLine2 $L_MsgLicenseStatusTimeRemaining.replace("%MINUTE%", $gpMin).replace("%DAY%", $gpDay) | |
| } | |
| elseif ($ls -eq 5) { | |
| Write-FormatLine2 $L_MsgLicenseStatusNotification_1 | |
| $lcr = [string]::format('{0:X}', $product.LicenseStatusReason) | |
| $msgOutput = if ($product.LicenseStatusReason -eq $HR_SL_E_NOT_GENUINE) { | |
| $L_MsgNotificationErrorReasonNonGenuine.replace("%ERRCODE%", $lcr) | |
| } elseif ($product.LicenseStatusReason -eq $HR_SL_E_GRACE_TIME_EXPIRED) { | |
| $L_MsgNotificationErrorReasonExpiration.replace("%ERRCODE%", $lcr) | |
| } else { | |
| $L_MsgNotificationErrorReasonOther.replace("%ERRCODE%", $lcr) | |
| } | |
| Write-FormatLine2 $msgOutput | |
| } | |
| else { | |
| Write-FormatLine2 $L_MsgLicenseStatusUnknown | |
| } | |
| if ($ls -and $bVerbose) { | |
| if ($null -ne $product.EvaluationEndDate -and $product.EvaluationEndDate.year -ge [datetime]::Now.year) { | |
| Write-FormatLine $L_MsgLicenseStatusEvalEndData $product.EvaluationEndDate | |
| } | |
| } | |
| if ($bVerbose) { | |
| if ($product.ApplicationId -eq $WindowsAppId) { | |
| Write-FormatLine2 $L_MsgRemainingWindowsRearmCount.replace("%COUNT%", $licService.RemainingWindowsReArmCount) | |
| } else { | |
| Write-FormatLine2 $L_MsgRemainingAppRearmCount.replace("%COUNT%", $product.RemainingAppReArmCount) | |
| } | |
| Write-FormatLine2 $L_MsgRemainingSkuRearmCount.replace("%COUNT%", $product.RemainingSkuReArmCount) | |
| if ($product.TrustedTime) { | |
| Write-FormatLine $L_MsgCurrentTrustedTime $product.TrustedTime | |
| } | |
| } | |
| # KMS client properties | |
| if ($bKmsClient) { | |
| if ($product.VLActivationTypeEnabled -eq 1) { | |
| Write-FormatLine2 $L_MsgVLActivationTypeAD | |
| } elseif ($product.VLActivationTypeEnabled -eq 2) { | |
| Write-FormatLine2 $L_MsgVLActivationTypeKMS | |
| } elseif ($product.VLActivationTypeEnabled -eq 3) { | |
| Write-FormatLine2 $L_MsgVLActivationTypeToken | |
| } else { | |
| Write-FormatLine2 $L_MsgVLActivationTypeAll | |
| } | |
| If ($product.VLActivationType -eq 1) { | |
| DisplayADClientInformation $licService $product # single | |
| } elseif (IsTokenActivated $product) { # single | |
| DisplayTkaClientInformation $licService $product # single | |
| } elseif ($ls -ne 1) { | |
| Write-FormatLine2 $L_MsgPleaseActivateRefreshKMSInfo | |
| } else { | |
| DisplayKMSClientInformation $licService $product # single but long | |
| } | |
| } | |
| if ($bKmsServer -or $iIsPrimaryWindowsSku -in 1,2) { | |
| DisplayKMSInformation $licService $product # single but long | |
| } | |
| if ($bAVMA) { | |
| $AVMAId = $product.IAID | |
| if ($AVMAId) { | |
| Write-FormatLine $L_MsgAVMAID $AVMAId | |
| } else { | |
| Write-FormatLine $L_MsgAVMAID $L_MsgNotAvailable | |
| } | |
| DisplayAVMAClientInformation $product # single but long | |
| } | |
| # We should stop processing if we aren't processing All and either we were told to process a single entry only or we found the primary SKU | |
| if ($cmdValue -ne 'all' -and $cmdValue -eq $SLActID) { | |
| return # no need to continue | |
| } | |
| Write-FormatLine0 | |
| } | |
| } # products | |
| If ($licService.SubscriptionType -ne 120) { | |
| Write-FormatLine $L_MsgSubscriptionEdition $licService.SubscriptionEdition | |
| If ($licService.SubscriptionType -eq 0) { | |
| Write-FormatLine $L_MsgSubscriptionType $L_MsgSubscriptionTypeUBS | |
| } elseif ($licService.SubscriptionType -eq 1) { | |
| Write-FormatLine $L_MsgSubscriptionType $L_MsgSubscriptionTypeDBS | |
| } elseif ($licService.SubscriptionType -eq 2) { | |
| Write-FormatLine $L_MsgSubscriptionType $L_MsgSubscriptionTypeABS | |
| } else { | |
| Write-FormatLine $L_MsgSubscriptionType $L_MsgSubscriptionTypeUnknown | |
| } | |
| If ($licService.SubscriptionStatus -eq 120) { | |
| Write-FormatLine $L_MsgSubscriptionStatus $L_MsgSubscriptionStatusExpired | |
| } elseif ($licService.SubscriptionStatus -eq 100) { | |
| Write-FormatLine $L_MsgSubscriptionStatus $L_MsgSubscriptionStatusDisabled | |
| } elseif ($licService.SubscriptionStatus -eq 1) { | |
| Write-FormatLine $L_MsgSubscriptionStatus $L_MsgSubscriptionStatusActive | |
| } else { | |
| Write-FormatLine $L_MsgSubscriptionStatus $L_MsgSubscriptionStatusNotActive | |
| } | |
| If ($licService.SubscriptionExpiry -And $licService.SubscriptionExpiry -ne "<unspecified>") { | |
| Write-FormatLine $L_MsgSubscriptionExpiry $licService.SubscriptionExpiry | |
| } else { | |
| Write-FormatLine $L_MsgSubscriptionExpiry $L_MsgSubscriptionExpiryUnknown | |
| } | |
| } | |
| if (-not $productKeyFound) { | |
| Write-FormatLine2 $L_MsgErrorPKey | |
| } | |
| } # END Get-LicenseInfo | |
| # CheckProductForCommand | |
| function Test-ProductForCommand ($product, [string]$ActivationID) { | |
| if ($ActivationID) {$product.ID -eq $ActivationID} | |
| else { | |
| $product.ApplicationId -eq $WindowsAppId -and -not $product.LicenseIsAddon | |
| } | |
| } # END Test-ProductForCommand | |
| # UninstallProductKey | |
| function Uninstall-ProductKey ([string]$ActivationID) { | |
| $kmsServerFound = $uninstallDone = $false | |
| $Version = (Get-LicensingService "Version").Version | |
| Get-ProductList "$ProductIsPrimarySkuSelectClause, ProductKeyID" $PartialProductKeyNonNullWhereClause | Foreach-Object { | |
| if (-not $_) {return} | |
| $product = $_ | |
| $pDescription = $product.Description | |
| $commandEnabled = Test-ProductForCommand $product $ActivationID | |
| if ($commandEnabled) { | |
| $iIsPrimaryWindowsSku = Test-PrimaryWindowsSKU $product | |
| if ($ActivationID -eq "" -and $iIsPrimaryWindowsSku -eq 2) { | |
| Write-UndeterminedOperationWarning $product | |
| } | |
| $result = Invoke-CimMethod -MethodName UninstallProductKey -CimClass $product.psbase.CimClass @connection | |
| # Uninstalling a product key could change Windows licensing state. | |
| # Since the service determines if it can shut down and when is the next start time | |
| # based on the licensing state we should reconsume the licenses here. | |
| $result = Invoke-CimMethod -MethodName RefreshLicenseStatus -CimClass $product.psbase.CimClass @connection | |
| # For Windows (i.e. if no activationID specified), always | |
| # ensure that product-key for primary SKU is uninstalled | |
| if ($ActivationID -or $iIsPrimaryWindowsSku -eq 1) { | |
| $uninstallDone = $true | |
| } | |
| Write-FormatLine2 $L_MsgUninstalledPKey | |
| # Check whether a ActID belongs to KMS server. | |
| # Do this for all ActID other than one whose pkey is being uninstalled | |
| } elseif (IsKmsServer $pDescription) { | |
| $kmsServerFound = $true | |
| } | |
| if ($kmsServerFound -and $uninstallDone) { | |
| break | |
| } | |
| } | |
| if ($kmsServerFound) { | |
| # Set KMS version in the registry (both 64 and 32 bit locations) | |
| $lRet = SetRegistryStr $HKEY_LOCAL_MACHINE $SLKeyPath "KeyManagementServiceVersion" $Version | |
| if ($lRet) { | |
| QuitWithError $lRet | |
| } | |
| $lRet = SetRegistryStr $HKEY_LOCAL_MACHINE $SLKeyPath32 "KeyManagementServiceVersion" $Version | |
| if ($lRet) { | |
| QuitWithError $lRet | |
| } | |
| } else { | |
| # Clear the KMS version from the registry (both 64 and 32 bit locations) | |
| $lRet = DeleteRegistryValue $HKEY_LOCAL_MACHINE $SLKeyPath "KeyManagementServiceVersion" | |
| if ($lRet -ne 0 -And $lRet -ne 2) { | |
| QuitWithError $lRet | |
| } | |
| $lRet = DeleteRegistryValue $HKEY_LOCAL_MACHINE $SLKeyPath32 "KeyManagementServiceVersion" | |
| if ($lRet -ne 0 -And $lRet -ne 2) { | |
| QuitWithError $lRet | |
| } | |
| } | |
| if (-not $uninstallDone) { | |
| Write-FormatLine2 $L_MsgErrorPKey | |
| } | |
| } # END Uninstall-ProductKey | |
| # InstallProductKey | |
| function Install-ProductKey ([string]$ProductKey) { | |
| if ($ProductKey -match '^%') { | |
| $ProductKey = Get-Gvlk $ProductKey | |
| if (-not $ProductKey) { | |
| Write-Warning 'Invalid version/edition specified.' | |
| return | |
| } | |
| } | |
| $licsvc = Get-CimClass -ClassName 'SoftwareLicensingService' -Namespace 'root\cimv2' -ErrorAction 0 | |
| $Version = (Get-LicensingService "Version").Version | |
| $result = Invoke-CimMethod -MethodName InstallProductKey -CimClass $licsvc -Arguments @{ProductKey=$ProductKey} @connection | |
| # Installing a product key could change Windows licensing state. | |
| # Since the service determines if it can shut down and when is the next start time | |
| # based on the licensing state we should reconsume the licenses here. | |
| $result = Invoke-CimMethod -MethodName RefreshLicenseStatus -CimClass $licsvc @connection | |
| $bIsKMS = $false | |
| Get-ProductList $ProductIsPrimarySkuSelectClause $PartialProductKeyNonNullWhereClause | Foreach-Object { | |
| if (-not $_ -or $bIsKMS) {return} | |
| $product = $_ | |
| $pDescription = $product.Description | |
| $iIsPrimaryWindowsSku = Test-PrimaryWindowsSKU $product | |
| if ($iIsPrimaryWindowsSku -eq 2) { | |
| Write-UndeterminedOperationWarning $product | |
| } | |
| If (IsKmsServer $pDescription) { | |
| $bIsKMS = $true | |
| return | |
| } | |
| } | |
| if ($bIsKMS -eq $true) { | |
| # Set KMS version in the registry (64 and 32 bit versions) | |
| $lRet = SetRegistryStr $HKEY_LOCAL_MACHINE $SLKeyPath "KeyManagementServiceVersion" $Version | |
| if ($lRet -ne 0) { | |
| QuitWithError $lRet | |
| } | |
| If (Test-RegistryKey $HKEY_LOCAL_MACHINE $SLKeyPath32) { | |
| $lRet = SetRegistryStr $HKEY_LOCAL_MACHINE $SLKeyPath32 "KeyManagementServiceVersion" $Version | |
| if ($lRet -ne 0) { | |
| QuitWithError $lRet | |
| } | |
| } | |
| } else { | |
| # Clear the KMS version in the registry (64 and 32 bit versions) | |
| $lRet = DeleteRegistryValue $HKEY_LOCAL_MACHINE $SLKeyPath "KeyManagementServiceVersion" | |
| if ($lRet -notin 0,2,5) { | |
| QuitWithError $lRet | |
| } | |
| $lRet = DeleteRegistryValue $HKEY_LOCAL_MACHINE $SLKeyPath32 "KeyManagementServiceVersion" | |
| if ($lRet -notin 0,2,5) { | |
| QuitWithError $lRet | |
| } | |
| } | |
| Write-FormatLine2 $L_MsgInstalledPKey.replace("%PKEY%", $ProductKey) | |
| } # END | |
| function ActivateProduct ([string]$ActivationID) { | |
| $foundAtLeastOneKey = $false | |
| $cimClass = Get-CimClass -ClassName 'SoftwareLicensingService' -Namespace 'root\cimv2' -ErrorAction 0 | |
| Get-ProductList "$ProductIsPrimarySkuSelectClause, LicenseStatus, VLActivationTypeEnabled" $PartialProductKeyNonNullWhereClause | Foreach-Object { | |
| if (-not $_) {return} | |
| $product = $_ | |
| $commandEnabled = Test-ProductForCommand $product $ActivationID | |
| if ($commandEnabled) { | |
| $iIsPrimaryWindowsSku = Test-PrimaryWindowsSKU $product | |
| if ($ActivationID -eq "" -and $iIsPrimaryWindowsSku -eq 2) { | |
| Write-UndeterminedOperationWarning $product | |
| } | |
| # This routine does not perform token-based activation. | |
| # If configured for TA, then show message to user. | |
| if ($product.VLActivationTypeEnabled -eq 3) { | |
| Write-FormatLine2 $L_MsgTokenBasedActivationMustBeDone | |
| break | |
| } | |
| $msgOutput = $L_MsgActivating.replace("%PRODUCTNAME%", $product.Name).replace("%PRODUCTID%", $product.ID) | |
| Write-FormatLine0 $msgOutput | |
| # Avoid using a MAK activation count up unless needed | |
| if ($product.Description -notmatch "MAK" -or $product.LicenseStatus -ne 1) { | |
| $result = Invoke-CimMethod -MethodName Activate -CimClass $product.psbase.CimClass @connection | |
| $result = Invoke-CimMethod -MethodName RefreshLicenseStatus -CimClass $cimClass @connection | |
| } | |
| DisplayActivatedStatus $product | |
| $foundAtLeastOneKey = $true | |
| if ($ActivationID -or $iIsPrimaryWindowsSku -eq 1) { | |
| break | |
| } | |
| } | |
| } | |
| if ($foundAtLeastOneKey) {return} | |
| Write-FormatLine2 $L_MsgErrorProductNotFound | |
| } # END | |
| function PhoneActivateProduct ([string]$CID, [string]$ActivationID) { | |
| $foundAtLeastOneKey = $false | |
| $cimClass = Get-CimClass -ClassName 'SoftwareLicensingService' -Namespace 'root\cimv2' -ErrorAction 0 | |
| Get-ProductList "$ProductIsPrimarySkuSelectClause, OfflineInstallationId, LicenseStatus, LicenseStatusReason" $PartialProductKeyNonNullWhereClause | Foreach-Object { | |
| if (-not $_) {return} | |
| $product = $_ | |
| $commandEnabled = Test-ProductForCommand $product $ActivationID | |
| if ($commandEnabled) { | |
| $iIsPrimaryWindowsSku = Test-PrimaryWindowsSKU $product | |
| if (-not $ActivationID -and $iIsPrimaryWindowsSku -eq 2) { | |
| Write-UndeterminedOperationWarning $product | |
| } | |
| $result = Invoke-CimMethod -MethodName DepositOfflineConfirmationId -CimClass $product.psbase.CimClass -Arguments @{InstallationId=$product.OfflineInstallationId; ConfirmationId=$CID} @connection | |
| $result = Invoke-CimMethod -MethodName RefreshLicenseStatus -CimClass $cimClass @connection | |
| if ($product.LicenseStatus -eq 1) { | |
| Write-FormatLine $L_MsgConfID.replace("%ACTID%", $product.ID) | |
| } elseif ($product.LicenseStatus -eq 4) { | |
| Write-FormatLine $L_MsgErrorText_8 $L_MsgErrorText_11 | |
| } elseif ($product.LicenseStatus -eq 5 -and $product.LicenseStatusReason -eq $HR_SL_E_NOT_GENUINE) { | |
| Write-FormatLine2 $L_MsgErrorText_8 $L_MsgErrorText_12 | |
| } elseif ($product.LicenseStatus -eq 6) { | |
| Write-FormatLine2 $L_MsgActivated | |
| Write-FormatLine2 $L_MsgLicenseStatusExtendedGrace_1 | |
| } else { | |
| Write-FormatLine2 $L_MsgActivated_Failed | |
| } | |
| $foundAtLeastOneKey = $true | |
| if ($ActivationID -or $iIsPrimaryWindowsSku -eq 1) { | |
| break | |
| } | |
| } | |
| } | |
| if ($foundAtLeastOneKey) {return} | |
| Write-FormatLine2 $L_MsgErrorProductNotFound | |
| } # END | |
| function DisplayIID ([string]$ActivationID) { | |
| $cp.tabalign = 15 # ??? | |
| $foundAtLeastOneKey = $false | |
| $plist = Get-ProductList "$ProductIsPrimarySkuSelectClause, OfflineInstallationId" $PartialProductKeyNonNullWhereClause | |
| foreach ($product in $plist) { | |
| $commandEnabled = Test-ProductForCommand $product $ActivationID | |
| if ($commandEnabled) { | |
| $iIsPrimaryWindowsSku = Test-PrimaryWindowsSKU $product | |
| if ($ActivationID -eq "" -and $iIsPrimaryWindowsSku -eq 2) { | |
| Write-UndeterminedOperationWarning $product | |
| } | |
| Write-FormatLine $L_MsgInstallationID $product.OfflineInstallationId | |
| $foundAtLeastOneKey = $true | |
| if ($ActivationID -or $iIsPrimaryWindowsSku -eq 1) { | |
| return | |
| } | |
| } | |
| } | |
| if ($foundAtLeastOneKey) { | |
| Write-FormatLine0 | |
| Write-FormatLine2 $L_MsgPhoneNumbers | |
| } else { | |
| Write-FormatLine2 $L_MsgErrorProductNotFound | |
| } | |
| } # END | |
| # single call | |
| function DisplayActivatingSku ($product) { | |
| Write-FormatLine2 $L_MsgActivating.replace("%PRODUCTNAME%", $product.Name).replace("%PRODUCTID%", $product.ID) | |
| } # END | |
| function DisplayActivatedStatus ($product) { | |
| if ($product.LicenseStatus -eq 1) { | |
| Write-FormatLine2 $L_MsgActivated | |
| } elseif ($product.LicenseStatus -eq 4) { | |
| Write-FormatLine2 $L_MsgErrorText_8 $L_MsgErrorText_11 | |
| } elseif ($product.LicenseStatus -eq 5 -and $product.LicenseStatusReason -eq $HR_SL_E_NOT_GENUINE) { | |
| Write-FormatLine $L_MsgErrorText_8 $L_MsgErrorText_12 | |
| } elseif ($product.LicenseStatus -eq 6) { | |
| Write-FormatLine2 $L_MsgActivated | |
| Write-FormatLine2 $L_MsgLicenseStatusExtendedGrace_1 | |
| } else { | |
| Write-FormatLine2 $L_MsgActivated_Failed | |
| } | |
| } # END | |
| function DisplayKMSInformation ($licService, $product) { | |
| $objProductKMSValues = Invoke-ProductQuery "IsKeyManagementServiceMachine, KeyManagementServiceCurrentCount, KeyManagementServiceTotalRequests, KeyManagementServiceFailedRequests, KeyManagementServiceUnlicensedRequests, KeyManagementServiceLicensedRequests, KeyManagementServiceOOBGraceRequests, KeyManagementServiceOOTGraceRequests, KeyManagementServiceNonGenuineGraceRequests, KeyManagementServiceNotificationRequests" "id = '$($product.ID)'" | |
| if ($objProductKMSValues.IsKeyManagementServiceMachine -eq 0) {return} | |
| Write-FormatLine | |
| Write-FormatLine2 $L_MsgKmsEnabled | |
| Write-FormatLine " " $L_MsgKmsCurrentCount $objProductKMSValues.KeyManagementServiceCurrentCount | |
| $dwValue = $licService.KeyManagementServiceListeningPort | |
| if (0 -eq $dwValue) { | |
| Write-FormatLine " " $L_MsgKmsListeningOnPort $DefaultPort | |
| } else { | |
| Write-FormatLine " " $L_MsgKmsListeningOnPort $dwValue | |
| } | |
| if ($licService.KeyManagementServiceDnsPublishing) { | |
| Write-FormatLine " " $L_MsgKmsDnsPublishingEnabled | |
| } else { | |
| Write-FormatLine " " $L_MsgKmsDnsPublishingDisabled | |
| } | |
| if ($licService.KeyManagementServiceLowPriority) { | |
| Write-FormatLine " " $L_MsgKmsPriLow | |
| } else { | |
| Write-FormatLine " " $L_MsgKmsPriNormal | |
| } | |
| if ($objProductKMSValues.KeyManagementServiceTotalRequests) { | |
| Write-FormatLine | |
| Write-FormatLine2 $L_MsgKmsCumulativeRequestsFromClients | |
| Write-FormatLine " " $L_MsgKmsTotalRequestsRecieved $objProductKMSValues.KeyManagementServiceTotalRequests | |
| Write-FormatLine " " $L_MsgKmsFailedRequestsReceived $objProductKMSValues.KeyManagementServiceFailedRequests | |
| Write-FormatLine " " $L_MsgKmsRequestsWithStatusUnlicensed $objProductKMSValues.KeyManagementServiceUnlicensedRequests | |
| Write-FormatLine " " $L_MsgKmsRequestsWithStatusLicensed $objProductKMSValues.KeyManagementServiceLicensedRequests | |
| Write-FormatLine " " $L_MsgKmsRequestsWithStatusInitialGrace $objProductKMSValues.KeyManagementServiceOOBGraceRequests | |
| Write-FormatLine " " $L_MsgKmsRequestsWithStatusLicenseExpiredOrHwidOot $objProductKMSValues.KeyManagementServiceOOTGraceRequests | |
| Write-FormatLine " " $L_MsgKmsRequestsWithStatusNonGenuineGrace $objProductKMSValues.KeyManagementServiceNonGenuineGraceRequests | |
| Write-FormatLine " " $L_MsgKmsRequestsWithStatusNotification $objProductKMSValues.KeyManagementServiceNotificationRequests | |
| } | |
| } # END | |
| function DisplayADClientInformation ($licService, $product) { | |
| Write-FormatLine0 | |
| Write-FormatLine2 $L_MsgVLMostrecentActivationInfo | |
| Write-FormatLine2 $L_MsgADInfo | |
| Write-FormatLine " " $L_MsgADInfoAOName $product.ADActivationobjectName | |
| Write-FormatLine " " $L_MsgADInfoAODN $product.ADActivationobjectDN | |
| Write-FormatLine " " $L_MsgADInfoExtendedPid $product.ADActivationCsvlkPid | |
| Write-FormatLine " " $L_MsgADInfoActID $product.ADActivationCsvlkSkuId | |
| } # END | |
| function DisplayTkaClientInformation ($licService, $product) { | |
| Write-FormatLine | |
| Write-FormatLine2 $L_MsgVLMostrecentActivationInfo | |
| Write-FormatLine2 $L_MsgTkaInfo | |
| Write-FormatLine " " $L_MsgTkaInfoILID.replace("%ILID%", $product.TokenActivationILID) | |
| Write-FormatLine " " $L_MsgTkaInfoILVID.replace("%ILVID%", $product.TokenActivationILVID) | |
| Write-FormatLine " " $L_MsgTkaInfoGrantNo.replace("%GRANTNO%", $product.TokenActivationGrantNumber) | |
| Write-FormatLine " " $L_MsgTkaInfoThumbprint.replace("%THUMBPRINT%", $product.TokenActivationCertificateThumbprint) | |
| } # END | |
| function DisplayKMSClientInformation ($licService, $product) { | |
| Write-FormatLine | |
| Write-FormatLine2 $L_MsgVLMostrecentActivationInfo | |
| Write-FormatLine2 $L_MsgKmsInfo | |
| Write-FormatLine " " $L_MsgCmid $licService.ClientMachineID | |
| $KmsLookupDomain = $product.KeyManagementServiceLookupDomain | |
| if ($KmsLookupDomain) { | |
| $bKmsLookupDomain = $true | |
| Write-FormatLine " " $L_MsgKmsLookupDomain $KmsLookupDomain | |
| } | |
| $KmsName = $product.KeyManagementServiceMachine | |
| if ($KmsName) { | |
| $bFixedKms = $true | |
| $portNumber = $product.KeyManagementServicePort | |
| if ($portNumber -eq 0) { | |
| $portNumber = $DefaultPort | |
| } | |
| Write-FormatLine " " $L_MsgRegisteredKmsName "${KmsName}:$portNumber" | |
| } else { | |
| $KmsName = $product.DiscoveredKeyManagementServiceMachineName | |
| $portNumber = $product.DiscoveredKeyManagementServiceMachinePort | |
| If (-not $KmsName -or -not $portNumber) { | |
| Write-FormatLine " " $L_MsgKmsFromDnsUnavailable | |
| } else { | |
| Write-FormatLine " " $L_MsgKmsFromDns "${KmsName}:$portNumber" | |
| } | |
| } | |
| $ipAddress = $product.DiscoveredKeyManagementServiceMachineIpAddress | |
| If (-not $ipAddress) { | |
| Write-FormatLine " " $L_MsgKmsIpAddressUnavailable | |
| } else { | |
| Write-FormatLine " " $L_MsgKmsIpAddress $ipAddress | |
| } | |
| Write-FormatLine " " $L_MsgKmsPID4 $product.KeyManagementServiceProductKeyID | |
| $msgOutput = $L_MsgActivationInterval.replace("%INTERVAL%", $product.VLActivationInterval) | |
| Write-FormatLine " " $msgOutput | |
| $msgOutput = $L_MsgRenewalInterval.replace("%INTERVAL%", $product.VLRenewalInterval) | |
| Write-FormatLine " " $msgOutput | |
| if ($licService.KeyManagementServiceHostCaching) { | |
| Write-FormatLine " " $L_MsgKmsHostCachingEnabled | |
| } else { | |
| Write-FormatLine " " $L_MsgKmsHostCachingDisabled | |
| } | |
| if ($bKmsLookupDomain -and $bFixedKms) { | |
| Write-FormatLine | |
| Write-FormatLine2 $L_MsgKmsUseMachineNameOverrides.replace("%KMS%", "${KmsName}:$portNumber") | |
| } | |
| } # END | |
| function DisplayAVMAClientInformation ($product) { | |
| $bHostName = -not [string]::IsNullOrEmpty($product.AutomaticVMActivationHostMachineName) | |
| $bFiletime = $product.AutomaticVMActivationLastActivationTime -is [datetime] | |
| $Pid2 = $product.AutomaticVMActivationHostDigitalPid2 | |
| $bPid = -not [string]::IsNullOrEmpty($Pid2) | |
| if ($bHostName -or $bFiletime -or $bPid) { | |
| Write-FormatLine | |
| Write-FormatLine2 $L_MsgVLMostrecentActivationInfo | |
| Write-FormatLine2 $L_MsgAVMAInfo | |
| if ($bHostName) { | |
| Write-FormatLine " " $L_MsgAVMAHostMachineName $product.AutomaticVMActivationHostMachineName | |
| } else { | |
| Write-FormatLine " " $L_MsgAVMAHostMachineName $L_MsgNotAvailable | |
| } | |
| if ($bFiletime) { | |
| Write-FormatLine " " $L_MsgAVMALastActTime $product.AutomaticVMActivationLastActivationTime | |
| } else { | |
| Write-FormatLine " " $L_MsgAVMALastActTime $L_MsgNotAvailable | |
| } | |
| if ($bPid) { | |
| Write-FormatLine " " $L_MsgAVMAHostPid2 $Pid2 | |
| } else { | |
| Write-FormatLine " " $L_MsgAVMAHostPid2 $L_MsgNotAvailable | |
| } | |
| } | |
| } # END | |
| # OutputIndeterminateOperationWarning | |
| function Write-UndeterminedOperationWarning ($product) { | |
| Write-FormatLine2 $L_MsgUndeterminedPrimaryKeyOperation | |
| Write-FormatLine2 $L_MsgUndeterminedOperationFormat.replace("%PRODUCTDESCRIPTION%", $product.Description).replace("%PRODUCTID%", $product.ID) | |
| } # END Write-UndeterminedOperationWarning | |
| # ClearPKeyFromRegistry | |
| function Clear-PKeyRegistry { | |
| $licsvc = Get-CimClass -ClassName 'SoftwareLicensingService' -Namespace 'root\cimv2' -ErrorAction 0 | |
| $result = Invoke-CimMethod -MethodName ClearProductKeyFromRegistry -CimClass $licsvc @connection | |
| if ($result -and $result.ReturnValue -eq 0) { | |
| Write-FormatLine2 $L_MsgClearedPKey | |
| } | |
| } # END Clear-PKeyRegistry | |
| # InstallLicenseFiles | |
| function Install-LicenseFile ([string]$ParentDirectory) { | |
| Get-ChildItem -LiteralPath $ParentDirectory -File -Filter "*.xrm-ms" -Force -ErrorAction 0 | | |
| ForEach-Object { | |
| Install-License $_.FullName -notest | |
| } | |
| } # END Install-LicenseFile | |
| # ReinstallLicenses | |
| function Reinstall-License { | |
| Write-FormatLine2 $L_MsgReinstallingLicenses | |
| $OemFolder = $env:SystemRoot,"system32\oem" -join '\' | |
| $SppTokensFolder = $env:SystemRoot, "system32\spp\tokens" -join '\' | |
| Install-LicenseFile $SppTokensFolder | |
| Get-ChildItem -LiteralPath $SppTokensFolder -Recurse -Directory -Force -ErrorAction 0 | ForEach-Object { | |
| Install-LicenseFile $_.FullName | |
| } | |
| Install-LicenseFile $OemFolder | |
| Get-ChildItem -LiteralPath $OemFolder -Recurse -Directory -Force -ErrorAction 0 | | |
| ForEach-Object { | |
| Install-LicenseFile $_.FullName | |
| } | |
| Write-FormatLine2 $L_MsgLicensesReinstalled | |
| } # END Reinstall-License | |
| function ReArmWindows { | |
| $licsvc = Get-CimClass -ClassName 'SoftwareLicensingService' -Namespace 'root\cimv2' -ErrorAction 0 | |
| $result = Invoke-CimMethod -MethodName ReArmWindows -CimClass $licsvc @connection | |
| if ($result -and $result.returnValue -eq 0) { | |
| Write-FormatLine2 $L_MsgRearm_1 | |
| Write-FormatLine2 $L_MsgRearm_2 | |
| } else {} | |
| } # END | |
| function ReArmApp ([string]$SLID) { | |
| $licsvc = Get-CimClass -ClassName 'SoftwareLicensingService' -Namespace 'root\cimv2' -ErrorAction 0 | |
| $result = Invoke-CimMethod -MethodName ReArmApp -CimClass $licsvc -Arguments @{ApplicationId=$SLID} @connection | |
| if ($result -and $result.returncode -eq 0) { | |
| Write-FormatLine2 $L_MsgRearm_1 | |
| } else {} | |
| } # END | |
| function ReArmSku ([string]$SLID) { | |
| $bSkuFound = $false | |
| foreach ($product in (Get-ProductList "ID" "ID = '$SLID'")) { | |
| if ($SLID -eq $product.ID) { | |
| $bSkuFound = $true | |
| #$result = $product | Invoke-CimMethod -MethodName ReArmsku @connection | |
| $result = Invoke-CimMethod -MethodName ReArmsku -CimClass $product.psbase.CimClass @connection | |
| if ($result -and $result.returncode -eq 0) { | |
| Write-FormatLine2 $L_MsgRearm_1 | |
| } else {} | |
| continue | |
| } | |
| } | |
| if (-not $bSkuFound) { | |
| Write-FormatLine2 $L_MsgErrorProductNotFound | |
| } | |
| } # END | |
| # ExpirationDatime | |
| function Show-ExpirationDate ($ActivationID) { | |
| $WhereClause = if ($ActivationId) { | |
| "ID = '$ActivationID' AND $PartialProductKeyNonNullWhereClause" | |
| } else { | |
| #"ApplicationId = '$WindowsAppId'" | |
| $PartialProductKeyNonNullWhereClause | |
| } | |
| #$WhereClause = "$WhereClause AND $PartialProductKeyNonNullWhereClause" | |
| $bFound = $false | |
| $msgOutput = $null | |
| Get-ProductList "$ProductIsPrimarySkuSelectClause, LicenseStatus, GracePeriodRemaining" $WhereClause | Foreach-Object { | |
| if (-not $_) {return} | |
| $product = $_ | |
| $SLActID = $product.ID | |
| $ls = $product.LicenseStatus | |
| $graceRemaining = $product.GracePeriodRemaining | |
| $graceEnd = [datetime]::now.AddMinutes($graceRemaining).ToString() | |
| $bFound = $true | |
| $iIsPrimaryWindowsSku = Test-PrimaryWindowsSKU $product | |
| if (-not $ActivationID -and $iIsPrimaryWindowsSku -eq 2) { | |
| Write-UndeterminedOperationWarning $product | |
| } | |
| $msgOutput = if ($ls -eq 0) { | |
| $L_MsgLicenseStatusUnlicensed | |
| } elseif ($ls -eq 1) { | |
| if ($graceRemaining) { | |
| $bTBL = IsTBL $product.Description | |
| $bAVMA = IsAVMA $product.Description | |
| if ($bTBL) { | |
| $L_MsgLicenseStatusTBL.replace("%ENDDATE%", $graceEnd) | |
| } elseif ($bAVMA) { | |
| $L_MsgLicenseStatusAVMA.replace("%ENDDATE%", $graceEnd) | |
| } else { | |
| $L_MsgLicenseStatusVL.replace("%ENDDATE%", $graceEnd) | |
| } | |
| } else { | |
| $L_MsgLicenseStatusLicensed | |
| } | |
| } elseif ($ls -eq 2) { | |
| $L_MsgLicenseStatusInitialGrace.replace("%ENDDATE%", $graceEnd) | |
| } elseif ($ls -eq 3) { | |
| $L_MsgLicenseStatusAdditionalGrace.replace("%ENDDATE%", $graceEnd) | |
| } elseif ($ls -eq 4) { | |
| $L_MsgLicenseStatusNonGenuineGrace.replace("%ENDDATE%", $graceEnd) | |
| } elseif ($ls -eq 5) { | |
| $L_MsgLicenseStatusNotification | |
| } elseif ($ls -eq 6) { | |
| $L_MsgLicenseStatusExtendedGrace.replace("%ENDDATE%", $graceEnd) | |
| } | |
| if ($msgOutput) { | |
| $cp.tabalign = 34 | |
| Write-FormatLine $product.Name $msgOutput | |
| } | |
| } # products | |
| if ($bFound -and -not $msgOutput) { | |
| Write-FormatLine2 $L_MsgErrorPKey | |
| } | |
| } # END Show-ExpirationDate | |
| #endregion GLOBAL OPTIONS | |
| #region Volume license service/client management | |
| # VBS artifact | |
| function QuitIfErrorRestoreKmsName ($target, [string]$KmsName) { | |
| if ($cp.error) { | |
| if (-not $KmsName) { | |
| $target.ClearKeyManagementServiceMachine | |
| $result = Invoke-CimMethod -MethodName ClearKeyManagementServiceMachine -CimClass $target.psbase.CimClass @connection | |
| } else { | |
| $result = Invoke-CimMethod -MethodName SetKeyManagementServiceMachine -CimClass $target.psbase.CimClass -arguments @{MachineName=$KmsName} @connection | |
| } | |
| #ShowError $L_MsgErrorText_8 $cp.error | |
| Exit-Script $cp.error | |
| } | |
| } # END | |
| function GetKmsClientobjectByActivationID ([string]$ActivationID) { | |
| if (-not $ActivationID) { | |
| Get-LicensingService "Version, $KMSClientLookupClause" | |
| } else { | |
| $target = Get-ProductList "ID, $KMSClientLookupClause" "ID='$ActivationID'" | |
| if ($target) { | |
| $target | |
| } else { | |
| Write-FormatLine2 $L_MsgErrorActivationID.replace("%ActID%", $ActivationID) | |
| } | |
| } | |
| } # END | |
| function SetKmsMachineName ([string[]]$kmsparameters) { | |
| $KmsNamePort, $ActivationID = $kmsparameters | |
| $target = GetKmsClientobjectByActivationID $ActivationID | |
| if ($target) { | |
| $KmsName,$KmsPort = $KmsNamePort.split(':',2).trim('[]') | |
| $KmsNamePrev = $objTtargetarget.KeyManagementServiceMachine | |
| if ($KmsName) { | |
| $result = Invoke-CimMethod -MethodName SetKeyManagementServiceMachine -CimClass $target.psbase.CimClass -arguments @{MachineName=$KmsName} @connection | |
| } | |
| if ($KmsPort) { | |
| $result = Invoke-CimMethod -MethodName SetKeyManagementServicePort -CimClass $target.psbase.CimClass @connection | |
| #QuitIfErrorRestoreKmsName $target $KmsNamePrev | |
| } else { | |
| $result = Invoke-CimMethod -MethodName ClearKeyManagementServicePort -CimClass $target.psbase.CimClass @connection | |
| #QuitIfErrorRestoreKmsName $target $KmsNamePrev | |
| } | |
| Write-FormatLine2 $L_MsgKmsNameSet.replace("%KMS%", $KmsNamePort) | |
| if ($target.KeyManagementServiceLookupDomain) { | |
| Write-FormatLine2 $L_MsgKmsUseMachineNameOverrides.replace("%KMS%",$KmsNamePort) | |
| } | |
| } | |
| } # END | |
| function ClearKms ([string]$ActivationID) { | |
| $target = GetKmsClientobjectByActivationID $ActivationID | |
| if ($target) { | |
| $result = Invoke-CimMethod -MethodName ClearKeyManagementServiceMachine -CimClass $target.psbase.CimClass @connection | |
| $result = Invoke-CimMethod -MethodName ClearKeyManagementServicePort -CimClass $target.psbase.CimClass @connection | |
| Write-FormatLine2 $L_MsgKmsNameCleared | |
| if ($target.KeyManagementServiceLookupDomain) { | |
| Write-FormatLine2 $L_MsgKmsUseLookupDomain.replace("%FQDN%",$target.KeyManagementServiceLookupDomain) | |
| } | |
| } | |
| } # END | |
| function SetKmsLookupDomain ([string[]]$kmsparameters) { | |
| $KmsLookupDomain, $ActivationID = $kmsparameters | |
| $target = GetKmsClientobjectByActivationID $ActivationID | |
| if ($target) { | |
| $result = Invoke-CimMethod -MethodName SetKeyManagementServiceLookupDomain -CimClass $target.psbase.CimClass -Arguments @{LookupDomain=$KmsLookupDomain} @connection | |
| Write-FormatLine2 $L_MsgKmsLookupDomainSet.replace("%FQDN%", $KmsLookupDomain) | |
| if ($target.KeyManagementServiceMachine) { | |
| $kms = $target.KeyManagementServiceMachine,$target.KeyManagementServicePort -join ':' | |
| Write-FormatLine2 $L_MsgKmsUseMachineNameOverrides.replace("%KMS%", $kms) | |
| } | |
| } | |
| } # END | |
| function ClearKmsLookupDomain ([string]$ActivationID) { | |
| $target = GetKmsClientobjectByActivationID $ActivationID | |
| if ($target) { | |
| $result = Invoke-CimMethod -MethodName ClearKeyManagementServiceLookupDomain -CimClass $target.psbase.CimClass @connection | |
| Write-FormatLine2 $L_MsgKmsLookupDomainCleared | |
| if ($target.KeyManagementServiceMachine) { | |
| $kms = $target.KeyManagementServiceMachine, $target.KeyManagementServicePort -join ':' | |
| Write-FormatLine2 $L_MsgKmsUseMachineName.replace("%KMS%", $kms) | |
| } | |
| } | |
| } # END | |
| function SetHostCachingDisable ($disable) { | |
| $licsvc = Get-CimClass -ClassName 'SoftwareLicensingService' -Namespace 'root\cimv2' -ErrorAction 0 | |
| $result = Invoke-CimMethod -MethodName DisableKeyManagementServiceHostCaching -CimClass $licsvc -Arguments @{DisableCaching=$disable} @connection | |
| if ($disable) { | |
| Write-FormatLine2 $L_MsgKmsHostCachingDisabled | |
| } else { | |
| Write-FormatLine2 $L_MsgKmsHostCachingEnabled | |
| } | |
| } # END | |
| function SetActivationInterval ([int]$interval) { | |
| if ($interval -lt 0) { | |
| Write-FormatLine2 $L_MsgInvalidDataError | |
| return | |
| } | |
| $licsvc = Get-CimClass -ClassName 'SoftwareLicensingService' -Namespace 'root\cimv2' -ErrorAction 0 | |
| $kmsFlag = $null | |
| Get-ProductList "ID, IsKeyManagementServiceMachine" $PartialProductKeyNonNullWhereClause | Foreach-Object { | |
| if (-not $_) {return} | |
| $product = $_ | |
| $kmsFlag = $product.IsKeyManagementServiceMachine | |
| if ($kmsFlag -eq 1) { | |
| $result = Invoke-CimMethod -MethodName SetVLActivationInterval -CimClass $licsvc -Arguments @{ActivationInterval=$interval} @connection | |
| Write-FormatLine2 $L_MsgActivationSet.replace("%ACTIVATION%", $interval) | |
| Write-FormatLine2 $L_MsgWarningKmsReboot | |
| return | |
| } | |
| } | |
| if ($kmsFlag -ne 1) { | |
| Write-FormatLine2 $L_MsgWarningActivation | |
| } | |
| } # END | |
| function SetRenewalInterval ([int]$interval) { | |
| if ($interval -lt 0) { | |
| Write-FormatLine2 $L_MsgInvalidDataError | |
| return | |
| } | |
| $licsvc = Get-CimClass -ClassName 'SoftwareLicensingService' -Namespace 'root\cimv2' -ErrorAction 0 | |
| $kmsFlag = $null | |
| Get-ProductList "ID, IsKeyManagementServiceMachine" $PartialProductKeyNonNullWhereClause | Foreach-Object { | |
| $product = $_ | |
| $kmsFlag = $product.IsKeyManagementServiceMachine | |
| if ($kmsFlag) { | |
| $result = Invoke-CimMethod -MethodName SetVLRenewalInterval -CimClass $licsvc -Arguments @{RenewalInterval=$interval} @connection | |
| Write-FormatLine2 $L_MsgRenewalSet.replace("%RENEWAL%", $interval) | |
| Write-FormatLine2 $L_MsgWarningKmsReboot | |
| return | |
| } | |
| } | |
| if ($kmsFlag -ne 1) { | |
| Write-FormatLine2 $L_MsgWarningRenewal | |
| } | |
| } # END | |
| function SetKmsListenPort ($portNumber) { | |
| $licsvc = Get-CimClass -ClassName 'SoftwareLicensingService' -Namespace 'root\cimv2' -ErrorAction 0 | |
| $kmsFlag = $null | |
| Get-ProductList "ID, IsKeyManagementServiceMachine" $PartialProductKeyNonNullWhereClause | Foreach-Object { | |
| if (-not $_) {return} | |
| $product = $_ | |
| $kmsFlag = $product.IsKeyManagementServiceMachine | |
| if ($kmsFlag) { | |
| $result = Invoke-CimMethod -MethodName SetKeyManagementServiceListeningPort -CimClass $licsvc -Arguments @{PortNumber=$portNumber} @connection | |
| Write-FormatLine2 $L_MsgKmsPortSet.replace("%PORT%", $portNumber) | |
| Write-FormatLine2 $L_MsgWarningKmsReboot | |
| return | |
| } | |
| } | |
| if ($kmsFlag -ne 1) { | |
| Write-FormatLine2 $L_MsgWarningKmsPort | |
| } | |
| } # END | |
| function SetDnsPublishingDisabled ($enable) { | |
| $licsvc = Get-CimClass -ClassName 'SoftwareLicensingService' -Namespace 'root\cimv2' -ErrorAction 0 | |
| $kmsFlag = $null | |
| Get-ProductList "ID, IsKeyManagementServiceMachine" $PartialProductKeyNonNullWhereClause | Foreach-Object { | |
| $product = $_ | |
| $kmsFlag = $product.IsKeyManagementServiceMachine | |
| if ($kmsFlag) { | |
| $result = Invoke-CimMethod -MethodName DisableKeyManagementServiceDnsPublishing -CimClass $licsvc -Arguments @{DisablePublishing=[int]$enable} @connection | |
| if ($enable) { | |
| Write-FormatLine2 $L_MsgKmsDnsPublishingDisabled | |
| } else { | |
| Write-FormatLine2 $L_MsgKmsDnsPublishingEnabled | |
| } | |
| Write-FormatLine2 $L_MsgWarningKmsReboot | |
| break | |
| } | |
| } | |
| if ($kmsFlag -ne 1) { | |
| Write-FormatLine2 $L_MsgKmsDnsPublishingWarning | |
| } | |
| } # END | |
| function SetKmsLowPriority ($enable) { | |
| $licsvc = Get-CimClass -ClassName 'SoftwareLicensingService' -Namespace 'root\cimv2' -ErrorAction 0 | |
| $kmsFlag = $null | |
| $plist = Get-ProductList "ID, IsKeyManagementServiceMachine" $PartialProductKeyNonNullWhereClause | |
| if ($plist) { | |
| $kmsFlag = $plist.IsKeyManagementServiceMachine | |
| if ($kmsFlag) { | |
| $result = Invoke-CimMethod -MethodName EnableKeyManagementServiceLowPriority -CimClass $licsvc -Arguments @{EnableLowPriority=$enable} @connection | |
| if ($enable) { | |
| Write-FormatLine2 $L_MsgKmsPriSetToLow | |
| } else { | |
| Write-FormatLine2 $L_MsgKmsPriSetToNormal | |
| } | |
| Write-FormatLine2 $L_MsgWarningKmsReboot | |
| } | |
| } | |
| if ($kmsFlag -ne 1) { | |
| Write-FormatLine2 $L_MsgWarningKmsPri | |
| } | |
| } # END | |
| function SetVLActivationType ($vlparameters) { | |
| enum ActType {All; AD; KMS; Token} | |
| $valueType, $ActivationID = $vlparameters | |
| if (-not $valueType) {$valueType = 0} | |
| $actval = try {[int]([ActType]$valueType).value__} catch { | |
| Write-FormatLine2 $L_MsgInvalidDataError | |
| return | |
| } | |
| $Target = GetKmsClientobjectByActivationID $ActivationID | |
| if ($Target) { | |
| if ($actval -gt 0) { | |
| $Target.SetVLActivationTypeEnabled($actval) | |
| $result = Invoke-CimMethod -MethodName SetVLActivationTypeEnabled -CimClass $Target.psbase.CimClass -Arguments @{ActivationType=$actval} @connection | |
| } else { | |
| $Target.ClearVLActivationTypeEnabled | |
| $result = Invoke-CimMethod -MethodName ClearVLActivationTypeEnabled -CimClass $Target.psbase.CimClass @connection | |
| } | |
| Write-FormatLine2 $L_MsgVLActivationTypeSet | |
| } | |
| } # END | |
| #endregion Volume license service/client management | |
| #region Token-based Activation Commands | |
| function IsTokenActivated ($product) { | |
| $ILVID = $product.TokenActivationILVID | |
| ($null -ne $product -and $ILVID -ne 0xFFFFFFFF) | |
| } # END | |
| # TkaListILs | |
| function Get-TkaLicense { | |
| $listCount = 0 | |
| $tkl = Get-CimInstance -ClassName $TkaLicenseClass @connection | |
| if ($null -ne $tkl) { | |
| Write-FormatLine2 $L_MsgTkaLicenses | |
| Write-FormatLine0 | |
| } | |
| foreach ($license in $tkl) { | |
| Write-FormatLine2 $L_MsgTkaLicenseHeader.replace("%ILID%" , $license.ILID ).replace("%ILVID%", $license.ILVID) | |
| Write-FormatLine " " $L_MsgTkaLicenseILID.replace("%ILID%", $license.ILID) | |
| Write-FormatLine " " $L_MsgTkaLicenseILVID.replace("%ILVID%", $license.ILVID) | |
| if ($license.ExpirationDate -is [datetime]) { | |
| Write-FormatLine " " $L_MsgTkaLicenseExpiration.replace("%TODATE%", $objWmiDate.GetVarDate) | |
| } | |
| if ($license.AdditionalInfo) { | |
| Write-FormatLine " " $L_MsgTkaLicenseAdditionalInfo.replace("%MOREINFO%", $license.AdditionalInfo) | |
| } | |
| if ($license.AuthorizationStatus -and $license.AuthorizationStatus -ne 0) { | |
| $strError = [string]::format('{0:X}', $license.AuthorizationStatus) | |
| Write-FormatLine " " $L_MsgTkaLicenseAuthZStatus.replace("%ERRCODE%", $strError) | |
| } else { | |
| Write-FormatLine " " $L_MsgTkaLicenseDescr.replace("%DESC%", $license.Description) | |
| } | |
| Write-FormatLine | |
| $listCount++ | |
| } | |
| if (0 -eq $listCount) { | |
| Write-FormatLine2 $L_MsgTkaLicenseNone | |
| } | |
| } # END Get-TkaLicense | |
| # TkaRemoveIL | |
| function Uninstall-TkaLicense ([string[]]$tkaparameters) { | |
| $ILID, [int]$ILVID = $tkaparameters | |
| Write-FormatLine2 $L_MsgTkaRemoving | |
| Write-FormatLine0 | |
| $removeCount = 0 | |
| Get-CimInstance -ClassName $TkaLicenseClass @connection | Foreach-Object { | |
| if (-not $_) {return} | |
| $license = $_ | |
| if ($ILID -eq $license.ILID -And $nILVID -eq $license.ILVID) { | |
| $Msg = $L_MsgTkaRemovedItem.replace("%SLID%", $license.ID) | |
| $result = Invoke-CimMethod -MethodName Uninstall -CimClass $license.psbase.CimClass @connection | |
| Write-FormatLine2 $Msg | |
| $removeCount++ | |
| } | |
| } | |
| if ($removeCount -eq 0) { | |
| Write-FormatLine2 $L_MsgTkaRemovedNone | |
| } | |
| } # END Uninstall-TkaLicense | |
| # TkaListCerts | |
| function Get-TkaCertificate { | |
| $product = TkaGetProduct | |
| $connection['erroraction'] = 0 | |
| $Grants = [System.Collections.Generic.List[string]]::new() #@() | |
| $result = Invoke-CimMethod -MethodName GetTokenActivationGrants -CimClass $product.psbase.CimClass -Arguments @{Grants=$Grants} @connection | |
| if ($null -eq $result -or $result.ReturnValue -ne 0) {return} | |
| $tokSigner = New-Object -ComObject "SPPWMI.SppWmiTokenActivationSigner" -ErrorAction Stop | |
| $Thumbprints = $tokSigner.GetCertificateThumbprints($Grants) | |
| foreach ($Thumb in $Thumbprints) { | |
| TkaPrintCertificate $Thumb | |
| } | |
| } # END Get-TkaCertificate | |
| function TkaActivate ([string[]]$tkaparameters) { | |
| $tokSigner = New-Object -ComObject "SPPWMI.SppWmiTokenActivationSigner" -ErrorAction Stop | |
| $product = TkaGetProduct | |
| DisplayActivatingSku $product | |
| $Thumbprint, $Pin = $tkaparameters | |
| $Challenge = $null | |
| $AuthInfo2 = $null | |
| $result = Invoke-CimMethod -MethodName GenerateTokenActivationChallenge -CimClass $product.psbase.CimClass -Arguments @{Challenge=$Challenge} @connection | |
| $AuthInfo1 = $tokSigner.Sign($Challenge, $Thumbprint, $Pin, $AuthInfo2) | |
| $result = Invoke-CimMethod -MethodName DepositTokenActivationResponse -CimClass $product.psbase.CimClass -Arguments @{Challenge=$Challenge; Response=$AuthInfo1; CertChain=$AuthInfo2} @connection | |
| $licsvc = Get-CimClass -ClassName 'SoftwareLicensingService' -Namespace 'root\cimv2' -ErrorAction 0 | |
| $result = Invoke-CimMethod -MethodName RefreshLicenseStatus -CimClass $licsvc @connection | |
| $cp.error = 0 | |
| DisplayActivatedStatus $product | |
| } # END | |
| function TkaGetProduct { | |
| $properties = "ID, Name, ApplicationId, PartialProductKey, Description, LicenseIsAddon" | |
| $filter = "ApplicationId = '$WindowsAppId' AND PartialProductKey <> NULL AND LicenseIsAddon = FALSE" | |
| Invoke-ProductQuery $properties $filter | |
| } # END TkaGetProduct | |
| function TkaPrintCertificate ([string]$Thumbprint) { | |
| $params = $Thumbprint.split("|") | |
| Write-FormatLine0 | |
| Write-FormatLine2 $L_MsgTkaCertThumbprint.replace("%THUMBPRINT%", $params[0]) | |
| Write-FormatLine2 $L_MsgTkaCertSubject.replace("%SUBJECT%", $params[1]) | |
| Write-FormatLine2 $L_MsgTkaCertIssuer.replace("%ISSUER%", $params[2]) | |
| Write-FormatLine2 $L_MsgTkaCertValidFrom.replace("%FROMDATE%", $params[3]) | |
| Write-FormatLine2 $L_MsgTkaCertValidTo.replace("%TODATE%", $params[4]) | |
| } # END TkaPrintCertificate | |
| #endregion TKA | |
| #region Active Directory Activation | |
| #Invoke-ADActivateOnline | |
| function ADActivateOnline ([string[]]$activationParameters) { | |
| Test-RemoteExec | |
| $ProductKey, $ActivationobjectName = $activationParameters | |
| $result = Invoke-CimMethod -MethodName DoActiveDirectoryOnlineActivation -CimClass $licsvc -Arguments @{ProductKey=$ProductKey; ActivationObjectName=$ActivationobjectName} @connection | |
| #if ($null -ne $result -and $result.ReturnValue -eq 0) { | |
| Write-FormatLine2 $L_MsgActivated | |
| #} | |
| } # END | |
| #Get-ADIID | |
| function ADGetIID ($ProductKey) { | |
| Test-RemoteExec | |
| $IID = $null | |
| $licsvc = Get-CimClass -ClassName 'SoftwareLicensingService' -Namespace 'root\cimv2' -ErrorAction 0 | |
| $result = Invoke-CimMethod -MethodName GenerateActiveDirectoryOfflineActivationId -CimClass $licsvc -Arguments @{ProductKey=$ProductKey; InstallationID=$IID} @connection | |
| Write-FormatLine2 $L_MsgInstallationID $IID | |
| Write-FormatLine2 | |
| Write-FormatLine2 $L_MsgPhoneNumbers | |
| } # END | |
| #Invoke-ADActivatePhone | |
| function ADActivatePhone ([string[]]$activationParameters) { | |
| Test-RemoteExec | |
| $ProductKey, $CID, $ActivationobjectName = $activationParameters | |
| $licsvc = Get-CimClass -ClassName 'SoftwareLicensingService' -Namespace 'root\cimv2' -ErrorAction 0 | |
| $result = Invoke-CimMethod -MethodName DepositActiveDirectoryOfflineActivationConfirmation -CimClass $licsvc -Arguments @{ProductKey=$ProductKey; ConfirmationID=$CID; ActivationObjectName=$ActivationobjectName} @connection | |
| #if ($null -ne $result -and $result.ReturnValue -eq 0) { | |
| Write-FormatLine2 $L_MsgActivated | |
| #} | |
| } # END | |
| #Get-ADActivationObject # not complete!!! | |
| function ADListActivationobjects { | |
| Test-RemoteExec | |
| $machineDomain = $env:USERDNSDOMAIN.tolower().split('.').foreach{"DC=$_"} -join ',' | |
| $fqdn = @("LDAP://CN=Activation Objects,CN=Microsoft SPP,CN=Services,CN=Configuration,$machineDomain") | |
| $params = @{ | |
| TypeName = "System.DirectoryServices.DirectoryEntry" | |
| ErrorAction = "Stop" # 0 $ErrorActionPreference | |
| } | |
| $params['ArgumentList'] = if ($cp.Credential) { | |
| #$password = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($cp.Credential.password)) | |
| #$password = $cp.Credential.GetNetworkCredential().Password | |
| ##$DomainEntry = [System.DirectoryServices.DirectoryEntry]::new("LDAP://$machineDomain", $cp.Credential.username, $password) | |
| $fqdn,$cp.Credential.username,$cp.Credential.GetNetworkCredential().Password | |
| } else {$fqdn} | |
| $DomainEntry = [pscustomobject]$params # try {} catch {} | |
| $searcher = [System.DirectoryServices.DirectorySearcher]::new() | |
| $searcher.PageSize = 1000 | |
| $searcher.SearchRoot = $DomainEntry | |
| $searcher.Filter = "(objectclass=msspp-activationobject)" | |
| #$searcher.PropertiesToLoad.Add('*') | |
| $SPPcontainer = $searcher.FindOne() | |
| # https://fromreallife.wordpress.com/2012/10/27/active-directory-based-activation-adba/ | |
| $found = $false | |
| if ($SPPcontainer) { | |
| Write-FormatLine2 $L_MsgActobjAvailable | |
| $SPPcontainer.psbase.Children | ForEach-Object { | |
| $found = $true | |
| Write-FormatLine " " $L_MsgADInfoAOName $_.Get($ADActobjDisplayName) | |
| Write-FormatLine " " $L_MsgActID (GuidTostring $_.Get($ADActobjAttribSkuId)) | |
| Write-FormatLine " " $L_MsgPartialPKey $_.Get($ADActobjAttribPartialPkey) | |
| Write-FormatLine " " $L_MsgADInfoExtendedPid $_.Get($ADActobjAttribPid) | |
| Write-FormatLine " " $L_MsgADInfoAODN $_.Get($ADActobjAttribDN) | |
| Write-FormatLine | |
| } | |
| } else { | |
| Write-FormatLine2 $L_MsgADSchemaNotSupported | |
| return | |
| } | |
| if (-not $found) { | |
| Write-FormatLine " " $L_MsgActobjNoneFound | |
| } | |
| } # END | |
| #Remove-ADActivationObject # not complete!!! | |
| function ADDeleteActivationobjects ([string]$Name) { | |
| Test-RemoteExec | |
| $machineDomain = $env:USERDNSDOMAIN.tolower().split('.').foreach{"DC=$_"} -join ',' | |
| # Check if AD schema supports Activation Objects containers | |
| $SPPcontainer = "LDAP://CN=Activation Objects,CN=Microsoft SPP,CN=Services,CN=Configuration,$machineDomain" | |
| $domainEntry = if ($cp.Credential) { | |
| $password = $cp.Credential.GetNetworkCredential().Password | |
| [System.DirectoryServices.DirectoryEntry]::new($SPPcontainer, $cp.Credential.username, $password) | |
| } else { | |
| [System.DirectoryServices.DirectoryEntry]::new($SPPcontainer) | |
| } | |
| if (-not $domainEntry) { | |
| Write-FormatLine2 $L_MsgADSchemaNotSupported | |
| return | |
| } | |
| If ($Name -match '\,CN\=') { | |
| $DN = $Name | |
| } else { | |
| # RDN was provided. Construct a full DN from it. | |
| # Use computer's domain name to construct the Activation Object DN. | |
| $configurationNC = ([ADSI]"LDAP://$machineDomain/RootDSE").configurationNamingContext | |
| $DN = [string]::format('{0},{1}{2}', $Name, $ADActobjContainer, $configurationNC) | |
| if ($Name -notmatch "^CN\=") {$DN = "CN=$DN"} | |
| Write-FormatLine " " $L_MsgADInfoAODN $DN | |
| Write-FormatLine | |
| } | |
| $object = [ADSI]"LDAP://$DN" | |
| $parent = $object.Parent | |
| if ($object.Class -eq $ADActobjClass) { | |
| $parent.Delete($object.Class, $object.Name) | |
| } | |
| Write-FormatLine2 $L_MsgSucess | |
| } # END | |
| function Get-AdsiObject ([string]$fqdn, [string]$filter, $credential, [switch]$test) { | |
| # https://github.com/RamblingCookieMonster/PowerShell/blob/master/Get-ADSIObject.ps1 | |
| if ($fqdn -notmatch '^ldap') {$fqdn = "LDAP://$fqdn"} | |
| $params = @{ | |
| TypeName = "System.DirectoryServices.DirectoryEntry" | |
| ErrorAction = "Stop" # 0 $ErrorActionPreference | |
| } | |
| $params['ArgumentList'] = if ($credential) { | |
| #$password = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($credential.password)) | |
| ##$DomainEntry = [System.DirectoryServices.DirectoryEntry]::new("LDAP://$machineDomain", $credential.username, $password) | |
| $fqdn,$credential.username,$credential.GetNetworkCredential().Password | |
| } else {$fqdn} | |
| $DomainEntry = [pscustomobject]$params # try {} catch {} | |
| if (-not $DomainEntry) {return} | |
| if ($test) {return $DomainEntry} | |
| $searcher = [System.DirectoryServices.DirectorySearcher]::new() | |
| $searcher.PageSize = 1000 | |
| $searcher.SearchRoot = $DomainEntry | |
| if ($filter) {$searcher.Filter = $filter} | |
| #???$searcher.PropertiesToLoad.Add('*') | |
| $searcher.FindAll() | |
| } # END Get-AdsiObject | |
| #endregion Active Directory Activation | |
| #region Generic helpers | |
| # InstallLicense | |
| function Install-License ([string]$licFile, [switch]$notest) { | |
| if (-not $notest -or -not $licFile -or -not (Test-Path $licFile)) {return} | |
| #$LicenseData = [System.IO.File]::ReadAllText($licFile,(GetFileEncoding $licFile)) | |
| $LicenseData = Get-Content -LiteralPath $licFile -Raw -Encoding (GetFileEncoding $licFile) | |
| $licsvc = Get-CimClass -ClassName 'SoftwareLicensingService' -Namespace 'root\cimv2' -ErrorAction 0 | |
| $result = Invoke-CimMethod -MethodName InstallLicense -CimClass $licsvc -Arguments @{License = $LicenseData} @connection | |
| if ($null -eq $result -or $result.ReturnValue -ne 0) {} | |
| Write-FormatLine2 $L_MsgLicenseFile.replace("%LICENSEFILE%", $licFile) | |
| } # END Install-License | |
| # !!! not complete; assumed to be wrapper for Invoke-CimMethod | |
| function Invoke-ServiceMethod { | |
| param ($method, [hashtable]$arguments, $cimClass, [switch]$passthru) | |
| if ($CimClass -isnot [CimClass]) { | |
| if (-not $CimClass) {return} | |
| $CimClass = get-cimclass -classname $CimClass -Namespace 'root\cimv2' -ErrorAction 0 | |
| } | |
| $result = Invoke-CimMethod -MethodName $method -Arguments $arguments -CimClass $CimClass @connection | |
| if ($passthru) {$result} | |
| } # END Invoke-ServiceMethod | |
| # Returns the encoding for a givven file. | |
| # Possible return values: ascii, unicode, unicodeFFFE (big-endian), utf-8 | |
| function GetFileEncoding ([string]$FileName) { | |
| ##if (-not $FileName -or -not (Test-Path $FileName)) {return} | |
| $bom = [System.Byte[]]::new(4) | |
| $file = [System.IO.FileStream]::new($FileName, 'Open', 'Read') | |
| $null = $file.Read($bom,0,4) | |
| $file.Close() | |
| $file.Dispose() | |
| if ($bom[0] -eq 0x2b -and $bom[1] -eq 0x2f -and $bom[2] -eq 0x76) { | |
| [System.Text.Encoding]::'UTF7' | |
| } elseif ($bom[0] -eq 0xff -and $bom[1] -eq 0xfe) { | |
| [System.Text.Encoding]::'Unicode' | |
| } elseif ($bom[0] -eq 0xfe -and $bom[1] -eq 0xff) { | |
| [System.Text.Encoding]::'BigEndianUnicode' | |
| } elseif ($bom[0] -eq 0x00 -and $bom[1] -eq 0x00 -and $bom[2] -eq 0xfe -and $bom[3] -eq 0xff) { | |
| [System.Text.Encoding]::'UTF32' | |
| } elseif ($bom[0] -eq 0xef -and $bom[1] -eq 0xbb -and $bom[2] -eq 0xbf) { | |
| [System.Text.Encoding]::'UTF8' | |
| } else {[System.Text.Encoding]::'ASCII'} | |
| } # END GetFileEncoding | |
| # !!! to be deleted after testing in ADListActivationobjects | |
| function GuidTostring ($ByteArray) { | |
| [guid]::new($ByteArray).guid | |
| } # END | |
| # not complete!!!!! | |
| function ShowError ($message, $objErr) { | |
| # Convert error number to text. Use hexadecimal format for negative values such as HRESULT errors. | |
| $errNumber = if ($cp.error -ge 0) { | |
| $cp.error | |
| } else { | |
| [string]::format('0x{0:x}', $cp.error) | |
| } | |
| $varname = [string]::format('L_MsgError_{0:X}', $cp.error) | |
| $description = Get-Variable varname -ValueOnly -ErrorAction 0 | |
| if (-not $description) { | |
| $description = if (-not $objErr.Description) { | |
| $L_MsgErrorText_6.replace("0x%ERRCODE%", $errNumber) | |
| } elseif (-not $objErr.Source) { | |
| $objErr.Description | |
| } else { | |
| [string]::format('{0} ({1})', $objErr.Description, $objErr.Source) | |
| } | |
| } | |
| $message = if ($message.Contains("0x%ERRCODE%")) { | |
| $message.replace("0x%ERRCODE%", $errNumber) | |
| } else { | |
| "{$message}$errNumber" | |
| } | |
| $message = if ($message.Contains("%ERRTEXT%")) { | |
| $message.replace("%ERRTEXT%", $description) | |
| } else { | |
| "$message $description" | |
| } | |
| Write-FormatLine2 $message.replace("%COMPUTERNAME%", $cp.ComputerName) | |
| } # END | |
| function Exit-Script ($retval) { | |
| if ($cp.ConsoleLine) { | |
| Write-FormatLine0 $cp.ConsoleLine | |
| } | |
| exit $retval | |
| } # END Exit-Script | |
| # VBS artifact | |
| function QuitWithError ($errNum) { | |
| #ShowError $L_MsgErrorText_8 $cp.error | |
| Write-FormatLine0 $L_MsgErrorText_8 $cp.error | |
| Exit-Script $errNum | |
| } # END | |
| # not complete!!! | |
| function Test-Exit ($result, $type) { # Test-OpError | |
| exit | |
| } # END Test-Exit | |
| # GetServiceObject | |
| function Get-LicensingService ([string]$property) { | |
| $param = @{ClassName = $ServiceClass} | |
| if ($property) {$param['Property'] = $property.split(',').trim()} | |
| Get-CimInstance @param @connection | |
| } # END Get-LicensingService | |
| # GetProductCollection | |
| function Get-ProductList ($selector, [string]$filter) { | |
| $param = @{ClassName = $ProductClass} | |
| if ($selector) {$param['Property'] = $selector.split(',').trim()} | |
| if ($filter) {$param['Filter'] = $filter} | |
| Get-CimInstance @param @connection | |
| } # END Get-ProductList | |
| # GetProductObject not complete!!! | |
| function Invoke-ProductQuery ($selector, $Where) { | |
| $colProducts = Get-ProductList $selector $Where | |
| # There should be exactly one product returned by the query. If there are none | |
| # assume the product key and/or licenses are missing. If there are more than one | |
| # fail with invalid arguments. | |
| if ($colProducts.count -eq 0) { | |
| Write-FormatLine2 $L_MsgErrorPKey | |
| $cp.error = $HR_SL_E_PKEY_NOT_INSTALLED | |
| } elseif ($colProducts.count -gt 1) { | |
| $cp.error = $HR_INVALID_ARG | |
| } | |
| $colProducts | Select-Object -First 1 | |
| } # END Invoke-ProductQuery | |
| function IsKmsClient ($pDescription) { | |
| $pDescription -match "VOLUME_KMSCLIENT" | |
| } # END | |
| function IsTkaClient ($pDescription) { | |
| $pDescription -match "VOLUME_KMSCLIENT" | |
| } # END | |
| function IsKmsServer ($pDescription) { | |
| $pDescription -notmatch "VOLUME_KMSCLIENT" -and $pDescription -match "VOLUME_KMS" | |
| } # END | |
| function IsTBL ($pDescription) { | |
| $pDescription -match "TIMEBASED_" | |
| } # END | |
| function IsAVMA ($pDescription) { | |
| $pDescription -match "VIRTUAL_MACHINE_ACTIVATION" | |
| } # END | |
| # FailRemoteExec | |
| function Test-RemoteExec { | |
| if ($cp.IsRemoteComputer) { | |
| Write-FormatLine0 $L_MsgRemoteExecNotSupported | |
| Exit-Script 1 | |
| } | |
| } # END Test-RemoteExec | |
| # GetIsPrimaryWindowsSKU | |
| # Returns 0 if this is not the primary SKU, 1 if it is, and 2 if we aren't certain (older clients) | |
| function Test-PrimaryWindowsSKU ($product) { | |
| # Verify the license is for Windows, that it has a partial key, and that | |
| if ($product.ApplicationId -eq $WindowsAppId -and $product.PartialProductKey) { | |
| # If we can get verify the AddOn property then we can be certain | |
| if ($product.LicenseIsAddon -ne $null) { | |
| [int](-not $product.LicenseIsAddon) | |
| #if ($product.LicenseIsAddon) {0} else {1} | |
| } else { | |
| # If we can not get the AddOn property then we assume this is a previous version | |
| # and we return a value of Uncertain, unless we can prove otherwise | |
| if ((IsKmsClient $product.Description) -or (IsKmsServer $product.Description)) { | |
| # If the description is KMS related, we can be certain that this is a primary SKU | |
| 1 | |
| } else { | |
| # Indeterminate since the property was missing and we can't verify KMS | |
| 2 | |
| } | |
| } | |
| } else {0} # not the primary SKU | |
| } # END Test-PrimaryWindowsSKU | |
| # orphan??? | |
| function WasPrimaryKeyFound ($PrimarySkuType) { | |
| (IsKmsServer $PrimarySkuType) -or (IsKmsClient $PrimarySkuType) -or | |
| ($PrimarySkuType -match "$NotSpecialCasePrimaryKey|$TblPrimaryKey|$IndeterminatePrimaryKeyFound") | |
| } # END | |
| # orphan??? | |
| function CanPrimaryKeyTypeBeDetermined ($PrimarySkuType) { | |
| ($PrimarySkuType -match "$IndeterminatePrimaryKeyFound|$NoPrimaryKeyFound") | |
| } # END | |
| # orphan??? | |
| function GetPrimarySKUType { | |
| $result = '' | |
| $licsvc = Get-ProductList $ProductIsPrimarySkuSelectClause $PartialProductKeyNonNullWhereClause | |
| foreach ($product in $licsvc) { | |
| $pDescription = $product.Description | |
| if ($product.ApplicationId -eq $WindowsAppId) { | |
| $iIsPrimaryWindowsSku = Test-PrimaryWindowsSKU $product | |
| if ($iIsPrimaryWindowsSku -eq 1) { | |
| if ((IsKmsServer $pDescription) -or (IsKmsClient $pDescription)) { | |
| $result = $pDescription | |
| continue # no need to continue | |
| } else { | |
| If (IsTBL $pDescription) { | |
| $result = $TblPrimaryKey | |
| continue | |
| } else { | |
| $result = $NotSpecialCasePrimaryKey | |
| } | |
| } | |
| } elseif ($iIsPrimaryWindowsSku -eq 2 -and $result -eq "") { | |
| $result = $IndeterminatePrimaryKeyFound | |
| } | |
| } else { | |
| $result = $pDescription | |
| continue # no need to continue | |
| } | |
| } | |
| if ($result -eq '') { | |
| $result = $NoPrimaryKeyFound | |
| } | |
| $result | |
| } # END GetPrimarySKUType | |
| function SetRegistryStr ($hKey, $KeyPath, $ValueName, $Value) { | |
| $CimClass = get-cimclass -classname 'StdRegProv' -Namespace 'root\cimv2' -ErrorAction 0 | |
| $result = Invoke-CimMethod -MethodName GetStringValue -arguments @{hDefKey=$hKey; sSubKeyName=$KeyPath; sValueName=$ValueName; sValue=$Value} -CimClass $CimClass @connection | |
| if ($null -ne $result) {$result.ReturnValue} else {-1} | |
| } # END | |
| function DeleteRegistryValue ($hKey, $KeyPath, $ValueName) { | |
| $CimClass = get-cimclass -classname 'StdRegProv' -Namespace 'root\cimv2' -ErrorAction 0 | |
| $result = Invoke-CimMethod -MethodName DeleteValue -arguments @{hDefKey=$hKey; sSubKeyName=$KeyPath; sValueName=$ValueName} -CimClass $CimClass @connection | |
| if ($null -ne $result) {$result.ReturnValue} else {-1} | |
| } # END | |
| # ExistsRegistryKey | |
| function Test-RegistryKey ($hKey, $KeyPath) { | |
| $CimClass = get-cimclass -classname 'StdRegProv' -Namespace 'root\cimv2' -ErrorAction 0 | |
| # Check for KEY_QUERY_VALUE for this key | |
| $granted = $false | |
| $result = invoke-cimmethod -MethodName CheckAccess -arguments @{hDefKey=$hKey; sSubKeyName=$KeyPath; uRequired=1; bGranted=$granted} -CimClass $CimClass @connection | |
| # Ignore real access rights, just look for existence of the key | |
| ($null -ne $result -and $result.ReturnValue -ne 2) | |
| } # END Test-RegistryKey | |
| # https://learn.microsoft.com/en-us/windows/win32/cimwin32prov/win32-operatingsystem | |
| function Get-SoftwareInfo { | |
| Get-CimInstance -ClassName Win32_OperatingSystem @connection | Select-Object @{n='ComputerName';e={$cp.ComputerName}}, Caption,Version,Description,InstallDate,LastBootUpTime,LocalDateTime,CurrentTimeZone,Locale,CountryCode,OSLanguage,OSType,OperatingSystemSKU,OSArchitecture,OSProductSuite,ProductType,SuiteMask,SerialNumber,WindowsDirectory,Status | |
| } # END Get-SoftwareInfo | |
| # experimental | |
| function Add-DataItem ([string]$data) { | |
| if (-not $data) {return} | |
| $item,$value = $data.split(':',2) | |
| $cp.output[$item] = $value | |
| } # END Add-DataItem | |
| function Write-FormatLine { | |
| if ($noformat) {return "$args"} | |
| if (-not $args.Count) {return} | |
| if ($args.count -lt 2) {"$args"; return} | |
| $align = $cp.tabalign | |
| if ($args[0].length -gt $align) {$args[0] = $args[0].Substring(0,$align)} | |
| $args[0] = [string]::Format("{0,-$align} :","$($args[0])".TrimEnd(': ')) | |
| ##[console]::Writeline("$args") | |
| "$args" | |
| } # END Write-FormatLine | |
| function Write-FormatLine2 { | |
| if ($noformat) {return "$args"} | |
| if (-not $args.Count) {return} | |
| $argall = if ($args.Count -gt 1) { | |
| $args[0].split(':',2).trim() + $args[1..($args.count-1)] | |
| } else {$args[0].split(':',2).trim()} | |
| if ($argall.count -lt 2) {return "$argall"} | |
| $align = $cp.tabalign | |
| if ($argall[0].length -gt $align) {$argall[0] = $argall[0].Substring(0,$align)} | |
| $argall[0] = [string]::Format("{0,-$align} :","$($argall[0])".TrimEnd(': ')) | |
| "$argall" | |
| } # END Write-FormatLine2 | |
| function Write-FormatLine0 { | |
| "$args" | |
| } # END Write-FormatLine0 | |
| #endregion Generic | |
| function Show-LSClass { | |
| Write-Host | |
| "Class Name : Service Class ($ServiceClass)" | |
| '--------------------------' | |
| Get-CimInstance -ClassName $ServiceClass @connection #| Format-List * | |
| "Class Name : Product Class ($ProductClass)" | |
| '--------------------------' | |
| '' | |
| Get-CimInstance -ClassName $ProductClass -Filter "ApplicationID='$WindowsAppId' AND PartialProductKey<>NULL" @connection #| Format-List * | |
| "Class Name : Tka License Class ($TkaLicenseClass)" | |
| '------------------------------' | |
| '' | |
| Get-CimInstance -ClassName $TkaLicenseClass @connection | |
| } # END Show-LSClass | |
| function Get-Gvlk ($kid) { | |
| if ($kid -eq '%') { | |
| $os = Get-CimInstance -ClassName Win32_OperatingSystem @connection | |
| if (-not $os) { | |
| Write-Warning 'Unable to detect operating system. Try again.' | |
| return | |
| } | |
| $version = [version]$os.Version | |
| $ver = if ($version.Major -eq 6 -and $version.Minor -eq 1) { | |
| if ($os.Caption -notmatch 'server') {7} | |
| } elseif ($version.Major -eq 6 -and $version.Minor -eq 2) { | |
| if ($os.Caption -notmatch 'server') {8} | |
| } else {11} | |
| $ed = if ($os.Caption -match 'server' -and $ver) { | |
| if ($os.Caption -match 'Standard') {'std'} | |
| elseif ($os.Caption -match 'Datacenter') {'dc'} | |
| $ver = if ($os.Build -gt 26000) {25} elseif ($os.Build -gt 20100) {22} elseif ($os.Build -gt 17100) {19} else {16} | |
| $ver = "s$ver" | |
| } elseif ($ver) { | |
| if ($os.Caption -match 'Pro') {'pro'} | |
| elseif ($os.Caption -match 'Enterpri') {'ent'} | |
| $ver = "w$ver" | |
| } | |
| if ($ed -and $ver) { | |
| $cp.gvlk[$ver].$ed # extract the product key | |
| } else { | |
| Write-Warning 'Invalid edition/version specified.' | |
| } | |
| } | |
| elseif ($kid -match '^%([wsWS]\d+)(\w+)?') { | |
| $ver = if ($kid -match '^%w10') {'w11'} else {$matches[1]} | |
| $ed = $matches[2] | |
| if (-not $ed -and $ver -match '^w') {$ed = 'pro'} | |
| if (-not $ed -and $ver -match '^s') {$ed = 'std'} | |
| $cp.gvlk[$ver].$ed # extract the product key | |
| } | |
| else { | |
| Write-Warning 'Invalid edition/version specified.' | |
| } | |
| } # END Get-Gvlk | |
| function Show-Help { | |
| $indent = ' ' | |
| $fmt1 = "$indent{0}{1}" | |
| $fmt2 = '-{0}' | |
| $fmt3 = "$indent{0,15} : {1}" | |
| $titlecolor = @{ForegroundColor = 'DarkYellow'} | |
| $paramcolor = @{ForegroundColor = 'DarkGray'} | |
| $usagecolor = @{ForegroundColor = 'DarkGray'} | |
| $appIdparam = '[-aid <Activation ID>]' | |
| Write-Host $L_MsgHelp_1 | |
| Write-Host $L_MsgHelp_2_1 | |
| Write-Host | |
| Write-Host 'GENERAL PARAMETER NAME NOTATION:' @titlecolor | |
| Write-Host ' - Starting with "d" - display' | |
| Write-Host ' - Starting with "s" - set' | |
| Write-Host ' - Starting with "c" - clear' | |
| Write-Host ' - Starting with "i" - install' | |
| Write-Host ' - Starting with "u" - uninstall' | |
| Write-Host ' - Starting with "r" - reset/remove' | |
| Write-Host ' - Starting with "a" - activate' | |
| Write-Host | |
| Write-Host $L_MsgConnectionOptions.ToUpper() @titlecolor | |
| Write-Host -$L_optConnectionCimSession $L_ParamsCimSession | |
| Write-Host ($fmt1 -f '',$L_ParamsCimSessionUsage) @usagecolor | |
| Write-Host -$L_optConnectionCredential $L_ParamsCredential | |
| Write-Host ($fmt1 -f '',$L_ParamsCredentialUsage) @usagecolor | |
| Write-Host | |
| Write-Host $L_MsgGlobalOptions.ToUpper() @titlecolor | |
| Write-Host '-aid <Activation ID>' | |
| Write-Host ($fmt1 -f '','Parameter for -ato, -xpr, -upk, -dti, -ckms, and -ckmsdomain options') @usagecolor | |
| Write-Host -$L_optInstallProductKey $L_ParamsProductKey | |
| Write-Host ($fmt1 -f '',$L_optInstallProductKeyUsage) @usagecolor | |
| Write-Host ($fmt1 -f '','To enter a GVLK key use special notation with prefix "%". See instructions below') @usagecolor | |
| Write-Host -$L_optActivateProduct $appIdparam #$L_ParamsActivationIDOptional | |
| Write-Host ($fmt1 -f '',$L_optActivateProductUsage) @usagecolor | |
| Write-Host -$L_optDisplayInformation $L_ParamsActIDOptional | |
| Write-Host ($fmt1 -f '',$L_optDisplayInformationUsage) @usagecolor | |
| Write-Host -$L_optDisplayInformationVerbose $L_ParamsActIDOptional | |
| Write-Host ($fmt1 -f '',$L_optDisplayInformationUsageVerbose) @usagecolor | |
| Write-Host -$L_optExpirationDatime $appIdparam #$L_ParamsActivationIDOptional | |
| Write-Host ($fmt1 -f '',$L_optExpirationDatimeUsage) @usagecolor | |
| Write-Host | |
| Write-Host $L_MsgAdvancedOptions.ToUpper() @titlecolor | |
| Write-Host -$L_optClearPKeyFromRegistry | |
| Write-Host ($fmt1 -f '',$L_optClearPKeyFromRegistryUsage) @usagecolor | |
| Write-Host -$L_optInstallLicense $L_ParamsLicenseFile | |
| Write-Host ($fmt1 -f '',$L_optInstallLicenseUsage) @usagecolor | |
| Write-Host -$L_optReinstallLicenses | |
| Write-Host ($fmt1 -f '',$L_optReinstallLicensesUsage) @usagecolor | |
| Write-Host -$L_optReArmWindows | |
| Write-Host ($fmt1 -f '',$L_optReArmWindowsUsage) @usagecolor | |
| Write-Host -$L_optReArmApplication $L_ParamsApplicationID | |
| Write-Host ($fmt1 -f '',$L_optReArmApplicationUsage) @usagecolor | |
| Write-Host -$L_optReArmSku $L_ParamsActivationID | |
| Write-Host ($fmt1 -f '',$L_optReArmSkuUsage) @usagecolor | |
| Write-Host -$L_optUninstallProductKey $appIdparam #$L_ParamsActivationIDOptional | |
| Write-Host ($fmt1 -f '',$L_optUninstallProductKeyUsage) @usagecolor | |
| Write-Host ($fmt1 -f '','Use parameter -dlv to see Activation ID') @usagecolor | |
| Write-Host -$L_optDisplayIID $appIdparam #$L_ParamsActivationIDOptional | |
| Write-Host ($fmt1 -f '',$L_optDisplayIIDUsage) @usagecolor | |
| Write-Host -$L_optPhoneActivateProduct "$L_ParamsPhoneActivate, $L_ParamsActivationIDOptional" | |
| Write-Host ($fmt1 -f '',$L_optPhoneActivateProductUsage) @usagecolor | |
| Write-Host | |
| Write-Host $L_MsgKmsClientOptions.ToUpper() @titlecolor | |
| Write-Host -$L_optSetKmsName "$L_ParamsSetKms, $L_ParamsActivationIDOptional" | |
| Write-Host ($fmt1 -f '',($L_optSetKmsNameUsage -replace '\. ',".`n$indent")) @usagecolor | |
| Write-Host -$L_optClearKmsName $appIdparam #$L_ParamsActivationIDOptional | |
| Write-Host ($fmt1 -f '',$L_optClearKmsNameUsage) @usagecolor | |
| Write-Host -$L_optSetKmsLookupDomain "$L_ParamsSetKmsLookupDomain, $L_ParamsActivationIDOptional" | |
| Write-Host ($fmt1 -f '',($L_optSetKmsLookupDomainUsage -replace '\. ',".`n$indent")) @usagecolor | |
| Write-Host -$L_optClearKmsLookupDomain $appIdparam #$L_ParamsActivationIDOptional | |
| Write-Host ($fmt1 -f '',($L_optClearKmsLookupDomainUsage -replace '\. ',".`n$indent")) @usagecolor | |
| Write-Host -$L_optSetKmsHostCaching | |
| Write-Host ($fmt1 -f '',$L_optSetKmsHostCachingUsage) @usagecolor | |
| Write-Host -$L_optClearKmsHostCaching | |
| Write-Host ($fmt1 -f '',$L_optClearKmsHostCachingUsage) @usagecolor | |
| Write-Host | |
| Write-Host $L_MsgTkaClientOptions.ToUpper() @titlecolor | |
| Write-Host -$L_optListInstalledILs | |
| Write-Host ($fmt1 -f '',$L_optListInstalledILsUsage) @usagecolor | |
| Write-Host -$L_optRemoveInstalledIL $L_ParamsRemoveInstalledIL | |
| Write-Host ($fmt1 -f '',$L_optRemoveInstalledILUsage) @usagecolor | |
| Write-Host -$L_optListTkaCerts | |
| Write-Host ($fmt1 -f '',$L_optListTkaCertsUsage) @usagecolor | |
| Write-Host -$L_optForceTkaActivation $L_ParamsForceTkaActivation | |
| Write-Host ($fmt1 -f '',$L_optForceTkaActivationUsage) @usagecolor | |
| Write-Host | |
| Write-Host $L_MsgKmsOptions.ToUpper() @titlecolor | |
| Write-Host -$L_optSetKmsListenPort $L_ParamsSetListenKmsPort | |
| Write-Host ($fmt1 -f '',$L_optSetKmsListenPortUsage) @usagecolor | |
| Write-Host -$L_optSetActivationInterval $L_ParamsSetActivationInterval | |
| Write-Host ($fmt1 -f '',($L_optSetActivationIntervalUsage -replace '\. ',".`n$indent")) @usagecolor | |
| Write-Host -$L_optSetRenewalInterval $L_ParamsSetRenewalInterval | |
| Write-Host ($fmt1 -f '',($L_optSetRenewalIntervalUsage -replace '\. ',".`n$indent")) @usagecolor | |
| Write-Host -$L_optSetDNS | |
| Write-Host ($fmt1 -f '',$L_optSetDNSUsage) @usagecolor | |
| Write-Host -$L_optClearDNS | |
| Write-Host ($fmt1 -f '',$L_optClearDNSUsage) @usagecolor | |
| Write-Host -$L_optSetNormalPriority | |
| Write-Host ($fmt1 -f '',$L_optSetNormalPriorityUsage) @usagecolor | |
| Write-Host -$L_optClearNormalPriority | |
| Write-Host ($fmt1 -f '',$L_optClearNormalPriorityUsage) @usagecolor | |
| Write-Host -$L_optSetVLActivationType "$L_ParamsVLActivationTypeOptional, $L_ParamsActivationIDOptional" | |
| Write-Host ($fmt1 -f '',$L_optSetVLActivationTypeUsage) @usagecolor | |
| Write-Host | |
| Write-Host $L_MsgADOptions.ToUpper() @titlecolor | |
| Write-Host -$L_optADActivate "$L_ParamsProductKey, $L_ParamsAONameOptional" | |
| Write-Host ($fmt1 -f '',$L_optADActivateUsage) @usagecolor | |
| Write-Host -$L_optADGetIID $L_ParamsProductKey | |
| Write-Host ($fmt1 -f '',$L_optADGetIIDUsage) @usagecolor | |
| Write-Host -$L_optADApplyCID "$L_ParamsProductKey, $L_ParamsPhoneActivate, $L_ParamsAONameOptional" | |
| Write-Host ($fmt1 -f '',$L_optADApplyCIDUsage) @usagecolor | |
| Write-Host -$L_optADListAOs | |
| Write-Host ($fmt1 -f '',$L_optADListAOsUsage) @usagecolor | |
| Write-Host -$L_optADDeleteAO $L_ParamsAODistinguishedName | |
| Write-Host ($fmt1 -f '',$L_optADDeleteAOsUsage) @usagecolor | |
| <#Write-Host | |
| Write-Host 'RUNTIME OPTIONS:' @titlecolor | |
| Write-Host '-quiet' | |
| Write-Host ($fmt1 -f '','Run silently') | |
| Write-Host '-noformat' | |
| Write-Host ($fmt1 -f '','Do not format output')#> | |
| #Write-Host | |
| #Write-Host 'NOTES:' @titlecolor | |
| Write-Host | |
| Write-Host 'GVLK PRODUCT KEY NOTATION:' @titlecolor | |
| Write-Host "- Input format : %<Type><Version>[<Edition>]" | |
| Write-Host "- % - prefix for GVLK" | |
| Write-Host '- Single "%" triggers to autodetect a target Operating System' | |
| Write-Host '- Type : w for workstation' | |
| Write-Host '- Type : s for server' | |
| Write-Host '- Version : 7, 8, 10, 11 for workstation' | |
| Write-Host '- Version : 16, 19, 22, 25 for server' | |
| Write-Host '- Edition : pro, ent for workstation; default is pro' | |
| Write-Host '- Edition : std, dc for server; default is std' | |
| Write-Host '- Examples : %w11ent, %s22dc, %s25, %' | |
| Write-Host | |
| Write-Host 'EXAMPLES:' @titlecolor | |
| } # END Show-Help | |
| function Show-GUIHelp {} # END Show-GUIHelp | |
| #region Messages | |
| # New options | |
| $L_MsgHelp_2_1 = 'Usage: slmgr.ps1 [<Connection options>] [<Slmgr option>] [<CommonParameters>]' | |
| $L_MsgConnectionOptions = 'Connection options:' | |
| $L_optConnectionCimSession = 'CimSession' | |
| $L_optConnectionCredential = 'Credential' | |
| $L_ParamsCimSession = '<CimSession | ComputerName>' | |
| $L_ParamsCredential = '<PSCredential | UserName>' | |
| $L_ParamsCredentialUsage = 'Account with required privilege on remote machine' | |
| $L_ParamsCimSessionUsage = 'Name of remote machine (default is local machine)' | |
| # Global options | |
| $L_optInstallProductKey = "ipk" | |
| $L_optInstallProductKeyUsage = "Install product key (replaces existing key)" | |
| $L_optUninstallProductKey = "upk" | |
| $L_optUninstallProductKeyUsage = "Uninstall product key" | |
| $L_optActivateProduct = "ato" | |
| $L_optActivateProductUsage = "Activate Windows" | |
| $L_optDisplayInformation = "dli" | |
| $L_optDisplayInformationUsage = "Display license information (default: current license)" | |
| $L_optDisplayInformationVerbose = "dlv" | |
| $L_optDisplayInformationUsageVerbose = "Display detailed license information (default: current license)" | |
| $L_optExpirationDatime = "xpr" | |
| $L_optExpirationDatimeUsage = "Expiration date for current license state" | |
| # Advanced options | |
| $L_optClearPKeyFromRegistry = "cpky" | |
| $L_optClearPKeyFromRegistryUsage = "Clear product key from the registry (prevents disclosure attacks)" | |
| $L_optInstallLicense = "ilc" | |
| $L_optInstallLicenseUsage = "Install license" | |
| $L_optReinstallLicenses = "rilc" | |
| $L_optReinstallLicensesUsage = "Re-install system license files" | |
| $L_optDisplayIID = "dti" | |
| $L_optDisplayIIDUsage = "Display Installation ID for offline activation" | |
| $L_optPhoneActivateProduct = "atp" | |
| $L_optPhoneActivateProductUsage = "Activate product with user-provided Confirmation ID" | |
| $L_optReArmWindows = "rearm" | |
| $L_optReArmWindowsUsage = "ReSet licensing status of the machine" | |
| $L_optReArmApplication = "rearmapp" | |
| $L_optReArmApplicationUsage = "ReSet licensing status of the given app" | |
| $L_optReArmSku = "rearmsku" | |
| $L_optReArmSkuUsage = "ReSet licensing status of the given sku" | |
| # KMS options | |
| $L_optSetKmsName = "skms" | |
| $L_optSetKmsNameUsage = "Set name and/or the port for the KMS computer this machine will use. IPv6 address must be specified in the format [hostname]:port" | |
| $L_optClearKmsName = "ckms" | |
| $L_optClearKmsNameUsage = "Clear name of KMS computer used (sets the port to the default)" | |
| $L_optSetKmsLookupDomain = "skmsdomain" | |
| $L_optSetKmsLookupDomainUsage = "Set specific DNS domain in which all KMS SRV records can be found. This setting has no effect if the specific single KMS host is via -skms option." | |
| $L_optClearKmsLookupDomain = "ckmsdomain" | |
| $L_optClearKmsLookupDomainUsage = "Clear the specific DNS domain in which all KMS SRV records can be found. The specific KMS host will be used if via -skms. Otherwise default KMS auto-discovery will be used." | |
| $L_optSetKmsHostCaching = "skhc" | |
| $L_optSetKmsHostCachingUsage = "Enable KMS host caching" | |
| $L_optClearKmsHostCaching = "ckhc" | |
| $L_optClearKmsHostCachingUsage = "Disable KMS host caching" | |
| $L_optSetActivationInterval = "sai" | |
| $L_optSetActivationIntervalUsage = "Set (minutes) for unactivated clients to attempt KMS connection. The activation interval must be between 15 minutes (min) and 30 days (max) although the default (2 hours) is recommended." | |
| $L_optSetRenewalInterval = "sri" | |
| $L_optSetRenewalIntervalUsage = "Set interval (minutes) for activated clients to attempt KMS connection. The renewal interval must be between 15 minutes (min) and 30 days (max) although the default (7 days) is recommended." | |
| $L_optSetKmsListenPort = "sprt" | |
| $L_optSetKmsListenPortUsage = "Set port KMS will use to communicate with clients" | |
| $L_optSetDNS = "sdns" | |
| $L_optSetDNSUsage = "Enable DNS publishing by KMS (default)" | |
| $L_optClearDNS = "cdns" | |
| $L_optClearDNSUsage = "Disable DNS publishing by KMS" | |
| $L_optSetNormalPriority = "spri" | |
| $L_optSetNormalPriorityUsage = "Set priority to normal (default)" | |
| $L_optClearNormalPriority = "cpri" | |
| $L_optClearNormalPriorityUsage = "Set priority to low" | |
| $L_optSetVLActivationType = "acttype" | |
| $L_optSetVLActivationTypeUsage = "Valid activation types are 0|All, 1|AD, 2|KMS, 3|Token" | |
| # Token-based Activation options | |
| $L_optListInstalledILs = "lil" | |
| $L_optListInstalledILsUsage = "List installed Token-based Activation Issuance Licenses" | |
| $L_optRemoveInstalledIL = "ril" | |
| $L_optRemoveInstalledILUsage = "Remove installed Token-based Activation Issuance License" | |
| $L_optListTkaCerts = "ltc" | |
| $L_optListTkaCertsUsage = "List Token-based Activation Certificates" | |
| $L_optForceTkaActivation = "fta" | |
| $L_optForceTkaActivationUsage = "Force Token-based Activation" | |
| # Active Directory Activation options | |
| $L_optADActivate = "adactivationonline" | |
| $L_optADActivateUsage = "Activate AD (Active Directory) forest with user-provided product key" | |
| $L_optADGetIID = "adactivationgetiid" | |
| $L_optADGetIIDUsage = "Display Installation ID for AD (Active Directory) forest" | |
| $L_optADApplyCID = "adactivationapplycid" | |
| $L_optADApplyCIDUsage = "Activate AD (Active Directory) forest with user-provided product key and Confirmation ID" | |
| $L_optADListAOs = "aolist" | |
| $L_optADListAOsUsage = "Display Activation Objects in AD (Active Directory)" | |
| $L_optADDeleteAO = "delao" | |
| $L_optADDeleteAOsUsage = "Delete Activation Objects in AD (Active Directory) for user-provided Activation Object" | |
| # Option parameters | |
| $L_ParamsActivationID = "<Activation ID>" | |
| $L_ParamsActivationIDOptional = "[Activation ID]" | |
| $L_ParamsActIDOptional = "[Activation ID | All]" | |
| $L_ParamsApplicationID = "<Application ID>" | |
| $L_ParamsProductKey = "<Product Key>" | |
| $L_ParamsLicenseFile = "<License file>" | |
| $L_ParamsPhoneActivate = "<Confirmation ID>" | |
| $L_ParamsSetKms = "<Name[:Port] | :port>" | |
| $L_ParamsSetKmsLookupDomain = "<FQDN>" | |
| $L_ParamsSetListenKmsPort = "<Port>" | |
| $L_ParamsSetActivationInterval = "<Activation Interval>" | |
| $L_ParamsSetRenewalInterval = "<Renewal Interval>" | |
| $L_ParamsVLActivationTypeOptional = "<Activation Type>" | |
| $L_ParamsRemoveInstalledIL = "<ILID>, <ILvID>" | |
| $L_ParamsForceTkaActivation = "<Certificate Thumbprint>, [<PIN>]" | |
| $L_ParamsAONameOptional = "[Activation Object name]" | |
| $L_ParamsAODistinguishedName = "<Activation Object DN | Activation Object RDN>" | |
| # Miscellaneous messages | |
| $L_MsgHelp_1 = "Windows Software Licensing Management Tool" | |
| $L_MsgHelp_2 = "Usage: slmgr.ps1 [-CimSession <CimSession>] [-Credential <PSCredential>] [<Option>]" | |
| $L_MsgHelp_3 = "MachineName: Name of remote machine (default is local machine)" | |
| $L_MsgHelp_4 = "User: Account with required privilege on remote machine" | |
| $L_MsgHelp_5 = "Password: password for the previous account" | |
| $L_MsgGlobalOptions = "GLOBAL OPTIONS:" | |
| $L_MsgAdvancedOptions = "ADVANCED OPTIONS:" | |
| $L_MsgKmsClientOptions = "VOLUME LICENSING: Key Management Service (KMS) Client Options:" | |
| $L_MsgKmsOptions = "VOLUME LICENSING: Key Management Service (KMS) Options:" | |
| $L_MsgADOptions = "VOLUME LICENSING: Active Directory (AD) Activation Options:" | |
| $L_MsgTkaClientOptions = "VOLUME LICENSING: Token-based Activation Options:" | |
| $L_MsgInvalidOptions = "Invalid combination of command parameters." | |
| $L_MsgUnrecognizedOption = "Unrecognized option: " | |
| $L_MsgErrorProductNotFound = "Error: product not found." | |
| $L_MsgClearedPKey = "Product key from registry cleared successfully." | |
| $L_MsgInstalledPKey = "Installed product key %PKEY% successfully." | |
| $L_MsgUninstalledPKey = "Uninstalled product key successfully." | |
| $L_MsgErrorPKey = "Error: product key not found." | |
| $L_MsgInstallationID = "Installation ID: " | |
| $L_MsgPhoneNumbers = "Product activation telephone numbers can be obtained by searching the phone.inf file for the appropriate phone number for your location/country. You can open the phone.inf file from a Command Prompt or the Start Menu by running: notepad %systemroot%\system32\sppui\phone.inf" | |
| $L_MsgActivating = "Activating %PRODUCTNAME% (%PRODUCTID%) ..." | |
| $L_MsgActivated = "Product activated successfully." | |
| $L_MsgActivated_Failed = "Error: Product activation failed." | |
| $L_MsgConfID = "Confirmation ID for product %ACTID% deposited successfully." | |
| $L_MsgErrorLocalWMI = "Error 0x%ERRCODE% occurred in connecting to the local WMI provider." | |
| $L_MsgErrorLocalRegistry = "Error 0x%ERRCODE% occurred in connecting to the local registry." | |
| $L_MsgErrorConnection = "Error 0x%ERRCODE% occurred in connecting to server %COMPUTERNAME%." | |
| $L_MsgInfoRemoteConnection = "Connected to server %COMPUTERNAME%." | |
| $L_MsgErrorConnectionRegistry = "Error 0x%ERRCODE% occurred in connecting to the registry on server %COMPUTERNAME%." | |
| $L_MsgErrorImpersonation = "Error 0x%ERRCODE% occurred in setting impersonation level." | |
| $L_MsgErrorAuthenticationLevel = "Error 0x%ERRCODE% occurred in setting authentication level." | |
| $L_MsgErrorWMI = "Error 0x%ERRCODE% occurred in creating a locator object." | |
| $L_MsgErrorText_6 = "On a computer running Microsoft Windows non-core edition, run # slui.exe 0x2a 0x%ERRCODE%# to display the error text." | |
| $L_MsgErrorText_8 = "Error: " | |
| $L_MsgErrorText_9 = "Error: option %OPTION% needs %PARAM%" | |
| $L_MsgErrorText_11 = "The machine is running within the non-genuine grace period. Run # slui.exe# to go online and make the machine genuine." | |
| $L_MsgErrorText_12 = "Windows is running within the non-genuine notification period. Run # slui.exe# to go online and validate Windows." | |
| $L_MsgLicenseFile = "License file %LICENSEFILE% installed successfully." | |
| $L_MsgKmsPriSetToLow = "KMS priority set to Low" | |
| $L_MsgKmsPriSetToNormal = "KMS priority set to Normal" | |
| $L_MsgWarningKmsPri = "Warning: Priority can only be set on a KMS machine that is also activated." | |
| $L_MsgKmsDnsPublishingDisabled = "DNS publishing disabled" | |
| $L_MsgKmsDnsPublishingEnabled = "DNS publishing enabled" | |
| $L_MsgKmsDnsPublishingWarning = "Warning: DNS Publishing can only be set on a KMS machine that is also activated." | |
| $L_MsgKmsPortSet = "KMS port set to %PORT% successfully." | |
| $L_MsgWarningKmsReboot = "Warning: a KMS reboot is needed for this setting to take effect." | |
| $L_MsgWarningKmsPort = "Warning: KMS port can only be set on a KMS machine that is also activated." | |
| $L_MsgRenewalSet = "Volume renewal interval set to %RENEWAL% minutes successfully." | |
| $L_MsgWarningRenewal = "Warning: Volume renewal interval can only be set on a KMS machine that is also activated." | |
| $L_MsgActivationSet = "Volume activation interval set to %ACTIVATION% minutes successfully." | |
| $L_MsgWarningActivation = "Warning: Volume activation interval can only be set on a KMS machine that is also activated." | |
| $L_MsgKmsNameSet = "Key Management Service machine name set to %KMS% successfully." | |
| $L_MsgKmsNameCleared = "Key Management Service machine name cleared successfully." | |
| $L_MsgKmsLookupDomainSet = "Key Management Service lookup domain set to %FQDN% successfully." | |
| $L_MsgKmsLookupDomainCleared = "Key Management Service lookup domain cleared successfully." | |
| $L_MsgKmsUseMachineNameOverrides = "Warning: -skms setting overrides the -skmsdomain setting. %KMS% will be used for activation." | |
| $L_MsgKmsUseMachineName = "Warning: -skms setting is in effect. %KMS% will be used for activation." | |
| $L_MsgKmsUseLookupDomain = "Warning: -skmsdomain setting is in effect. %FQDN% will be used for DNS SRV record lookup." | |
| $L_MsgKmsHostCachingDisabled = "KMS host caching is disabled" | |
| $L_MsgKmsHostCachingEnabled = "KMS host caching is enabled" | |
| $L_MsgErrorActivationID = "Error: Activation ID (%ActID%) not found." | |
| $L_MsgVLActivationTypeSet = "Volume activation type set successfully." | |
| $L_MsgRearm_1 = "Command completed successfully." | |
| $L_MsgRearm_2 = "Please restart the system for the changes to take effect." | |
| $L_MsgRemainingWindowsRearmCount = "Remaining Windows rearms: %COUNT%" | |
| $L_MsgRemainingSkuRearmCount = "Remaining SKU rearms: %COUNT%" | |
| $L_MsgRemainingAppRearmCount = "Remaining App rearms: %COUNT%" | |
| # Used for xpr | |
| $L_MsgLicenseStatusUnlicensed = "Unlicensed" | |
| $L_MsgLicenseStatusVL = "Volume activation will expire %ENDDATE%" | |
| $L_MsgLicenseStatusTBL = "Timebased activation will expire %ENDDATE%" | |
| $L_MsgLicenseStatusAVMA = "Automatic VM activation will expire %ENDDATE%" | |
| $L_MsgLicenseStatusLicensed = "The machine is permanently activated." | |
| $L_MsgLicenseStatusInitialGrace = "Initial grace period ends %ENDDATE%" | |
| $L_MsgLicenseStatusAdditionalGrace = "Additional grace period ends %ENDDATE%" | |
| $L_MsgLicenseStatusNonGenuineGrace = "Non-genuine grace period ends %ENDDATE%" | |
| $L_MsgLicenseStatusNotification = "Windows is in Notification mode" | |
| $L_MsgLicenseStatusExtendedGrace = "Extended grace period ends %ENDDATE%" | |
| # Used for dli/dlv | |
| $L_MsgLicenseStatusUnlicensed_1 = "License Status: Unlicensed" | |
| $L_MsgLicenseStatusLicensed_1 = "License Status: Licensed" | |
| $L_MsgLicenseStatusVL_1 = "Volume activation expiration: %MINUTE% minute(s) (%DAY% day(s))" | |
| $L_MsgLicenseStatusTBL_1 = "Timebased activation expiration: %MINUTE% minute(s) (%DAY% day(s))" | |
| $L_MsgLicenseStatusAVMA_1 = "Automatic VM activation expiration: %MINUTE% minute(s) (%DAY% day(s))" | |
| $L_MsgLicenseStatusInitialGrace_1 = "License Status: Initial grace period" | |
| $L_MsgLicenseStatusAdditionalGrace_1 = "License Status: Additional grace period (KMS license expired or hardware out of tolerance)" | |
| $L_MsgLicenseStatusNonGenuineGrace_1 = "License Status: Non-genuine grace period." | |
| $L_MsgLicenseStatusNotification_1 = "License Status: Notification" | |
| $L_MsgLicenseStatusExtendedGrace_1 = "License Status: Extended grace period" | |
| $L_MsgNotificationErrorReasonNonGenuine = "Notification Reason: 0x%ERRCODE% (non-genuine)." | |
| $L_MsgNotificationErrorReasonExpiration = "Notification Reason: 0x%ERRCODE% (grace time expired)." | |
| $L_MsgNotificationErrorReasonOther = "Notification Reason: 0x%ERRCODE%." | |
| $L_MsgLicenseStatusTimeRemaining = "Time remaining: %MINUTE% minute(s) (%DAY% day(s))" | |
| $L_MsgLicenseStatusUnknown = "License Status: Unknown" | |
| $L_MsgLicenseStatusEvalEndData = "Evaluation End Date: " | |
| $L_MsgReinstallingLicenses = "Re-installing license files ..." | |
| $L_MsgLicensesReinstalled = "License files re-installed successfully." | |
| $L_MsgServiceVersion = "Software licensing service version :" | |
| $L_MsgProductName = "Name: " | |
| $L_MsgProductDesc = "Description: " | |
| $L_MsgActID = "Activation ID: " | |
| $L_MsgAppID = "Application ID: " | |
| $L_MsgPID4 = "Extended PID: " | |
| $L_MsgChannel = "Product Key Channel: " | |
| $L_MsgProcessorCertUrl = "Processor Certificate URL: " | |
| $L_MsgMachineCertUrl = "Machine Certificate URL: " | |
| $L_MsgUseLicenseCertUrl = "License URL: " | |
| $L_MsgPKeyCertUrl = "Product Key Certificate URL: " | |
| $L_MsgValidationUrl = "Validation URL: " | |
| $L_MsgPartialPKey = "Partial Product Key: " | |
| $L_MsgErrorLicenseNotInUse = "This license is not in use." | |
| $L_MsgKmsInfo = "Key Management Service client information" | |
| $L_MsgCmid = "Client Machine ID (CMID): " | |
| $L_MsgRegisteredKmsName = "Registered KMS machine name: " | |
| $L_MsgKmsLookupDomain = "Registered KMS SRV record lookup domain: " | |
| $L_MsgKmsFromDnsUnavailable = "DNS auto-discovery: KMS name not available" | |
| $L_MsgKmsFromDns = "KMS machine name from DNS: " | |
| $L_MsgKmsIpAddress = "KMS machine IP address: " | |
| $L_MsgKmsIpAddressUnavailable = "KMS machine IP address: not available" | |
| $L_MsgKmsPID4 = "KMS machine extended PID: " | |
| $L_MsgActivationInterval = "Activation interval: %INTERVAL% minutes" | |
| $L_MsgRenewalInterval = "Renewal interval: %INTERVAL% minutes" | |
| $L_MsgKmsEnabled = "Key Management Service is enabled on this machine" | |
| $L_MsgKmsCurrentCount = "Current count: " | |
| $L_MsgKmsListeningOnPort = "Listening on Port: " | |
| $L_MsgKmsPriNormal = "KMS priority: Normal" | |
| $L_MsgKmsPriLow = "KMS priority: Low" | |
| $L_MsgVLActivationTypeAll = "Configured Activation Type: All" | |
| $L_MsgVLActivationTypeAD = "Configured Activation Type: AD" | |
| $L_MsgVLActivationTypeKMS = "Configured Activation Type: KMS" | |
| $L_MsgVLActivationTypeToken = "Configured Activation Type: Token" | |
| $L_MsgVLMostrecentActivationInfo = "Most recent activation information:" | |
| $L_MsgInvalidDataError = "Error: The data is invalid" | |
| $L_MsgUndeterminedPrimaryKey = "Warning: SLMGR was not able to validate the current product key for Windows. Please upgrade to the latest service pack." | |
| $L_MsgUndeterminedPrimaryKeyOperation = "Warning: This operation may affect more than one target license. Please verify the results." | |
| $L_MsgUndeterminedOperationFormat = "Processing the license for %PRODUCTDESCRIPTION% (%PRODUCTID%)." | |
| $L_MsgPleaseActivateRefreshKMSInfo = "Please use slmgr.ps1 -ato to activate and update KMS client information in order to update values." | |
| $L_MsgTokenBasedActivationMustBeDone = "This system is configured for Token-based activation only. Use slmgr.ps1 -fta to initiate Token-based activation, or slmgr.ps1 -acttype to change the activation type setting." | |
| $L_MsgSubscriptionEdition = "Subscription edition: " | |
| $L_MsgSubscriptionType = "Subscription type: " | |
| $L_MsgSubscriptionTypeABS = "Azure based subscription" | |
| $L_MsgSubscriptionTypeDBS = "Device based subscription" | |
| $L_MsgSubscriptionTypeUBS = "User based subscription" | |
| $L_MsgSubscriptionTypeUnknown = "Unknown" | |
| $L_MsgSubscriptionStatus = "Subscription status: " | |
| $L_MsgSubscriptionStatusActive = "Active" | |
| $L_MsgSubscriptionStatusNotActive = "Not active" | |
| $L_MsgSubscriptionStatusDisabled = "Disabled" | |
| $L_MsgSubscriptionExpiry = "Subscription expiry: " | |
| $L_MsgSubscriptionStatusExpired = "Expired" | |
| $L_MsgSubscriptionExpiryUnknown = "Unknown" | |
| $L_MsgKmsCumulativeRequestsFromClients = "Key Management Service cumulative requests received from clients" | |
| $L_MsgKmsTotalRequestsRecieved = "Total requests received: " | |
| $L_MsgKmsFailedRequestsReceived = "Failed requests received: " | |
| $L_MsgKmsRequestsWithStatusUnlicensed = "Requests with License Status Unlicensed: " | |
| $L_MsgKmsRequestsWithStatusLicensed = "Requests with License Status Licensed: " | |
| $L_MsgKmsRequestsWithStatusInitialGrace = "Requests with License Status Initial grace period: " | |
| $L_MsgKmsRequestsWithStatusLicenseExpiredOrHwidOot = "Requests with License Status License expired or Hardware out of tolerance: " | |
| $L_MsgKmsRequestsWithStatusNonGenuineGrace = "Requests with License Status Non-genuine grace period: " | |
| $L_MsgKmsRequestsWithStatusNotification = "Requests with License Status Notification: " | |
| $L_MsgRemoteWmiVersionMismatch = "The remote machine does not support this version of SLMgr.ps1" | |
| $L_MsgRemoteExecNotSupported = "This command of SLMgr.ps1 is not supported for remote execution" | |
| # Token-based Activation issuance licenses | |
| $L_MsgTkaLicenses = "Token-based Activation Issuance Licenses:" | |
| $L_MsgTkaLicenseHeader = "%ILID% %ILVID%" | |
| $L_MsgTkaLicenseILID = "License ID (ILID): %ILID%" | |
| $L_MsgTkaLicenseILVID = "Version ID (ILvID): %ILVID%" | |
| $L_MsgTkaLicenseExpiration = "Valid to: %TODATE%" | |
| $L_MsgTkaLicenseAdditionalInfo = "Additional Information: %MOREINFO%" | |
| $L_MsgTkaLicenseAuthZStatus = "Error: 0x%ERRCODE%" | |
| $L_MsgTkaLicenseDescr = "Description: %DESC%" | |
| $L_MsgTkaLicenseNone = "No licenses found." | |
| $L_MsgTkaRemoving = "Removing Token-based Activation License ..." | |
| $L_MsgTkaRemovedItem = "Removed license with SLID=%SLID%." | |
| $L_MsgTkaRemovedNone = "No licenses found." | |
| $L_MsgTkaInfoAdditionalInfo = "Additional Information: %MOREINFO%" | |
| $L_MsgTkaInfo = "Token-based Activation information" | |
| $L_MsgTkaInfoILID = "License ID (ILID): %ILID%" | |
| $L_MsgTkaInfoILVID = "Version ID (ILvID): %ILVID%" | |
| $L_MsgTkaInfoGrantNo = "Grant Number: %GRANTNO%" | |
| $L_MsgTkaInfoThumbprint = "Certificate Thumbprint: %THUMBPRINT%" | |
| $L_MsgTkaCertThumbprint = "Thumbprint: %THUMBPRINT%" | |
| $L_MsgTkaCertSubject = "Subject: %SUBJECT%" | |
| $L_MsgTkaCertIssuer = "Issuer: %ISSUER%" | |
| $L_MsgTkaCertValidFrom = "Valid from: %FROMDATE%" | |
| $L_MsgTkaCertValidTo = "Valid to: %TODATE%" | |
| # AD Activation messages | |
| $L_MsgADInfo = "AD Activation client information" | |
| $L_MsgADInfoAOName = "Activation object name: " | |
| $L_MsgADInfoAODN = "AO DN: " | |
| $L_MsgADInfoExtendedPid = "AO extended PID: " | |
| $L_MsgADInfoActID = "AO activation ID: " | |
| $L_MsgActobjAvailable = "Activation objects" | |
| $L_MsgActobjNoneFound = "No objects found" | |
| $L_MsgSucess = "Operation completed successfully." | |
| $L_MsgADSchemaNotSupported = "Active Directory-Based Activation is not supported in the current Active Directory schema." | |
| # Automatic VM Activation messages | |
| $L_MsgAVMAInfo = "Automatic VM Activation client information" | |
| $L_MsgAVMAID = "Guest IAID: " | |
| $L_MsgAVMAHostMachineName = "Host machine name: " | |
| $L_MsgAVMALastActTime = "Activation time: " | |
| $L_MsgAVMAHostPid2 = "Host Digital PID2: " | |
| $L_MsgNotAvailable = "Not Available" | |
| $L_MsgCurrentTrustedTime = "Trusted time: " | |
| $NoPrimaryKeyFound = "NoPrimaryKeyFound" | |
| $TblPrimaryKey = "TblPrimaryKey" | |
| $notSpecialCasePrimaryKey = "NotSpecialCasePrimaryKey" | |
| $IndeterminatePrimaryKeyFound = "IndeterminatePrimaryKey" | |
| $L_MsgError_C004C001 = "The activation server determined the specified product key is invalid" | |
| $L_MsgError_C004C003 = "The activation server determined the specified product key is blocked" | |
| $L_MsgError_C004C017 = "The activation server determined the specified product key has been blocked for this geographic location." | |
| $L_MsgError_C004B100 = "The activation server determined that the computer could not be activated" | |
| $L_MsgError_C004C008 = "The activation server determined that the specified product key could not be used" | |
| $L_MsgError_C004C020 = "The activation server reported that the Multiple Activation Key has exceeded its limit" | |
| $L_MsgError_C004C021 = "The activation server reported that the Multiple Activation Key extension limit has been exceeded" | |
| $L_MsgError_C004D307 = "The maximum allowed number of re-arms has been exceeded. You must re-install the OS before trying to re-arm again" | |
| $L_MsgError_C004F009 = "The software Licensing Service reported that the grace period expired" | |
| $L_MsgError_C004F00F = "The Software Licensing Server reported that the hardware ID binding is beyond level of tolerance" | |
| $L_MsgError_C004F014 = "The Software Licensing Service reported that the product key is not available" | |
| $L_MsgError_C004F025 = "Access denied: the requested action requires elevated privileges" | |
| $L_MsgError_C004F02C = "The software Licensing Service reported that the format for the offline activation data is incorrect" | |
| $L_MsgError_C004F035 = "The software Licensing Service reported that the computer could not be activated with a Volume license product key. Volume licensed systems require upgrading from a qualified operating system. Please contact your system administrator or use a different type of key" | |
| $L_MsgError_C004F038 = "The software Licensing Service reported that the computer could not be activated. The count reported by your Key Management Service (KMS) is insufficient. Please contact your system administrator" | |
| $L_MsgError_C004F039 = "The software Licensing Service reported that the computer could not be activated. The Key Management Service (KMS) is not enabled" | |
| $L_MsgError_C004F041 = "The software Licensing Service determined that the Key Management Server (KMS) is not activated. KMS needs to be activated" | |
| $L_MsgError_C004F042 = "The software Licensing Service determined that the specified Key Management Service (KMS) cannot be used" | |
| $L_MsgError_C004F050 = "The Software Licensing Service reported that the product key is invalid" | |
| $L_MsgError_C004F051 = "The software Licensing Service reported that the product key is blocked" | |
| $L_MsgError_C004F064 = "The software Licensing Service reported that the non-Genuine grace period expired" | |
| $L_MsgError_C004F065 = "The software Licensing Service reported that the application is running within the valid non-genuine period" | |
| $L_MsgError_C004F066 = "The Software Licensing Service reported that the product SKU is not found" | |
| $L_MsgError_C004F06B = "The software Licensing Service determined that it is running in a virtual machine. The Key Management Service (KMS) is not supported in this mode" | |
| $L_MsgError_C004F074 = "The Software Licensing Service reported that the computer could not be activated. No Key Management Service (KMS) could be contacted. Please see the Application Event Log for additional information." | |
| $L_MsgError_C004F075 = "The Software Licensing Service reported that the operation cannot be completed because the service is stopping" | |
| $L_MsgError_C004F304 = "The Software Licensing Service reported that required license could not be found." | |
| $L_MsgError_C004F305 = "The Software Licensing Service reported that there are no certificates found in the system that could activate the product." | |
| $L_MsgError_C004F30A = "The Software Licensing Service reported that the computer could not be activated. The certificate does not match the conditions in the license." | |
| $L_MsgError_C004F30D = "The Software Licensing Service reported that the computer could not be activated. The thumbprint is invalid." | |
| $L_MsgError_C004F30E = "The Software Licensing Service reported that the computer could not be activated. A certificate for the thumbprint could not be found." | |
| $L_MsgError_C004F30F = "The Software Licensing Service reported that the computer could not be activated. The certificate does not match the criteria specified in the issuance license." | |
| $L_MsgError_C004F310 = "The Software Licensing Service reported that the computer could not be activated. The certificate does not match the trust point identifier (TPID) specified in the issuance license." | |
| $L_MsgError_C004F311 = "The Software Licensing Service reported that the computer could not be activated. A soft token cannot be used for activation." | |
| $L_MsgError_C004F312 = "The Software Licensing Service reported that the computer could not be activated. The certificate cannot be used because its private key is exportable." | |
| $L_MsgError_5 = "Access denied: the requested action requires elevated privileges" | |
| $L_MsgError_80070005 = "Access denied: the requested action requires elevated privileges" | |
| $L_MsgError_80070057 = "The parameter is incorrect" | |
| $L_MsgError_8007232A = "DNS server failure" | |
| $L_MsgError_8007232B = "DNS name does not exist" | |
| $L_MsgError_800706BA = "The RPC server is unavailable" | |
| $L_MsgError_8007251D = "No records found for DNS query" | |
| # Registry constants | |
| $HKEY_LOCAL_MACHINE = 0x80000002 | |
| $HKEY_NETWORK_SERVICE = 0x80000003 | |
| $DefaultPort = "1688" | |
| $intKnownOption = 0 | |
| $intUnknownOption = 1 | |
| $SLKeyPath = "SOFTWARE\Microsoft\Windows NT\CurrentVersion\SoftwareProtectionPlatform" | |
| $SLKeyPath32 = "SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\SoftwareProtectionPlatform" | |
| $NSKeyPath = "S-1-5-20\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SoftwareProtectionPlatform" | |
| $HR_S_OK = 0 | |
| $HR_ERROR_FILE_NOT_FOUND = 0x80070002 | |
| $HR_SL_E_GRACE_TIME_EXPIRED = 0xC004F009 | |
| $HR_SL_E_NOT_GENUINE = 0xC004F200 | |
| $HR_SL_E_PKEY_NOT_INSTALLED = 0xC004F014 | |
| $HR_INVALID_ARG = 0x80070057 | |
| $HR_ERROR_DS_NO_SUCH_objECT = 0x80072030 | |
| # AD Activation constants | |
| $ADLdapProvider = "LDAP:" | |
| $ADLdapProviderPrefix = "LDAP://" | |
| $ADRootDSE = "rootDSE" | |
| $ADConfigurationNC = "configurationNamingContext" | |
| $ADActobjContainer = "CN=Activation Objects,CN=Microsoft SPP,CN=Services," | |
| $ADActobjContainerClass = "msSPP-ActivationobjectsContainer" | |
| $ADActobjClass = "msSPP-Activationobject" | |
| $ADActobjAttribSkuId = "msSPP-CSVLKSkuId" | |
| $ADActobjAttribPid = "msSPP-CSVLKPid" | |
| $ADActobjAttribPartialPkey = "msSPP-CSVLKPartialProductKey" | |
| $ADActobjDisplayName = "displayName" | |
| $ADActobjAttribDN = "distinguishedName" | |
| $ADS_READONLY_SERVER = 4 | |
| # CIM class names | |
| $ServiceClass = "SoftwareLicensingService" | |
| $ProductClass = "SoftwareLicensingProduct" | |
| $TkaLicenseClass = "SoftwareLicensingTokenActivationLicense" | |
| $WindowsAppId = "55c92734-d682-4d71-983e-d6ec3f16059f" | |
| $ProductIsPrimarySkuSelectClause = "ID, ApplicationId, PartialProductKey, LicenseIsAddon, Description, Name" | |
| $KMSClientLookupClause = "KeyManagementServiceMachine, KeyManagementServicePort, KeyManagementServiceLookupDomain" | |
| $PartialProductKeyNonNullWhereClause = "PartialProductKey <> null" | |
| $EmptyWhereClause = "" | |
| $wbemImpersonationLevelImpersonate = 3 | |
| $wbemAuthenticationLevelPktPrivacy = 6 | |
| #endregion Messages | |
| # The show begins here | |
| main | |
| #Exit-Script 0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment