private/MDT/Select-MDTDeploymentShare.ps1
|
function Select-MdtDeploymentShare { <# .SYNOPSIS Selects the active MDT Deployment Share for the current session. .DESCRIPTION Calls Get-MDTPersistentDrive to retrieve all persisted MDT deployment shares registered on this machine. - Zero shares : issues a warning and returns $null. - One share : selects it automatically. - Multiple : displays an Out-GridView picker so the user can choose exactly one. The selected share is stored in the module-level variable $script:MDTDeploymentShare for use by other OSDeployMDT functions, and is persisted to "$env:ProgramData\OSDeployCore\cache\osdeploymdt\config.json" so the choice survives between sessions. .EXAMPLE Select-MdtDeploymentShare Prompts the user to pick a share when more than one is registered, then saves the selection to the .env file and returns the drive object. .EXAMPLE $share = Select-MdtDeploymentShare Write-Host "Working share: $($share.Name) -> $($share.Root)" Stores the returned drive object in a local variable for further use. .INPUTS None. This function does not accept pipeline input. .OUTPUTS System.Management.Automation.PSDriveInfo Returns the selected MDT PSDrive object, or $null if no share is found or the user cancels the picker. .NOTES Author: David Segura Company: Recast Software Persistence file: $env:ProgramData\OSDeployCore\cache\osdeploymdt\config.json #> [CmdletBinding()] [OutputType([System.Management.Automation.PSDriveInfo])] param () #region PS7: use bridge-aware Get-MDTDeploymentShare + console picker if ($PSEdition -eq 'Core') { $drives = @(Get-MDTDeploymentShare) #region Remove stale shares whose paths no longer exist on disk $staleNames = @($drives | Where-Object { -not (Test-Path -LiteralPath $_.Path) } | ForEach-Object { $_.Name }) if ($staleNames.Count -gt 0) { foreach ($staleName in $staleNames) { Write-Warning "[$(Get-Date -format s)] Path not found for '$staleName'. Removing from MDT persistent drives." } $staleList = $staleNames -join ',' $pruneScript = @" try { `$installDir = `$null try { `$regVal = Get-ItemPropertyValue -Path 'HKLM:\SOFTWARE\Microsoft\Deployment 4' -Name 'Install Dir' -ErrorAction Stop `$regVal = `$regVal.TrimEnd('\\') if (Test-Path -Path `$regVal) { `$installDir = `$regVal } } catch {} if ([string]::IsNullOrEmpty(`$installDir)) { `$dp = 'C:\Program Files\Microsoft Deployment Toolkit' if (Test-Path -Path `$dp) { `$installDir = `$dp } } if (-not [string]::IsNullOrEmpty(`$installDir)) { `$mdtModule = Join-Path -Path `$installDir -ChildPath 'bin\MicrosoftDeploymentToolkit.psd1' Import-Module -Name `$mdtModule -ErrorAction Stop '$staleList' -split ',' | ForEach-Object { Remove-MDTPersistentDrive -Name `$_ -ErrorAction SilentlyContinue } } } catch {} "@ & powershell.exe -NoProfile -NonInteractive -Command $pruneScript 2>$null $drives = @($drives | Where-Object { Test-Path -LiteralPath $_.Path }) } #endregion if ($null -eq $drives -or $drives.Count -eq 0) { return $null } if ($drives.Count -eq 1) { $selected = $drives[0] Write-Verbose "[$(Get-Date -format s)] Auto-selected '$($selected.Name)' ($($selected.Path))" } else { Write-Host "[$(Get-Date -format s)] Select MDT Deployment Share:" -ForegroundColor DarkCyan for ($i = 0; $i -lt $drives.Count; $i++) { Write-Host " [$($i + 1)] $($drives[$i].Name) $($drives[$i].Path)" } $choice = Read-Host 'Enter number' $choiceIndex = -1 if (-not [int]::TryParse($choice, [ref]$choiceIndex)) { Write-Warning "[$(Get-Date -format s)] Invalid input. No deployment share was selected." return $null } $choiceIndex -= 1 if ($choiceIndex -lt 0 -or $choiceIndex -ge $drives.Count) { Write-Warning "[$(Get-Date -format s)] No deployment share was selected." return $null } $selected = $drives[$choiceIndex] } $script:MDTDeploymentShare = $selected Write-Verbose "[$(Get-Date -format s)] Active share set to '$($selected.Name)'" #region Persist to OSDeployCore\cache\osdeploymdt\config.json $configFolder = "$env:ProgramData\OSDeployCore\cache\osdeploymdt" if (-not (Test-Path -Path $configFolder)) { New-Item -Path $configFolder -ItemType Directory -Force | Out-Null } $configPath = Join-Path -Path $configFolder -ChildPath 'config.json' $configObject = [ordered]@{} if (Test-Path -LiteralPath $configPath -PathType Leaf) { try { $rawConfig = Get-Content -LiteralPath $configPath -Raw -ErrorAction Stop if (-not [string]::IsNullOrWhiteSpace($rawConfig)) { $existingConfig = $rawConfig | ConvertFrom-Json -ErrorAction Stop foreach ($property in $existingConfig.PSObject.Properties) { $configObject[$property.Name] = $property.Value } } } catch { Write-Warning "[$(Get-Date -format s)] Failed to parse '$configPath'. Recreating." $configObject = [ordered]@{} } } $configObject.MDTDriveName = $selected.Name $configObject.MDTDrivePath = $selected.Path $configObject | ConvertTo-Json -Depth 10 | Set-Content -LiteralPath $configPath -Encoding UTF8 -Force Write-Verbose "[$(Get-Date -format s)] Selection saved to '$configPath'" #endregion return $selected } #endregion #region Ensure MDT cmdlets are available if (-not (Import-MDTCmdlets)) { Write-Warning "[$(Get-Date -format s)] MDT cmdlets could not be loaded. Ensure MDT is installed." return $null } #endregion #region Retrieve persisted MDT drives $drives = @(Get-MDTPersistentDrive -ErrorAction SilentlyContinue) if ($drives.Count -eq 0) { Write-Warning "[$(Get-Date -format s)] No persisted MDT deployment shares were found." Write-Warning "[$(Get-Date -format s)] Use Add-MDTPersistentDrive to register a deployment share first." return $null } #endregion #region Remove stale shares whose paths no longer exist on disk $staleDrives = @($drives | Where-Object { -not (Test-Path -LiteralPath $_.Path) }) if ($staleDrives.Count -gt 0) { foreach ($staleDrive in $staleDrives) { Write-Warning "[$(Get-Date -format s)] Path not found: '$($staleDrive.Path)'. Removing '$($staleDrive.Name)' from MDT persistent drives." Remove-MDTPersistentDrive -Name $staleDrive.Name -ErrorAction SilentlyContinue } $drives = @($drives | Where-Object { Test-Path -LiteralPath $_.Path }) if ($drives.Count -eq 0) { Write-Warning "[$(Get-Date -format s)] No reachable MDT deployment shares remain." return $null } } #endregion #region Resolve working share if ($drives.Count -eq 1) { $selected = $drives[0] Write-Verbose "[$(Get-Date -format s)] Auto-selected '$($selected.Name)' ($($selected.Path))" } else { $selected = $drives | Select-Object -Property Name, Path, Description | Out-GridView -Title 'Select MDT Deployment Share' -OutputMode Single if ($null -eq $selected) { Write-Warning "[$(Get-Date -format s)] No deployment share was selected." return $null } # Re-resolve full drive object from the name chosen in the picker $selected = $drives | Where-Object { $_.Name -eq $selected.Name } | Select-Object -First 1 } #endregion #region Store in module scope $script:MDTDeploymentShare = $selected Write-Verbose "[$(Get-Date -format s)] Active share set to '$($selected.Name)'" #endregion #region Persist to OSDeployCore\cache\osdeploymdt\config.json $configFolder = "$env:ProgramData\OSDeployCore\cache\osdeploymdt" if (-not (Test-Path -Path $configFolder)) { New-Item -Path $configFolder -ItemType Directory -Force | Out-Null } $configPath = Join-Path -Path $configFolder -ChildPath 'config.json' $configObject = [ordered]@{} if (Test-Path -LiteralPath $configPath -PathType Leaf) { try { $raw = Get-Content -LiteralPath $configPath -Raw -ErrorAction Stop if (-not [string]::IsNullOrWhiteSpace($raw)) { $existingConfig = $raw | ConvertFrom-Json -ErrorAction Stop foreach ($property in $existingConfig.PSObject.Properties) { $configObject[$property.Name] = $property.Value } } } catch { Write-Warning "[$(Get-Date -format s)] Failed to parse '$configPath'. Recreating config file." $configObject = [ordered]@{} } } $configObject.MDTDriveName = $selected.Name $configObject.MDTDrivePath = $selected.Path $configObject | ConvertTo-Json -Depth 10 | Set-Content -LiteralPath $configPath -Encoding UTF8 -Force Write-Verbose "[$(Get-Date -format s)] Selection saved to '$configPath'" #endregion return $selected } |