{"id":7031,"date":"2015-03-27T00:01:00","date_gmt":"2015-03-27T00:01:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2015\/03\/27\/use-powershell-to-remove-optional-features-from-windows-vhd\/"},"modified":"2019-02-18T10:30:07","modified_gmt":"2019-02-18T17:30:07","slug":"use-powershell-to-remove-optional-features-from-windows-vhd","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/use-powershell-to-remove-optional-features-from-windows-vhd\/","title":{"rendered":"Use PowerShell to Remove Optional Features from Windows VHD"},"content":{"rendered":"<p><b style=\"font-size:12px\">Summary<\/b><span style=\"font-size:12px\">: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell to remove optional features from Windows virtual hard disks.<\/span><\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/q-for-powertip.jpg\" alt=\"Hey, Scripting Guy! Question\" \/>&nbsp;Hey, Scripting Guy! I have a number of virtual machines that have optional features that they do not need, such as Windows Media Player. In fact, the virtual machines are set up with no audio, so having Windows Media Player is sort of a waste. How can I easily remove this feature?<\/p>\n<p>&mdash;CG<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/a-for-powertip.jpg\" alt=\"Hey, Scripting Guy! Answer\" \/>&nbsp;Hello CG,<\/p>\n<p>Microsoft Scripting Guy, Ed Wilson, is here. This morning started off early. IIS MVP, <a href=\"https:\/\/devblogs.microsoft.com\/scripting\/tag\/terri-donahue\/\" target=\"_blank\">Teri Donahue<\/a>,&nbsp;stopped by to pick up Teresa&rsquo;s Surface Pro&nbsp;2. Teri and Teresa are meeting at an MVP conference in Philly. I had to get a new SIM card for the Surface because the dial-up adapter quit working, and Teri is taking it to Teresa, who is pretty much going through withdraw without her device.<\/p>\n<p>Not that she is completely deviceless, she had my Surface Pro&nbsp;2 and her original Surface&nbsp;RT with her, not to mention her Windows Phone, but still she was jonesing without her favorite device. Thanks Teri! Anyway, I took the early morning wake up to head to the gym to get my workout over so I could get back to work answering email sent to <a href=\"mailto:scripter@microsoft.com\">scripter@microsoft.com<\/a>.<\/p>\n<p>CG, speaking of withdrawl&hellip;<\/p>\n<p>It is actually pretty easy to use Windows PowerShell to remove unneeded features from your VHDs. (This technique also works for WIM images.)<\/p>\n<p>One of the cool things about using the DISM cmdlets is that it permits me to work with optional features in a supportable and reliable method. In the old days, I had to worry about dependencies and hope that I did not break things when I used tools that were designed to shrink Windows images, but that is no longer the case.<\/p>\n<p>The first thing I do is mount an image that I want to work with to a folder. Here is the code I use:<\/p>\n<p style=\"margin-left:30px\">$image = &quot;E:\\vms\\vhd\\c1\\c1.vhdx&quot;<\/p>\n<p style=\"margin-left:30px\">$path = &quot;c:\\image&quot;<\/p>\n<p style=\"margin-left:30px\">&nbsp;MD $path<\/p>\n<p style=\"margin-left:30px\">&nbsp;Mount-WindowsImage -ImagePath $image -Path $path -Index 1<\/p>\n<p>After I have my virtual machine mounted to a folder, I use the <b>Get-WindowsOptionalFeature<\/b> to look at the optional features:<\/p>\n<p style=\"margin-left:30px\">Get-WindowsOptionalFeature -Path $path<\/p>\n<p>The following image shows the output from this command:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/5618.hsg-3-27-15-01.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/5618.hsg-3-27-15-01.png\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<p><span style=\"font-size:12px\">To find related features, use wildcard characters. The following command illustrates finding media-related features:<\/span><\/p>\n<p style=\"margin-left:30px\">PS C:\\&gt; Get-WindowsOptionalFeature -Path C:\\image -FeatureName *media*<\/p>\n<p style=\"margin-left:30px\">Feature Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : MediaPlayback<\/p>\n<p style=\"margin-left:30px\">Display Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : Media Features<\/p>\n<p style=\"margin-left:30px\">Description&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : Controls media features such as Windows Media Player and Windows Media<span style=\"font-size:12px\">&nbsp;Center.<\/span><\/p>\n<p style=\"margin-left:30px\">Restart Required&nbsp; : Possible<\/p>\n<p style=\"margin-left:30px\">State&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : Enabled<\/p>\n<p style=\"margin-left:30px\">Custom Properties :<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \\SoftBlockLink : http:\/\/go.microsoft.com\/fwlink?LinkID=153156<span style=\"font-size:12px\">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<\/span><\/p>\n<p style=\"margin-left:30px\">Feature Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : WindowsMediaPlayer<\/p>\n<p style=\"margin-left:30px\">Display Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : Windows Media Player<\/p>\n<p style=\"margin-left:30px\">Description&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : Windows Media Player<\/p>\n<p style=\"margin-left:30px\">Restart Required&nbsp; : Possible<\/p>\n<p style=\"margin-left:30px\">State&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : Enabled<\/p>\n<p style=\"margin-left:30px\">Custom Properties :<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\\SoftBlockLink : http:\/\/go.microsoft.com\/fwlink?LinkID=140092<\/p>\n<p>To remove an optional Windows feature, I pipe the results of the <b>Get-WindowsOptionalFeature<\/b> cmdlet to the <b>Disable-WindowsOptionalFeature<\/b> cmdlet. I also use the <b>&ndash;Remove<\/b> switch to actually remove the feature and not simply disable the feature. This command is shown here (this is a single-line command that wraps at the pipe character for readability):<\/p>\n<p style=\"margin-left:30px\">Get-WindowsOptionalFeature -Path C:\\image -FeatureName *media* |<\/p>\n<p style=\"margin-left:30px\">Disable-WindowsOptionalFeature -Remove<\/p>\n<p>Now, I put everything together into a script:<\/p>\n<p style=\"margin-left:30px\">Push-Location<\/p>\n<p style=\"margin-left:30px\">Set-Location c:\\<\/p>\n<p style=\"margin-left:30px\">WorkFlow Service-Image<\/p>\n<p style=\"margin-left:30px\">{<\/p>\n<p style=\"margin-left:30px\">&nbsp;$image = &quot;E:\\vms\\vhd\\c1\\c1.vhdx&quot;<\/p>\n<p style=\"margin-left:30px\">&nbsp;$path = &quot;c:\\image&quot;<\/p>\n<p style=\"margin-left:30px\">&nbsp;MD $path<\/p>\n<p style=\"margin-left:30px\">&nbsp; Sequence {<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp; Mount-WindowsImage -ImagePath $image -Path $path -Index 1<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp; Get-WindowsOptionalFeature -Path C:\\image -FeatureName *media* |<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp; Disable-WindowsOptionalFeature -Remove<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp; Dismount-WindowsImage -Path $path -Save<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp; RD $path -Force<\/p>\n<p style=\"margin-left:30px\">&nbsp;} }<\/p>\n<p style=\"margin-left:30px\">Service-Image<\/p>\n<p style=\"margin-left:30px\">Pop-Location<\/p>\n<p>When I run the script, the following output appears:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/4645.hsg-3-27-15-02.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/4645.hsg-3-27-15-02.png\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<p><span style=\"font-size:12px\">CG, that is all there is to using Windows PowerShell to remove optional features from virtual machines. Join me tomorrow when I will have a guest blog post by Windows PowerShell MVP, Teresa Wilson. She will talk about plans for the Scripting Guys Ignite booth.<\/span><\/p>\n<p>I invite you to follow me on <a href=\"http:\/\/bit.ly\/scriptingguystwitter\" target=\"_blank\">Twitter<\/a> and <a href=\"http:\/\/bit.ly\/scriptingguysfacebook\" target=\"_blank\">Facebook<\/a>. If you have any questions, send email to me at <a href=\"mailto:scripter@microsoft.com\" target=\"_blank\">scripter@microsoft.com<\/a>, or post your questions on the <a href=\"http:\/\/bit.ly\/scriptingforum\" target=\"_blank\">Official Scripting Guys Forum<\/a>. See you tomorrow. Until then, peace.<\/p>\n<p><b>Ed Wilson, Microsoft Scripting Guy<\/b><span style=\"font-size:12px\">&nbsp;<\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell to remove optional features from Windows virtual hard disks. &nbsp;Hey, Scripting Guy! I have a number of virtual machines that have optional features that they do not need, such as Windows Media Player. In fact, the virtual machines are set up with no audio, [&hellip;]<\/p>\n","protected":false},"author":596,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[51,3,4,45],"class_list":["post-7031","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-getting-started","tag-scripting-guy","tag-scripting-techniques","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell to remove optional features from Windows virtual hard disks. &nbsp;Hey, Scripting Guy! I have a number of virtual machines that have optional features that they do not need, such as Windows Media Player. In fact, the virtual machines are set up with no audio, [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/7031","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/596"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=7031"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/7031\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=7031"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=7031"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=7031"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}