<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>DSC on CodeBytes - The Curious Engineer</title><link>https://chris-ayers.com/tags/dsc/</link><description>Recent content in DSC on CodeBytes - The Curious Engineer</description><generator>Hugo -- gohugo.io</generator><language>en-US</language><copyright>© 2026 Chris Ayers</copyright><lastBuildDate>Sun, 23 Aug 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://chris-ayers.com/tags/dsc/index.xml" rel="self" type="application/rss+xml"/><item><title>Automate Your Windows Dev Machine with WinGet DSC</title><link>https://chris-ayers.com/posts/winget-dsc-windows-setup/</link><pubDate>Sun, 23 Aug 2026 00:00:00 +0000</pubDate><guid>https://chris-ayers.com/posts/winget-dsc-windows-setup/</guid><description>&lt;p&gt;Stop manually installing tools on a fresh Windows machine — declare what you want and let WinGet DSC handle the rest.&lt;/p&gt;</description><content:encoded>&lt;p&gt;Stop manually installing tools on a fresh Windows machine — declare what you want and let WinGet DSC handle the rest.&lt;/p&gt;&#10;&lt;p&gt;I recently got a new work laptop, which meant setting everything up from scratch again — the perfect excuse to finally revise my machine setup and move it to something more maintainable. What I wanted was simple: run one command, walk away, and come back to a fully configured dev box — the same way every time, on any machine.&lt;/p&gt;&#10;&lt;p&gt;This post walks through how I got there with WinGet DSC: the declarative config that drives the whole thing, the bootstrapper that makes a fresh machine ready to run it, and the extras — Dev Drive, security hardening, and shell setup — that turn a pile of installers into a single source of truth.&lt;/p&gt;&#10;&#10;&lt;h2 class="relative group"&gt;The Problem&#10; &#10; &#10; &#10; &#10;&lt;/h2&gt;&#10;&lt;p&gt;Every developer knows the pain. You get a new Windows machine — or reinstall the OS — and then spend hours clicking through installers, tweaking settings, and trying to remember what tools you had. Maybe you have a checklist somewhere. Maybe you wing it.&lt;/p&gt;&#10;&lt;p&gt;I used to maintain a &lt;a href="https://github.com/codebytes/windows-setup" target="_blank" rel="noreferrer"&gt;PowerShell script&lt;/a&gt; with dozens of imperative &lt;code&gt;winget install&lt;/code&gt; commands. It worked, but it was fragile — if a package was already installed, I needed extra logic to skip it. If a setting was already applied, I had to check first. The script grew to 750+ lines of defensive code.&lt;/p&gt;&#10;&lt;p&gt;There&amp;rsquo;s a better way.&lt;/p&gt;&#10;&#10;&lt;h2 class="relative group"&gt;Enter WinGet DSC&#10; &#10; &#10; &#10; &#10;&lt;/h2&gt;&#10;&lt;p&gt;&lt;a href="https://learn.microsoft.com/en-us/windows/package-manager/configuration/" target="_blank" rel="noreferrer"&gt;WinGet DSC&lt;/a&gt; (Desired State Configuration) lets you describe the &lt;strong&gt;desired state&lt;/strong&gt; of your machine in a YAML file. WinGet reads the file and makes your machine match — installing what&amp;rsquo;s missing, skipping what&amp;rsquo;s already there, and configuring settings to your spec.&lt;/p&gt;&#10;&lt;p&gt;It&amp;rsquo;s &lt;strong&gt;declarative&lt;/strong&gt; instead of &lt;strong&gt;imperative&lt;/strong&gt;. You say &lt;em&gt;what&lt;/em&gt; you want, not &lt;em&gt;how&lt;/em&gt; to get there.&lt;/p&gt;&#10;&#10;&lt;h3 class="relative group"&gt;A Simple Example&#10; &#10; &#10; &#10; &#10;&lt;/h3&gt;&#10;&lt;p&gt;Here&amp;rsquo;s what installing VS Code looks like with WinGet DSC:&lt;/p&gt;&#10;&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;configurationVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0.2.0&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Microsoft.WinGet.DSC/WinGetPackage&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;vscode&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;directives&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Install Visual Studio Code&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;allowPrerelease&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Microsoft.VisualStudioCode&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;winget&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;p&gt;Compare that to the imperative approach:&lt;/p&gt;&#10;&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;$output&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;winget&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;-id&lt;/span&gt; &lt;span class="n"&gt;Microsoft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;VisualStudioCode&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="o"&gt;-exact&lt;/span&gt; &lt;span class="mf"&gt;2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="vm"&gt;$null&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$output&lt;/span&gt; &lt;span class="o"&gt;-notmatch&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Microsoft.VisualStudioCode&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;winget&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;-id&lt;/span&gt; &lt;span class="n"&gt;Microsoft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;VisualStudioCode&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="o"&gt;-exact&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;-silent&lt;/span&gt; &lt;span class="p"&gt;`&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;-accept-package-agreements&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;-accept-source-agreements&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;p&gt;The DSC version handles the &amp;ldquo;is it already installed?&amp;rdquo; check automatically. Multiply that across 30+ packages and you&amp;rsquo;ve eliminated hundreds of lines of defensive code.&lt;/p&gt;&#10;&#10;&lt;figure&gt;&#10; &lt;img&#10; class="my-0 rounded-md mx-auto"&#10; loading="lazy"&#10; decoding="async"&#10; fetchpriority="auto"&#10; alt="Imperative script flow vs declarative WinGet DSC approach"&#10; width="1026"&#10; height="472"&#10; src="https://chris-ayers.com/images/diagrams/winget-dsc-imperative-vs-declarative.drawio_hu_3893d25ef9c56644.png"&#10; srcset="https://chris-ayers.com/images/diagrams/winget-dsc-imperative-vs-declarative.drawio_hu_3893d25ef9c56644.png 800w,/images/diagrams/winget-dsc-imperative-vs-declarative.drawio_hu_1187b5a7d5b353bf.png 1280w"&#10; sizes="(min-width: 768px) 50vw, 65vw"&#10; data-zoom-src="https://chris-ayers.com/images/diagrams/winget-dsc-imperative-vs-declarative.drawio.png"&#10; /&gt;&#10; &#10; &#10; &lt;/figure&gt;&#10;&#10;&lt;h2 class="relative group"&gt;My Setup: codebytes/windows-setup&#10; &#10; &#10; &#10; &#10;&lt;/h2&gt;&#10;&lt;p&gt;I recently revamped my &lt;a href="https://github.com/codebytes/windows-setup" target="_blank" rel="noreferrer"&gt;windows-setup&lt;/a&gt; repo to use this pattern, inspired by &lt;a href="https://github.com/shanselman/wingetdevsetup" target="_blank" rel="noreferrer"&gt;Scott Hanselman&amp;rsquo;s wingetdevsetup&lt;/a&gt;. Here&amp;rsquo;s the architecture:&lt;/p&gt;&#10;&#10;&lt;figure&gt;&#10; &lt;img&#10; class="my-0 rounded-md mx-auto"&#10; loading="lazy"&#10; decoding="async"&#10; fetchpriority="auto"&#10; alt="WinGet DSC architecture showing boot.ps1 bootstrapper flowing into DSC engine processing packages, settings, scripts, and Dev Drive"&#10; width="835"&#10; height="381"&#10; src="https://chris-ayers.com/images/diagrams/winget-dsc-architecture.drawio_hu_e357c17b87dc67d1.png"&#10; srcset="https://chris-ayers.com/images/diagrams/winget-dsc-architecture.drawio_hu_e357c17b87dc67d1.png 800w,/images/diagrams/winget-dsc-architecture.drawio_hu_1a46533084c2d190.png 1280w"&#10; sizes="(min-width: 768px) 50vw, 65vw"&#10; data-zoom-src="https://chris-ayers.com/images/diagrams/winget-dsc-architecture.drawio.png"&#10; /&gt;&#10; &#10; &#10; &lt;/figure&gt;&#10;&#10;&lt;h3 class="relative group"&gt;The Bootstrapper: boot.ps1&#10; &#10; &#10; &#10; &#10;&lt;/h3&gt;&#10;&lt;p&gt;The bootstrapper handles the chicken-and-egg problem — you need WinGet to run a WinGet DSC configuration, but WinGet might not be ready on a fresh machine.&lt;/p&gt;&#10;&lt;p&gt;&lt;code&gt;boot.ps1&lt;/code&gt; does three things:&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;&lt;strong&gt;Self-elevates&lt;/strong&gt; to Administrator (DSC needs admin rights)&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Ensures WinGet is ready&lt;/strong&gt; using &lt;code&gt;Repair-WinGetPackageManager&lt;/code&gt; with a manual fallback&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Runs the DSC configuration&lt;/strong&gt; from a raw GitHub URL with cache busting&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;$dscBase&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;https://raw.githubusercontent.com/codebytes/windows-setup/main/&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;$dscFile&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;codebytes.dev.dsc.yml&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;$cacheBust&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;?v=&lt;/span&gt;&lt;span class="p"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;Get-Date&lt;/span&gt; &lt;span class="n"&gt;-Format&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;yyyyMMddHHmmss&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;$dscUrl&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$dscBase&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="nv"&gt;$dscFile&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="nv"&gt;$cacheBust&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;winget&lt;/span&gt; &lt;span class="n"&gt;configure&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;-enable&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;winget&lt;/span&gt; &lt;span class="n"&gt;configure&lt;/span&gt; &lt;span class="o"&gt;-f&lt;/span&gt; &lt;span class="nv"&gt;$dscUrl&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;-accept-configuration-agreements&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&#10;&lt;h3 class="relative group"&gt;The Configuration: codebytes.dev.dsc.yml&#10; &#10; &#10; &#10; &#10;&lt;/h3&gt;&#10;&lt;p&gt;The YAML file is organized by category. Here&amp;rsquo;s what mine includes:&lt;/p&gt;&#10;&#10;&lt;figure&gt;&#10; &lt;img&#10; class="my-0 rounded-md mx-auto"&#10; loading="lazy"&#10; decoding="async"&#10; fetchpriority="auto"&#10; alt="Package categories in the WinGet DSC configuration including Git, Editors, Runtimes, Containers, Terminal, WSL, Dev Tools, and Daily Apps"&#10; width="1096"&#10; height="609"&#10; src="https://chris-ayers.com/images/diagrams/winget-dsc-package-categories.drawio_hu_44ec2f2ddba3f2c9.png"&#10; srcset="https://chris-ayers.com/images/diagrams/winget-dsc-package-categories.drawio_hu_44ec2f2ddba3f2c9.png 800w,/images/diagrams/winget-dsc-package-categories.drawio_hu_7bd7e6107bf21d20.png 1280w"&#10; sizes="(min-width: 768px) 50vw, 65vw"&#10; data-zoom-src="https://chris-ayers.com/images/diagrams/winget-dsc-package-categories.drawio.png"&#10; /&gt;&#10; &#10; &#10; &lt;/figure&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Category&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Packages&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;Git &amp;amp; GitHub&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Git, GitHub CLI, GitHub Desktop, GitHub Copilot CLI&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;Editors&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;VS Code, Visual Studio Enterprise&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;Runtimes&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;.NET 8, .NET 9, .NET 10, Python 3.12, Node.js&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;Containers&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Docker Desktop&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;Terminal&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Windows Terminal, PowerShell 7, Oh My Posh&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;WSL&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;WSL + Ubuntu 24.04&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;Dev Tools&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;UniGetUI, LINQPad 8, Azure CLI, Azure Developer CLI, Foundry Local, Ollama, Kusto Explorer&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;Daily Apps&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Chrome, PowerToys&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;Personalization&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;PowerShell profile, Oh My Posh theme, Nerd Fonts, Windows Terminal config&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;Cleanup &amp;amp; Security&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Bloatware removal, PUA protection, autoplay/autorun/delivery-optimization disabled&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&#10;&lt;h3 class="relative group"&gt;Beyond Packages: Settings and Scripts&#10; &#10; &#10; &#10; &#10;&lt;/h3&gt;&#10;&lt;p&gt;WinGet DSC isn&amp;rsquo;t just for packages. You can configure Windows settings declaratively:&lt;/p&gt;&#10;&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Microsoft.Windows.Developer/WindowsExplorer&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;directives&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Show file extensions in Explorer&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;FileExtensions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Show&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Microsoft.Windows.Developer/Taskbar&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;directives&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Hide widgets from taskbar&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;WidgetsButton&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Hide&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;p&gt;For things without native DSC resources — bloatware removal, registry tweaks, profile setup — you can use &lt;code&gt;PSDscResources/Script&lt;/code&gt; blocks with proper &lt;code&gt;TestScript&lt;/code&gt; guards for idempotency:&lt;/p&gt;&#10;&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;PSDscResources/Script&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;SecuritySettings&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;directives&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Enable PUA protection and harden system settings&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;allowPrerelease&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;TestScript&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="sd"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; try {&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; $pua = (Get-MpPreference).PUAProtection -eq 1&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; $autoplay = (Get-ItemProperty -Path &amp;#39;HKCU:\...\AutoplayHandlers&amp;#39; ...).DisableAutoplay -eq 1&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; $autorun = (Get-ItemProperty -Path &amp;#39;HKLM:\...\Policies\Explorer&amp;#39; ...).NoDriveTypeAutoRun -eq 255&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; $delopt = (Get-ItemProperty -Path &amp;#39;HKLM:\...\DeliveryOptimization&amp;#39; ...).DODownloadMode -eq 100&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; return ($pua -and $autoplay -and $autorun -and $delopt)&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; } catch { return $false }&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;SetScript&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="sd"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; Set-MpPreference -PUAProtection 1&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; # ... registry changes for autoplay, autorun, delivery optimization&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;p&gt;The &lt;code&gt;TestScript&lt;/code&gt; runs first — if it returns &lt;code&gt;$true&lt;/code&gt;, the &lt;code&gt;SetScript&lt;/code&gt; is skipped entirely. This is what makes re-runs safe.&lt;/p&gt;&#10;&#10;&lt;figure&gt;&#10; &lt;img&#10; class="my-0 rounded-md mx-auto"&#10; loading="lazy"&#10; decoding="async"&#10; fetchpriority="auto"&#10; alt="DSC resource lifecycle showing TestScript check leading to either Skip or SetScript execution"&#10; width="825"&#10; height="341"&#10; src="https://chris-ayers.com/images/diagrams/winget-dsc-resource-lifecycle.drawio_hu_5b4ac1df39e7bf75.png"&#10; srcset="https://chris-ayers.com/images/diagrams/winget-dsc-resource-lifecycle.drawio_hu_5b4ac1df39e7bf75.png 800w,/images/diagrams/winget-dsc-resource-lifecycle.drawio_hu_5ab2b38ee88815e5.png 1280w"&#10; sizes="(min-width: 768px) 50vw, 65vw"&#10; data-zoom-src="https://chris-ayers.com/images/diagrams/winget-dsc-resource-lifecycle.drawio.png"&#10; /&gt;&#10; &#10; &#10; &lt;/figure&gt;&#10;&#10;&lt;h3 class="relative group"&gt;Dev Drive&#10; &#10; &#10; &#10; &#10;&lt;/h3&gt;&#10;&lt;p&gt;One of my favorite additions is automatic &lt;a href="https://learn.microsoft.com/en-us/windows/dev-drive/" target="_blank" rel="noreferrer"&gt;Dev Drive&lt;/a&gt; creation. Instead of repartitioning a physical disk, the config creates a 50 GB VHDX virtual disk and mounts it as D: — no partition changes needed:&lt;/p&gt;&#10;&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;PSDscResources/Script&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;DevDrive&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;directives&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Create Dev Drive VHD on D:&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;allowPrerelease&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;TestScript&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="sd"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; # Skip if D: is already available&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; return (Test-Path &amp;#39;D:\&amp;#39;)&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;SetScript&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="sd"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; $vhdPath = &amp;#39;C:\Users\Public\devdrive.vhdx&amp;#39;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; $vhd = New-VHD -Path $vhdPath -Dynamic -SizeBytes 50GB&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; $disk = $vhd | Mount-VHD -Passthru&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; $init = $disk | Initialize-Disk -Passthru&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; $part = $init | New-Partition -DriveLetter D -UseMaximumSize&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; $part | Format-Volume -DevDrive -FileSystem ReFS `&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; -NewFileSystemLabel &amp;#39;Dev Drive&amp;#39; -Confirm:$false -Force&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; # Auto-mount on boot via Task Scheduler&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; Register-ScheduledTask -TaskName &amp;#39;Mount Dev Drive&amp;#39; `&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; -Action (New-ScheduledTaskAction -Execute &amp;#39;powershell.exe&amp;#39; `&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; -Argument &amp;#34;-NoProfile -Command `&amp;#34;Mount-VHD -Path &amp;#39;$vhdPath&amp;#39;`&amp;#34;&amp;#34;) `&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; -Trigger (New-ScheduledTaskTrigger -AtStartup) `&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; -Principal (New-ScheduledTaskPrincipal -UserId &amp;#39;SYSTEM&amp;#39; -RunLevel Highest) `&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; -Force | Out-Null&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;p&gt;Dev Drive uses ReFS with performance optimizations for developer workloads — faster git operations, faster builds, better antivirus exclusion support. The VHD approach is non-destructive (it skips entirely if D: already exists) and registers a startup task so the drive auto-mounts on boot.&lt;/p&gt;&#10;&#10;&lt;h3 class="relative group"&gt;Bloatware Removal&#10; &#10; &#10; &#10; &#10;&lt;/h3&gt;&#10;&lt;p&gt;The config also cleans up pre-installed apps you probably don&amp;rsquo;t want on a dev machine:&lt;/p&gt;&#10;&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;PSDscResources/Script&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;RemoveBloatware&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;directives&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Remove selected built-in UWP apps&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;TestScript&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="sd"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; $packages = @(&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; &amp;#39;Disney.37853FC22B2CE&amp;#39;, &amp;#39;Microsoft.BingNews&amp;#39;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; &amp;#39;Microsoft.GetHelp&amp;#39;, &amp;#39;Microsoft.Getstarted&amp;#39;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; &amp;#39;Microsoft.MicrosoftSolitaireCollection&amp;#39;, &amp;#39;Microsoft.MicrosoftOfficeHub&amp;#39;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; &amp;#39;Microsoft.WindowsFeedbackHub&amp;#39;, &amp;#39;SpotifyAB.SpotifyMusic&amp;#39;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; &amp;#39;TeamViewer.TeamViewer.Host&amp;#39;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; )&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; $found = $packages | Where-Object {&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; Get-AppxPackage -Name $_ -ErrorAction SilentlyContinue }&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; return ($found.Count -eq 0)&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;SetScript&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="sd"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; # Remove each unwanted app&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&#10;&lt;h3 class="relative group"&gt;Shell Personalization&#10; &#10; &#10; &#10; &#10;&lt;/h3&gt;&#10;&lt;p&gt;The configuration goes further than just installing Oh My Posh — it sets up the full terminal experience:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Downloads the Oh My Posh theme from the repo&lt;/li&gt;&#10;&lt;li&gt;Creates PowerShell 7 and Windows PowerShell profiles&lt;/li&gt;&#10;&lt;li&gt;Installs Terminal-Icons and z modules&lt;/li&gt;&#10;&lt;li&gt;Installs the CascadiaCode and Meslo Nerd Fonts&lt;/li&gt;&#10;&lt;li&gt;Configures Windows Terminal to use the font&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;All of this is handled by a single &lt;code&gt;PSDscResources/Script&lt;/code&gt; block with dependencies on the terminal tools being installed first.&lt;/p&gt;&#10;&#10;&lt;h2 class="relative group"&gt;Running It&#10; &#10; &#10; &#10; &#10;&lt;/h2&gt;&#10;&#10;&lt;h3 class="relative group"&gt;Fresh machine (one command)&#10; &#10; &#10; &#10; &#10;&lt;/h3&gt;&#10;&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;Set-ExecutionPolicy&lt;/span&gt; &lt;span class="n"&gt;Bypass&lt;/span&gt; &lt;span class="n"&gt;-Scope&lt;/span&gt; &lt;span class="k"&gt;Process&lt;/span&gt; &lt;span class="n"&gt;-Force&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;$script&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Join-Path&lt;/span&gt; &lt;span class="nv"&gt;$env:TEMP&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;windows-setup-boot.ps1&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;irm &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;https://raw.githubusercontent.com/codebytes/windows-setup/main/boot.ps1&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;Set-Content&lt;/span&gt; &lt;span class="n"&gt;-Path&lt;/span&gt; &lt;span class="nv"&gt;$script&lt;/span&gt; &lt;span class="n"&gt;-Encoding&lt;/span&gt; &lt;span class="n"&gt;UTF8&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;$script&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&#10;&lt;h3 class="relative group"&gt;From a clone&#10; &#10; &#10; &#10; &#10;&lt;/h3&gt;&#10;&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;git&lt;/span&gt; &lt;span class="n"&gt;clone&lt;/span&gt; &lt;span class="n"&gt;https&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="p"&gt;//&lt;/span&gt;&lt;span class="n"&gt;github&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="n"&gt;codebytes&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="nb"&gt;windows-setup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;git&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd windows-setup&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;.\&lt;/span&gt;&lt;span class="n"&gt;boot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ps1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&#10;&lt;h3 class="relative group"&gt;After setup&#10; &#10; &#10; &#10; &#10;&lt;/h3&gt;&#10;&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;gh&lt;/span&gt; &lt;span class="n"&gt;auth&lt;/span&gt; &lt;span class="n"&gt;login&lt;/span&gt; &lt;span class="c"&gt;# Authenticate with GitHub&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;.\&lt;/span&gt;&lt;span class="nb"&gt;clone-repos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;ps1&lt;/span&gt; &lt;span class="c"&gt;# Clone your repos to D:\github (falls back to ~/source/repos)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;Restart-Computer&lt;/span&gt; &lt;span class="c"&gt;# Finish pending installs (WSL, VS, etc.)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;p&gt;The &lt;code&gt;clone-repos.ps1&lt;/code&gt; script checks &lt;code&gt;gh auth status&lt;/code&gt;, then clones your repos to &lt;code&gt;D:\github&lt;/code&gt; if the Dev Drive is available, falling back to &lt;code&gt;$env:USERPROFILE\source\repos&lt;/code&gt; otherwise. It skips repos that already exist.&lt;/p&gt;&#10;&#10;&lt;h2 class="relative group"&gt;Customizing for Your Setup&#10; &#10; &#10; &#10; &#10;&lt;/h2&gt;&#10;&lt;p&gt;The beauty of this approach is how easy it is to fork and customize:&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;Add a package:&lt;/strong&gt; Find the winget ID (&lt;code&gt;winget search &amp;quot;App Name&amp;quot;&lt;/code&gt;) and add a resource block.&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;Remove a package:&lt;/strong&gt; Delete its resource block from the YAML.&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;Change VS workloads:&lt;/strong&gt; Edit the &lt;code&gt;.vsconfig&lt;/code&gt; file.&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;Change the shell theme:&lt;/strong&gt; Edit &lt;code&gt;codebytes.omp.json&lt;/code&gt;.&lt;/p&gt;&#10;&lt;p&gt;No PowerShell logic to understand. No control flow to trace. Just a flat list of desired state.&lt;/p&gt;&#10;&#10;&lt;h2 class="relative group"&gt;Why DSC Over Imperative Scripts?&#10; &#10; &#10; &#10; &#10;&lt;/h2&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Imperative Script&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;WinGet DSC&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;Re-run safety&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Manual skip logic per package&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Built-in idempotency&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;Readability&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;750+ lines of PowerShell&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Flat YAML resource list&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;Adding packages&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Add function call + skip check&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Add YAML block&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;Error recovery&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Script stops at first error&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Each resource independent&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;Windows settings&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Registry hacks&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Native DSC resources&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;The biggest win is &lt;strong&gt;maintainability&lt;/strong&gt;. Adding a new tool to my setup is a 6-line YAML block instead of debugging PowerShell error handling.&lt;/p&gt;&#10;&#10;&lt;h2 class="relative group"&gt;Inspiration&#10; &#10; &#10; &#10; &#10;&lt;/h2&gt;&#10;&lt;p&gt;This approach was heavily inspired by &lt;a href="https://github.com/shanselman/wingetdevsetup" target="_blank" rel="noreferrer"&gt;Scott Hanselman&amp;rsquo;s wingetdevsetup&lt;/a&gt; repo. Scott&amp;rsquo;s been using DSC configurations for his machine setup, and after seeing how clean it was compared to my imperative script, I made the switch.&lt;/p&gt;&#10;&lt;p&gt;Key patterns I adopted from his approach:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;&lt;code&gt;boot.ps1&lt;/code&gt;&lt;/strong&gt; as a thin bootstrapper that ensures WinGet is ready&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;DSC YAML&lt;/strong&gt; as the single source of truth for machine state&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;&lt;code&gt;.vsconfig&lt;/code&gt;&lt;/strong&gt; for Visual Studio workload management&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Oh My Posh theme&lt;/strong&gt; stored in the repo for easy version control&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;&lt;code&gt;clone-repos.ps1&lt;/code&gt;&lt;/strong&gt; as a post-setup step after GitHub auth&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&#10;&lt;h2 class="relative group"&gt;Resources&#10; &#10; &#10; &#10; &#10;&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;a href="https://github.com/codebytes/windows-setup" target="_blank" rel="noreferrer"&gt;codebytes/windows-setup&lt;/a&gt; — My setup repo&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://github.com/shanselman/wingetdevsetup" target="_blank" rel="noreferrer"&gt;shanselman/wingetdevsetup&lt;/a&gt; — Scott Hanselman&amp;rsquo;s setup&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/windows/package-manager/configuration/" target="_blank" rel="noreferrer"&gt;WinGet Configuration Docs&lt;/a&gt; — Official Microsoft docs&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/windows/dev-drive/" target="_blank" rel="noreferrer"&gt;Dev Drive Overview&lt;/a&gt; — Performance-optimized developer volumes&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://aka.ms/configuration-dsc-schema/0.2" target="_blank" rel="noreferrer"&gt;DSC Schema Reference&lt;/a&gt; — YAML schema for DSC configurations&lt;/li&gt;&#10;&lt;/ul&gt;</content:encoded><media:content xmlns:media="http://search.yahoo.com/mrss/" url="https://chris-ayers.com/posts/winget-dsc-windows-setup/featured.png"/></item></channel></rss>