public/Install-OSDWorkspace.ps1
function Install-OSDWorkspace { <# .SYNOPSIS Initializes and configures the OSDWorkspace environment. .DESCRIPTION The Install-OSDWorkspace function performs a series of checks and setup steps to ensure the OSDWorkspace is correctly configured. This includes verifying the operating system, required software (VS Code, Git), PowerShell modules (NuGet, PackageManagement, PowerShellGet, platyPS, OSD), and setting up the OSDWorkspace directory structure, Git repository, and necessary configuration files. It also creates registry entries for OSDWorkspace and updates the default library paths. The function requires Administrator privileges for the initial setup if the OSDWorkspace directory does not exist. .NOTES Author: David Segura Requires Administrator privileges for the first run to create the OSDWorkspace directory. Ensures that the operating system is Windows Client OS, build 26100 or higher. Installs or updates necessary PowerShell modules like PackageManagement, PowerShellGet, platyPS, and OSD. Verifies the installation of VS Code and Git. Initializes the OSDWorkspace git repository if it doesn't exist. Creates standard OSDWorkspace files like .gitattributes, .gitignore, .github/copilot-instructions.md, and OSD.code-workspace. .EXAMPLE Install-OSDWorkspace Description: Runs the OSDWorkspace installation and configuration process. This command should be run in a PowerShell console. If it's the first time running and the OSDWorkspace directory (e.g., C:\OSDWorkspace) doesn't exist, it must be run with Administrator privileges. #> [CmdletBinding()] param () #================================================= $Error.Clear() Write-Verbose "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] Start" #================================================= $ModuleBase = Get-OSDWorkspaceModulePath Write-Host -ForegroundColor DarkGray "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] ModuleBase: $ModuleBase" $ModuleVersion = Get-OSDWorkspaceModuleVersion Write-Host -ForegroundColor DarkGray "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] ModuleVersion: $ModuleVersion" #================================================= $IsAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) #================================================= # Make sure we are running in a Windows Client OS $osInfo = Get-CimInstance Win32_OperatingSystem if ($osInfo.ProductType -eq 1) { Write-Host -ForegroundColor DarkGray "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] OSDWorkspace is running on a Windows Client OS" } else { Write-Warning "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] OSDWorkspace is not running on a Windows Client OS" Write-Warning "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] This configuration is not supported and initialization will not continue" Write-Warning "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] OSDWorkspace is only supported on Windows 11 24H2 and newer" return } #================================================= # Make sure we are running in a Windows Client OS with BuildNumber 26100 or higher $osInfo = Get-CimInstance Win32_OperatingSystem if ($osInfo.BuildNumber -ge 26100) { Write-Host -ForegroundColor DarkGray "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] OSDWorkspace is running on a Windows Client OS with BuildNumber $($osInfo.BuildNumber)" } else { Write-Warning "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] OSDWorkspace requires a Windows Client OS with BuildNumber 26100 or higher" Write-Warning "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] This configuration is not supported and initialization will not continue" Write-Warning "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] OSDWorkspace is only supported on Windows 11 24H2 and newer" return } #================================================= # Make sure the OSDWorkspace machine has Nuget installed if ($(Get-PackageProvider).Name -notcontains "NuGet") { Write-Warning "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] OSDWorkspace requires the NuGet package provider to be installed" Write-Warning "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] Refer to the OSD.Workspace Wiki for instructions on how to install it" Write-Warning "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] https://github.com/OSDeploy/OSD.Workspace/wiki" return } #================================================= # Is PackageManagement installed? $InstalledModule = Get-Module -Name PackageManagement -ListAvailable | Where-Object { $_.Version -ge '1.4.8.1' } if (-not ($InstalledModule)) { Write-Warning "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] OSDWorkspace requires PackageManagement 1.4.8.1 or greater to be installed" Write-Warning "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] Refer to the OSD.Workspace Wiki for instructions on how to install it" Write-Warning "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] https://github.com/OSDeploy/OSD.Workspace/wiki" return } #================================================= # Is PowerShellGet installed? $InstalledModule = Get-Module -Name PowerShellGet -ListAvailable | Where-Object { $_.Version -ge '2.2.5'} if (-not ($InstalledModule)) { Write-Warning "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] OSDWorkspace requires PowerShellGet 2.2.5 or greater to be installed" Write-Warning "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] Refer to the OSD.Workspace Wiki for instructions on how to install it" Write-Warning "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] https://github.com/OSDeploy/OSD.Workspace/wiki" return } #================================================= # VS Code if (Get-Command 'code' -ErrorAction SilentlyContinue) { Write-Host -ForegroundColor DarkGray "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] Microsoft Visual Studio Code is installed" } elseif (Get-Command 'code-insiders' -ErrorAction SilentlyContinue) { Write-Host -ForegroundColor DarkGray "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] Microsoft Visual Studio Code Insiders is installed" } else { Write-Warning "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] OSDWorkspace requires Microsoft Visual Studio Code" Write-Warning "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] Refer to the OSD.Workspace Wiki for instructions on how to install it" Write-Warning "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] https://github.com/OSDeploy/OSD.Workspace/wiki" return } #================================================= # Git for Windows - Reload environment if (-not (Get-Command 'git.exe' -ErrorAction SilentlyContinue)) { Write-Verbose "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] Updating environment variables" $RegPath = 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Environment', 'HKCU:\Environment' $RegPath | ForEach-Object { $k = Get-Item $_ $k.GetValueNames() | ForEach-Object { $name = $_ $value = $k.GetValue($_) Set-Item -Path Env:\$name -Value $value } } } #================================================= # Git for Windows if (-not (Get-Command 'git.exe' -ErrorAction SilentlyContinue)) { Write-Warning "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] OSDWorkspace requires Git for Windows" Write-Warning "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] Refer to the OSD.Workspace Wiki for instructions on how to install it" Write-Warning "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] https://github.com/OSDeploy/OSD.Workspace/wiki" return } #================================================= # Make sure we can get the path from the Global Variable $OSDWorkspacePath = $OSDWorkspace.path if ($OSDWorkspacePath) { Write-Host -ForegroundColor DarkGray "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] OSDWorkspace will be located at $OSDWorkspacePath" } else { Write-Warning "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] OSDWorkspace encountered an unknown error" Write-Warning "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] Initialization will not continue" return } #================================================= # Test if OSDWorkspace exists without Git if ((Test-Path -Path $OSDWorkspacePath) -and (-not (Test-Path -Path "$OSDWorkspacePath\.git"))) { Write-Warning "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] OSDWorkspace exists but is not git initialized" Write-Warning "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] This configuration is not supported and initialization will not continue" Write-Warning "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] Remove $OSDWorkspacePath to continue" return } #================================================= # Create OSDWorkspace if it does not exist if (Test-Path -Path $OSDWorkspacePath) { Write-Host -ForegroundColor DarkGray "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] OSDWorkspace exists at $OSDWorkspacePath" } else { Write-Host -ForegroundColor DarkGray "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] OSDWorkspace does not exist at $OSDWorkspacePath" if (-not $IsAdmin ) { Write-Warning "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] OSDWorkspace first run requires Administrator rights (elevated)" Write-Warning "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] Initialization will not continue" Write-Warning "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] Restart in PowerShell with Administrator rights (elevated)" return } Write-Host -ForegroundColor DarkGray "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] Creating $OSDWorkspacePath" Write-Host -ForegroundColor DarkGray "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] git init $OSDWorkspacePath" $null = git init "$OSDWorkspacePath" } #================================================= # Make sure platyPS is installed $platyPS = Get-Module -Name platyPS -ListAvailable if (-not $platyPS) { Write-Host -ForegroundColor DarkGray "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] Installing PowerShell Module platyPS" Install-Module -Name platyPS -AllowClobber -SkipPublisherCheck } else { Write-Verbose "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] PowerShell Module platyPS is already installed" } #================================================= # Make sure OSD is installed $OSD = Get-Module -Name OSD -ListAvailable if (-not $OSD) { Write-Host -ForegroundColor DarkGray "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] Installing PowerShell Module OSD" Install-Module -Name OSD -AllowClobber -SkipPublisherCheck } else { Write-Verbose "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] PowerShell Module OSD is already installed" } #================================================= # Add Registry Key for OSDWorkspace $RegKey = 'HKCU:\Software\OSDWorkspace' $RegName = 'Install-OSDWorkspace' $RegValue = $ModuleVersion # Test if RegKey exists if (-not (Test-Path $RegKey -ErrorAction SilentlyContinue)) { try {New-Item 'HKCU:\Software' -Name 'OSDWorkspace' -Force | Out-Null} catch {} } # Set the value in the registry if (-not (Get-ItemProperty $RegKey -Name $RegName -ErrorAction SilentlyContinue)) { try {New-ItemProperty -Path $RegKey -Name $RegName -Value $RegValue -Force | Out-Null} catch {} } # Read the value from the registry # $GetValue = (Get-ItemProperty $RegKey -Name $RegName).$RegName #================================================= # Add .github if (-not (Test-Path "$OSDWorkspacePath\.github")) { Write-Host -ForegroundColor DarkGray "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] Creating $OSDWorkspacePath\.github" New-Item -Path "$OSDWorkspacePath\.github" -ItemType Directory -Force | Out-Null } #================================================= # Add .vscode if (-not (Test-Path "$OSDWorkspacePath\.vscode")) { Write-Host -ForegroundColor DarkGray "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] Creating $OSDWorkspacePath\.vscode" New-Item -Path "$OSDWorkspacePath\.vscode" -ItemType Directory -Force | Out-Null } #================================================= # Add .gitattributes $Content = Get-Content -Path "$($MyInvocation.MyCommand.Module.ModuleBase)\core\gitattributes.txt" -Raw $Path = "$OSDWorkspacePath\.gitattributes" Write-Host -ForegroundColor DarkGray "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] Adding $Path" Set-Content -Path $Path -Value $Content -Encoding UTF8 -Force #================================================= # Add .gitignore $Content = Get-Content -Path "$($MyInvocation.MyCommand.Module.ModuleBase)\core\gitignore.txt" -Raw $Path = "$OSDWorkspacePath\.gitignore" Write-Host -ForegroundColor DarkGray "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] Adding $Path" Set-Content -Path $Path -Value $Content -Encoding UTF8 -Force #================================================= # Add or update copilot-instructions.md $Content = Get-Content -Path "$($MyInvocation.MyCommand.Module.ModuleBase)\core\copilot-instructions.md" -Raw $Path = "$OSDWorkspacePath\.github\copilot-instructions.md" Write-Host -ForegroundColor DarkGray "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] Adding $Path" Set-Content -Path $Path -Value $Content -Encoding UTF8 -Force #================================================= # Update Content in the registry $RegName = 'Content' try { New-ItemProperty -Path $RegKey -Name $RegName -Value $RegValue -Force | Out-Null } catch {} #================================================= # Add or update Update-OSDWorkspaceHelp.ps1 Update-OSDWorkspaceHelp -Force #================================================= # Add tasks.json <# $Content = Get-Content -Path "$($MyInvocation.MyCommand.Module.ModuleBase)\core\tasks.json" -Raw $Path = "$OSDWorkspacePath\.vscode\tasks.json" if (-not (Test-Path -Path $Path)) { Write-Host -ForegroundColor DarkGray "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] Adding $Path" Set-Content -Path $Path -Value $Content -Encoding UTF8 -Force # Set the value in the registry $RegName = 'tasks.json' if (-not (Get-ItemProperty $RegKey -Name $RegName -ErrorAction SilentlyContinue)) { try { New-ItemProperty -Path $RegKey -Name $RegName -Value $RegValue -Force | Out-Null } catch {} } } #> #================================================= # Update Default Library $LibraryDefaultPath = $OSDWorkspace.paths.library_default if (-not (Test-Path "$LibraryDefaultPath\winpe-driver\amd64")) { Write-Host -ForegroundColor DarkGray "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] Creating $LibraryDefaultPath\winpe-driver" New-Item -Path "$LibraryDefaultPath\winpe-driver\amd64" -ItemType Directory -Force | Out-Null } if (-not (Test-Path "$LibraryDefaultPath\winpe-driver\arm64")) { New-Item -Path "$LibraryDefaultPath\winpe-driver\arm64" -ItemType Directory -Force | Out-Null } if (-not (Test-Path "$LibraryDefaultPath\winpe-script")) { Write-Host -ForegroundColor DarkGray "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] Creating $LibraryDefaultPath\winpe-script" New-Item -Path "$LibraryDefaultPath\winpe-script" -ItemType Directory -Force | Out-Null } if (-not (Test-Path "$LibraryDefaultPath\winpe-mediascript")) { Write-Host -ForegroundColor DarkGray "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] Creating $LibraryDefaultPath\winpe-mediascript" New-Item -Path "$LibraryDefaultPath\winpe-mediascript" -ItemType Directory -Force | Out-Null } #================================================= # Add OSD.code-workspace $Content = Get-Content -Path "$($MyInvocation.MyCommand.Module.ModuleBase)\core\OSD.code-workspace" -Raw $Path = "$OSDWorkspacePath\OSD.code-workspace" Write-Host -ForegroundColor DarkGray "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] Adding $Path" Set-Content -Path $Path -Value $Content -Encoding UTF8 -Force Write-Host -ForegroundColor Cyan "[$(Get-Date -format G)] [$($MyInvocation.MyCommand.Name)] In Windows Explorer, open the file C:\OSDWorkspace\OSD.code-workspace" #================================================= # CachePowerShellModules <# $CachePowerShellModules = $OSDWorkspace.paths.powershell_modules if (-not (Test-Path -Path $CachePowerShellModules)) { New-Item -Path $CachePowerShellModules -ItemType Directory -Force | Out-Null Save-Module -Name PackageManagement -Path $CachePowerShellModules -Repository PSGallery -Force -ErrorAction SilentlyContinue Save-Module -Name PowerShellGet -Path $CachePowerShellModules -Repository PSGallery -Force -ErrorAction SilentlyContinue } #> #================================================= # CachePSRepository <# $CachePSRepository = $OSDWorkspace.paths.psrepository if (-not (Test-Path -Path $CachePSRepository)) { New-Item -Path $CachePSRepository -ItemType Directory -Force | Out-Null if (-not (Get-PSRepository -Name OSDWorkspace -ErrorAction Ignore)) { Register-PSRepository -Name OSDWorkspace -SourceLocation $CachePSRepository -PublishLocation $CachePSRepository -InstallationPolicy Trusted Set-PSRepository -Name OSDWorkspace -InstallationPolicy Trusted } $ModuleBase = Get-Module -Name PackageManagement -ListAvailable | Where-Object { $_.Version -ge '1.4.8.1'} | Select-Object -First 1 -ExpandProperty ModuleBase Publish-Module -Path $ModuleBase -Repository OSDWorkspace -NuGetApiKey x -Force -Verbose $ModuleBase = Get-Module -Name PowerShellGet -ListAvailable | Where-Object { $_.Version -ge '2.2.5'} | Select-Object -First 1 -ExpandProperty ModuleBase Publish-Module -Path $ModuleBase -Repository OSDWorkspace -NuGetApiKey x -Force -Verbose Unregister-PSRepository -Name OSDWorkspace -ErrorAction SilentlyContinue } #> #================================================= } |