Thursday, November 24, 2016

Windows 10 Delivery Optimization Service

Ok so how the heck didn't I know this was a thing?

https://privacy.microsoft.com/en-US/windows-10-windows-update-delivery-optimization

From that site

How is my PC used to send apps and updates to other PCs?
Delivery Optimization downloads the same updates and apps that you get through Windows Update and the Windows Store. Delivery Optimization creates a local cache, and stores files that it has downloaded in that cache for a short period of time. Depending on your settings, Windows then send parts of those files to other PCs on your local network or PCs on the Internet that are downloading the same files.

So I'm essentially seeding windows updates from my home PC? Which is great and all, a really efficient use of resources... For the people trying to distribute the updates.
Me I guess I've gotta suck up the rest of the month (22 days) with no download allowance. How generous of me.

Running with the powershell theme that we're all about here... Here's how you would stop that;

Get-Service DoSvc | Set-Service -StartupType Disabled

Sunday, April 17, 2016

Everyday Powershell - Part 40 - Get folder size

So my daughter (10 months) and I were hanging out on the couch listening to Pandora. I encourage her to play with the media center keyboard and she was doing that with gusto. When WHAM! Media Center PC hangs and when it reboots is unable to start the operating system.

We did a full power cycle and it came back fine, but reported low disk space. So it looks like my little girl hit her first problem with a full disk and windows hibernation. I'm so proud!

Her spamming had apparently asked the computer to hibernate. It tried but ran out of disk. So after getting back into the OS we needed to do a bit of a review and free up some space. At this point it dawned on us what our next part of Everyday Powershell was going to be about!

function get-foldersizes{
    param($startFolder )

    $report = @()

    $count = 0
    $colItems = ((Get-ChildItem $startFolder ) + (Get-ChildItem $startFolder -Hidden))
    foreach ($i in $colItems){
        write-progress -activity "Coutin Files" -Status $i.fullname -percentcomplete (($count / $colitems.count) * 100)
        if($i.PSIsContainer){
            $subFolderItems = (Get-ChildItem $i.FullName -File -Recurse | Measure-Object -property length -sum)
        }
        else{
            $subFolderItems = $i.FullName | Measure-Object -property length -sum
        }
        $temp = "" | select folder, size
        $temp.folder = $i.FullName
        $temp.size = [math]::round(($subFolderItems.sum / 1MB),2)
        $report += $temp
        $count++
    }
    $report | sort size
}

Super simple function that gets the size of all folders in $startfolder if that's null it just grabs the current folder.

So once the function was up and running my girl and I found an old copy of marvel heroes taking up 11gb. We deleted that and got back to the important business of playing with blocks!

Reference - We used this technet article as the basis for our script.


Monday, March 7, 2016

Everyday Powershell - Part 39 - Scheduling a Powershell Script in powershell

We've covered this ground before back in the early parts of everyday powershell. But now if you've got at least windows 8 or server 2012 there's actually really good support in the shell for scheduled tasks now.

We powershell enthusiasts spend a lot of time scheduling jobs to run scripts of various sorts. That's a lot of repetitive work. You know what? If you are doing a job manually a lot, might be a good idea to script it.

Here's a quick function that wraps up the new-scheduled task commands and makes it quick and easy to schedule a powershell script.

function new-scheduledscript{
    param(
        [Parameter(Mandatory=$true)]
        $scriptpath,
        [Parameter(Mandatory=$true)]
        $user,
        [Parameter(Mandatory=$true)]
        $password,
        [Parameter(Mandatory=$true)]
        $time,
        [Parameter(Mandatory=$true)]
        $taskname
    )
    $A = New-ScheduledTaskAction –Execute C:\windows\system32\WindowsPowerShell\v1.0\powershell.exe -Argument "-file `"$scriptpath`""
    $T = New-ScheduledTaskTrigger -Daily -At $time
    $S = New-ScheduledTaskSettingsSet
    $D = New-ScheduledTask -Action $A -Trigger $T -Settings $S
    Register-ScheduledTask $taskname -InputObject $D -User $user -Password $password
}

Pulled  the syntax for this from the documentation over here; https://technet.microsoft.com/en-us/library/jj649810(v=wps.630).aspx


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