{"id":9325,"date":"2024-03-01T09:04:57","date_gmt":"2024-03-01T14:04:57","guid":{"rendered":"https:\/\/jdhitsolutions.com\/blog\/?p=9325"},"modified":"2024-03-01T09:05:00","modified_gmt":"2024-03-01T14:05:00","slug":"powershell-refresh","status":"publish","type":"post","link":"https:\/\/jdhitsolutions.com\/blog\/powershell\/9325\/powershell-refresh\/","title":{"rendered":"PowerShell Refresh"},"content":{"rendered":"\n<h1 class=\"wp-block-heading\" id=\"powershell-refresh\"><\/h1>\n\n\n\n<p>The other day on X, I was asked about what things I would setup or configure on a new PowerShell installation. This is something I actually have thought about and face all the time when I setup a new demo virtual machine. I had been meaning to build new tooling to meet this challenge, and the question provided the spark I needed to get off my butt and get it done.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"windows-powershell-essentials\">Windows PowerShell Essentials<\/h2>\n\n\n\n<p>If you are running PowerShell 7, many of the critical items on my list are already addressed, so my code samples today will focus on Windows PowerShell 5.1 running on Windows 10 or Windows 11. The goal is to configure the Windows PowerShell environment for interactive use and code development.<\/p>\n\n\n\n<p>Out of the box, Windows PowerShell ships with several features that have undergone significant changes. I want to update these features. The tricky thing is that because they are included with the operating system, you can't perform a simple update. For me, I want to make sure I have the latest version of the PSReadLine and Pester modules. I also want to use the newer Microsoft.PowerShell.PSResourceGet module which replaces the older PowerShellGet module. However, before I can install and use PSResourceGet, I need to update PowerShellGet.<\/p>\n\n\n\n<p>Check to see what version you are using.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"powershell\" class=\"language-powershell\">PS C:\\> Get-Module PowerShellGet -ListAvailable\n\n\n    Directory: C:\\Program Files\\WindowsPowerShell\\Modules\n\n\nModuleType Version    Name                       ExportedCommands\n---------- -------    ----                       ----------------\nScript     1.0.0.1    PowerShellGet              {Install-Module, Find-Modul...}<\/code><\/pre>\n\n\n\n<p>If you see this, you need to update the module. However, you can't update it because it wasn't installed using <code>Install-Module<\/code>. This means you have to install as a new module.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"powershell\" class=\"language-powershell\">Install-Module -Name PowerShellGet -Force -AllowClobber -repository PSGallery<\/code><\/pre>\n\n\n\n<p>Answer yes if prompted about updating the NuGet provider.<\/p>\n\n\n\n<p>Depending on your system, you might need to adjust your TLS settings to communicate with the PowerShell Gallery.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"powershell\" class=\"language-powershell\">[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12<\/code><\/pre>\n\n\n\n<p>Once the new version is installed, you either need to restart PowerShell to use the new version or manually remove and re-import it.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"powershell\" class=\"language-powershell\">Remove-Module PowerShellGet\nImport-Module PowerShellGet\n``\n\nNext, I can install PSResourceGet module using the older `Install-Module` command.\n\n```powershell\nInstall-Module -Name Microsoft.PowerShell.PSResourceGet -Force -repository PSGallery<\/code><\/pre>\n\n\n\n<p>With the new module, I can refresh the Pester and PSReadLine modules. These too ship with Windows PowerShell on Windows 10 and 11 so I need tdo install them as new modules.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"powershell\" class=\"language-powershell\">Install-Module -Name Pester -TrustRepository -repository PSGallery\nInstall-Module -Name PSReadLine -TrustRepository -repository PSGallery<\/code><\/pre>\n\n\n\n<p>The last minimal PowerShell refresh step is to update the help files.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"powershell\" class=\"language-powershell\">Update-Help -Force<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"winget\">WinGet<\/h2>\n\n\n\n<p>The other setup task I would want to take is to add the necessary tools to my Windows 10 or Windows 11 environment related to PowerShell scripting. At a minimum this means installing:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>git<\/li>\n\n\n\n<li>VSCode<\/li>\n\n\n\n<li>The GitHub CLI<\/li>\n<\/ul>\n\n\n\n<p>The best solution will be to use a package manager to install these tools. You can use whatever package manager you prefer, but I am going to use the Windows Package Manager, WinGet.<\/p>\n\n\n\n<p>I could take the easy route and install the tools manually, but I want to automate the process, including installing <code>Winget<\/code>. This  gets slightly complicated. <code>Winget<\/code> has several dependencies I have to account for. I can get them from Nuget.org but I'll need to add a new package source.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"powershell\" class=\"language-powershell\">Register-PackageSource -Name Nuget.org -ProviderName NuGet -Force -ForceBootstrap -Location 'https:\/\/nuget.org\/api\/v2'<\/code><\/pre>\n\n\n\n<p>I can use this source to install the first dependency.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"powershell\" class=\"language-powershell\">Install-Package -Name microsoft.ui.xaml -Source nuget.org -Force<\/code><\/pre>\n\n\n\n<p>This process doesn't install it like a piece of software. But I can get what I need from the package contents. The installed file has a <code>.nuget<\/code> extension, but the file is a zip file. I can extract the contents to a folder get the file I need, which I can then install using <code>Add-AppxPackage<\/code>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"powershell\" class=\"language-powershell\">Copy-Item -Path (Get-Package microsoft.ui.xaml).source -Destination $env:TEMP\\microsoft.ui.xaml.zip\nExpand-Archive $env:temp\\microsoft.ui.xaml.zip -DestinationPath \"$env:temp\\ui\" -Force\nAdd-AppxPackage $env:temp\\ui\\tools\\appx\\x64\\release\\Microsoft.UI.Xaml.2.8.appx<\/code><\/pre>\n\n\n\n<p>The other dependency I can download directly and add with <code>Add-AppxPackage<\/code>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"powershell\" class=\"language-powershell\">Invoke-WebRequest -Uri'https:\/\/aka.ms\/Microsoft.VCLibs.x64.14.00.Desktop.appx' -OutFile $env:temp\\VCLibs.appx\nAdd-AppxPackage $env:temp\\VCLibs.appx<\/code><\/pre>\n\n\n\n<p>Once these dependencies are installed, I can install <code>Winget<\/code> by downloading it from Github.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"powershell\" class=\"language-powershell\">#get the current release\n$uri = 'https:\/\/api.github.com\/repos\/microsoft\/winget-cli\/releases'\n$get = Invoke-RestMethod -Uri $uri -Method Get -ErrorAction stop\n#get the URL to the current release asset\n$current = $get[0].assets | Where-Object name -Match 'msixbundle'\n#define a path to save the file\n$out = Join-Path -Path $env:temp -child $current.name\n#download the file\nInvoke-WebRequest -Uri $current.browser_download_url -OutFile $out\n#install the file\nAdd-AppxPackage -Path $out<\/code><\/pre>\n\n\n\n<p>This is about a 250MB file so if you think you will be installing it often, you will want to save the file.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"packages\">Packages<\/h2>\n\n\n\n<p>Now, I can install the <code>Winget<\/code> packages. I use the package <code>ID<\/code>. I want the installation to be silent and completely hands-free.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"powershell\" class=\"language-powershell\">winget install --id git.git --silent --accept-package-agreements --accept-source-agreements --source winget\nwinget install --id github.cli --silent --accept-package-agreements --accept-source-agreements --source winget\nwinget install --id Microsoft.VisualStudioCode --silent --accept-package-agreements --accept-source-agreements --source winget<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"an-automated-solution\">An Automated Solution<\/h2>\n\n\n\n<p>Naturally, I want to automate this entire process. So I wrote a PowerShell script file.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"powershell\" class=\"language-powershell\">#requires -version 5.1\n#requires -RunAsAdministrator\n\n#PSRefresh.ps1\n\n&lt;#\nUpdate key PowerShell components on a new Windows 10\/11 installation.\n\nThis script is not intended for server operating systems. The script\nshould be run in an interactive console session and not in a remoting session.\n\nYou can modify this script to use a different package manager like Chocolatey.\n\nIf you use the Offline option, make sure your file names match the script.\n\nThis script is offered AS-IS and without warranty. Use at your own risk.\n#>\n\n#TODO: Add SupportsShouldProcess code\n#TODO: Add proper error handling\n\n[CmdletBinding()]\nParam(\n    [Parameter(Position = 0,Mandatory,HelpMessage = 'The path to a configuration data file')]\n    [ValidateScript({ Test-Path -Path $_})]\n    [ValidatePattern('\\.psd1$')]\n    [string]$ConfigurationData,\n    [Parameter(HelpMessage = 'Specify a location with previously installed Appx packages')]\n    [ValidateScript({ Test-Path -Path $_ })]\n    [string]$Offline\n)\n\n#this script should be run in the console, not the ISE or VSCode\nif ($Host.name -ne 'ConsoleHost') {\n    Write-Warning 'This script should be run in the PowerShell console, not the ISE or VSCode'\n    return\n}\n\n#region Setup\nTry {\n    $data = Import-PowerShellDataFile -Path $ConfigurationData -ErrorAction Stop\n}\nCatch {\n    Write-Warning \"Failed to import $ConfigurationData\"\n    Return\n}\n\n#define a list of winget package IDs\n#$wingetPackages = @('Microsoft.VisualStudioCode', 'Git.Git', 'GitHub.cli', 'Microsoft.WindowsTerminal')\n$wingetPackages = $data.wingetPackages\n$PSModules = $data.PSModules\n$Scope = $data.Scope\n$vscExtensions = $data.vscExtensions\n\n#install winget apps and additional PowerShell modules via background jobs\n$jobs = @()\n\n$installParams = @{\n    Scope        = $Scope\n    Repository   = 'PSGallery'\n    Force        = $true\n    AllowClobber = $true\n    Name         = $null\n}\n\n$progParams = @{\n    Activity = $MyInvocation.MyCommand\n    Status   = 'Initializing'\n    CurrentOperation = 'Bootstrapping a NuGet provider update'\n    PercentComplete = 1\n}\n\n#set TLS just in case\n[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12\n\nWrite-Progress @progParams\n\n#Bootstrap Nuget provider update  to avoid interactive prompts\n[void](Install-PackageProvider -Name Nuget -ForceBootstrap -Force)\n\n#endregion\n\n#region Update PowerShellGet\n$progParams.Status = \"Module updates\"\n$progParams.CurrentOperation = \"Updating PowerShellGet\"\n$progParams.PercentComplete = 10\nWrite-Progress @progParams\n\n$get = Get-Module PowerShellGet -ListAvailable | Select-Object -First 1\nif ($get.Version.major -eq 1) {\n    #Write-Host 'Installing the latest version of PowerShellGet' -ForegroundColor Yellow\n    $installParams.Name = 'PowerShellGet'\n    Install-Module @installParams\n}\nelse {\n    #Write-Host 'Updating PowerShellGet' -ForegroundColor Yellow\n    Update-Module -Name PowerShellGet -Force\n}\n\n#reload PowerShellGet\nRemove-Module PowerShellGet\nImport-Module PowerShellGet\n\n#endregion\n\n#region Install Microsoft.PowerShell.PSResourceGet\n$progParams.Status = \"Module updates\"\n$progParams.CurrentOperation = \"Microsoft.PowerShell.PSResourceGet\"\n$progParams.PercentComplete = 20\nWrite-Progress @progParams\n#Write-Host 'Installing Microsoft.PowerShell.PSResourceGet' -ForegroundColor Yellow\n$installParams.Name = 'Microsoft.PowerShell.PSResourceGet'\nInstall-Module @installParams\n\nImport-Module Microsoft.PowerShell.PSResourceGet\n\n#endregion\n\n#region Install updated Modules\n\n$progParams.Status = \"Module updates\"\n$progParams.CurrentOperation = \"PSReadLine\"\n$progParams.PercentComplete = 25\nWrite-Progress @progParams\n\n#Write-Host 'Installing PSReadLine' -ForegroundColor Yellow\nInstall-PSResource -Name PSReadLine -Scope $Scope -Repository PSGallery -TrustRepository\n\n$progParams.Status = \"Module updates\"\n$progParams.CurrentOperation = \"Pester - You may see a warning.\"\n$progParams.PercentComplete = 30\nWrite-Progress @progParams\n\n#Write-Host 'Installing Pester. You might see a warning.' -ForegroundColor Yellow\nInstall-PSResource -Name Pester -Scope $Scope -Repository PSGallery -TrustRepository\n\n#endregion\n\n#region install winget dependencies\n\n$progParams.Status = \"Installing Winget\"\n$progParams.CurrentOperation = \"Processing dependencies\"\n$progParams.PercentComplete = 40\nWrite-Progress @progParams\n#Write-Host 'Adding Nuget.org as a package source' -ForegroundColor Yellow\n[void](Register-PackageSource -Name Nuget.org -ProviderName NuGet -Force -ForceBootstrap -Location 'https:\/\/nuget.org\/api\/v2')\n\n#Write-Host 'Installing winget dependencies' -ForegroundColor Yellow\n\nif ($Offline) {\n    Add-AppxPackage \"$Offline\\microsoft.ui.xaml.2.8.appx\"\n    Add-AppxPackage \"$Offline\\VCLibs.appx\"\n}\nelse {\n    [void](Install-Package -Name microsoft.ui.xaml -Source nuget.org -Force)\n    Copy-Item -Path (Get-Package microsoft.ui.xaml).source -Destination $env:TEMP\\microsoft.ui.xaml.zip\n    Expand-Archive $env:temp\\microsoft.ui.xaml.zip -DestinationPath \"$env:temp\\ui\" -Force\n    Add-AppxPackage $env:temp\\ui\\tools\\appx\\x64\\release\\Microsoft.UI.Xaml.2.8.appx\n    $uri = 'https:\/\/aka.ms\/Microsoft.VCLibs.x64.14.00.Desktop.appx'\n    Invoke-WebRequest -Uri $uri -OutFile $env:temp\\VCLibs.appx\n    Add-AppxPackage $env:temp\\VCLibs.appx\n}\n\n#endregion\n\n#region Install winget\n\n#Write-Host 'Installing winget' -ForegroundColor Yellow\n$progParams.Status = \"Installing Winget\"\n$progParams.CurrentOperation = \"Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle\"\n$progParams.PercentComplete = 50\nWrite-Progress @progParams\nif ($Offline) {\n    Add-AppxPackage \"$Offline\\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle\"\n}\nelse {\n    #Winget is a 246MB download\n    $uri = 'https:\/\/api.github.com\/repos\/microsoft\/winget-cli\/releases'\n    $get = Invoke-RestMethod -Uri $uri -Method Get -ErrorAction stop\n    $current = $get[0].assets | Where-Object name -Match 'msixbundle'\n\n    #Write-Host \"Downloading $($current.name)\" -ForegroundColor Yellow\n    $out = Join-Path -Path $env:temp -child $current.name\n    Try {\n        Invoke-WebRequest -Uri $current.browser_download_url -OutFile $out -ErrorAction Stop\n        Add-AppxPackage -Path $out\n    }\n    Catch {\n        $_\n    }\n}\n\n#endregion\n\n#region Install winget packages\n$progParams.Status = \"Installing packages via winget\"\n$pct = 50\n\nforeach ($package in $wingetPackages) {\n    $progParams.CurrentOperation = $package\n    $progParams.PercentComplete = $pct+=2\n    Write-Progress @progParams\n    $jobs+= Start-Job -Name $package -ScriptBlock {\n        #This script does not take scope into account for Winget installations.\n        #You might want to change that.\n        Param($package)\n        winget install --id $package --silent --accept-package-agreements --accept-source-agreements --source winget\n    } -ArgumentList $package\n\n    #Write-Host \"Installing $package\" -ForegroundColor Yellow\n    #winget install --id $package --silent --accept-package-agreements --accept-source-agreements --source winget\n} #foreach package\n\n#endregion\n\n#region install additional PowerShell modules\n\nif ($PSModules) {\n    $progParams.Status = \"Installing additional PowerShell modules\"\n    foreach ($Mod in $PSModules) {\n        $progParams.CurrentOperation = $Mod\n        $progParams.PercentComplete = $pct+=2\n        Write-Progress @progParams\n        $jobs+= Start-Job -Name $Mod -ScriptBlock {\n            #This script does not take scope into account for Winget installations.\n            #You might want to change that.\n            Param($ModuleName,$scope)\n            Import-Module Microsoft.PowerShell.PSResourceGet\n            Install-PSResource -Name $ModuleName -Scope $Scope -Repository PSGallery -AcceptLicense -TrustRepository -Quiet\n        } -ArgumentList $Mod,$Scope\n    } #foreach module\n}\n\n#endregion\n\n#region install VSCode extensions\n\nif ($vscExtensions) {\n\n    $progParams.Status = \"Installing VSCode extensions\"\n    $progParams.PercentComplete = $pct+=2\n    foreach ($Extension in $vscExtensions) {\n        $progParams.CurrentOperation = $Extension\n        Write-Progress @progParams\n        $jobs+= Start-Job -Name $Extension -ScriptBlock {\n        Param($Name)\n        &amp;\"$HOME\\AppData\\Local\\Programs\\Microsoft VS Code\\bin\\code.cmd\" --install-extension $Name --force\n        } -ArgumentList $Extension\n    }\n}\n\n#endregion\n\n#region Update help\n\n$progParams.Status = \"Updating Help. Some errors are to be expected.\"\n$progParams.CurrentOperation = \"Update-Help -Force\"\n$progParams.PercentComplete = $pct+=5\nWrite-Progress @progParams\n#Write-Host 'Updating PowerShell help. Some errors are to be expected.' -ForegroundColor Yellow\nUpdate-Help -Force\n\n#endregion\n\n#region Wait for end\n$progParams.Status = \"Waiting for $($jobs.count) background jobs to complete\"\n$progParams.CurrentOperation = \"Wait-Job\"\n$progParams.PercentComplete = $pct+=2\nWrite-Progress @progParams\n$jobs | Wait-Job | Select-Object Name,State\n\nWrite-Progress -Activity $progParams.Activity -Completed -Status \"All tasks completed.\" -PercentComplete 100\n\n$msg = @'\n\nRefresh is complete. You might also want to install the following modules using Install-PSResource:\n\n    Microsoft.Winget.Client\n    Microsoft.PowerShell.SecretStore\n    Microsoft.PowerShell.SecretManagement\n    Platyps\n\nAnd the following packages via Winget:\n\n    Microsoft.PowerToys\n    Microsoft.PowerShell\n\nYou will need to configure VSCode with your preferred extensions and settings or configure\nit to synch your saved settings.\n\nPlease restart your PowerShell session.\n\n'@\n\nWrite-Host $msg -ForegroundColor Green\n\n#endregion\n\n#EOF<\/code><\/pre>\n\n\n\n<p>The script uses <code>Write-Progress<\/code>, but I've left the original <code>Write-Host<\/code> commands in the script commented out.<\/p>\n\n\n\n<p>In the initial versions of the script, I included additional PowerShell modules and packages directly in the code. Some items, like installing Pester and PSReadLine are special cases so I don't have problem with that code. But everything else can be moved to a configuration data file. This is a good example of the concept of separating the data you need to use from the code itself.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"powershell\" class=\"language-powershell\">#PSRefresh.psd1\n#PSModules should be new modules to install\n#Scope can be 'CurrentUser' or 'AllUsers'\n#vscExtensions are Visual Studio Code extensions to install\n@{\n    wingetPackages = @(\n        'Microsoft.VisualStudioCode',\n        'Git.Git',\n        'GitHub.cli',\n        'Microsoft.WindowsTerminal',\n        'github.githubdesktop',\n        'Microsoft.PowerShell'\n        )\n    PSModules = @(\"PSScriptTools\",\"PSProjectStatus\",\"PSStyle\",\"Platyps\")\n    vscExtensions = @(\n        'github.copilot',\n        'github.copilot-chat',\n        'github.remotehub',\n        'ms-vscode.powershell',\n        'davidanson.vscode-markdownlint',\n        'inu1255.easy-snippet',\n        'gruntfuggly.todo-tree'\n    )\n    Scope = 'AllUsers'\n    Version = '1.2.0'\n}<\/code><\/pre>\n\n\n\n<p>My script will also install VSCode extensions. I included this more as a demonstration than anything. Normally, I synchronize my VSCode settings across installations, but it is possible I'm setting up a new demo environment where I'm not going to login so this could be useful.<\/p>\n\n\n\n<p>The configuration file is mandatory.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"powershell\" class=\"language-powershell\">c:\\scripts\\psrefresh.ps1 -configurationdata c:\\scripts\\psrefresh.psd1<\/code><\/pre>\n\n\n\n<p>If I decide to change modules or packages, all I have to do is edit the configuration file. I don't have to worry about messing up my code with revisions.<\/p>\n\n\n\n<p>The other feature in my script is the ability to install the Appx packages offline. The <code>Winget<\/code> dependencies don't change often so I can save the files that I've downloaded. Likewise, I can periodically download the latest <code>Winget<\/code> release for future installations. The packages should go in the same folder. Be sure to use the same file names as in the script.<\/p>\n\n\n\n<p>To use, all I need to do is specify the path to the saved files.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"powershell\" class=\"language-powershell\">c:\\scripts\\psrefresh.ps1 -configurationdata c:\\scripts\\psrefresh.psd1 -offline d:\\saved<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"background-jobs\">Background Jobs<\/h2>\n\n\n\n<p>The other feature of the script to note is the use of background jobs. Once the core steps are out of the way, installing additional modules and packages can happen in parallel. The easiest way in Windows PowerShell is to run each activity in a background job.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"powershell\" class=\"language-powershell\">foreach ($Mod in $PSModules) {\n    $progParams.CurrentOperation = $Mod\n    $progParams.PercentComplete = $pct+=2\n    Write-Progress @progParams\n    $jobs+= Start-Job -Name $Mod -ScriptBlock {\n        Param($ModuleName,$scope)\n        Import-Module Microsoft.PowerShell.PSResourceGet\n        Install-PSResource -Name $ModuleName -Scope $Scope -Repository PSGallery -AcceptLicense -TrustRepository -Quiet\n    } -ArgumentList $Mod,$Scope\n} #foreach module\n\nThe jobs run while PowerShell is updated. The script waits for all jobs to complete before displaying a completion message.\n\n```powershell\n$jobs | Wait-Job | Select-Object Name,State\n$msg = @'\n\nRefresh is complete. You might also want to install the following modules using Install-PSResource:\n\n    Microsoft.Winget.Client\n    Microsoft.PowerShell.SecretStore\n    Microsoft.PowerShell.SecretManagement\n    Platyps\n\nAnd the following packages via Winget:\n\n    Microsoft.PowerToys\n    Microsoft.PowerShell\n\nYou will need to configure VSCode with your preferred extensions and settings or configure\nit to synch your saved settings.\n\nPlease restart your PowerShell session.\n\n'@\n\nWrite-Host $msg -ForegroundColor Green<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"your-turn\">Your Turn<\/h2>\n\n\n\n<p>You are welcome to give my code a try. I have posted the files as a <a href=\"https:\/\/gist.github.com\/jdhitsolutions\/a4bf620bf367ef55151398e4464339e5\"><strong>GitHub gist<\/strong><\/a>, which I'll try to keep updated. The files are offered AS-IS for educational purposes as much as anything. The script is not 100% production-ready and lacks error handling. And of course, the extra modules and packages are things that I would want to install it. I'd love to hear what you think.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The other day on X, I was asked about what things I would setup or configure on a new PowerShell installation. This is something I actually have thought about and face all the time when I setup a new demo virtual machine. I had been meaning to build new tooling to meet this challenge, and&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"My take on automating the refresh of a new Windows PowerShell 5.1 environment.","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[4,8],"tags":[22,534,540],"class_list":["post-9325","post","type-post","status-publish","format-standard","hentry","category-powershell","category-scripting","tag-automation","tag-powershell","tag-scripting"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>PowerShell Refresh &#8226; The Lonely Administrator<\/title>\n<meta name=\"description\" content=\"My process and tooling for refreshing a new Windows PowerShell environment.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/jdhitsolutions.com\/blog\/powershell\/9325\/powershell-refresh\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"PowerShell Refresh &#8226; The Lonely Administrator\" \/>\n<meta property=\"og:description\" content=\"My process and tooling for refreshing a new Windows PowerShell environment.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/jdhitsolutions.com\/blog\/powershell\/9325\/powershell-refresh\/\" \/>\n<meta property=\"og:site_name\" content=\"The Lonely Administrator\" \/>\n<meta property=\"article:published_time\" content=\"2024-03-01T14:04:57+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-03-01T14:05:00+00:00\" \/>\n<meta name=\"author\" content=\"Jeffery Hicks\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@JeffHicks\" \/>\n<meta name=\"twitter:site\" content=\"@JeffHicks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Jeffery Hicks\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"5 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/9325\\\/powershell-refresh\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/9325\\\/powershell-refresh\\\/\"},\"author\":{\"name\":\"Jeffery Hicks\",\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/#\\\/schema\\\/person\\\/d0258030b41f07fd745f4078bdf5b6c9\"},\"headline\":\"PowerShell Refresh\",\"datePublished\":\"2024-03-01T14:04:57+00:00\",\"dateModified\":\"2024-03-01T14:05:00+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/9325\\\/powershell-refresh\\\/\"},\"wordCount\":977,\"commentCount\":6,\"publisher\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/#\\\/schema\\\/person\\\/d0258030b41f07fd745f4078bdf5b6c9\"},\"keywords\":[\"Automation\",\"PowerShell\",\"Scripting\"],\"articleSection\":[\"PowerShell\",\"Scripting\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/9325\\\/powershell-refresh\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/9325\\\/powershell-refresh\\\/\",\"url\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/9325\\\/powershell-refresh\\\/\",\"name\":\"PowerShell Refresh &#8226; The Lonely Administrator\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/#website\"},\"datePublished\":\"2024-03-01T14:04:57+00:00\",\"dateModified\":\"2024-03-01T14:05:00+00:00\",\"description\":\"My process and tooling for refreshing a new Windows PowerShell environment.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/9325\\\/powershell-refresh\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/9325\\\/powershell-refresh\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/9325\\\/powershell-refresh\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"PowerShell\",\"item\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/category\\\/powershell\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"PowerShell Refresh\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/\",\"name\":\"The Lonely Administrator\",\"description\":\"Practical Advice for the Automating IT Pro\",\"publisher\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/#\\\/schema\\\/person\\\/d0258030b41f07fd745f4078bdf5b6c9\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/#\\\/schema\\\/person\\\/d0258030b41f07fd745f4078bdf5b6c9\",\"name\":\"Jeffery Hicks\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg\",\"caption\":\"Jeffery Hicks\"},\"logo\":{\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"PowerShell Refresh &#8226; The Lonely Administrator","description":"My process and tooling for refreshing a new Windows PowerShell environment.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/jdhitsolutions.com\/blog\/powershell\/9325\/powershell-refresh\/","og_locale":"en_US","og_type":"article","og_title":"PowerShell Refresh &#8226; The Lonely Administrator","og_description":"My process and tooling for refreshing a new Windows PowerShell environment.","og_url":"https:\/\/jdhitsolutions.com\/blog\/powershell\/9325\/powershell-refresh\/","og_site_name":"The Lonely Administrator","article_published_time":"2024-03-01T14:04:57+00:00","article_modified_time":"2024-03-01T14:05:00+00:00","author":"Jeffery Hicks","twitter_card":"summary_large_image","twitter_creator":"@JeffHicks","twitter_site":"@JeffHicks","twitter_misc":{"Written by":"Jeffery Hicks","Est. reading time":"5 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/9325\/powershell-refresh\/#article","isPartOf":{"@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/9325\/powershell-refresh\/"},"author":{"name":"Jeffery Hicks","@id":"https:\/\/jdhitsolutions.com\/blog\/#\/schema\/person\/d0258030b41f07fd745f4078bdf5b6c9"},"headline":"PowerShell Refresh","datePublished":"2024-03-01T14:04:57+00:00","dateModified":"2024-03-01T14:05:00+00:00","mainEntityOfPage":{"@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/9325\/powershell-refresh\/"},"wordCount":977,"commentCount":6,"publisher":{"@id":"https:\/\/jdhitsolutions.com\/blog\/#\/schema\/person\/d0258030b41f07fd745f4078bdf5b6c9"},"keywords":["Automation","PowerShell","Scripting"],"articleSection":["PowerShell","Scripting"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/jdhitsolutions.com\/blog\/powershell\/9325\/powershell-refresh\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/9325\/powershell-refresh\/","url":"https:\/\/jdhitsolutions.com\/blog\/powershell\/9325\/powershell-refresh\/","name":"PowerShell Refresh &#8226; The Lonely Administrator","isPartOf":{"@id":"https:\/\/jdhitsolutions.com\/blog\/#website"},"datePublished":"2024-03-01T14:04:57+00:00","dateModified":"2024-03-01T14:05:00+00:00","description":"My process and tooling for refreshing a new Windows PowerShell environment.","breadcrumb":{"@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/9325\/powershell-refresh\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/jdhitsolutions.com\/blog\/powershell\/9325\/powershell-refresh\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/9325\/powershell-refresh\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"PowerShell","item":"https:\/\/jdhitsolutions.com\/blog\/category\/powershell\/"},{"@type":"ListItem","position":2,"name":"PowerShell Refresh"}]},{"@type":"WebSite","@id":"https:\/\/jdhitsolutions.com\/blog\/#website","url":"https:\/\/jdhitsolutions.com\/blog\/","name":"The Lonely Administrator","description":"Practical Advice for the Automating IT Pro","publisher":{"@id":"https:\/\/jdhitsolutions.com\/blog\/#\/schema\/person\/d0258030b41f07fd745f4078bdf5b6c9"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/jdhitsolutions.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/jdhitsolutions.com\/blog\/#\/schema\/person\/d0258030b41f07fd745f4078bdf5b6c9","name":"Jeffery Hicks","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg","url":"https:\/\/secure.gravatar.com\/avatar\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg","caption":"Jeffery Hicks"},"logo":{"@id":"https:\/\/secure.gravatar.com\/avatar\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg"}}]}},"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"jetpack-related-posts":[{"id":7361,"url":"https:\/\/jdhitsolutions.com\/blog\/scripting\/7361\/powershell-7-cross-platform-scripting-tips-and-traps\/","url_meta":{"origin":9325,"position":0},"title":"PowerShell 7 Cross-Platform Scripting Tips and Traps","author":"Jeffery Hicks","date":"March 13, 2020","format":false,"excerpt":"One of the reasons you want to adopt PowerShell 7 on your desktop, is that it can\u00a0 be used cross-platform. Theoretically, you can write a PowerShell script or function that works on Windows, Linux, and Mac. However, this is not without challenges. In some ways, it feels like we are\u2026","rel":"","context":"In &quot;PowerShell 7&quot;","block_context":{"text":"PowerShell 7","link":"https:\/\/jdhitsolutions.com\/blog\/category\/powershell-7\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/03\/hicks-scripting-4.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/03\/hicks-scripting-4.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/03\/hicks-scripting-4.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/03\/hicks-scripting-4.png?resize=700%2C400&ssl=1 2x"},"classes":[]},{"id":8420,"url":"https:\/\/jdhitsolutions.com\/blog\/powershell\/8420\/managing-the-windows-10-taskbar-with-powershell\/","url_meta":{"origin":9325,"position":1},"title":"Managing the Windows 10 Taskbar with PowerShell","author":"Jeffery Hicks","date":"May 20, 2021","format":false,"excerpt":"When I'm working on a Pluralsight course, I tend to setup a virtual machine for recording. Although, lately I've been trying with Windows 10 Sandbox. This is handy when all I need is a Windows 10 desktop. When I setup the system, I have particular settings I need to configure.\u2026","rel":"","context":"In &quot;PowerShell&quot;","block_context":{"text":"PowerShell","link":"https:\/\/jdhitsolutions.com\/blog\/category\/powershell\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/05\/taskbar-regsettings.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/05\/taskbar-regsettings.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/05\/taskbar-regsettings.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/05\/taskbar-regsettings.png?resize=700%2C400&ssl=1 2x"},"classes":[]},{"id":153,"url":"https:\/\/jdhitsolutions.com\/blog\/powershell\/153\/primalforms-now-available\/","url_meta":{"origin":9325,"position":2},"title":"PrimalForms now Available","author":"Jeffery Hicks","date":"November 3, 2008","format":false,"excerpt":"Even though PowerShell is by design a console based management tool, there are instances where you would like to use a GUI. PowerShell can use the Windows forms classes from the .NET Framework. However in the past creating anything other than the simplest of forms was very tedious and time\u2026","rel":"","context":"In &quot;PowerShell&quot;","block_context":{"text":"PowerShell","link":"https:\/\/jdhitsolutions.com\/blog\/category\/powershell\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":7969,"url":"https:\/\/jdhitsolutions.com\/blog\/powershell-7\/7969\/deploy-openssh-server-to-windows-10\/","url_meta":{"origin":9325,"position":3},"title":"Deploy OpenSSH Server to Windows 10","author":"Jeffery Hicks","date":"December 16, 2020","format":false,"excerpt":"PowerShell 7 offers a number of compelling reasons to adopt it. One of the best is support for SSH as a PowerShell remoting protocol. Unfortunately, this is not a topic that typically comes up for Windows-centric IT Pros. I know this is definitely true in my case, and a deficiency\u2026","rel":"","context":"In &quot;PowerShell&quot;","block_context":{"text":"PowerShell","link":"https:\/\/jdhitsolutions.com\/blog\/category\/powershell\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/12\/sshserver-installed.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/12\/sshserver-installed.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/12\/sshserver-installed.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/12\/sshserver-installed.png?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/12\/sshserver-installed.png?resize=1050%2C600&ssl=1 3x, https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/12\/sshserver-installed.png?resize=1400%2C800&ssl=1 4x"},"classes":[]},{"id":165,"url":"https:\/\/jdhitsolutions.com\/blog\/powershell\/165\/primalforms-2009-now-available\/","url_meta":{"origin":9325,"position":4},"title":"PrimalForms 2009 Now Available","author":"Jeffery Hicks","date":"August 4, 2009","format":false,"excerpt":"SAPIEN Technologies finally released PrimalForms 2009. If you have any sort of requirement to create a graphical interface to your PowerShell script, this is the tool to get.\u00a0 SAPIEN will continue to offer the free community version of Primal Forms from their community tools page. PrimalForms 2009 includes these features:\u2026","rel":"","context":"In &quot;PowerShell&quot;","block_context":{"text":"PowerShell","link":"https:\/\/jdhitsolutions.com\/blog\/category\/powershell\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":5633,"url":"https:\/\/jdhitsolutions.com\/blog\/powershell\/5633\/get-git-with-powershell\/","url_meta":{"origin":9325,"position":5},"title":"Get Git with PowerShell","author":"Jeffery Hicks","date":"August 25, 2017","format":false,"excerpt":"If you are creating PowerShell scripts, tools or modules today, you are most likely using Git. What? You're not? Is it because you haven't gotten around to installing it? I have some \"quick and dirty\" PowerShell hacks to help you out on Windows systems. Linux boys and girls already know\u2026","rel":"","context":"In &quot;Git&quot;","block_context":{"text":"Git","link":"https:\/\/jdhitsolutions.com\/blog\/category\/git\/"},"img":{"alt_text":"image","src":"https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2017\/08\/image_thumb-8.png?resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2017\/08\/image_thumb-8.png?resize=350%2C200 1x, https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2017\/08\/image_thumb-8.png?resize=525%2C300 1.5x, https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2017\/08\/image_thumb-8.png?resize=700%2C400 2x"},"classes":[]}],"_links":{"self":[{"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/posts\/9325","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/comments?post=9325"}],"version-history":[{"count":1,"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/posts\/9325\/revisions"}],"predecessor-version":[{"id":9326,"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/posts\/9325\/revisions\/9326"}],"wp:attachment":[{"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/media?parent=9325"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/categories?post=9325"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/tags?post=9325"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}