# Use Windows Sysprep with resource handlers

> Generate Windows Sysprep Answer files to customize Windows VMs provisioned through Cloud Management Platform (CMP) resource handlers

---

Site [llms.txt](/llms.txt)

---

[Microsoft Windows System Preparation (Sysprep)](https://learn.microsoft.com/en-us/windows-hardware/manufacture/desktop/sysprep--system-preparation--overview?view=windows-11) prepares a Windows installation for imaging by removing system-specific data, allowing it to be deployed on other machines.

Sysprep can be used independently or with an **[Answer file](https://learn.microsoft.com/en-us/windows-hardware/manufacture/desktop/update-windows-settings-and-scripts-create-your-own-answer-file-sxs)** (also known as an *unattend file* or *unattend.xml*). The Answer file instructs Sysprep how to configure the operating system during the next boot.

<div class="alert alert-info" role="alert">


When using Sysprep with an Answer file that includes CMP resource handlers, note that the XML Answer file adheres to a strict schema. **Sysprep fails if the Answer file contains malformed XML, misplaced values, or incorrectly structured elements.**
</div>


## Resource handler Sysprep support

The following resource handlers natively support VM customization with Sysprep:

| Resource handler | Parameter name |
| --- | --- |
| [Hyper-V](/docs/cmp/configure/infrastructure/resource-handlers/hyper-v/) | `hyperv_sysprep_file` |
| [Nutanix Acropolis](/docs/cmp/configure/infrastructure/resource-handlers/nutanix/) | `acropolis_sysprep_file` |
| [Oracle Linux Virtualization Manager](/docs/cmp/configure/infrastructure/resource-handlers/olvm/) | `olvm_sysprep_file` |
| [VMware](/docs/cmp/configure/infrastructure/resource-handlers/vmware-vcenter/) | `vmware_sysprep_file` |

<div class="alert alert-info" role="alert">


Other resource handlers can use Sysprep through remote scripts or CMP plugins executed during post-provision orchestration, but they do not provide native Sysprep integration.
</div>


## Preparing a Sysprep Answer file

To prepare an Answer file for a Windows image:

1. **Install the [Windows Assessment and Deployment Kit (Windows ADK)](https://learn.microsoft.com/en-us/windows-hardware/get-started/adk-install).**

   This installs **[Windows System Image Manager (Windows SIM)](https://learn.microsoft.com/en-us/windows-hardware/customize/desktop/wsim/windows-system-image-manager-technical-reference)**, a tool for importing Windows images and creating Answer files.

1. **Import the Windows image into Windows SIM.**

   ![Windows SIM with the Answer File and Windows Image panes highlighted.](/img/cmp/use/servers/windows-sysprep/windows-sim.png)

   *Windows SIM with the Answer file and Windows Image panes highlighted.*

1. **Add configuration components.**

   Expand the image's components or packages, then drag items into the appropriate [configuration pass](https://learn.microsoft.com/en-us/windows-hardware/manufacture/desktop/how-configuration-passes-work) (for example, *specialize*). Windows SIM prevents components from being dropped into the wrong pass.

   ![Components tree expanded, Edit > Find used to locate ServerManager, and the amd64 component dragged to the specialize pass and configured with DoNotOpenServerManager = true.](/img/cmp/use/servers/windows-sysprep/windows-sim-config.png)

   *Components tree expanded, **Edit** > **Find** used to locate **ServerManager**, and the **amd64** component dragged to the **specialize** pass and configured with `DoNotOpenServerManagerAtLogon = true`.*

1. **Save the Answer file.**

   Go to **File** > **Save Answer File** to generate the XML file.

   ```xml
   <?xml version="1.0" encoding="utf-8"?>
   <unattend xmlns="urn:schemas-microsoft-com:unattend">
     <settings pass="specialize">
       <component name="Microsoft-Windows-ServerManager-SvrMgrNc" 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">
         <DoNotOpenServerManagerAtLogon>true</DoNotOpenServerManagerAtLogon>
       </component>
       <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">
         <ComputerName>SOMESERVER</ComputerName>
       </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>
           <HideOEMRegistrationScreen>true</HideOEMRegistrationScreen>
           <HideOnlineAccountScreens>true</HideOnlineAccountScreens>
           <HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>
           <ProtectYourPC>3</ProtectYourPC>
           <SkipMachineOOBE>true</SkipMachineOOBE>
           <SkipUserOOBE>true</SkipUserOOBE>
           <UnattendEnableRetailDemo>false</UnattendEnableRetailDemo>
         </OOBE>
         <UserAccounts>
           <AdministratorPassword>
             <Value>UwBvAG0AZQBQAGEAcwBzAHcAbwByAGQAMQAyADMAQQBkAG0AaQBuAGkAcwB0AHIAYQB0AG8AcgBQAGEAcwBzAHcAbwByAGQA</Value>
             <PlainText>false</PlainText>
           </AdministratorPassword>
           <LocalAccounts>
             <LocalAccount wcm:action="add">
               <Password>
                 <Value>UwBvAG0AZQBQAGEAcwBzAHcAbwByAGQAMQAyADMAUABhAHMAcwB3AG8AcgBkAA==</Value>
                 <PlainText>false</PlainText>
               </Password>
               <Name>cbadmin</Name>
               <Group>Administrators</Group>
               <DisplayName>CloudBolt Admin</DisplayName>
               <Description>another administrator</Description>
             </LocalAccount>
           </LocalAccounts>
         </UserAccounts>
       </component>
     </settings>
   </unattend>
   ```

   *Example Answer file.*

## Templatizing an Answer file

To use an Answer file with resource handlers, you can convert static XML values into dynamic template variables. CMP substitutes values based on the object.

Templatization replaces XML values with variables using CMP's template syntax.

### Example: Templatizing the computer name

**Before:**

```xml
<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">
  <ComputerName>SOMESERVER</ComputerName>
</component>
```

**After:**

```xml
<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">
  <ComputerName>{{ server.hostname }}</ComputerName>
</component>
```

### Example: Templatizing the administrator password

<div class="alert alert-info" role="alert">


Answer files expect administrator passwords to be encoded when the PlainText value is False. CMP provides the Django filter `salt_and_encode_windows_password` to produce an encoded password for Sysprep.
</div>


**Before:**

```xml
<AdministratorPassword>
  <Value>UwBvAG0AZQBQAGEAcwBzAHcAbwByAGQAMQAyADMAQQBkAG0AaQBuAGkAcwB0AHIAYQB0AG8AcgBQAGEAcwBzAHcAbwByAGQA</Value>
  <PlainText>false</PlainText>
</AdministratorPassword>
```

**After:**

```xml
<AdministratorPassword>
  <Value>{{ server.password|salt_and_encode_windows_password }}</Value>
  <PlainText>false</PlainText>
</AdministratorPassword>
```

### Example: Templatizing local accounts

Some Answer file sections, such as `LocalAccounts`, require different salting rules.

**Provide the required salt type as an argument to the filter:**

```xml
<Value>{{ server.password|salt_and_encode_windows_password:"Password" }}</Value>
```

**You may also templatize account or display names:**

```xml
<Name>{{ server.owner.username }}</Name>
<DisplayName>{{ server.owner.first_name}} {{server.owner.last_name }}</DisplayName>
```

## Common Answer file issues

### Unintended spaces in templated values

Spaces inside `<value>` tags are interpreted literally, altering the encoded value and preventing Sysprep from decoding it.

**Invalid:**

```xml
<Value> {{ server.password|salt_and_encode_windows_password:"Password" }} </Value>
```

Both leading and trailing spaces produce an incorrect password value.

<div class="alert alert-info" role="alert">


Spaces **inside** the template braces are allowed (`{{ variable }}`): CMP renders Answer files with [Django's template language](https://docs.djangoproject.com/en/stable/ref/templates/language/), which ignores whitespace inside variable tags, so it does not affect the final value.
</div>


### Passwords failing complexity requirements

If a generated password does not meet Windows password complexity requirements, Sysprep exits with an error. CMP does not validate password complexity for Answer files—this is the administrator's responsibility.

## Troubleshooting Answer files using Shell Plus

CMP's **Shell Plus** tool helps validate templated Answer files by rendering them with server object values.

<div class="alert alert-info" role="alert">


Shell Plus requires root privileges.
</div>


1. **Start Shell Plus on the CMP appliance.**

   ```bash
   /opt/cloudbolt/manage.py shell_plus
   ```

1. **Define your Answer file template.**

   ```python
   sysprep_template = """
   <?xml version="1.0" encoding="utf-8"?>
   <unattend xmlns="urn:schemas-microsoft-com:unattend">
       <settings pass="specialize">
           <component name="Microsoft-Windows-ServerManager-SvrMgrNc" processorArchitecture="{{ sysprep_processor_architecture }}" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
               <DoNotOpenServerManagerAtLogon>true</DoNotOpenServerManagerAtLogon>
           </component>
           <component name="Microsoft-Windows-Shell-Setup" processorArchitecture="{{ sysprep_processor_architecture }}" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
               <ComputerName>{{ server.hostname }}</ComputerName>
           </component>
       </settings>
       <settings pass="oobeSystem">
           <component name="Microsoft-Windows-Shell-Setup" processorArchitecture="{{ sysprep_processor_architecture }}" 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>
                   <HideOEMRegistrationScreen>true</HideOEMRegistrationScreen>
                   <HideOnlineAccountScreens>true</HideOnlineAccountScreens>
                   <HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>
                   <ProtectYourPC>3</ProtectYourPC>
                   <SkipMachineOOBE>true</SkipMachineOOBE>
                   <SkipUserOOBE>true</SkipUserOOBE>
                   <UnattendEnableRetailDemo>false</UnattendEnableRetailDemo>
               </OOBE>
               <UserAccounts>
                   <AdministratorPassword>
                       <Value>{{ server.password|salt_and_encode_windows_password }}</Value>
                       <PlainText>false</PlainText>
                   </AdministratorPassword>
               </UserAccounts>
           </component>
       </settings>
   </unattend>
   """
   ```

1. **Define the server object.**

   ```python
   server = Server.objects.get(id=1234)
   ```

   **Note:** Update the ID for the target server.

1. **Generate the Answer file.**

   ```python
   from common.methods import generate_string_from_template_for_server

   answer_file = generate_string_from_template_for_server(
       sysprep_template, server
   )
   print(answer_file)
   ```

If the output is blank, malformed, or missing values, check for:

- Invalid XML syntax
- Typographical errors in variable names
- Template variables that do not exist in the server object

## Next steps

With a Sysprep Answer file generated, you can use it with a **[Hyper-V](/docs/cmp/configure/infrastructure/resource-handlers/hyper-v/)**, **[Nutanix Acropolis](/docs/cmp/configure/infrastructure/resource-handlers/nutanix/)**, **[Oracle Linux Virtualization Manager](/docs/cmp/configure/infrastructure/resource-handlers/olvm/)**, or **[VMware](/docs/cmp/configure/infrastructure/resource-handlers/vmware-vcenter/)** resource handler.
