{"id":94,"date":"2014-12-10T00:00:00","date_gmt":"2013-01-01T00:00:00","guid":{"rendered":"https:\/\/www.sqlhammer.com\/blog\/start-and-save-hyper-v-vms-with-powershell"},"modified":"2026-03-18T21:51:27","modified_gmt":"2026-03-18T21:51:27","slug":"start-and-save-hyper-v-vms-with-powershell","status":"publish","type":"post","link":"https:\/\/sqlhammer.com\/index.php\/2014\/12\/10\/start-and-save-hyper-v-vms-with-powershell\/","title":{"rendered":"Start and Save Hyper-V VMs with PowerShell"},"content":{"rendered":"<p>I use Windows 8 or Windows Server 2012 R2 on most of my local workstations between home and work. In order to conserve memory, I turn my Hypver-V lab environments on and off as I need them. Given that my smallest environment is a grouping of five virtual machines (VMs), I quickly got tired of all of the clicks necessary to start up all of the machines, in order, or save them all when I was done.<\/p>\n<p>To solve this problem, I wrote the below functions in PowerShell and added them to my <a href=\"http:\/\/technet.microsoft.com\/en-us\/library\/bb613488(v=VS.85\">Windows PowerShell Profile<\/a>.aspx). These functions take advantage of the <a href=\"http:\/\/technet.microsoft.com\/en-us\/library\/hh846767.aspx\">Hyper-V module<\/a>, available in Windows 8 and above or Windows 2012 and above. There are over <a href=\"http:\/\/technet.microsoft.com\/library\/hh848559.aspx\">160 Cmdlets<\/a> to pick from. In this post we will only demonstrate two, <a href=\"http:\/\/technet.microsoft.com\/en-US\/library\/hh848589.aspx\">Start-VM<\/a> and <a href=\"http:\/\/technet.microsoft.com\/en-US\/library\/hh848590.aspx\">Save-VM<\/a>.<\/p>\n<h2>Functions<\/h2>\n<p><em>It is important to run the Hyper-V cmdlets in a PowerShell session that is running \u201cAs Administrator\u201d.<\/em><\/p>\n<pre><code class=\"language-\">function Start-MyVMs\n{\n    #start AD VM\n    Start-VM 'v-hammer-ad';\n\n<p>#start SQL VMs\n    $SqlVms = @('v-hammer-01','v-hammer-02',\n        'v-hammer-03','v-hammer-04');\n    $jobs = @();\n    foreach($VM in $SqlVms)\n    {\n        $args = @($VM);\n        $jobs += Start-Job -ScriptBlock { Start-VM $args[0] } <code>\n            -ArgumentList $args;\n    }<\/p>\n\n<p>$jobs | Wait-Job | Receive-Job | Remove-Job;\n}<\/code><\/pre>\n<\/p>\n<pre><code class=\"language-\">function Save-MyVMs\n{\n    #Save SQL VMs\n    $SqlVms = @('v-hammer-01','v-hammer-02',\n        'v-hammer-03','v-hammer-04');\n    $jobs = @();\n    foreach($VM in $SqlVms)\n    {\n        $args = @($VM);\n        $jobs += Start-Job -ScriptBlock { Save-VM $args[0] } <\/code>\n            -ArgumentList $args;\n    }\n\n<p>$jobs | Wait-Job | Receive-Job | Remove-Job;\n \n    #Save AD VM\n    Save-VM 'v-hammer-ad';\n}<\/code><\/pre>\n<\/p>\n<h2>Quick overview<\/h2>\n<p>In this particular lab environment I have an Active Directory server with four VMs joined to the domain. This is an environment that I use to run tests on a SQL Server Availability Group configuration.<\/p>\n<p>I\u2019ve decided that I want my VMs to start and be saved with the AD VM online at all times. I also don\u2019t want to have to wait for each one to start or save individually. To accomplish these goals I\u2019ve used the Start-VM and Save-VM cmdlets for V-HAMMER-AD by themselves. I then used the <a href=\"http:\/\/technet.microsoft.com\/en-us\/library\/hh849698.aspx\">Start-Job<\/a>\u00a0cmdlet to spawn asynchronous jobs. These jobs run in parallel and bring the remaining SQL VMs up as fast as my hardware will allow. Then I wait for the jobs to complete (<a href=\"http:\/\/technet.microsoft.com\/en-us\/library\/hh849735.aspx\">Wait-Job<\/a>), output the error or information messages to my console (<a href=\"http:\/\/technet.microsoft.com\/en-us\/library\/hh849718.aspx\">Receive-Job<\/a>), and dispose of the jobs (<a href=\"http:\/\/technet.microsoft.com\/en-us\/library\/hh849742.aspx\">Remove-Job<\/a>).<\/p>\n<p>Since these have been added to my profile, every time I open a PowerShell console window the functions are loaded and a single cmdlet manages my lab environment\u2019s state.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I use Windows 8 or Windows Server 2012 R2 on most of my local workstations between home and work. In order to conserve memory, I turn my Hypver-V lab environments on and off as I need them. Given that my smallest environment is a grouping of five virtual machines (VMs), I quickly got tired of [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-94","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/sqlhammer.com\/index.php\/wp-json\/wp\/v2\/posts\/94","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sqlhammer.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sqlhammer.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sqlhammer.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/sqlhammer.com\/index.php\/wp-json\/wp\/v2\/comments?post=94"}],"version-history":[{"count":1,"href":"https:\/\/sqlhammer.com\/index.php\/wp-json\/wp\/v2\/posts\/94\/revisions"}],"predecessor-version":[{"id":357,"href":"https:\/\/sqlhammer.com\/index.php\/wp-json\/wp\/v2\/posts\/94\/revisions\/357"}],"wp:attachment":[{"href":"https:\/\/sqlhammer.com\/index.php\/wp-json\/wp\/v2\/media?parent=94"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sqlhammer.com\/index.php\/wp-json\/wp\/v2\/categories?post=94"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sqlhammer.com\/index.php\/wp-json\/wp\/v2\/tags?post=94"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}