Wednesday, February 24, 2016

Everyday Powershell - Part 38 - Get-WindowsUpdateStatus

Got annoyed this week with some windows update configuration issues, so wrote this powershell to pull the relevant configuration information from the windows registry;

function get-windowsupdatestatus{
    param(
        $COMPUTERNAME
    )
    $report = invoke-command -ComputerName $COMPUTERNAME -ScriptBlock {
            $days = "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
            $auoptions = "Notify before download","Automatically download and notify of installation","Automatically download and schedule installation","Automatic Updates is required and users can configure it"
            $temp= "" | select UpdateServer, UpdateDay, UpdateTime, NoAutoRebootWithLoggedOnUsers, NoAutoUpdate, UpdateOptions
            $temp.updateserver = (get-itemproperty HKLM:\\Software\Policies\Microsoft\Windows\WindowsUpdate).wuserver
            $schedule = get-itemproperty HKLM:\\Software\Policies\Microsoft\Windows\WindowsUpdate\AU
            $temp.NoAutoRebootWithLoggedOnUsers = $schedule.NoAutoRebootWithLoggedOnUsers
            $temp.NoAutoUpdate = $schedule.NoAutoUpdate
            $temp.UpdateOptions = $auoptions[$schedule.AUOptions -2]
            $temp.updateday = $days[$schedule.ScheduledInstallDay -1]
            $temp.updatetime = (get-date -Hour ($schedule.ScheduledInstallTime).tostring().padleft(2,'0'-Minute 00 -Second 00 -Format "HH:mm")
            $temp
    }
    $report | select PScomputername, NoAutoRebootWithLoggedOnUsers,NoAutoUpdate,UpdateDay, UpdateTime,UpdateServer, UpdateOptions
}

This allowed us to see at a glance where the issues were across all our servers.

The script only runs in a single thread so it's slow. But it wouldn't be hard to multi-thread. In our case there were less than 100 servers to be reviewed so it wasn't a priority. If there's demand for a faster version we'll make it happen. Might be a good demo of how to take a single threaded powershell function and make it multi-threaded.


Monday, February 15, 2016

Everyday Powershell - Part 37 - Powershell Subnet Scanner

So we had a need to run a subnet scan this morning on a host where installing a subnet scanner would be a hassle. So powershell to the rescue!

Turns out there's a really easy but slow way to do this...
1..254 | ForEach-Object {test-connection ("192.168.6." + $_)}
Then there's a tricky way that's much quicker.
function start-subnetscan{
    param(
        $addressspace = "192.168.6.",
        $startip = 1,
        $endip = 254,
        $concurrentthreads = 30
    )
    $report = @()
    $startip..$endip | ForEach-Object {
        Write-Progress -Activity "Pinging Computers" -Status ("Pinging " + $addressspace + $_.tostring().padleft(3,"0"+ " Starting Jobs. Started " + (get-job).count) -PercentComplete (($_ / $endip* 100)
        start-job -scriptblock {
            $temp = "" | select IP, Online
            $temp.ip = ($args[0] + $args[1].tostring().padleft(3,"0"))
            $temp.online = test-connection $temp.ip -Quiet -Count 1
            $temp
        } -ArgumentList $addressspace, $_  
        while((get-job).count -ge $concurrentthreads){
            Write-Progress -Activity "Pinging Computers" -Status ("Waiting for resources. " + (get-job).count + " jobs running"-PercentComplete (($_ / $endip* 100)
            $report += Get-Job | where state -eq 'completed' | Receive-Job
            Get-job | where state -eq 'completed' | Remove-Job
        }                           
    }
    $report += get-job | wait-job | Receive-Job
    $report | select IP, Online | sort IP | ft
    Get-job | wait-job  | Remove-Job
}

So to give you an idea of the power of multi threading we setup both commands so we could run them through measure-command and then we raced them!
Measure-Command -Expression {start-subnetscan} 
Days              : 0
Hours             : 0
Minutes           : 2
Seconds           : 55
Milliseconds      : 951
Ticks             : 1759513835
TotalDays         : 0.00203647434606481
TotalHours        : 0.0488753843055556
TotalMinutes      : 2.93252305833333
TotalSeconds      : 175.9513835
TotalMilliseconds : 175951.3835

Measure-Command -Expression {1..254 | ForEach-Object {test-connection ("192.168.6." + $_) -count 1}} 
Days              : 0
Hours             : 0
Minutes           : 11
Seconds           : 26
Milliseconds      : 940
Ticks             : 6869401183
TotalDays         : 0.00795069581365741
TotalHours        : 0.190816699527778
TotalMinutes      : 11.4490019716667
TotalSeconds      : 686.9401183
TotalMilliseconds : 686940.1183
 
Have a look at that! Running it multi-threaded made it 3 times faster.

Sunday, February 14, 2016

50000 Page Views

We just clocked over 50000 page views.


To celebrate lets review our most popular posts;
Looks like it's quick simple functionality that people are after. Well that's great because that's what we're all about with the everyday powershell series. Quick (and sometimes dirty) shell scripts that just get the job done.

We'll keep posting if you guys keep reading! Thanks for your attention and support over the years. If you've got any requests tweet them or google+ them at me @benhaslett