bladefirelight / windowsimagetools Goto Github PK
View Code? Open in Web Editor NEWPowerShell Tools creating and updating Windows Images
License: MIT License
PowerShell Tools creating and updating Windows Images
License: MIT License
Noticed the validation script is bulky. Maybe this can be avoided using strongly typed parameters.
# Timezone (default: your local time)
[System.TimeZoneInfo]
$TimeZone = [System.TimeZoneInfo]::Local,
# Specifies the system input locale and the keyboard layout (default: en-US)
[Parameter(ValueFromPipelineByPropertyName)]
[System.Globalization.CultureInfo]$InputLocale = [System.Globalization.CultureInfo]::GetCultureInfo('en-US'),
# Specifies the language for non-Unicode programs (default: en-US)
[Parameter(ValueFromPipelineByPropertyName)]
[System.Globalization.CultureInfo]$SystemLocale = [System.Globalization.CultureInfo]::GetCultureInfo('en-US'),
# Specifies the per-user settings used for formatting dates, times, currency and numbers (default: en-US)
[Parameter(ValueFromPipelineByPropertyName)]
[System.Globalization.CultureInfo]$UserLocale = [System.Globalization.CultureInfo]::GetCultureInfo('en-US'),
# Specifies the system default user interface (UI) language (default: en-US)
[System.Globalization.CultureInfo]$UILanguage = [System.Globalization.CultureInfo]::GetCultureInfo('en-US'),
Then the Id/Name property can be used in the unattended file.
Hi there, just be interesting, in the front page that said:
This module provides tools to quickly convert a WIM into bookable VHD(x) and Create fully updated WIM/VHD(x)
I am interesting that you said Create fully updated WIM
How come the tool will modify WIM ?
Being a DBA guy, I like some partitions to be formatted with a 64k allocation unit size. I don't see anything in an unattended xml that supports this; however, I'm adding the formatted VHDX drives before the deployment, so I could use New-DataVHD. Both NTFS and ReFS support 64K, so a 64K switch would work. For more general support, a ALU size parameter would be better.
Adding a ALU parameter value of 64KB to New-DataVHD would format a data partition using 64k allocation unit size. The OS drive would still use a 4 KB ALU.
Would there ever be a reason to use a smaller (e.g., 512) or a larger ALU for the OS partition? If so, perhaps the ALU parameter should apply for the data partition on the OS drive as well.
The allocation unit size is always 4k.
Add a parameter for the ALU to both New-DataVHD and Initialize-Partition
# Format drive using 4K or 64K allocation unit size rather then the default 4K (Only applies when DiskLayout = Data)
[int]
[ValidateSet(4KB, 64KB)]
$DataALU=4KB,
Update the hashtable in New-DataVHD used to pass values to Initialize-VHDPartition
$InitializeVHDPartitionParam = @{
'Size' = $Size
'Path' = $Path
'force' = $true
'DiskLayout' = 'Data'
'DataFormat' = $DataFormat
'DataALU' = $DataALU
}
Update the data partition format code to use the ALU size.
#region Create the Primay partition
# Refresh $disk to update free space
$disk = Get-Disk -Number $disknumber | Get-Disk
$NewPartitionParam = @{
DiskNumber = $disknumber
Size = $disk.LargestFreeExtent - $Recovery
}
if ($PartitionStyle -eq 'GPT') { $NewPartitionParam.add('GptType', '{ebd0a0a2-b9e5-4433-87c0-68b6b72699c7}') }
Write-Verbose "[$($MyInvocation.MyCommand)] [$disknumber] : Primary : Creating partition of [$($disk.LargestFreeExtent - $Recovery)] bytes"
Write-Verbose ($NewPartitionParam | out-string)
$windowsPartition = New-Partition @NewPartitionParam
$FileSystem = 'NTFS'
$AllocationUnitsize = 4KB
$Label = 'Windows'
if ($DiskLayout -eq 'Data')
{
$FileSystem = $DataFormat
$AllocationUnitsize = $DataALU
$Label = 'Data'
}
Write-Verbose "[$($MyInvocation.MyCommand)] [$disknumber] : Primary : Formatting volume [$FileSystem]"
$null = Format-Volume -Partition $windowsPartition -NewFileSystemLabel $Label -FileSystem $FileSystem -Force -Confirm:$false -AllocationUnitSize $AllocationUnitsize
#endregion Primay Partiton
I have not tested this.
We use domain trusts, so I can use my account to add machines to other domains.
I expect my domain account to be used to add the machine to the domain.
An attempt will me made to use an account of the same username in the domain joined to add the machine to the domain. This account might not exist.
Fortunately, the same object with the username and password also has the domain.
Current code:
$IdJoinDomainElement = $identificationElement.AppendChild($unattendXml.CreateElement('JoinDomain', 'urn:schemas-microsoft-com:unattend'))
$Null = $IdJoinDomainElement.AppendChild($unattendXml.CreateTextNode($domain))
Proposed code:
$IdJoinDomainElement = $identificationElement.AppendChild($unattendXml.CreateElement('JoinDomain', 'urn:schemas-microsoft-com:unattend'))
$Null = $IdJoinDomainElement.AppendChild($unattendXml.CreateTextNode($JoinAccount.GetNetworkCredential().Domain))
I've only tested in one domain and it's fine. I have not tried to join a machine to a different domain yet, but will eventually do so.
It appears that domain accounts can be added to local groups.
New-Unattended has a parameter Domain accounts to add one or more domain accounts to the local administrators group.
Not an option.
Add parameter:
# domain account to add to Administators group in domain\name format
[ValidatePattern('^([a-z0-9]+(-[a-z0-9]+)*)\\[A-Za-z0-9][A-Za-z\d_!@#$%^()\-''{}\.~]{0,14}$')]
[string[]]
$DomainAccount,
After the block of code for $UserAccount:
if ($DomainAccount) {
Write-Verbose -Message "[$($MyInvocation.MyCommand)] Adding Domain Account(s) for $($component.'processorArchitecture') Architecture"
$UserAccountsElement = $component.UserAccounts
$DomainAccountsElement = $UserAccountsElement.AppendChild($unattendXml.CreateElement('DomainAccounts', 'urn:schemas-microsoft-com:unattend'))
$DomainAccountGroups = $DomainAccount | %{$temp = $_.Split('\'); [ordered]@{'domain'=$temp[0]; 'name'=$temp[1]}} | %{[pscustomobject]$_} | sort domain, name | group-object domain
foreach ($DomainAccountGroup in $DomainAccountGroups) {
$DomainAccountListElement = $DomainAccountsElement.AppendChild($unattendXml.CreateElement('DomainAccountList', 'urn:schemas-microsoft-com:unattend'))
$null = $DomainAccountListElement.SetAttribute('action', 'http://schemas.microsoft.com/WMIConfig/2002/State', 'add')
foreach ($Account in $DomainAccountGroup.Group.Name) {
$DomainAccountElement = $DomainAccountListElement.AppendChild($unattendXml.CreateElement('DomainAccount', 'urn:schemas-microsoft-com:unattend'))
$null = $DomainAccountElement.SetAttribute('action', 'http://schemas.microsoft.com/WMIConfig/2002/State', 'add')
$DomainAccountGroupElement = $DomainAccountElement.AppendChild($unattendXml.CreateElement('Group', 'urn:schemas-microsoft-com:unattend'))
$null = $DomainAccountGroupElement.AppendChild($unattendXml.CreateTextNode('Administrators'))
$DomainAccountNameElement = $DomainAccountElement.AppendChild($unattendXml.CreateElement('Name', 'urn:schemas-microsoft-com:unattend'))
$null = $DomainAccountNameElement.AppendChild($unattendXml.CreateTextNode($Account))
}
$DomainElement = $DomainAccountListElement.AppendChild($unattendXml.CreateElement('Domain', 'urn:schemas-microsoft-com:unattend'))
$null = $DomainElement.AppendChild($unattendXml.CreateTextNode($DomainAccountGroup.Name))
}
}
I've tried to add it, but it does not work. It might be that I do not have access to do so and that GPO will have to be used in my case.
I should be able to import the module.
Error trying to import the module.
import-module : The specified module 'WindowsImageTools' was not loaded because no valid module file was found in any module directory.
Looks like the psm1 file is empty.
This is my first attempt trying to get a module from GitHub. Could be me.
WinRe.wim size for Windows Server 2019 is 438Mb, $RESize = 350MB in Private/Initialize-DiskPartition.ps1 is too small.
The function New-UnattendXml is not public.
I should be able to execute either New-UnattendXml or New-Unattend
New-UnattendXml is not available.
Rename the function from New-UnattendXml to New-Unattended. Or rename the file from New-Unattend to New-UnattendXml and update the FunctionToExport for the new name.
I'm going to try to automatically set the computer name, administrator password, and partition letters for extra drives. I will also try to add my domain account as local admin and add the VM to the domain.
Report a error message that can be used to diagnose/fix whatever caused the error
Currently Set-DiskPartition and the functions that use it throw a generic "Error setting partition content" without reporting why there was an error.
Passthrough or hardcode the error that is actually caught.
I'm using Convert-Wim2VHD in a VM creation script, usually it works perfectly but recently I had to run it on a machine that had an Intune policy set to prevent writing to non-bitlocker drives (including apparently mounted image files). I could only find out this was the cause after editing the psm1 file to include Write-Host $_.Exception commands before the Write-Error around line 1190 that replaced the actual error message.
Please create the recovery partition as first partition when creating a VHD(x) from a WIM, just like a normal installation does.
Currently, the recovery partition as created as last partition, which means the OS partition cannot be extended afterwards, unless the recovery partition is deleted.
Once I get an set of disks built for a VM, I will want to copy them for each new VM. Because I do not have all the info (e.g., computer name and OU), perhaps the injection of the unattended file should be separate. Then the unattended can be applied to a copy of a VHDX. Are there other things that should be separate?
Also, from what I've read online, it appears that both x86 and amd64 sections for the some thing will both run on an amd64 system if both are present. The WinPE pass needs to be x86 or amd64, depending upon what WinPE is using. The other passes are only in the x86 or amd64 of the OS deployed? Can the WinPE and OS architectures be detected from the image?
The unattended file generated should have one section per architecture. The architecture of the section needs to be appropriate for both the WinPE and OS deployed. The unattended file will be specific to each deployment, so it needs to be applied (or re-applied) after the base image is copied.
The unattended can have both or have x86 when deploying to amd64. If I copy the VHDX files for a new VM, I will need to create a new function to call New-UnattendedXMl and replace the existing unattended file. Or I will need to manually mount the VHDX and update the unattended file.
Use only amd64 in the template. Change the attribute to x86 in WinPE pass components if WinPe is x86. Change the other components proc attribute to x86 is the OS is 32 bit. In those rare cases that the x86 and amd64 components for the same thing are different, then include both in the template and later remove any that do not apply.
The code should be x86 and amd64 agnostic unless there is a real difference in how the xml is constructed. The x86/amd64 attribute can be altered as needed for those that are otherwise identical.
I'm testing with a windows server 2019 image. I changed all "x86" entries in the New-UnattendedXML template to "amd64" and removed duplicates. Then I updated the code to insure there was no duplicate processing or specific test for x86. Works for the amd64 only case.
In Private/Set-DiskPartition.ps1:
if ($DiskLayout -eq 'BIOS') Run-Executable -Executable "$windir\System32\bcdboot.exe"
is wrong, it should be bcdedit.exe
I tried to use New-DataVHD to create a few 5 GB drive, but it generated an error re a minimum size requirement.
New-DataVHD should only test that the size is greater than a very small value.
New-DataVHD is limited to creating OS sized drives when it can be used to create small non-OS drives in addition.
Convert-Wim2VHD already tests the size [ValidateRange(25GB, 64TB)] to insure it's big enough for a OS. New-DataVHD can have a different range.
I'm a DBA trying to script the creation of a SQL Server 2017/2019 VM. Hoping to have the VM start, add itself to the domain (in the correct OU somehow), and run powershell to install and configure SQL. BTW, I do not like the sysprep support in SQL. It would have been okay if instances could be renamed and if the post sysprep complete did not take just as long as a normal install.
I don't know if Microsoft did change the parameter set, but in the Script Set-Diskpartition.ps1 at line 432 the parameter in ArgumentList called /setosimage
should be /setreimage
.
Checked the behaviour on Windows 10 (10.0.17134) and Windows Server 2016 (10.0.14393).
Regards Bent
In the helpfile an paramater -wimfile is showed, However this parameter is not working. Should be -sourcepath
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.