Help in Powershell

Hi Experts,

I need from your valuable experience to help me to write a PowerShell script to perform the following:

Given a CSV or TXT file containing server name, FQDN, IP, domain, I would like to get an script that  shutdown all VMs for every physical standalone host, then reboot the host where these VMs resides on,  and once the physical host is up, power on all of VMs. Then validate the SMS smart agent host service is running for each hosts and VMs

We are using Windows 2008 R2 and 2012 servers, the idea is automate the process of shutdown VMs and reboot physical Hyper-V host , then validate that the SMS agent host service is running for each VM and hosts. The results of the whole process should be shown in a log file indicating the final status of all VMs and hosts, and the services that were restarted automatic

Any ideas?
Jerry SeinfieldAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Rob StoneCommented:
If nobody comes up with anything I'll have a go over the weekend.

I don't have Hyper-V atm so will need to prep a lab up for that.

Is it log files you want, or would you prefer to put the information into a custom Event Log?

As for the services you can use the following snippet:
$SMSAgent=(get-service -DisplayName 'SMS Agent Host').Status
if ($SMSAgent -ne "Running"){
  Start-Service "SMS Agent Host"
}

Open in new window

0
Jerry SeinfieldAuthor Commented:
I would like to have both options, log and/or put the info into a custom event log
0
Rob StoneCommented:
OK, I presume each CSV file will contain the VM's for each host and each VM is a Windows OS?
0
Redefine Your Security with AI & Machine Learning

The implications of AI and machine learning in cyber security are massive and constantly growing, creating both efficiencies and new challenges across the board. Check out our on-demand webinar to learn more about how AI can help your organization!

Jerry SeinfieldAuthor Commented:
Well, not sure

Perhaps a single CSV or multiple CSV? or XLS?

Lets say we do have 6 physical hosts

Each physical host contains 20 VMs

so,they information that we should see in the report is

Host 1. | VM1, VM2, .... VMn |Physical Host1 windows services automatically started
|,  VM Windows services automatically started|

Host 2. VM1,, VM2.. VMn... Physical host 2Windows services automatically started. VM1

so, to recap

The script will do:

For each physical host will shutdown all VMs. The procedure we are performing is from HyperV manager, highlight all VMs at once, right-click, click shutdown. Once all VMs are shutdown, reboot the physical host,, once the physical host is up, highlight all VMs, right-click power on, this will power on each VM under this physical host

Once all tasks above are completed, let's continue with the next physical hosts, and repeat same steps above
0
Rob StoneCommented:
OK, I've knocked up a script which I've tested on a 2012 Hyper-V host. It logs to an event log and a log file.

Instead of making it a simple script that is completely automated, I've given you options to start with. You can remove some of these as you see fit or comment them out with a '#' before the cmdlet on that line.

In addition to the few options, it will also prompt you to reboot the Hyper-V host. As my lab only had two VM's running, I would suggest you test this script on a low priority Hyper-V host to start with if possible.

For the service check, I had to disable the Windows firewall. Obviously I could have looked for the rule, but I've ran out of time for that.
#With elevated Admin on PowerShell run this command - 
#New-EventLog -Logname "Mycompany Scripts" -Source "VMScript"
#Limit-EventLog -OverflowAction OverWriteAsNeeded -MaximumSize 20480KB -LogName "Mycompany Scripts"
#Get-EventLog -List |Where-Object {$_.Log -contains "Mycompany Scripts"}
#http://blogs.technet.com/b/heyscriptingguy/archive/2013/02/01/use-powershell-to-create-and-to-use-a-new-event-log.aspx

#Variables
$SMSAgent=@()
$HVHost=(Get-VMHost).Name
$Date=Get-Date -Format yyyyMMdd #Change the date format if you need, UK format used in reverse for better indexing
$DateTime=Get-Date -Format yyyyMMdd_HHmmss 
$Logpath="\\DC-HV1\Logs\" #Replace with your UNC path
$CSVFile=$Logpath+$DateTime+"_"+$HVHost+"_"+"VMStats.csv"
$Log="VMScript.log" #Replace with your log file name
$Logfile=$Logpath+$Date+"_"+$HVHost+"_"+$Log
$File= Test-Path $Logfile
If ($File -match "False"){New-Item -Path $Logfile -ItemType File}

#Functions
Function PowerOffVMs{
    #VMStatus
    ForEach ($VM in $VMs){
        If ($VM.State -eq "Running"){
            Stop-VM $VM.Name
            Write-Host "Stopping $VM.Name"
            $EventID1Inf = $VM.Name
            $DateTime=Get-Date -Format yyyyMMdd_HHmmss
            Add-Content -Path "$Logfile" -Value "$DateTime - Shutdown sequence initiated on server $EventID1Inf"
            Write-EventLog -Logname "Mycompany Scripts" -EntryType Information -EventID "1" -Source "VMScript" -Message "Shutdown sequence initiated on server $EventID1Inf"
        }
    }
}

Function PowerOnVMs{
    ForEach ($VM in $VMs){
        If ($VM.State -eq "Off"){
            Start-VM $VM.Name
            Write-Host "Starting $VM.Name"
            $EventID2Inf = $VM.Name
            $DateTime=Get-Date -Format yyyyMMdd_HHmmss
            Add-Content -Path "$Logfile" -Value "$DateTime - Startup sequence initiated on server $EventID2Inf"
            Write-EventLog -Logname "Mycompany Scripts" -EntryType Information -EventID "2" -Source "VMScript" -Message "Startup sequence initiated on server $EventID2Inf"
            Start-Sleep 15 #This allows each VM to start 15 seconds apart to reduce initial load on Hyper-V host
        }
    }
}

Function MainMenu{
    Write-Host "Do you want to initiate the Shutdown or Startup sequence?"
    $Response1= Read-Host "Enter: 1 = Shutdown, 2 = Startup"
    If ($Response1 -eq "1"){
        Write-Host "Option 1 - Shutdown sequence selected"
        Write-Host "Do you wish to continue? Y/N"
        $Response2 = Read-Host "Enter Y or N"
        If ($Response2 -eq "N"){
            Write-Host "Aborting script"
            $DateTime=Get-Date -Format yyyyMMdd_HHmmss
            Add-Content -Path "$Logfile" -Value "$DateTime - Shutdown sequence aborted."
            Start-Sleep 2
        }
        If ($Response2 -eq "Y"){
            Write-Host "Shutdown sequence initiated"
            Write-EventLog -LogName "Mycompany Scripts" -EntryType Information -EventID "101" -Source "VMScript" -Message "Shutting down all Virtual Machines on Hyper-V Host:$HVHost"
            $VMs=@()
            $VMs=Get-VM |Select-Object Name,State,Status,Uptime,ReplicationState
            Write-Host "Current VM status:"
            $VMs
            $DateTime=Get-Date -Format yyyyMMdd_HHmmss
            Add-Content -Path "$Logfile" -Value "$DateTime - Shutting down all Virtual Machines on Hyper-V Host:$HVHost."
            PowerOffVMs
            Write-Host "Waiting for 5 minutes to allow for VM's to power down gracefully"
            $DateTime=Get-Date -Format yyyyMMdd_HHmmss
            Add-Content -Path "$Logfile" -Value "$DateTime - 5 minute timer started. Script will continue when 5 minutes have expired to allow servers to shutdown."
            Start-Sleep 300
            Write-Host "5 minutes have elapsed, confirming status of VMs State"
            $VMsShutdownCheck=(Get-VM |Select-Object Name,State,Uptime)
            If ($VMsShutdownCheck.State -ne "Off"){
                Clear-Host
                Write-Host "WARNING: The following VMs are still running, please check manually to ensure they are powering down:"
                $VMsShutdownCheck
                $DateTime=Get-Date -Format yyyyMMdd_HHmmss
                Add-Content -Path "$Logfile" -Value "$DateTime - WARNING: The following VMs are still running, please check manually to ensure they are powering down:"
                ForEach ($VMRunning in $VMsShutdownCheck){
                    $EventID1Warning = $VMRunning.Name
                    Write-EventLog -Logname "Mycompany Scripts" -EntryType Warning -EventID "1" -Source "VMScript" -Message "$EventID1Warning is still running after the shutdown sequence was initiated 5 minutes ago"
                }
            }
            If ($VMsShutdownCheck.State -eq "Off"){
                Clear-Host
                $VMsShutdownCheck
                Write-Host "All VMs are powered off"
                ForEach ($VMOff in $VMsShutdownCheck){
                    $EventID3Inf = $VMOff.Name
                    Write-EventLog -Logname "Mycompany Scripts" -EntryType Information -EventID "3" -Source "VMScript" -Message "$EventID3Inf status is currently 'Off'"
                    $DateTime=Get-Date -Format yyyyMMdd_HHmmss
                    Add-Content -Path "$Logfile" -Value "$DateTime - $EventID3Inf status is currently 'Off'"
                }
            Write-Host "All VM's are offline, rebooting Hyper-V Host $HVHost"
            Write-EventLog -Logname "Mycompany Scripts" -EntryType Information -EventID "1000" -Source "VMScript" -Message "Rebooting $HVHost"
            $DateTime=Get-Date -Format yyyyMMdd_HHmmss
            Add-Content -Path "$Logfile" -Value "$DateTime - **********Rebooting $HVHost**********"
            Restart-Computer -Confirm
            }
        }
    }
    If ($Response1 -eq "2"){
        Write-Host "Option 2 - Startup sequence selected"
        Write-Host "Do you wish to continue? Y/N"
        $Response3 = Read-Host "Enter Y or N"
        If ($Response3 -eq "N"){
            Write-Host "Aborting script"
            Start-Sleep 2
        }
        If ($Response3 -eq "Y"){
            Write-Host "Startup sequence initiated"
            $DateTime=Get-Date -Format yyyyMMdd_HHmmss
            Add-Content -Path "$Logfile" -Value "$DateTime - Starting up all Virtual Machines on Hyper-V Host:$HVHost"
            Write-EventLog -LogName "Mycompany Scripts" -EntryType Information -EventID "102" -Source "VMScript" -Message "Starting up all Virtual Machines on Hyper-V Host:$HVHost"
            $VMs=@()
            $VMs=Get-VM |Select-Object Name,State,Status,Uptime,ReplicationState
            Write-Host "Current VM status:"
            $VMs
            PowerOnVMs
            Start-Sleep 10
            $VMsStartupCheck=(Get-VM |Select-Object Name,State,Uptime) 
            If ($VMsStartupCheck.State -ne "Running"){
                Clear-Host
                Write-Host "WARNING: The following VMs are still powered off, please check manually to ensure they are powering up:"
                $VMsStartupCheck
                ForEach ($VMOff in $VMsStartupCheck){
                    $EventID2Warning = $VMOff.Name
                    Write-EventLog -Logname "Mycompany Scripts" -EntryType Warning -EventID "2" -Source "VMScript" -Message "WARNING: $EventID2Warning failed to start after running the startup sequence"
                    $DateTime=Get-Date -Format yyyyMMdd_HHmmss
                    Add-Content -Path "$Logfile" -Value "$DateTime - WARNING: $EventID2Warning failed to start after running the startup sequence"
                }
            }
            If ($VMsStartupCheck.State -eq "Running"){
                Clear-Host
                $VMsStartupCheck
                $VMOn=$null
                $VMOnName=$null
                ForEach ($VMOn in $VMsStartupCheck){
                    $EventID4Inf = $VMOn.Name
                    Write-EventLog -Logname "Mycompany Scripts" -EntryType Information -EventID "4" -Source "VMScript" -Message "$EventID4Inf is now 'Running'"
                    $DateTime=Get-Date -Format yyyyMMdd_HHmmss
                    Add-Content -Path "$Logfile" -Value "$DateTime - $EventID4Inf is now 'Running'"
                }
                
            }
            StartupCheck
        }
    }
}

Function StartupCheck{
    Write-Host "Waiting 5 minutes for VMs to power on"
    Start-Sleep 3
    $VMsStartupCheck=@()
    $VMsStartupCheck=(Get-VM |Select-Object Name,State,Uptime)
    ForEach ($VMService in $VMsStartupCheck){
        $SMSAgent=$VMService.name
        #$VMService=(get-service -Computername $SMSAgent -DisplayName 'SMS Agent Host' -ErrorAction SilentlyContinue).Status 
        $VMService=(get-service -Computername $SMSAgent -DisplayName 'Windows Update' -ErrorAction SilentlyContinue).Status
        If ($VMService -ne "Running"){
            #Start-Service -computername $SMSAgent -DisplayName "SMS Agent Host"  
            Invoke-Command -ComputerName $SMSAgent {Start-Service -DisplayName "Windows Update"}
            Write-EventLog -Logname "Mycompany Scripts" -EntryType Information -EventID "5" -Source "VMScript" -Message "A start request has been made to the 'SMS Agent Host' service on $SMSAgent"
            $DateTime=Get-Date -Format yyyyMMdd_HHmmss
            Add-Content -Path "$Logfile" -Value "$DateTime - A start request has been made to the 'SMS Agent Host' service on $SMSAgent"
            $VMService2=(get-service -Computername $SMSAgent -DisplayName 'Windows Update' -ErrorAction SilentlyContinue).Status
            Start-Sleep 10
            If ($VMService2 -ne "Running"){
                Write-EventLog -Logname "Mycompany Scripts" -EntryType Error -EventID "1" -Source "VMScript" -Message "The 'SMS Agent Host' service on $SMSAgent is not 'Running'"
                $DateTime=Get-Date -Format yyyyMMdd_HHmmss
                Add-Content -Path "$Logfile" -Value "$DateTime - 2nd check and the 'SMS Agent Host' service on $SMSAgent is not 'Running'"
            }
        }
        If ($VMService -eq "Running"){
            Write-EventLog -Logname "Mycompany Scripts" -EntryType Information -EventID "6" -Source "VMScript" -Message "The 'SMS Agent Host' service on $SMSAgent is 'Running'"
            $DateTime=Get-Date -Format yyyyMMdd_HHmmss
            Add-Content -Path "$Logfile" -Value "$DateTime - The 'SMS Agent Host' service on $SMSAgent is 'Running'"
        }
    
    }
}

Get-VM |Select-Object VMName, ComputerName, DynamicMemoryEnabled, HardDrives, IsClustered, IsDeleted, MemoryStatus, NetworkAdapters, ReplicationState, ReplicateionHealth, State, Uptime |Export-Csv -Path $CSVFile
MainMenu

Open in new window

0
Jerry SeinfieldAuthor Commented:
Thanks Stoner,

What is the input file for the host and/or VMs to be rebooted?

Do I need an input file with the names of hosts and VMs for each host?
0
Jerry SeinfieldAuthor Commented:
Hi Stoner,

You mentioned earlier, that instead of making a single script automated you are giving the options to start with? what do you mean by this? what line should i see and/or modify?

you mentioned you tested this script on a Windows 2012 host, Do you know if the script works for Windows 2008 R2?

You mentioned you only had 2 VMS in your lab. What part of your code should I modify to allow to work with 20 03 30 VMs, or x number of VMs and hosts?

What if I need a single script completely automated? Is your script still valid?

Looking forward hearing from you
0
Rob StoneCommented:
Hi febenitezc.

I've not tested it on a 2008 host. If its got PowerShell v3 on it then it won't be any issue, if it's still running PS2 I'm not sure if it will work without tweaking.

There is no imput file for this script, you run it and the script will store all the VM's in a variable and then either do a startup or shutdown loop for whichever option you chose. I use Get-VM for this against the $VMs variable:
$VMs=Get-VM |Select-Object Name,State,Status,Uptime,ReplicationState

Open in new window

You will have a few log files created in the following variable:
$Logpath="\\DC-HV1\Logs\" # replace the server path with yours.

Open in new window

The .log file will just be extracts from the script as it's going through each stage. The CSV file is an overview of the VM's and their state before the script is ran.  You can run this cmdlet to view the output on screen:
Get-VM |Select-Object VMName, ComputerName, DynamicMemoryEnabled, HardDrives, IsClustered, IsDeleted, MemoryStatus, NetworkAdapters, ReplicationState, ReplicateionHealth, State, Uptime

Open in new window

If you want to change the objects, type Get-VM |Get-Member to list what options you can have on the output.

It's easy enough to make a script completely automated, it will cut a lot of this out to be honest, but when I start a script to do something fairly big I tend to put points in so I can confirm it's doing whats intended.

If you have a box you can test this on and if it's doing what you need I can spend a bit of time doing a completely automated script for you.

As for 2008R2, the fundamentals of the script will work, but some commands might not parse as they do in PS V3, like:
(get-service -Computername $SMSAgent -DisplayName 'SMS Agent Host' -ErrorAction SilentlyContinue).Status

Open in new window

The only other thing to mention is that the script will give errors on screen around the SMS Agent check if you don't have access with the credentials you are using, or a firewall is in place.  Another reason to test the script like this before running a completely automated one first imo so you are comfortable with it.

I'll provide you an automated one (once you've selected option 1 or 2 on the first instance) if you like, or can provide two scripts - one for startup and one for shutdown.  I may get abit of time at work to have a look otherwise it will be a few days before I can get these to you.
0
Jerry SeinfieldAuthor Commented:
Thanks Stoner,

So, basically you said, that if I installed powershell v3 on a WIndows 2008 R2 host, the script should work? Am I correct?

You mentioned earlier:

There is no imput file for this script, you run it and the script will store all the VM's in a variable and then either do a startup or shutdown loop for whichever option you chose. I use Get-VM for this against the $VMs variable:
$VMs=Get-VM |Select-Object Name,State,Status,Uptime,ReplicationState

How the script will now the host name and its VMs I would like to perform the actions? Will the script ask me for the host name?

I guess if there is no CSV input file the script will work against all hosts in my domain? Please advice
0
Rob StoneCommented:
Sorry for not making that a bit clearer, at the moment it's designed to run from powershell on the hyper-v host itself.

As I don't have the luxury of testing a multi host setup in my lab I was restricted to that, however, you could store the script on each Hyper-V host and remotely connect with Powershell and run it.

This blog shows you how to do that:
http://blogs.technet.com/b/heyscriptingguy/archive/2011/11/17/learn-how-to-manage-remote-powershell-sessions.aspx

In essence, it's two commands
1)$cred = Get-Credential -Credential domain\username
2)Enter-PSSession -ComputerName %hyper-vhost% -Credential $cred

As for PowerShell v3, I'm assuming that to be the case as that's what I used, its not something I have access to. It may well work in PowerShell v2 but you won't know until you try.  You could just copy and paste a few cmdlets in the powershell v2 console and see if it gives the results you would get on powershell v3.
0
Jerry SeinfieldAuthor Commented:
Hi Stoner,

Thank you so much for all the help. I'll be testing your script in QA tomorrow. In the meantime, I will need from you to complete this request:

1. Provide a single master automated script to perform all requests [validate it works with both Windows 2008 R2 and WIndows server 2012]. I have a mixed environment with hyperv host running both version Windows server 2008 R2 and 2012

2. Provide 2 scripts one for startup and one for shutdown.

I do understand this will take some time, please keep me posted

Thanks and have nice weekend
0
Rob StoneCommented:
Hi febenitezc,  I left a few mistakes in that script from my lab. As I didn't have the SMS Agent installed I used my test against the Windows Update service.

I've created two new scripts, I'll test them when I get a chance on my lab at home (probably tomorrow evening).
0
Rob StoneCommented:
Here is a startup script, I've also included an option for an email alert which is currently commented so you'll need to configure the 3 variables for email and then uncomment the line near the bottom with Send-MailMessage if you want to test that too.
#Variables
$SMSAgent=@()
$HVHost=(Get-VMHost).Name
$Date=Get-Date -Format yyyyMMdd #Change the date format if you need, UK format used in reverse for better indexing
$DateTime=Get-Date -Format yyyyMMdd_HHmmss
$Logpath="\\DC-HV1\Logs\" #Replace with your UNC path
$CSVFile=$Logpath+$DateTime+"_"+$HVHost+"_"+"VMStats.csv"
$Log="VMScript.log" #Replace with your log file name
$Logfile=$Logpath+$Date+"_"+$HVHost+"_"+$Log
$File= Test-Path $Logfile

#Email alert variables
$fromAddr = "$HVHost@company.com"                 							# Sending email address
$toAddr = "IT@company.com"		                # Recipient email address
$smtpsrv = "192.168.16.1" # Enter your SMTP server IPv4 Address 

If ($File -match "False"){New-Item -Path $Logfile -ItemType File}

#Functions
Function RefreshDateTime{
    $DateTime=Get-Date -Format yyyyMMdd_HHmmss
}
RefreshDateTime

Function PowerOnVMs{
    ForEach ($VM in $VMs){
        If ($VM.State -eq "Off"){
            Start-VM $VM.Name
            Write-Host "Starting $VM.Name"
            $EventID2Inf = $VM.Name            
            RefreshDateTime
            Add-Content -Path "$Logfile" -Value "$DateTime - Startup sequence initiated on server $EventID2Inf"
            Write-EventLog -Logname "Mycompany Scripts" -EntryType Information -EventID "2" -Source "VMScript" -Message "Startup sequence initiated on server $EventID2Inf"
            Start-Sleep 15 #This allows each VM to start 15 seconds apart to reduce initial load on Hyper-V host
        }
    }
}

#Script

Write-Host "Startup sequence initiated"
RefreshDateTime
Add-Content -Path "$Logfile" -Value "$DateTime - Starting up all Virtual Machines on Hyper-V Host:$HVHost"
Write-EventLog -LogName "Mycompany Scripts" -EntryType Information -EventID "102" -Source "VMScript" -Message "Starting up all Virtual Machines on Hyper-V Host:$HVHost"
$VMs=@()
$VMs=Get-VM |Select-Object Name,State,Status,Uptime,ReplicationState
Write-Host "Current VM status:"
$VMs
PowerOnVMs
Start-Sleep 10 
$VMsStartupCheck=(Get-VM |Select-Object Name,State,Uptime)
If ($VMsStartupCheck.State -ne "Running"){
    Write-Host "WARNING: The following VMs are still powered off, please check manually to ensure they are powering up:"
    $VMsStartupCheck |Select-Object Name, State, Uptime| Where-Object {$_.State -ne "Running"}
    ForEach ($VMOff in $VMsStartupCheck){
        $EventID2Warning = $VMOff.Name
        Write-EventLog -Logname "Mycompany Scripts" -EntryType Warning -EventID "2" -Source "VMScript" -Message "WARNING: $EventID2Warning failed to start after running the startup sequence."
        RefreshDateTime
        Add-Content -Path "$Logfile" -Value "$DateTime - WARNING: $EventID2Warning failed to start after running the startup sequence"
    }
}

If ($VMsStartupCheck.State -eq "Running"){
    $VMsStartupCheck
    $VMOn=$null
    $VMOnName=$null
    ForEach ($VMOn in $VMsStartupCheck){
        $EventID4Inf = $VMOn.Name
        Write-EventLog -Logname "Mycompany Scripts" -EntryType Information -EventID "4" -Source "VMScript" -Message "$EventID4Inf is now 'Running'"
        RefreshDateTime
        Add-Content -Path "$Logfile" -Value "$DateTime - $EventID4Inf is now 'Running'"
    }
    Write-Host "Waiting 5 minutes for VMs to power on"
    Start-Sleep 30 #Change this to allow your VMs to power up fully and load their services.  Take the slowest boot time from your estate and convert it to seconds.      
    ForEach ($VM in $VMsStartupCheck){
        $Comp=$VM.name
        $VMService=$null
        $VMService=(get-service -Computername $Comp -DisplayName 'SMS Agent Host' -ErrorAction SilentlyContinue).Status        
        If ($VMService -ne "Running"){
            Invoke-Command -ComputerName $Comp {Start-Service -DisplayName "SMS Agent Host"}
            Write-EventLog -Logname "Mycompany Scripts" -EntryType Information -EventID "5" -Source "VMScript" -Message "A start request has been made to the 'SMS Agent Host' service on $Comp"
            Start-Sleep 30 #Another sleep timer if some servers are slow at coming up.
            RefreshDateTime            
            Add-Content -Path "$Logfile" -Value "$DateTime - A start request has been made to the 'SMS Agent Host' service on $Comp"
            $VMService2=(get-service -Computername $Comp -DisplayName 'SMS Agent Host' -ErrorAction SilentlyContinue).Status
            If ($VMService2 -ne "Running"){
                Write-EventLog -Logname "Mycompany Scripts" -EntryType Error -EventID "1" -Source "VMScript" -Message "The 'SMS Agent Host' service on $Comp is not 'Running'"
                RefreshDateTime
                Add-Content -Path "$Logfile" -Value "$DateTime - WARNING: 2nd validation check and the 'SMS Agent Host' service on $Comp is still not 'Running'"
                $EmailWarning=@()
                $EmailWarning=$EventID5
                #Send-MailMessage -To $toAddr -From $fromAddr -Subject "SMS Agent - Not started on the following servers" -SmtpServer $smtpsrv -Message "All VMs have been powered up on $HVHost. Some SMS Agent services have failed to start: $EmailWarning=$EventID5" #Enable this line if you have an SMTP server and want email notifications of SMS Agent's failing to start.
            }
        }
        If ($VMService -eq "Running"){
            Write-EventLog -Logname "Mycompany Scripts" -EntryType Information -EventID "6" -Source "VMScript" -Message "The 'SMS Agent Host' service on $Comp is 'Running'"
            RefreshDateTime
            Add-Content -Path "$Logfile" -Value "$DateTime - The 'SMS Agent Host' service on $Comp is 'Running'"
        }
   
    }
}
Get-VM |Select-Object VMName, ComputerName, DynamicMemoryEnabled, HardDrives, IsClustered, IsDeleted, MemoryStatus, NetworkAdapters, ReplicationState, ReplicateionHealth, State, Uptime |Export-Csv -Path $CSVFile

Open in new window

0
Rob StoneCommented:
Shutdown script
#Variables
$HVHost=(Get-VMHost).Name
$Date=Get-Date -Format yyyyMMdd #Change the date format if you need, UK format used in reverse for better indexing
$DateTime=Get-Date -Format yyyyMMdd_HHmmss
$Logpath="\\$HVHost\Logs\" #Replace with your UNC path
$CSVFile=$Logpath+$DateTime+"_"+$HVHost+"_"+"VMStats.csv"
$Log="VMScript.log" #Replace with your log file name
$Logfile=$Logpath+$DateTime+"_"+$HVHost+"_"+$Log
$File= Test-Path $Logfile

#Email alert variables
$fromAddr = "$HVHost@company.com"                 							# Sending email address
$toAddr = "IT@company.com"		                # Recipient email address
$smtpsrv = "192.168.16.1" # Enter your SMTP server IPv4 Address 

#Function(s)
Function PowerOffVMs{
    ForEach ($VM in $VMs){
        If ($VM.State -eq "Running"){
            Stop-VM $VM.Name
            Write-Host "Stopping $VM.Name"
            $EventID1Inf = $VM.Name
            $DateTime=Get-Date -Format yyyyMMdd_HHmmss
            Add-Content -Path "$Logfile" -Value "$DateTime - Shutdown sequence initiated on server $EventID1Inf"
            Write-EventLog -Logname "Mycompany Scripts" -EntryType Information -EventID "1" -Source "VMScript" -Message "Shutdown sequence initiated on server $EventID1Inf"
        }
    }
}

Function RefreshDateTime{
    $DateTime=Get-Date -Format yyyyMMdd_HHmmss3
}
RefreshDateTime

If ($File -match "False"){
    New-Item -Path $Logfile -ItemType File
}

Get-VM |Select-Object VMName, ComputerName, DynamicMemoryEnabled, HardDrives, IsClustered, IsDeleted, MemoryStatus, NetworkAdapters, ReplicationState, ReplicateionHealth, State, Uptime |Export-Csv -Path $CSVFile
Write-EventLog -LogName "Mycompany Scripts" -EntryType Information -EventID "101" -Source "VMScript" -Message "Shutting down all Virtual Machines on Hyper-V Host:$HVHost"
$VMs=@()
$VMs=Get-VM |Select-Object Name,State,Status,Uptime,ReplicationState
Write-Host "Current VM status:"
$VMs
RefreshDateTime
Add-Content -Path "$Logfile" -Value "$DateTime - Shutting down all Virtual Machines on Hyper-V Host:$HVHost."
PowerOffVMs
Write-Host "Waiting for 5 minutes to allow for VM's to power down gracefully"
RefreshDateTime
Add-Content -Path "$Logfile" -Value "$DateTime - 5 minute timer started. Script will continue when 5 minutes have expired to allow servers to shutdown. Go grab a drink!"
Start-Sleep 300 #300 seconds = 5 minutes, adjust as needed
Write-Host "5 minutes have elapsed, confirming status of VMs State"
$VMsShutdownCheck=(Get-VM |Select-Object Name,State,Uptime)
If ($VMsShutdownCheck.State -ne "Off"){
    Clear-Host
    Write-Host "WARNING: The following VMs are still running, please check manually to ensure they are powering down:"
    $VMsShutdownCheck    
    RefreshDateTime
    Add-Content -Path "$Logfile" -Value "$DateTime - WARNING: The following VMs are still running, please check manually to ensure they are powering down:"
    ForEach ($VMRunning in $VMsShutdownCheck){
        $EventID1Warning = $VMRunning.Name
        Write-EventLog -Logname "Mycompany Scripts" -EntryType Warning -EventID "1" -Source "VMScript" -Message "$EventID1Warning is still running after the shutdown sequence was initiated 5 minutes ago"
    }
}
If ($VMsShutdownCheck.State -eq "Off"){
    Clear-Host
    $VMsShutdownCheck
    Write-Host "All VMs are powered off"
    ForEach ($VMOff in $VMsShutdownCheck){
        $EventID3Inf = $VMOff.Name
        Write-EventLog -Logname "Mycompany Scripts" -EntryType Information -EventID "3" -Source "VMScript" -Message "$EventID3Inf status is currently 'Off'"
        RefreshDateTime
        Add-Content -Path "$Logfile" -Value "$DateTime - $EventID3Inf status is currently 'Off'"
    }
Write-Host "All VM's are offline, rebooting Hyper-V Host $HVHost"
Write-EventLog -Logname "Mycompany Scripts" -EntryType Information -EventID "1000" -Source "VMScript" -Message "Rebooting $HVHost"

RefreshDateTime
Add-Content -Path "$Logfile" -Value "$DateTime - **********Rebooting $HVHost**********"
Start-Sleep 10
Send-MailMessage -To $toAddr -From $fromAddr -Subject "Hyper-V Powerdown" -SmtpServer $smtpsrv -Message "All VMs have been powered down on $HVHost. $HVHost is now being rebooted."
Restart-Computer -Confirm
}

Open in new window

0
Rob StoneCommented:
So, adjust the timings to suit your environment (look for Start-Sleep) in the scripts and adjust the seconds.

Change the variables to whatever you need (all variables begin with a $ - so the ones at the top of the script will be the ones you need to adjust).

I've not been able to install 2008R2 and test it. Providing 2008 R2 PowerShell v2 has the following cmdlets you should be ok:
Get-VM
Start-VM
Stop-VM
Get-VMHost

You can type 'get-command get-vm' to confirm this for example, or get-command -name *VM* to get a list of cmdlets.

Let me know how you get on in 2008 R2 with it.
0
Jerry SeinfieldAuthor Commented:
Thanks Stoner,  you rock

One more question. From the shutdown, I've noticed the last 4 lines are about to reboot the hyperV host once all VMs are off, now, how can I repeat the same process for other hosts?

Should I run the same powershell script for& From every host to be rebooted?

Please advice
0
Rob StoneCommented:
Yes, if you run the script on each HV Host individually.

You may have noticed, but to get the Event Logging to work you need to run the following PowerShell command with an elevated PowerShell window:
New-EventLog -Logname "Mycompany Scripts" -Source "VMScript"
Limit-EventLog -OverflowAction OverWriteAsNeeded -MaximumSize 20480KB -LogName "Mycompany Scripts"
Get-EventLog -List |Where-Object {$_.Log -contains "Mycompany Scripts"}

Change the Mycompany Scripts to what you want.

I've just had a read and it looks like the cmdlets aren't in PowerShell on 2008/R2.  There are modules out there which apparently work but I've not tested this - http://pshyperv.codeplex.com/

For 2008/R2 you need to utilise WMI from PowerShell.....that's out of my depth at the moment I'm afraid so I would suggest updating a test 2008 VM with PowerShell 3.0 and check to see if the cmdlets are in there by default (I'm expecting they are).
0
Jerry SeinfieldAuthor Commented:
Thanks Stoner,

I guess i will need to create a scheduled job on each host to be rebooted and call your scripts

I'll keep you posted
0
Rob StoneCommented:
The line at the bottom of the shutdown script will reboot the host you run the script on:
Restart-Computer -Confirm

It will prompt for confirmation with the -Confirm switch, remove that if you want to force a reboot with no user intervention.
0
Rob StoneCommented:
I've just spent another hour or two playing with the 2008 stuff. I updated PowerShell to v3, the Hyper-V cmdlets aren't there :(

So, I installed the cmdlets here -http://pshyperv.codeplex.com/

Good news is these seem to work, bad news is they have different object names to Powershell v3.0 so the script won't work in 2008 as it is.....seeing if I can do a quick fix on them.
0
Rob StoneCommented:
No quick fix :(

A number of elements aren't returning results as I'd expect so more effort needed.  I'm busy for the rest of the week so this may take a while.
0
Jerry SeinfieldAuthor Commented:
Ok, thanks

Please send me the update for Windows 2008 R2 next week. I need the 2 scripts for both platforms Windows 2008 R2 and WIndows 2012

Have a nice day
0
Rob StoneCommented:
Can you do me a favour and run this command from a 2012 server against a 2008 host and let me know the response:

get-vm -computername "Win2008 HV Host Name"
0
Jerry SeinfieldAuthor Commented:
Hi Stoner

Please see attached file with error found
errorfromwindows2012against2008r.jpg
0
Rob StoneCommented:
Thanks, it was going to a be a bit too easy having that work :)

I will look at the PowerShell v2 Hyper-V cmdlets over the weekend and get a script going on that for you.
0
Rob StoneCommented:
2008 Startup script (using the downloaded and installed cmdlets from http://pshyperv.codeplex.com/)
Import-Module "Put the path to hyper-v.psd1 from the install"

#Variables
$SMSAgent=@()
$Date=Get-Date -Format yyyyMMdd #Change the date format if you need, UK format used in reverse for better indexing
$DateTime=Get-Date -Format yyyyMMdd_HHmmss
$hostname=hostname
$Logpath="\\2008R2-DC1\Logs\" #Replace with your UNC path
$CSVFile=$Logpath+$DateTime+"_"+$hostname+"_"+"VMStats.csv"
$Log="VMScript.log" #Replace with your log file name
$Logfile=$Logpath+$Date+"_"+$Hostname+"_"+$Log
$File= Test-Path $Logfile

#Email alert variables
$fromAddr = "$Hostname@company.com"                 							# Sending email address
$toAddr = "IT@company.com"		                # Recipient email address
$smtpsrv = "192.168.16.1" # Enter your SMTP server IPv4 Address 

If ($File -match "False"){New-Item -Path $Logfile -ItemType File}

#Functions
Function RefreshDateTime{
    $DateTime=Get-Date -Format yyyyMMdd_HHmmss
}
RefreshDateTime

Function PowerOnVMs{
    ForEach ($VM in $var){        
            Start-VM -VM $VM
            Write-Host "Starting $VM"
            $EventID2Inf = $VM           
            RefreshDateTime
            Add-Content -Path "$Logfile" -Value "$DateTime - Startup sequence initiated on server $EventID2Inf"
            Write-EventLog -Logname "Mycompany Scripts" -EntryType Information -EventID "2" -Source "VMScript" -Message "Startup sequence initiated on server $EventID2Inf"
            Start-Sleep 15 #This allows each VM to start 15 seconds apart to reduce initial load on Hyper-V host
        }
}


#Script

Write-Host "Startup sequence initiated"
RefreshDateTime
Add-Content -Path "$Logfile" -Value "$DateTime - Starting up all Virtual Machines on Hyper-V Host:$Hostname"
Write-EventLog -LogName "Mycompany Scripts" -EntryType Information -EventID "102" -Source "VMScript" -Message "Starting up all Virtual Machines on Hyper-V Host:$Hostname"
$VMs=@()
$VMs=Get-VM
Write-Host "Current VM status:"
$VMs
$VMsNotOn=Get-VM -Stopped -Suspended |Select-Object VMElementName
$var=$VMsNotOn.VMElementName
PowerOnVMs
Start-Sleep 10 
$VMsStartupCheckOff=$null
$VMsStartupCheckOff=Get-VM -Stopped -Suspended
Write-Host "WARNING: The following VMs are still powered off, please check manually to ensure they are powering up:"
$VMsStartupCheckOff
$VMsStartupCheckOffName=$VMsStartupCheckOff |Select-Object VMElementName
ForEach ($VMOff in $VMsStartupCheckOffName){
    $EventID2Warning = $VMOff
    Write-EventLog -Logname "Mycompany Scripts" -EntryType Warning -EventID "2" -Source "VMScript" -Message "WARNING: $EventID2Warning failed to start after running the startup sequence."
    RefreshDateTime
    Add-Content -Path "$Logfile" -Value "$DateTime - WARNING: $EventID2Warning failed to start after running the startup sequence"
}

$VMsStartupCheckOn=Get-VM -Running |Select-Object VMElementName
$VMsStartupCheckOn
$VMOn=$null
$VMOnName=$null
$VMOnName=$VMsStartupCheckOn.VMElementName
    ForEach ($VMOn in $VMOnName){        
        Write-EventLog -Logname "Mycompany Scripts" -EntryType Information -EventID "4" -Source "VMScript" -Message "$VMOn is now 'Running'"
        RefreshDateTime
        Add-Content -Path "$Logfile" -Value "$DateTime - $VMOn is now 'Running'"
    }
    Write-Host "Waiting 5 minutes for VMs to power on"
    Start-Sleep 30 #Change this to allow your VMs to power up fully and load their services.  Take the slowest boot time from your estate and convert it to seconds.      
    ForEach ($VM in $VMOnName){
        $VMService=$null
        $VMService=(get-service -Computername $VM -DisplayName 'SMS Agent Host' -ErrorAction SilentlyContinue).Status        
        If ($VMService -ne "Running"){
            Invoke-Command -ComputerName $VM {Start-Service -DisplayName "SMS Agent Host"}
            Write-EventLog -Logname "Mycompany Scripts" -EntryType Information -EventID "5" -Source "VMScript" -Message "A start request has been made to the 'SMS Agent Host' service on $VM"
            Start-Sleep 30 #Another sleep timer if some servers are slow at coming up.
            RefreshDateTime            
            Add-Content -Path "$Logfile" -Value "$DateTime - A start request has been made to the 'SMS Agent Host' service on $VM"
            $VMService2=(get-service -Computername $VM -DisplayName 'SMS Agent Host' -ErrorAction SilentlyContinue).Status
            If ($VMService2 -ne "Running"){
                Write-EventLog -Logname "Mycompany Scripts" -EntryType Error -EventID "1" -Source "VMScript" -Message "The 'SMS Agent Host' service on $VM is not 'Running'"
                RefreshDateTime
                Add-Content -Path "$Logfile" -Value "$DateTime - WARNING: 2nd validation check and the 'SMS Agent Host' service on $VM is still not 'Running'"
                $EmailWarning=@()
                $EmailWarning=$EventID5
                #Send-MailMessage -To $toAddr -From $fromAddr -Subject "SMS Agent - Not started on the following servers" -SmtpServer $smtpsrv -Message "All VMs have been powered up on $Hostname. Some SMS Agent services have failed to start: $EmailWarning=$EventID5" #Enable this line if you have an SMTP server and want email notifications of SMS Agent's failing to start.
            }
        }
        If ($VMService -eq "Running"){
            Write-EventLog -Logname "Mycompany Scripts" -EntryType Information -EventID "6" -Source "VMScript" -Message "The 'SMS Agent Host' service on $VM is 'Running'"
            RefreshDateTime
            Add-Content -Path "$Logfile" -Value "$DateTime - The 'SMS Agent Host' service on $VM is 'Running'"
        }
   
    }

Get-VM |Select * |Export-Csv -Path $CSVFile

Open in new window

0
Jerry SeinfieldAuthor Commented:
Hi Stoner,

Thanks a lot for your help

What do you mean by
Import-Module "Put the path to hyper-v.psd1 from the install" ?

Was the script above only for startup? what about power down? Please clarify

Is it safe to assume the new script above will work for Windows server 2008 R2?

Is there any dependency with the cmdlets used from the site below? if so, why do we have to use those cmdlets?

 2008 Startup script (using the downloaded and installed cmdlets from http://pshyperv.codeplex.com/
0
Rob StoneCommented:
I've still got the shutdown one to do.

The 2008 scripts won't work unless you import the module that has the cmdlets in. So once you install the cmdlets, you just need that line with the path pointing to the file I mentioned at the top of the script.

If you aren't able to download and install those cmdlets from the site on 2008 R2 I'm unable to provide you a script for 2008 as I don't have any WMI scripting skills needed for Hyper-V out of the box on 2008.
0
Rob StoneCommented:
Cheers Qlemo, didn't see that option :)

Shutdown script for 2008.

Import-Module "C:\HyperV_Install\HyperV_Install\HyperV.psd1" -ErrorAction SilentlyContinue

#Variables
$HVHost=hostname
$Date=Get-Date -Format yyyyMMdd #Change the date format if you need, UK format used in reverse for better indexing
$DateTime=Get-Date -Format yyyyMMdd_HHmmss
$Logpath="\\$HVHost\Logs\" #Replace with your UNC path
$CSVFile=$Logpath+$DateTime+"_"+$HVHost+"_"+"VMStats.csv"
$Log="VMShutdownScript.log" #Replace with your log file name
$Logfile=$Logpath+$Date+"_"+$HVHost+"_"+$Log
$File= Test-Path $Logfile

#Email alert variables
$fromAddr = "$HVHost@company.com"                                                           # Sending email address
$toAddr = "IT@company.com"                            # Recipient email address
$smtpsrv = "192.168.16.1" # Enter your SMTP server IPv4 Address

#Function(s)
Function PowerOffVMs{
   ForEach ($VM in $VMsNotOff){        
        Stop-VM -VM $VM -force
        Write-Host "Stopping $VM"
        $EventID1Inf = $VM
        $DateTime=Get-Date -Format yyyyMMdd_HHmmss
        Add-Content -Path "$Logfile" -Value "$DateTime - Shutdown sequence initiated on server $EventID1Inf"
        Write-EventLog -Logname "Mycompany Scripts" -EntryType Information -EventID "1" -Source "VMScript" -Message "Shutdown sequence initiated on server $EventID1Inf"
    }
}


Function RefreshDateTime{
    $DateTime=Get-Date -Format yyyyMMdd_HHmmss3
}
RefreshDateTime

If ($File -match "False"){
    New-Item -Path $Logfile -ItemType File
}

Get-VM |Select * |Export-Csv -Path $CSVFile
Write-EventLog -LogName "Mycompany Scripts" -EntryType Information -EventID "101" -Source "VMScript" -Message "Shutting down all Virtual Machines on Hyper-V Host:$HVHost"
$VMsNotOff=(Get-VM -Running).VMElementName 
Write-Host "Current VM status:"
Get-VM
RefreshDateTime
Add-Content -Path "$Logfile" -Value "$DateTime - Shutting down all Virtual Machines on Hyper-V Host:$HVHost."
PowerOffVMs
Write-Host "Waiting for 5 minutes to allow for VM's to power down gracefully"
RefreshDateTime
Add-Content -Path "$Logfile" -Value "$DateTime - 5 minute timer started. Script will continue when 5 minutes have expired to allow servers to shutdown. Go grab a drink!"
Start-Sleep 300 #300 seconds = 5 minutes, adjust as needed
Write-Host "5 minutes have elapsed, confirming status of VMs State"
Get-VM
$VMsShutdownCheck=$null
$VMsShutdownCheck=(Get-VM -Running).VMElementName
If ($VMsShutdownCheck -ne $null){
    Clear-Host
    Write-Host "WARNING: The following VMs are still running, please check manually to ensure they are powering down:"
    $VMsShutdownCheck    
    RefreshDateTime
    Add-Content -Path "$Logfile" -Value "$DateTime - WARNING: The following VMs are still running, please check manually to ensure they are powering down:"
    ForEach ($VMRunning in $VMsShutdownCheck){
        $EventID1Warning = $VMRunning
        Write-EventLog -Logname "Mycompany Scripts" -EntryType Warning -EventID "1" -Source "VMScript" -Message "$EventID1Warning is still running after the shutdown sequence was initiated 5 minutes ago"
    }
}
If ($VMsShutdownCheck -eq $null){
    Clear-Host
    $VMsShutdownCheck
    Write-Host "All VMs are powered off"
    ForEach ($VMOff in $VMsShutdownCheck){
        $EventID3Inf = $VMOff
        Write-EventLog -Logname "Mycompany Scripts" -EntryType Information -EventID "3" -Source "VMScript" -Message "$EventID3Inf status is currently 'Off'"
        RefreshDateTime
        Add-Content -Path "$Logfile" -Value "$DateTime - $EventID3Inf status is currently 'Off'"
    }
Write-Host "All VM's are offline, rebooting Hyper-V Host $HVHost"
Write-EventLog -Logname "Mycompany Scripts" -EntryType Information -EventID "1000" -Source "VMScript" -Message "Rebooting $HVHost"

RefreshDateTime
Add-Content -Path "$Logfile" -Value "$DateTime - **********Rebooting $HVHost**********"
Start-Sleep 10
#Send-MailMessage -To $toAddr -From $fromAddr -Subject "Hyper-V Powerdown" -SmtpServer $smtpsrv -Message "All VMs have been powered down on $HVHost. $HVHost is now being rebooted."
Restart-Computer -Confirm
} 

Open in new window


And a slightly revised Startup 2008 Script (Logging was creating too many files)
Import-Module "C:\HyperV_Install\HyperV_Install\HyperV.psd1" -ErrorAction SilentlyContinue

#Variables
$SMSAgent=@()
$Date=Get-Date -Format yyyyMMdd #Change the date format if you need, UK format used in reverse for better indexing
$DateTime=Get-Date -Format yyyyMMdd_HHmmss
$HVHost=hostname
$Logpath="\\2008R2-DC1\Logs\" #Replace with your UNC path
$CSVFile=$Logpath+$DateTime+"_"+$HVHost+"_"+"VMStats.csv"
$Log="VMStartupScript.log" #Replace with your log file name
$Logfile=$Logpath+$Date+"_"+$HVHost+"_"+$Log
$File= Test-Path $Logfile

#Email alert variables
$fromAddr = "$HVHost@company.com"                 							# Sending email address
$toAddr = "IT@company.com"		                # Recipient email address
$smtpsrv = "192.168.16.1" # Enter your SMTP server IPv4 Address 

If ($File -match "False"){New-Item -Path $Logfile -ItemType File}

#Functions
Function RefreshDateTime{
    $DateTime=Get-Date -Format yyyyMMdd_HHmmss
}
RefreshDateTime

Function PowerOnVMs{
    ForEach ($VM in $VMsNotOn){        
            Start-VM -VM $VM
            Write-Host "Starting $VM"
            $EventID2Inf = $VM           
            RefreshDateTime
            Add-Content -Path "$Logfile" -Value "$DateTime - Startup sequence initiated on server $EventID2Inf"
            Write-EventLog -Logname "Mycompany Scripts" -EntryType Information -EventID "2" -Source "VMScript" -Message "Startup sequence initiated on server $EventID2Inf"
            Start-Sleep 15 #This allows each VM to start 15 seconds apart to reduce initial load on Hyper-V host
        }
}

Write-Host "Startup sequence initiated"
RefreshDateTime
Add-Content -Path "$Logfile" -Value "$DateTime - Starting up all Virtual Machines on Hyper-V Host:$HVHost"
Write-EventLog -LogName "Mycompany Scripts" -EntryType Information -EventID "102" -Source "VMScript" -Message "Starting up all Virtual Machines on Hyper-V Host:$HVHost"
Write-Host "Current VM status:"
Get-VM
$VMsNotOn=(Get-VM -Stopped -Suspended).VMElementName
PowerOnVMs
Start-Sleep 10 
$VMsStartupCheckOff=$null
$VMsStartupCheckOff=(Get-VM -Stopped -Suspended).VMElementName
Write-Host "WARNING: The following VMs are still powered off, please check manually to ensure they are powering up:"
$VMsStartupCheckOff
ForEach ($VMOff in $VMsStartupCheckOff){
    $EventID2Warning = $VMOff
    Write-EventLog -Logname "Mycompany Scripts" -EntryType Warning -EventID "2" -Source "VMScript" -Message "WARNING: $EventID2Warning failed to start after running the startup sequence."
    RefreshDateTime
    Add-Content -Path "$Logfile" -Value "$DateTime - WARNING: $EventID2Warning failed to start after running the startup sequence"
}

$VMsStartupCheckOn=(Get-VM -Running).VMElementName
$VMsStartupCheckOn
$VMOn=$null
ForEach ($VMOn in $VMsStartupCheckOn){        
    Write-EventLog -Logname "Mycompany Scripts" -EntryType Information -EventID "4" -Source "VMScript" -Message "$VMOn is now 'Running'"
    RefreshDateTime
    Add-Content -Path "$Logfile" -Value "$DateTime - $VMOn is now 'Running'"
}
Write-Host "Waiting 5 minutes for VMs to power on"
Start-Sleep 30 #Change this to allow your VMs to power up fully and load their services.  Take the slowest boot time from your estate and convert it to seconds.      
ForEach ($VM in $VMsStartupCheckOn){
    $VMService=$null
    $VMService=(get-service -Computername $VM -DisplayName 'SMS Agent Host' -ErrorAction SilentlyContinue).Status        
    If ($VMService -ne "Running"){
        Invoke-Command -ComputerName $VM {Start-Service -DisplayName "SMS Agent Host"}
        Write-EventLog -Logname "Mycompany Scripts" -EntryType Information -EventID "5" -Source "VMScript" -Message "A start request has been made to the 'SMS Agent Host' service on $VM"
        Start-Sleep 30 #Another sleep timer if some servers are slow at coming up.
        RefreshDateTime            
        Add-Content -Path "$Logfile" -Value "$DateTime - A start request has been made to the 'SMS Agent Host' service on $VM"
        $VMService2=(get-service -Computername $VM -DisplayName 'SMS Agent Host' -ErrorAction SilentlyContinue).Status
        If ($VMService2 -ne "Running"){
            Write-EventLog -Logname "Mycompany Scripts" -EntryType Error -EventID "1" -Source "VMScript" -Message "The 'SMS Agent Host' service on $VM is not 'Running'"
            RefreshDateTime
            Add-Content -Path "$Logfile" -Value "$DateTime - WARNING: 2nd validation check and the 'SMS Agent Host' service on $VM is still not 'Running'"
            $EmailWarning=@()
            $EmailWarning=$EventID5
            #Send-MailMessage -To $toAddr -From $fromAddr -Subject "SMS Agent - Not started on the following servers" -SmtpServer $smtpsrv -Message "All VMs have been powered up on $HVHost. Some SMS Agent services have failed to start: $EmailWarning=$EventID5" #Enable this line if you have an SMTP server and want email notifications of SMS Agent's failing to start.
        }
    }
    If ($VMService -eq "Running"){
        Write-EventLog -Logname "Mycompany Scripts" -EntryType Information -EventID "6" -Source "VMScript" -Message "The 'SMS Agent Host' service on $VM is 'Running'"
        RefreshDateTime
        Add-Content -Path "$Logfile" -Value "$DateTime - The 'SMS Agent Host' service on $VM is 'Running'"
    }
   
}

Get-VM |Select * |Export-Csv -Path $CSVFile

Open in new window

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Jerry SeinfieldAuthor Commented:
Many thanks, I will be testing all scripts next week, and will get back to you

Have a nice weekend
0
Jerry SeinfieldAuthor Commented:
Hi Stoner,

I know this is probably a silly question, but why should I import the module of C:\HyperV_Install\HyperV_Install\HyperV.psd1 to build both scripts in Windows 2008 R2?

Can you explain what the process does once the files are imported?

so, basically the import of the module will automatically install all the objects and cmdlets required to run your script?
0
Rob StoneCommented:
Exactly that febenitezc.

As 2008R2 doesn't come with any Hyper-V cmdlets, that download provides them. Although they aren't the same as 2012, they are similar hence the different switches.

2012 PowerShell has more modules imported by default too so you don't have to worry about that.

If you run the script without importing the module, you'll get plenty of errors, even running Get-VM will result in an error saying it can't find the cmdlet.

Cheers
0
Jerry SeinfieldAuthor Commented:
Hi Stoner,

The script worked. Many thanks for that. I will be opening a new case next week to deal with Hyper-V cluster and failover VMs from one host to another one, then shutdown all vms and reboot the host. My guess is that we can use the existing code to build the new script

I hope you can assist with the new requirement

Thanks, and will be closing this ticket shortly
0
Rob StoneCommented:
Hi febenitezc,

Thanks for the update.  I'll have a look when you open the other ticket but I'm not sure I'll have the hardware in my lab to mirror your setup for the clustering.

Cheers
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Powershell

From novice to tech pro — start learning today.