Showing posts with label PowerShell. Show all posts
Showing posts with label PowerShell. Show all posts

Saturday, 11 November 2017

Hyper-V Auditing With PowerShell

Wanted to share some handy PowerShell constructions for extracting information from Hyper-V servers - particularly useful if you have multiple hosts and are trying to work out how all the VMs are configured across them all and different storage devices

Bring up an administrative PowerShell prompt (note run on Windows 10 or Server 2016, some of this doesn't work on 2012 R2), and first set up some credentials and a list of the hosts you want to query:


$cred = Get-Credential domain\adminaccount
$hosts = ('host001','host002','host003','host004')


Then grab the relevant command from below:


# get all vmswitches
$hosts | % { invoke-command -computername $_ -credential $cred -ScriptBlock {get-vmswitch}}

#show location of all hard disks
$hosts | % { invoke-command -computername $_ -credential $cred -scriptblock {(Get-VM).HardDrives }} | select VMName, ComputerName, Path | ft -autosize

# show location of all other (non-vhd) files
$hosts | % { invoke-command -computername $_ -credential $cred -scriptblock {Get-VM}} | select VMName, ComputerName, Path, CheckpointFileLocation, ConfigurationLocation, SmartPagingFilePath, SnapshotFileLocation | ft -autosize

# show all network adpaters
$hosts | % { invoke-command -computername $_ -credential $cred -scriptblock {( Get-VM).NetworkAdapters }} | select VMName, ComputerName, SwitchName, Status, IPAddresses | ft -autosize

# show all VM cpu and RAM
$hosts | % { invoke-command -computername $_ -credential $cred -scriptblock {(Get-VM) }} | ft VMName, ComputerName, @{Expression={$_.ProcessorCount};Label="Cores"}, @{Expression={[math]::Round($_.MemoryStartup/1024/1024/1024)};Label="RAM"}, @{Expression={$_.DynamicMemoryEnabled};Label="DynamicRAM"}

# show all dynamic disks
$hosts | % { invoke-command -computername $_ -credential $cred -scriptblock {(Get-VM).HardDrives } | % {get-vhd -Path $_.path}} | ft Path, VhdType, @{Expression={[math]::Round($_.FileSize/1024/1024/1024,2)};Label="FileSize (GB)"}, @{Expression={$_.Size/1024/1024/1024};Label="Size (GB)"}

If you have a lot of host servers that you are querying then this will all take some time - you can speed this up by using a workflow to query each host in parallel rather than seqeuntially:


# using a workflow to query each host in parallel
workflow getVHDLocations {
  param([string[]]$computers)
  ForEach -parallel ($vmhost in $computers) {
    InlineScript {invoke-command -computername $using:vmhost -scriptblock {(Get-VM).HardDrives } }
  }
}

getVHDLocations $hosts | select VMName, ComputerName, Path | ft -autosize

Monday, 24 September 2012

Threat Management Gateway Monitoring with PowerShell


I knocked up this quick and dirty script to help find the cause of a memory issue for a client but it could easily be extended to automate and monitor any number of TMG tasks.

As is, the script lists non-paged memory pool usage and the number of active firewall sessions, but the main purpose in posting it here is to demonstrate how to access Microsoft Threat Management Gateway COM objects through PowerShell.


$smtpserver = "EXCHANGE001"
$sender = "monitoring@clientdomain.example"
$client = "Client Name"
$recipient = "support@mydomain.example"
$subject = "TMG Monitoring"


$FPC = New-Object -ComObject FPC.root
$TMGArray = $FPC.GetContainingArray()
$SessionMonitor = $TMGArray.SessionsMonitors.SessionsMonitorFirewall
$TMGFilter = New-Object -ComObject FPC.FPCFilterExpressions
$SessionMonitor.ExecuteQuery($TMGFilter,10000)
$count = 0
$SessionMonitor | forEach-Object {$count++}


$message = $message + "<p>TMG Firewall Session Count: " + $count + "</p>"
$message = $message + "<p>TMG Non-Paged Pool Memory Usage (bytes)</p>"
$message = $message + "<table>"
$message = $message + "<tr><th>Process</th><th>PID</th><th>Non-Paged Memory (bytes)</th></tr>"
$procs = get-process | ? {$_.NPM -gt 1000000} | select Name, Id, NPM | sort "NPM" -Descending
Foreach ($proc in $procs) {
         $message = $message + "<tr><td>" + $proc.Name + "</td><td>" + $proc.Id + "</td><td>" + [math]::round($proc.NPM/1024) + "</td></tr>"
}
$message = $message + "</table>"

write $message

$smtp = new-object Net.Mail.SmtpClient($smtpserver)
$msg = new-object Net.Mail.MailMessage
$msg.From = $sender
$msg.To.Add($recipient)
$msg.Subject = $subject
$msg.Body = $message
$msg.IsBodyHTML = $true
$smtp.Send($msg)

Monday, 19 December 2011

How To Get Full IPv6 Net Sessions Addresses

Net Sessions is a tool I use frequently when working on client systems to find IP addresses of machines connected to servers.  However, with IPv6 addresses the net sessions command truncates the address rendering it useless.

Below is a powershell command I found to get the full IPv6 address:


gwmi win32_serversession | ft –Property ComputerName,UserName

Thursday, 15 December 2011

Automated Notifications For Machines Not Checking In To WSUS

Recently had a problem with an anti-virus update preventing computers from checking in with the WSUS server. Not too big a deal except for the fact that we didn't actually notice until our client pointed out that all the machines were showing errors connecting to the server.

Looking into this, the email notifications in WSUS (which we had set up and were working) do not list machines that have not checked in for a long time so it was not at all obvious that there was a problem. Further more, there is no way within the WSUS administration console to set up email notifications for this.

After a bit of research, I managed to put together the following PowerShell script which others may find useful (be sure to change the variables at the top, in red, to appropriate values for your environment)



# find stale computers in WSUS
# based on code:
# http://www.sapien.com/forums/scriptinganswers/forum_posts.asp?TID=4306
# http://msdn.microsoft.com/en-us/library/ee958382(v=VS.85).aspx


$smtpserver = "myExchangeServer"
$sender = "
WSUS@myDomain.example"
$recipient = "
Support@myDomain.example"
$maxAge =
14

$smtp = new-object Net.Mail.SmtpClient($smtpserver)
$msg = new-object Net.Mail.MailMessage
$msg.From = $sender
$msg.To.Add($recipient)
$msg.Subject = "WSUS Machines Not Checking-In Report"
$msg.Body = "<p>WSUS Machines that have not checked-in in the last $maxAge days</p>"
$msg.Body += "<table>"

$lastValidContactDate = $(Get-Date).Adddays(-$maxAge)
[reflection.assembly]::LoadWithPartialName("Microsoft.UpdateServices.Administration") | out-null
$wsus = [Microsoft.UpdateServices.Administration.AdminProxy]::GetUpdateServer()
$computerScope = new-object Microsoft.UpdateServices.Administration.ComputerTargetScope

$computerScope.ToLastSyncTime = $lastValidContactDate
$wsus.GetComputerTargets($computerScope) | foreach {
$msg.Body += "<tr><td>" + $_.FullDomainName + "</td><td>" + $_.LastSyncTime + "</td></tr>"
}
$msg.Body += "</table>"
$msg.IsBodyHTML = $true
$smtp.Send($msg)

Saturday, 10 September 2011

Automated Disk Usage Reports With Powershell

Just a quick one today, a simple script to produce a nicely formatted email showing disk space usage.

When I set out to do this, I assumed it would be easy and expected to find hundreds of examples, but couldn't find any that did what I wanted.

This script uses Powershell and du.exe from Sysinternals (now part of Microsoft).


# uses du.exe from sysinternals
# http://technet.microsoft.com/en-us/sysinternals/bb896651.aspx

$dir="C:\users"
$smtpserver = "mail.example.local"
$sender = "sender@example.local"
$server = "file.example.local"
$recipient = "recipient@example.local"

$du=C:\utilities\du.exe -accepteula -l 1 $dir | sort -desc

$smtp = new-object Net.Mail.SmtpClient($smtpserver)
$msg = new-object Net.Mail.MailMessage

$msg.From = $sender
$msg.To.Add($recipient)
$msg.Subject = "$server Disk Usage Report"
$msg.Body = "<p>$server Disk Usage Report in KB</p>"

$msg.Body += "<table>"
$du[4 .. $du.length] | forEach-Object {
$fields = $_.split(" ",[StringSplitOptions]::RemoveEmptyEntries)
$msg.Body += "<tr><td>$($fields[0]) </td><td>$($fields[1 .. $fields.length]) <td></tr>"
}
$msg.Body += "</table>"

$msg.IsBodyHTML = $true
$smtp.Send($msg)