Freigeben über


Automating WIM2VHD

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="https://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="https://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="https://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="https://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="https://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="https://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="https://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="https://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="https://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="https://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="https://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="https://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="https://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="https://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="https://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="https://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="https://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="https://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="https://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="https://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="https://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="https://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="https://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="https://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

Unattend.zip

Comments

  • Anonymous
    June 27, 2011
    The comment has been removed

  • Anonymous
    July 06, 2011
    The comment has been removed

  • Anonymous
    July 06, 2011
    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

  • Anonymous
    August 03, 2011
    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