Mdt the unattend answer file contains an invalid product key

From Svendsen Tech PowerShell Wiki
Jump to: navigation, search




General Information

So you set up MDT (Microsoft Deployment Tools) and want to deploy Windows 7 or Server 2008 R2 (or Vista/2008); you import the OS install files or a custom image and go through the task sequence setup procedure; here you specify a product key when asked (if you read what it says, you're not supposed to do this for Windows 2008/Vista and later), and when you try to deploy, you get the dreaded "The unattend(ed) answer file contains an invalid product key" error message.

Error Message

The error message you will get is:

Title: Install Windows

The unattend answer file contains an invalid product key. Either remove the
invalid key or provide a valid product key in the unattend answer file to proceed
with Windows installation.

Screenshot from Microsoft Deployment Tools 2012:

Mdt-the-unattend-answer-file-contains-an-invalid-product-key.png

Overall Summary Deployment Error Message

Operating system deployment did not complete successfully

Please review the log files to determine the cause of the problem.

During the deployment process, 9 errors and 0 warnings were reported.

Details...
Setup failed applying image \\server\DeploymentShare$\Operating Systems\
Windows Server 2008 R2 x64\Sources\install.wim, rc = 31

ZTI ERROR - Non-zero return code by LTIApply, rc = 31

Litetouch deployment failed, Return Code = -2147467259 0x80004005

Failed to run the action: Install Operating System.
A device attached to the system is not functioning.
(Error: 0000001F; Source: Windows)

The execution of the group (Install) has failed and the execution
has been aborted. An action failed.

Operation aborted (Error: 80004004; Source: Windows)

Failed to run the last action: Install Operating System.
Execution of task sequence failed.
[...]

Mdt-deployment-summary-error.png

Solution

To solve this, you need to do what it says: Remove the product key (from the correct location). Make sure you back up the original file before you edit it. Just "copy .\Unattend.xml Unattend-original.xml" from PowerShell or a quick Ctrl-C + Ctrl-V on the file in Windows Explorer will do.

I've found that the simplest way of doing this is starting an administrator PowerShell console and navigating to <drive>:\DeploymentShare\control\<task_sequence_ID> - where the drive and task sequence ID are from your environment.

Then you can pop up notepad from the administrator PowerShell console and remove the first occurrence of a product key you see in the "UserData" section - or run a pretty nasty PowerShell one-liner, which you can see below.

An example of the commands to execute for the "notepad method" is:

PS C:\> cd "C:\DeploymentShare\control\2008R2CORE-001"
PS C:\DeploymentShare\control\2008R2CORE-001> notepad unattend.xml

With Notepad

Delete this highlighted section indicated in the picture:

Mdt-unattend-xml-productkey-delete.png

With PowerShell

I wrote a one-liner that does it with a pretty nasty regexp (read more about PowerShell regular expressions here). This isn't best practices by any means, but I'm adding it anyway. Be aware that you can't copy/paste the command from this page directly into the PowerShell console window, because I added newlines for readability.

This one-liner will open Unattend.xml (gc .\Unattend.xml), join it with newlines and run my magic regexp against the string. Then this will be split on newlines again to preserve layout. Then it's piped to Where-Object/?/Where, which removes blank lines; otherwise you will have a blank line, but it doesn't break the XML, so it's not strictly necessary. Then it's finally piped to Out-File which saves it to "Unattend-temp.xml", using UTF-8 encoding.

PS C:\DeploymentShare\control\2008R2CORE-001>
((gc .\Unattend.xml) -join "`n" -ireplace
'(?s)(<UserData>.*?)<ProductKey>.*?<Key>[^<]*</Key>.*?</ProductKey>(.*?</UserData>)',
'${1}${2}') -split "`n" | ? { $_ -match '\S' } | Out-File -Encoding utf8 .\Unattend-temp.xml

Here is a paste-friendly version:

((gc .\Unattend.xml) -join "`n" -ireplace '(?s)(<UserData>.*?)<ProductKey>.*?<Key>[^<]*</Key>.*?</ProductKey>(.*?</UserData>)', '${1}${2}') -split "`n" | ? { $_ -match '\S' } | Out-File -Encoding utf8 .\Unattend-temp.xml

Verifying Results From The Command Line

First, we can look at what's in the UserData section in the original file:

PS C:\DeploymentShare\control\2008R2CORE-001>
((gc .\Unattend.xml) -join "`n") -match '(?s)(\s+<UserData>.+?</UserData>)'; $matches[1]
True

      <UserData>
        <AcceptEula>true</AcceptEula>
        <ProductKey>
          <Key>12345-ABCDE-12345-ABCDE-12345</Key>
        </ProductKey>
      </UserData>


Then look at the temp file we created with the one-liner above to see that the product key and the tags indeed are removed from the UserData section:

PS C:\DeploymentShare\control\2008R2CORE-001>
((gc .\Unattend-temp.xml) -join "`n") -match '(?s)(\s+<UserData>.+?</UserData>)'; $matches[1]
True

      <UserData>
        <AcceptEula>true</AcceptEula>
      </UserData>

Put the New Unattend.xml File To Use

Then you need to swap the files to put Unattend-temp.xml to use:

PS C:\DeploymentShare\control\2008R2CORE-001> move .\Unattend.xml .\Unattend-old.xml
PS C:\DeploymentShare\control\2008R2CORE-001> move .\Unattend-temp.xml Unattend.xml