Showing posts with label function. Show all posts
Showing posts with label function. Show all posts

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.


Wednesday, August 12, 2015

Everyday Powershell - Part 33 - New-RandomPassword

Everyday Powershell returns! This series is about providing easily digestible chucks of powershell goodness so those of us new to the world or the shell can start leveraging the awesome power of the shell!

If you are the kind of person who creates a lot of accounts for any reason you know the value of having a password randomiser handy.

function new-randompassword{
    param(
        [Parameter(mandatory=$false,ValueFromPipeline=$True,ValueFromPipelinebyPropertyName=$True)]
        [int]$length = 25
    )

    $possiblecharacters = "1","2","3","4","5","6","7","8","9","0","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","Q","R","S","T","U","V","W","Y","X","Z"
    $password = ""
    $i = 0
    While($i -le $length){
        $password += get-random -InputObject $possiblecharacters
        $i++
    }
    $password
}

Really straight forward and easy to understand function here with one parameter -length. Easily extended to support more characters. You could even remove possible similar looking characters from the list 1, I, l  kind look the same as do 0,O and o. It's all up to you! That's the great thing with writing your own functions. If you don't like what it does you can just change it right there and make it do what you want!

Have a great day Powershellers!

Tuesday, October 14, 2014

Everyday Powershell - Part 29 - Add-SMTPAlias

It's funny. When you think about how many clicks you need to go through to add an SMTP alias to an Exchange mailbox... There's a lot of clicks! Or you could just use this function and be done in 5 seconds.

function Add-SMTPAlias{
    <# Add-SMTPAlias
    .SYNOPSIS Adds smtp alias to a given mailbox

    .DESCRIPTION

    .PARAMETER alias
    Users Alias

    .PARAMETER
    newsmtpaddress desired email alias

    .EXAMPLE
    Add-IPToSMTPRelay -alias someuser -newsmtpaddress someusersotheremail@someserver.com 
    #>

    [CmdletBinding()]
    param (
        [Parameter(mandatory=$true,ValueFromPipeline=$true)]
        $alias,
        [Parameter(mandatory=$true,ValueFromPipeline=$true)]
        [mailaddress]$newsmtpaddress
    )
    process{
        $emailaddresses = (get-mailbox $alias).emailaddresses
        $emailaddresses += $newsmtpaddress.ToString()
        try{
            Set-Mailbox $alias -EmailAddresses $emailaddresses -ErrorAction stop
        }
        catch{
            write-warning ("Problem setting email address " + $_)
        }
    }
}

5 minutes or 5 seconds, the choice is yours GUI fans. Maybe it's time to give in to the power of the shell?

Wednesday, September 10, 2014

Everyday Powershell - Part 28 - Add-IPToSMTPRelay

Here's one that came up when we'd provisioned a new powershell integration server and couldn't send email from it!

Turns out our email server's weren't allowing it relay. So we needed to add it's IP to the RemoteIPRanges parameter and as Paul Cunningham  points out this can be tricky.

function Add-IPToSMTPRelay{
    <#
    Add-IPToSMTPRelay
    .SYNOPSIS
    Adds an IP address to the allow anonymous SMTP relay Receive connector on TMAIL

    .DESCRIPTION
    You will need to know your receive connectors name... use get-recieveconnector We only use one so it's been hard coded into the funtion, this could be parameterised if you need
    
    .PARAMETER
    IP IP Address to add to allowed anonymous SMTP relay 

    .EXAMPLE
    Add-IPToSMTPRelay 192.168.1.1
    #>

    [CmdletBinding()]
    param (
        [Parameter(mandatory=$true,ValueFromPipeline=$true)]
        [ipaddress]$ip
    )
    process{
        $remoteipranges = (Get-ReceiveConnector "smtp relays").remoteipranges
        $remoteipranges += ($ip).ToString()
        Set-ReceiveConnector "smtp relays" -RemoteIPRanges $remoteipranges
    }
}

You may be saying... "WOAH WOAH WOAH this looks different to your usual posts! What's all this function param process stuff?"

Well as you can see we wrapped up the powershell in a Function. The Comment block at the top is the help. The Param block defines any parameters in this case we've just got $IP. The process block is what actually happens and would be what we'd normally post.

This allows us to embed the function in a module and then stick the module in our powershell profile so it's always available!

This is far better than digging around in a scripts folder we'll dig into setting up a module in the next few weeks.