Install Volume License (MAK) key and activate Windows 8

I’ve always wondered why Microsoft did not turn the slmgr.vbs script (Software Licensing Manager) to Powershell.

There’s now in V3 a cmdlet called Set-WindowsProductKey coming from the DISM built-in module. It’s seems to have a promising -Online parameter according to the following online help
online switch
However it doesn’t work. I believe that the DISM module is primarily used for servicing offline images and that the Online parameterSet hasn’t been implemented yet 😦
online fails

Ed Wilson, the Hey Scripting Guy showed us yesterday how to check for the license status of Windows 8. It’s a nice valuable article that you can read on this page.

I propose to show how to actually install a volume license and activate it

# Requires -version 3.0

Function Set-VLkey
{
[CmdletBinding()]
param(

    [Parameter(ValueFromPipeline,ValueFromPipelineByPropertyName)]            
    [Alias("CN","__SERVER","IPAddress")]            
    [system.string[]]$ComputerName = ".",

    [parameter()]
    [System.Management.Automation.PSCredential]$Credential,

    [parameter(Mandatory)]
    [ValidatePattern('(([0-9A-Z]{5}\-)){4}([0-9A-Z]{5})$')]    
    [system.string]$Key=$null
)
Begin {
    # Make sure we run as admin            
    $usercontext = [Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()            
    $IsAdmin = $usercontext.IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")                               
    if (-not($IsAdmin))            
    {            
        Write-Warning "Must run powerShell as Administrator to perform these actions"            
        return            
    }
    # Define some registry constants            
    $HKLM = 2147483650
    $Key1 = 'SOFTWARE\Microsoft\Windows NT\CurrentVersion\SoftwareProtectionPlatform'
    $Key2 = 'SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\SoftwareProtectionPlatform'
}    
Process {
    $ComputerName | ForEach-Object -Process {
        $TargetComputer = $_
        # Prepare a default HT            
        $wmiHT = @{            
            ErrorAction = "Stop";            
        }            
        Switch ($TargetComputer)
        {
            {$_ -eq ($Env:Computername)} {$IsRemoteComputer = $false ; break}
            {$_ -eq "."}                 {$IsRemoteComputer = $false ; break}
            {$_ -eq "::1"}               {$IsRemoteComputer = $false ; break}
            {$_ -eq "127.0.0.1"}         {$IsRemoteComputer = $false ; break}
            {$_ -eq "localhost"}         {$IsRemoteComputer = $false ; break}
            default {
                $IsRemoteComputer = $true
            }            
        }
        if($IsRemoteComputer)
        {
            $wmiHT += @{ 
                Authentication = 6;
                Impersonation  = 3;
                Computername   = $TargetComputer;
            }
            if ($Credential)
            {
                $wmiHT += @{ Credential = $Credential }
            }
        }
        # Get the SPP service version on the remote machine
        try
        {
            $SLsvc = Get-WmiObject -Query 'Select Version from SoftwareLicensingService' @wmiHT
        } catch {
            Write-Warning -Message "Failed to query WMI on $TargetComputer because $($_.Exception.Message)"
        }
        if ($SLsvc)
        {
            $Version = $SLsvc.Version
        } else {
            # We could not connect, skip that computer
            return
        }
        if($IsRemoteComputer)
        {
            # Make sure the remote computer is W8/2012 as it seems that: 
            # 'The Windows 8 version of SLMgr.vbs does not support remote connections to Vista/WS08 and Windows 7/WS08R2 machines'
            if (-not([version]$Version -gt ([version]'6.2')))            
            {            
                Write-Warning -Message "The remote machine $TargetComputer does not support this version of SLMgr.vbs"
                return            
            }
        }        
        # Here we go!
        try
        {
            Write-Verbose -Message "Installing product key $MAK on $TargetComputer"
            Invoke-WmiMethod -InputObject $SLsvc -Name InstallProductKey -ArgumentList $MAK @wmiHT | Out-Null
            Invoke-WmiMethod -InputObject $SLsvc -Name RefreshLicenseStatus @wmiHT | Out-Null
            $SLProduct = Get-WmiObject -Query 'Select * FROM SoftwareLicensingProduct WHERE PartialProductKey <> null' @wmiHT
            Invoke-WmiMethod -Path "ROOT\DEFAULT:StdRegProv" -Name SetStringValue -ArgumentList $HKLM,$Key1,$Version,"KeyManagementServiceVersion" @wmiHT | Out-Null
            Invoke-WmiMethod -Path "ROOT\DEFAULT:StdRegProv" -Name SetStringValue -ArgumentList $HKLM,$Key2,$Version,"KeyManagementServiceVersion" @wmiHT | Out-Null
            'Installed product key {0} successfully on {1}.' -f $MAK,$TargetComputer
            # ' Avoid using a MAK activation count up unless needed'
            'Activating {0} ({1}) ...' -f ($SLProduct.Name),($SLProduct.ID)
            if (($SLProduct.Description -notmatch "MAK") -or ($SLProduct.LicenseStatus -ne 1))
            {
                Write-Verbose -Message "Attempting to activate product on $TargetComputer"
                Invoke-WmiMethod -InputObject $SLProduct -Name Activate @wmiHT | Out-Null
                Invoke-WmiMethod -InputObject $SLSvc -Name RefreshLicenseStatus @wmiHT | Out-Null
            }
            'Product activated successfully on {0}.' -f $TargetComputer
        } catch {
            Write-Warning -Message "Failed to install key and activate computer $TargetComputer because $($_.Exception.Message)"
            return
        }
    }
}
End {}
<#
.SYNOPSIS    
    Set the volume license key
 
.DESCRIPTION  
    Install a volume license key and activate it online if required

.PARAMETER ComputerName
    Array of computers to target
 
.PARAMETER Credential
    Specify the credential to use to target remote computers

.PARAMETER Key
    ProductKey to be installed in format '12345-12345-12345-12345-12345'

.EXAMPLE    
    Set-VLkey -Key '12345-12345-12345-12345-12345'

.EXAMPLE    
    Set-VLkey -Key '12345-12345-12345-12345-12345' -Verbose 

.EXAMPLE    
     "RemotePC1","RemotePC2" | Set-VLkey -Key '12345-12345-12345-12345-12345' -Credential (Get-Credential) -Verbose 

.NOTES    
    Name: Set-VLkey
    Author: Emin Atac
    DateCreated: 22/08/2012
 
.LINK    
    https://p0w3rsh3ll.wordpress.com
 
#>
}

Something strange also with the SetStringValue and the Invoke-WMIMethod. I have had to invert the ValueName and the Value to have it correctly set in the registry whereas it’s mentioned differently on this page.

Advertisements

3 thoughts on “Install Volume License (MAK) key and activate Windows 8

  1. I have used the heart of the Set-VLkey function to inject my MAK key and activate online my Windows 8.
    I haven’t been able to fully test the function against remote computers.
    If you like that post and used the function (there’s a source button on the top right corner of the code block) to activate successfully your Windows 8, pls post a comment here to let me know that it works.
    If you encounter a coding error, pls also let me know… but pls don’t flood the comments list with errors related to your key (ex: injecting a wrong key like a Windows Vista/7 key on a W8 won’t work).

  2. Updated code to replace a previous undefined variable $MAK by the correct function argument $Key

    # Requires -version 3.0
    
    Function Set-VLkey
    {
    [CmdletBinding()]
    param(
    
        [Parameter(ValueFromPipeline,ValueFromPipelineByPropertyName)]            
        [Alias("CN","__SERVER","IPAddress")]            
        [system.string[]]$ComputerName = ".",
    
        [parameter()]
        [System.Management.Automation.PSCredential]$Credential,
    
        [parameter(Mandatory)]
        [ValidatePattern('(([0-9A-Z]{5}\-)){4}([0-9A-Z]{5})$')]    
        [system.string]$Key=$null
    )
    Begin {
        # Make sure we run as admin            
        $usercontext = [Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()            
        $IsAdmin = $usercontext.IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")                               
        if (-not($IsAdmin))            
        {            
            Write-Warning "Must run powerShell as Administrator to perform these actions"            
            return            
        }
        # Define some registry constants            
        $HKLM = 2147483650
        $Key1 = 'SOFTWARE\Microsoft\Windows NT\CurrentVersion\SoftwareProtectionPlatform'
        $Key2 = 'SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\SoftwareProtectionPlatform'
    }    
    Process {
        $ComputerName | ForEach-Object -Process {
            $TargetComputer = $_
            # Prepare a default HT            
            $wmiHT = @{            
                ErrorAction = "Stop";            
            }            
            Switch ($TargetComputer)
            {
                {$_ -eq ($Env:Computername)} {$IsRemoteComputer = $false ; break}
                {$_ -eq "."}                 {$IsRemoteComputer = $false ; break}
                {$_ -eq "::1"}               {$IsRemoteComputer = $false ; break}
                {$_ -eq "127.0.0.1"}         {$IsRemoteComputer = $false ; break}
                {$_ -eq "localhost"}         {$IsRemoteComputer = $false ; break}
                default {
                    $IsRemoteComputer = $true
                }            
            }
            if($IsRemoteComputer)
            {
                $wmiHT += @{ 
                    Authentication = 6;
                    Impersonation  = 3;
                    Computername   = $TargetComputer;
                }
                if ($Credential)
                {
                    $wmiHT += @{ Credential = $Credential }
                }
            }
            # Get the SPP service version on the remote machine
            try
            {
                $SLsvc = Get-WmiObject -Query 'Select Version from SoftwareLicensingService' @wmiHT
            } catch {
                Write-Warning -Message "Failed to query WMI on $TargetComputer because $($_.Exception.Message)"
            }
            if ($SLsvc)
            {
                $Version = $SLsvc.Version
            } else {
                # We could not connect, skip that computer
                return
            }
            if($IsRemoteComputer)
            {
                # Make sure the remote computer is W8/2012 as it seems that: 
                # 'The Windows 8 version of SLMgr.vbs does not support remote connections to Vista/WS08 and Windows 7/WS08R2 machines'
                if (-not([version]$Version -gt ([version]'6.2')))            
                {            
                    Write-Warning -Message "The remote machine $TargetComputer does not support this version of SLMgr.vbs"
                    return            
                }
            }        
            # Here we go!
            try
            {
                Write-Verbose -Message "Installing product key $Key on $TargetComputer"
                Invoke-WmiMethod -InputObject $SLsvc -Name InstallProductKey -ArgumentList $Key @wmiHT | Out-Null
                Invoke-WmiMethod -InputObject $SLsvc -Name RefreshLicenseStatus @wmiHT | Out-Null
                $SLProduct = Get-WmiObject -Query 'Select * FROM SoftwareLicensingProduct WHERE PartialProductKey <> null' @wmiHT
                Invoke-WmiMethod -Path "ROOT\DEFAULT:StdRegProv" -Name SetStringValue -ArgumentList $HKLM,$Key1,$Version,"KeyManagementServiceVersion" @wmiHT | Out-Null
                Invoke-WmiMethod -Path "ROOT\DEFAULT:StdRegProv" -Name SetStringValue -ArgumentList $HKLM,$Key2,$Version,"KeyManagementServiceVersion" @wmiHT | Out-Null
                'Installed product key {0} successfully on {1}.' -f $Key,$TargetComputer
                # ' Avoid using a MAK activation count up unless needed'
                'Activating {0} ({1}) ...' -f ($SLProduct.Name),($SLProduct.ID)
                if (($SLProduct.Description -notmatch "MAK") -or ($SLProduct.LicenseStatus -ne 1))
                {
                    Write-Verbose -Message "Attempting to activate product on $TargetComputer"
                    Invoke-WmiMethod -InputObject $SLProduct -Name Activate @wmiHT | Out-Null
                    Invoke-WmiMethod -InputObject $SLSvc -Name RefreshLicenseStatus @wmiHT | Out-Null
                }
                'Product activated successfully on {0}.' -f $TargetComputer
            } catch {
                Write-Warning -Message "Failed to install key and activate computer $TargetComputer because $($_.Exception.Message)"
                return
            }
        }
    }
    End {}
    <#
    .SYNOPSIS    
        Set the volume license key
     
    .DESCRIPTION  
        Install a volume license key and activate it online if required
    
    .PARAMETER ComputerName
        Array of computers to target
     
    .PARAMETER Credential
        Specify the credential to use to target remote computers
    
    .PARAMETER Key
        ProductKey to be installed in format '12345-12345-12345-12345-12345'
    
    .EXAMPLE    
        Set-VLkey -Key '12345-12345-12345-12345-12345'
    
    .EXAMPLE    
        Set-VLkey -Key '12345-12345-12345-12345-12345' -Verbose 
    
    .EXAMPLE    
         "RemotePC1","RemotePC2" | Set-VLkey -Key '12345-12345-12345-12345-12345' -Credential (Get-Credential) -Verbose 
    
    .NOTES    
        Name: Set-VLkey
        Author: Emin Atac
        DateCreated: 22/08/2012
     
    .LINK    
        https://p0w3rsh3ll.wordpress.com
     
    #>
    }
    
    

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s