PSD icon indicating copy to clipboard operation
PSD copied to clipboard

How to create additional partition? (PSDPartition.ps1)

Open wehr opened this issue 7 months ago • 2 comments

Hi,

Im trying to create an additional partition in the task sequence. No matter what values I put into "Format and Partition Disk" step the result is always an OS disk with 99%.

It seems to be hardcoded in PSDPartition.ps1?

Line 103: $osSize = $disk.Size - 499MB - 128MB - 1024MB

best regards

Markus

wehr avatar Jun 11 '25 06:06 wehr

It is hardcoded in PSDPartition.ps1

You can rewrite this script, so it excepts the diskparameters stored in variables as input for the disk cmdlets. My Script looks like this (I've not tested adding disk. you might have to check this and eventually rewrite the code a bit!):

Powershell

<#
.SYNOPSIS
    Partition and format the disk.
.DESCRIPTION
    Partition and format the disk.
    Partition scheme in TS step does not do anything
    Order and size of partitions must be set in this script!
.LINK
    https://github.com/FriendsOfMDT/PSD
.NOTES
          FileName: PSDPartition.ps1
          Solution: PowerShell Deployment for MDT
          Author: PSD Development Team
          Contact: @Mikael_Nystrom , @jarwidmark , @mniehaus
          Primary: @Mikael_Nystrom 
          Created: 
          Modified: 2022-06-20

          Version - 0.0.1 - () - Finalized functional version 1.
          Version - 0.0.5 - () - Fixed spelling.
          Version - 0.0.6 - (Mikael_Nystrom) - Replaced Clear-Disk with Clear-PSDDisk
          Version - 0.0.7 - (WELS) - Changed order of Disks
          Version - 0.0.8 - (WELS) - Changed description  
          Version - 0.1.0 - (WELS) - loop through partitions and get the parameters from MDT Workbench
                            Use order, size and partition type from tasksequence
          TODO:

.Example
#>

[CmdLetBinding()]
param(
)

if($PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent){
    $VerbosePreference = "Continue"
}
Write-Verbose "Verbose is on"

# Set scriptversion for logging
$ScriptVersion = "0.1.0"

# Load core modules
Import-Module Microsoft.BDD.TaskSequenceModule -Scope Global
Import-Module PSDUtility

# Check for debug in PowerShell and TSEnv
if($TSEnv:PSDDebug -eq "YES"){
    $Global:PSDDebug = $true
}
if($PSDDebug -eq $true)
{
    $verbosePreference = "Continue"
}

Write-PSDLog -Message "$($MyInvocation.MyCommand.Name): Starting: $($MyInvocation.MyCommand.Name) - Version $ScriptVersion"
Write-PSDLog -Message "$($MyInvocation.MyCommand.Name): The task sequencer log is located at $("$tsenv:_SMSTSLogPath\SMSTS.LOG"). For task sequence failures, please consult this log."
Write-PSDEvent -MessageID 41000 -severity 1 -Message "Starting: $($MyInvocation.MyCommand.Name)"

# Keep the logging out of the way

$currentLocalDataPath = Get-PSDLocalDataPath
if ($currentLocalDataPath -NotLike "X:\*")
{
    Write-PSDLog -Message "$($MyInvocation.MyCommand.Name): Stop-PSDLogging, need to keep the logging out of the way"
    Stop-PSDLogging
    $logPath = "X:\MININT\Logs"
    if ((Test-Path $logPath) -eq $false) {
        New-Item -ItemType Directory -Force -Path $logPath | Out-Null
    }
    Start-Transcript "$logPath\PSDPartition.ps1.log"
}

# Get the dynamic variable
foreach($i in (Get-ChildItem -Path TSEnv:)){
    Write-PSDLog -Message "$($MyInvocation.MyCommand.Name): Property $($i.Name) is $($i.Value)"
}

# Partition and format the disk
Write-PSDLog -Message "$($MyInvocation.MyCommand.Name): Partition and format the disk [$tsenv:OSDDiskIndex]"
Show-PSDActionProgress -Message "Partition and format disk [$tsenv:OSDDiskIndex]" -Step "1" -MaxStep "1"
Update-Disk -Number $tsenv:OSDDiskIndex
$disk = Get-Disk -Number $tsenv:OSDDiskIndex

if ($tsenv:IsUEFI -eq "True") {
    # Load Task Sequence Environment
    $tsenv = New-Object -ComObject Microsoft.SMS.TSEnvironment

    # Get disk index and partition style
    $diskIndex = $tsenv.Value("OSDDiskIndex")
    $partitionStyle = $tsenv.Value("OSDPartitionStyle")
    $partitionCount = [int]$tsenv.Value("OSDPartitions")

    # UEFI partitioning
    Write-PSDLog -Message "$($MyInvocation.MyCommand.Name): UEFI partitioning"

    # Clean the disk if it isn't raw
    Write-PSDLog -Message "$($MyInvocation.MyCommand.Name): Clean the disk if it isn't raw"
    if ($disk.PartitionStyle -ne "RAW") {
        Write-PSDLog -Message "$($MyInvocation.MyCommand.Name): Clearing disk"
        Show-PSDActionProgress -Message "Clearing disk" -Step "1" -MaxStep "1"
        # Clear-Disk -Number $tsenv:OSDDiskIndex -RemoveData -RemoveOEM -Confirm:$false
        Clear-PSDDisk -Number $diskIndex
    }
    
    # Initialize the disk
    Write-PSDLog -Message "$($MyInvocation.MyCommand.Name): Initializing disk $diskIndex with $partitionStyle style"
    Show-PSDActionProgress -Message "Initialize the disk" -Step "1" -MaxStep "1"
    Initialize-Disk -Number $diskIndex -PartitionStyle $partitionStyle   
    $disk = Get-Disk -Number $diskIndex

    # Loop through partitions
    for ($i = 0; $i -lt $partitionCount; $i++) {
        $type = $tsenv.Value("OSDPartitions${i}Type")
        $size = $tsenv.Value("OSDPartitions${i}Size")
        $sizeUnits = $tsenv.Value("OSDPartitions${i}SizeUnits")
        $fileSystem = $tsenv.Value("OSDPartitions${i}FileSystem")
        $bootable = $tsenv.Value("OSDPartitions${i}Bootable")
        $volumeName = $tsenv.Value("OSDPartitions${i}VolumeName")
        $format = $tsenv.Value("OSDPartitions${i}QuickFormat")
        # Convert type to guid
        switch ($volumeName) {
            "Boot" { $gpttype = "{ebd0a0a2-b9e5-4433-87c0-68b6b72699c7}"; $driveletter = "W" }
            "Reserved" { $gpttype = "{e3c9e316-0b5c-4db8-817d-f92df00215ae}"; $driveletter = "" }
            "Recovery" { $gpttype = "{de94bba4-06d1-4d40-a16a-bfd50179d6ac}"; $driveletter = "R" }
            "Windows" { $gpttype = "{ebd0a0a2-b9e5-4433-87c0-68b6b72699c7}"; $driveletter = "S" }
        }
        # Convert size to bytes
        switch ($sizeUnits) {
            "MB" { $sizeBytes = [int64]$size * 1MB }
            "GB" { $sizeBytes = [int64]$size * 1GB }
            "%"  { $sizeBytes = $null } # Use remaining space
        }
        Write-PSDLog -Message "$($MyInvocation.MyCommand.Name): Create volume $type"
        # Create partition
        if ($sizeBytes) {
            $partition = New-Partition -DiskNumber $diskIndex -Size $sizeBytes -GptType $gpttype
        } else {
            $partition = New-Partition -DiskNumber $diskIndex -UseMaximumSize -GptType $gpttype
        }

        # Assign driveletter
        if ($type -ne "MSR") {
            Set-Partition -DiskNumber $diskIndex -PartitionNumber $partition.PartitionNumber -NewDriveLetter $driveletter
        }
        
        Write-PSDLog -Message "$($MyInvocation.MyCommand.Name): Format the volume $volumeName"
        # Format volumes
        if ($format -and $type -ne "MSR") {
            Format-Volume -Partition $partition -FileSystem $fileSystem -NewFileSystemLabel $volumeName -Confirm:$false
        }
        
        # Set recovery partition gpt flag via dsikpart
        if ($type -eq "Recovery") {
            $gptattribute = "0x8000000000000001"
            $cmd = @"
select disk $($tsenv:OSDDiskIndex)
select part $($partition.PartitionNumber)
gpt attributes=$gptattribute
exit
"@
            $cmd | diskpart
        }

        Write-PSDLog -Message "$($MyInvocation.MyCommand.Name): Created partition $($i+1): $type, $size$sizeUnits, FS=$fileSystem, Bootable=$bootable"

        # Save the drive letters and volume GUIDs to task sequence variables
        Write-PSDLog -Message "$($MyInvocation.MyCommand.Name): Save the drive letters and volume GUIDs to task sequence variables"

        if ($type -eq "EFI") { $tsenv:BootVolumeGuid =  $partition.Guid; $tsenv:BootVolume = "W" }
        if ($type -eq "Recovery") { $tsenv:RecoveryVolumeGuid = $partition.Guid; $tsenv:RecoveryVolume = "R" }
        if ($type -eq "Primary") { $tsenv:OSVolumeGuid = $partition.Guid; $tsenv:OSVolume = "S" }
    }
}
else {
    # Load Task Sequence Environment
    $tsenv = New-Object -ComObject Microsoft.SMS.TSEnvironment

    # Get disk index and partition style
    $diskIndex = $tsenv.Value("OSDDiskIndex")
    $partitionStyle = $tsenv.Value("OSDPartitionStyle")
    $partitionCount = [int]$tsenv.Value("OSDPartitions")

    # Clean the disk if it isn't raw
    Write-PSDLog -Message "$($MyInvocation.MyCommand.Name): Clean the disk if it isn't raw"
    if ($disk.PartitionStyle -ne "RAW") {
        Write-PSDLog -Message "$($MyInvocation.MyCommand.Name): Clearing disk"
        Show-PSDActionProgress -Message "Clearing disk" -Step "1" -MaxStep "1"
        # Clear-Disk -Number $tsenv:OSDDiskIndex -RemoveData -RemoveOEM -Confirm:$false
        Clear-PSDDisk -Number $diskIndex
    }

    # Initialize the disk
    Write-PSDLog -Message "$($MyInvocation.MyCommand.Name): Initialize the disk"
    Show-PSDActionProgress -Message "Initialize the disk" -Step "1" -MaxStep "1"
    Initialize-Disk -Number $diskIndex -PartitionStyle MBR
    $disk = Get-Disk -Number $diskIndex

    # Loop through partitions
    for ($i = 0; $i -lt $tsenv:OSDPartitions; $i++) {
        $type = $tsenv.Value("OSDPartitions${i}Type")
        $size = $tsenv.Value("OSDPartitions${i}Size")
        $sizeUnits = $tsenv.Value("OSDPartitions${i}SizeUnits")
        $fileSystem = $tsenv.Value("OSDPartitions${i}FileSystem")
        $bootable = $tsenv.Value("OSDPartitions${i}Bootable")
        $volumeName = $tsenv.Value("OSDPartitions${i}VolumeName")
        $format = $tsenv.Value("OSDPartitions${i}QuickFormat")
        $label = $tsenv.Value("OSDPartitions${i}VolumeName")
        # Convert type to guid
        switch ($volumeName) {
            "System Reserved" { $driveletter = "W" }
            "Recovery" { $driveletter = "R" }
            "Windows" { $driveletter = "S" }
        }
        # Convert size to bytes
        switch ($sizeUnits) {
            "MB" { $sizeBytes = [int64]$size * 1MB }
            "GB" { $sizeBytes = [int64]$size * 1GB }
            "%"  { $sizeBytes = $null } # Use remaining space
        }
        Write-PSDLog -Message "$($MyInvocation.MyCommand.Name): Create volume $volumeName"
        # Create partition
        if ($sizeBytes) {
            $partition = New-Partition -DiskNumber $diskIndex -Size $sizeBytes
        } else {
            $partition = New-Partition -DiskNumber $diskIndex -UseMaximumSize
        }

        # Assign driveletter
        Set-Partition -DiskNumber $diskIndex -PartitionNumber $partition.PartitionNumber -NewDriveLetter $driveletter
        
        Write-PSDLog -Message "$($MyInvocation.MyCommand.Name): Format the volume $volumeName"
        # Format volumes
        if ($format) {
            Format-Volume -Partition $partition -FileSystem $fileSystem -NewFileSystemLabel $volumeName -Confirm:$false
        }

        # Make bootable if required
        if ($bootable -eq "True") {
            Set-Partition -PartitionNumber $partition.PartitionNumber -IsActive $true
            Write-PSDLog -Message "$($MyInvocation.MyCommand.Name): Set partition active $($partition.PartitionNumber))"
        }

        Write-PSDLog -Message "$($MyInvocation.MyCommand.Name): Created partition $($i+1): $type, $size$sizeUnits, FS=$fileSystem, Bootable=$bootable"

        # Save the drive letters and volume GUIDs to task sequence variables
        Write-PSDLog -Message "$($MyInvocation.MyCommand.Name): Save the drive letters and volume GUIDs to task sequence variables"

        if ($volumeName -eq "System Reserved") { $tsenv:BootVolumeGuid =  $partition.Guid; $tsenv:BootVolume = "W" }
        if ($volumeName -eq "Recovery") { $tsenv:RecoveryVolumeGuid = $partition.Guid; $tsenv:RecoveryVolume = "R" }
        if ($volumeName -eq "Windows") { $tsenv:OSVolumeGuid = $partition.Guid; $tsenv:OSVolume = "S" }
    }
}

# Make sure there is a PSDrive for the OS volume
if ((Test-Path "$($tsenv:OSVolume):\") -eq $false){
    New-PSDrive -Name $tsenv:OSVolume -PSProvider FileSystem -Root "$($tsenv:OSVolume):\" -Verbose
}

# If the old local data path survived the partitioning, copy it to the new location
# Write-PSDLog -Message "$($MyInvocation.MyCommand.Name): If the old local data path survived the partitioning, copy it to the new location"
if (Test-Path $currentLocalDataPath){
    # Copy files to new data path
    # Write-PSDLog -Message "$($MyInvocation.MyCommand.Name): Copy files to new data path"
    $newLocalDataPath = Get-PSDLocalDataPath -Move
    if ($currentLocalDataPath -ine $newLocalDataPath){
        Write-PSDLog -Message "$($MyInvocation.MyCommand.Name): Copying $currentLocalDataPath to $newLocalDataPath"
        Copy-PSDFolder $currentLocalDataPath $newLocalDataPath
        
        # Change log location for LogPath, since we now have a volume
        $Global:LogPath = "$newLocalDataPath\SMSOSD\OSDLOGS\PSDPartition.log"
        Write-PSDLog -Message "$($MyInvocation.MyCommand.Name): Now logging to $Global:LogPath"
    }
}

# Dumping out variables for troubleshooting
# Write-PSDLog -Message "$($MyInvocation.MyCommand.Name): Dumping out variables for troubleshooting"
# Write-PSDLog -Message "$($MyInvocation.MyCommand.Name): tsenv:BootVolume  is $tsenv:BootVolume"
# Write-PSDLog -Message "$($MyInvocation.MyCommand.Name): tsenv:OSVolume is $tsenv:OSVolume"
# Write-PSDLog -Message "$($MyInvocation.MyCommand.Name): tsenv:RecoveryVolume is $tsenv:RecoveryVolume"
# Write-PSDLog -Message "$($MyInvocation.MyCommand.Name): tsenv:IsUEFI is $tsenv:IsUEFI"

# Save all the current variables for later use
Write-PSDLog -Message "$($MyInvocation.MyCommand.Name): Save all the current variables for later use"
Save-PSDVariables


stefanweilguni-oss avatar Dec 09 '25 18:12 stefanweilguni-oss

Or you can skip the partitioning step altogether and run a script of yours to partition per your requirements.

GeoSimos avatar Dec 09 '25 20:12 GeoSimos