Automating WIM2VHD

Automating WIM2VHD

Rate This
  • Comments 4


As I mentioned yesterday – I have been working on a completely automated virtual machine build process that does not use templates (but build everything from scratch).  One of the key tools that I have been using for this process is WIM2VHD – which allows me to generate new VHD files directly from Windows installation media.

However – I wanted to go a step further and have the virtual machines generated using this process boot in a completely unattended fashion.  My ultimate goal here was to go from nothing to having a virtual machine logged into the desktop with no external interaction.

Luckily, WIM2VHD allows you to specify a unattended installation file to be injected into the virtual hard disk.  I installed the Windows Automated Installation Kit for Windows 7 and then used the Windows System Image Manager to create some unattended installation files.  One of the interesting problems though is that not all sections of the unattended file are referenced when used with WIM2VHD.  In fact, only the specialize and oobeSystem sections are used.  So I had to figure out how to do everything I wanted in these two sections.

Below are the unattended files that I created (with serial numbers struck out):

Unattended file for Windows 7 32-bit:

<?xml version="1.0" encoding="utf-8"?>
<unattend xmlns="urn:schemas-microsoft-com:unattend">
    <settings pass="specialize">
        <component name="Microsoft-Windows-Shell-Setup" processorArchitecture="x86" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
            <AutoLogon>
                <Password>
                    <Value>p@ssw0rd</Value>
                    <PlainText>true</PlainText>
                </Password>
                <Domain>QuickSetup</Domain>
                <Enabled>true</Enabled>
                <LogonCount>1</LogonCount>
                <Username>Test</Username>
            </AutoLogon>
            <ComputerName>QuickSetup</ComputerName>
            <ProductKey>*****-*****-*****-*****-*****</ProductKey>
            <TimeZone>Pacific Standard Time</TimeZone>
        </component>
        <component name="Microsoft-Windows-UnattendedJoin" processorArchitecture="x86" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
            <Identification>
                <JoinWorkgroup>QuickWorkgroup</JoinWorkgroup>
                <UnsecureJoin>true</UnsecureJoin>
            </Identification>
        </component>
    </settings>
    <settings pass="oobeSystem">
        <component name="Microsoft-Windows-Shell-Setup" processorArchitecture="x86" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
            <OOBE>
                <HideEULAPage>true</HideEULAPage>
                <HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>
                <NetworkLocation>Work</NetworkLocation>
                <ProtectYourPC>3</ProtectYourPC>
            </OOBE>
            <UserAccounts>
                <AdministratorPassword>
                    <Value>p@ssw0rd</Value>
                    <PlainText>true</PlainText>
                </AdministratorPassword>
                <LocalAccounts>
                    <LocalAccount wcm:action="add">
                        <Password>
                           <Value>p@ssw0rd</Value>
                           <PlainText>true</PlainText>
                        </Password>
                        <Description>Test</Description>
                        <DisplayName>Test</DisplayName>
                        <Group>Administrators</Group>
                        <Name>Test</Name>
                    </LocalAccount>
                </LocalAccounts>
            </UserAccounts>
        </component>
        <component name="Microsoft-Windows-International-Core" processorArchitecture="x86" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
            <InputLocale>en-us</InputLocale>
            <SystemLocale>en-us</SystemLocale>
            <UILanguage>en-us</UILanguage>
            <UILanguageFallback>en-us</UILanguageFallback>
            <UserLocale>en-us</UserLocale>
        </component>
    </settings>
</unattend>

Unattended file for Windows 7 64-bit:

<?xml version="1.0" encoding="utf-8"?>
<unattend xmlns="urn:schemas-microsoft-com:unattend">
    <settings pass="specialize">
        <component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
            <AutoLogon>
                <Password>
                    <Value>p@ssw0rd</Value>
                    <PlainText>true</PlainText>
                </Password>
                <Domain>QuickSetup</Domain>
                <Enabled>true</Enabled>
                <LogonCount>1</LogonCount>
                <Username>Test</Username>
            </AutoLogon>
            <ComputerName>QuickSetup</ComputerName>
            <ProductKey>*****-*****-*****-*****-*****</ProductKey>
            <TimeZone>Pacific Standard Time</TimeZone>
        </component>
        <component name="Microsoft-Windows-UnattendedJoin" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
            <Identification>
                <JoinWorkgroup>QuickWorkgroup</JoinWorkgroup>
                <UnsecureJoin>true</UnsecureJoin>
            </Identification>
        </component>
    </settings>
    <settings pass="oobeSystem">
        <component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
            <OOBE>
                <HideEULAPage>true</HideEULAPage>
                <HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>
                <NetworkLocation>Work</NetworkLocation>
                <ProtectYourPC>3</ProtectYourPC>
            </OOBE>
            <UserAccounts>
                <AdministratorPassword>
                    <Value>p@ssw0rd</Value>
                    <PlainText>true</PlainText>
                </AdministratorPassword>
                <LocalAccounts>
                    <LocalAccount wcm:action="add">
                        <Password>
                           <Value>p@ssw0rd</Value>
                           <PlainText>true</PlainText>
                        </Password>
                        <Description>Test</Description>
                        <DisplayName>Test</DisplayName>
                        <Group>Administrators</Group>
                        <Name>Test</Name>
                    </LocalAccount>
                </LocalAccounts>
            </UserAccounts>
        </component>
        <component name="Microsoft-Windows-International-Core" processorArchitecture="x86" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
            <InputLocale>en-us</InputLocale>
            <SystemLocale>en-us</SystemLocale>
            <UILanguage>en-us</UILanguage>
            <UILanguageFallback>en-us</UILanguageFallback>
            <UserLocale>en-us</UserLocale>
        </component>
    </settings>
</unattend>

Unattended file for Windows Server 2008 R2:

<?xml version="1.0" encoding="utf-8"?>
<unattend xmlns="urn:schemas-microsoft-com:unattend">
    <servicing></servicing>
    <settings pass="specialize">
        <component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
            <AutoLogon>
                <Password>
                    <Value>p@ssw0rd</Value>
                    <PlainText>True</PlainText>
                </Password>
                <Domain>QuickSetup</Domain>
                <Enabled>true</Enabled>
                <LogonCount>1</LogonCount>
                <Username>Administrator</Username>
            </AutoLogon>
            <ComputerName>QuickSetup</ComputerName>
            <ProductKey>*****-*****-*****-*****-*****</ProductKey>
            <RegisteredOrganization>Microsoft</RegisteredOrganization>
            <RegisteredOwner>Ben Armstrong</RegisteredOwner>
            <TimeZone>Pacific Standard Time</TimeZone>
        </component>
        <component name="Microsoft-Windows-UnattendedJoin" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
            <Identification>
                <JoinWorkgroup>QuickWorkgroup</JoinWorkgroup>
                <UnsecureJoin>true</UnsecureJoin>
            </Identification>
        </component>
    </settings>
    <settings pass="oobeSystem">
        <component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
            <OOBE>
                <HideEULAPage>true</HideEULAPage>
                <HideLocalAccountScreen>true</HideLocalAccountScreen>
                <HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>
                <NetworkLocation>Work</NetworkLocation>
                <ProtectYourPC>1</ProtectYourPC>
            </OOBE>
            <UserAccounts>
                <AdministratorPassword>
                    <Value>p@ssw0rd</Value>
                    <PlainText>True</PlainText>
                </AdministratorPassword>
            </UserAccounts>
        </component>
        <component name="Microsoft-Windows-International-Core" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
            <InputLocale>en-us</InputLocale>
            <SystemLocale>en-us</SystemLocale>
            <UILanguage>en-us</UILanguage>
            <UILanguageFallback>en-us</UILanguageFallback>
            <UserLocale>en-us</UserLocale>
        </component>
    </settings>
</unattend>

Using these files with WIM2VHD is quite simple – you just use a command like this:

cscript wim2vhd.wsf /wim:"I:\sources\install.wim" /sku:ULTIMATE /VHD:".\NewClient.vhd" /size:40000 /disktype:dynamic /unattend:unattendClient32.xml

Cheers,
Ben

Attachment: Unattend.zip
Leave a Comment
  • Please add 8 and 4 and type the answer here:
  • Post
  • I was using W2K8 R2 SP1 bits from technet and made single change to the startup command: "/sku:SERVERENTERPRISE". It failed saying that is unable to process oobeSystem part of unattend.xml file. Further investigation revealed that the problem is caused by "HideLocalAccountScreen" component that does not belong there. Any idea how it got there? :) Anyway - after removing it everything works like a charm! Good job!

  • FYI: In your "Unattended file for Windows 7 64-bit" - in the last component secton 'name="Microsoft-Windows-International-Core"' - you left processorArchitecture="x86", instead of "amd64"...

    Ah! - the joys of cut-and-paste...

    Thanks for the great solution!!!

  • BruceH -

    That is not a "cut and paste" issue.  For reasons that I do not understand, the x64 unattend file still has a x86 section for the International configuration.  This is what the image management tool generates - and if you change it to x64 it will not work.

    Cheers,

    Ben

  • Hi Ben,

    Great stuff which I'll happily use for easy deployment of VM's. I'll also look into adapting this for the unattended deployment of physical Hyper-V Server 2008R2 clusternodes so based on standardized hardware I can add more power (by adding more nodes) to my cluster or in case of hardware failure, easy replace the node.

    Recently started a personal project: I'm currently building a low-power, well-performing three-node-cluster based on Hyper-V Server 2008R2 from scratch (literally throwing the hardware together) to configuring to fully operational.

    You can follow the progress on: www.mdg4projects.nl/technotes

    You're definitely an inspiration!

    Thx!

    Ray

Page 1 of 1 (4 items)