PowerShell Functions

Here are some PowerShell Functions

Retrieves free space percentages


001
002
003
004
005
006
007
008
009
Function Get-FreeSpace
{
    Get-WmiObject Win32_LogicalDisk | Where-Object { $_.DriveType -eq "3" } | Select-Object SystemName,
                @{ Name = "Drive" ; Expression = { ( $_.DeviceID ) } },
                @{ Name = "Size (GB)" ; Expression = {"{0:N1}" -f$_.Size / 1gb)}},
                @{ Name = "FreeSpace (GB)" ; Expression = {"{0:N1}" -f$_.Freespace / 1gb ) } },
                @{Name = "PercentFree" ; Expression = {"{0:P1}" -f$_.FreeSpace / $_.Size ) } }
}
Get-Freespace #Format-Table -AutoSize

Sample Output:

PS C:\> Get-Freespace | Format-Table -AutoSize

SystemName      VolumeName Drive Size (GB) FreeSpace (GB) PercentFree
----------      ---------- ----- --------- -------------- -----------
PSDSCPULLSERVER DSC        B:    48.8      48.6           99.5 %
PSDSCPULLSERVER            C:    77.7      68.8           88.6 %


PS C:\>

Performs a cleanup of WSUS & Outputs the results to a text file.


001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
Start-WSUSCleanup
{
    $outFilePath = '.\wsusClean.txt'
    [reflection.assembly]::LoadWithPartialName("Microsoft.UpdateServices.Administration"| out-null
    $wsus = [Microsoft.UpdateServices.Administration.AdminProxy]::GetUpdateServer();
    $cleanupScope = new-object Microsoft.UpdateServices.Administration.CleanupScope;
    $cleanupScope.DeclineSupersededUpdates         = $true
    $cleanupScope.DeclineExpiredUpdates            = $true
    $cleanupScope.CleanupObsoleteUpdates           = $true
    $cleanupScope.CompressUpdates                  = $true
    #$cleanupScope.CleanupObsoleteComputers = $true
    $cleanupScope.CleanupUnneededContentFiles      = $true
    $cleanupManager = $wsus.GetCleanupManager();
    $cleanupManager.PerformCleanup($cleanupScope|
    Out-File -FilePath $outFilePath
}


Clean up a C:\ Drive


001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
Function Cleanup
{
<#
.CREATED BY:
    Matthew A. Kerfoot
.CREATED ON:
    10\17\2013
.Synopsis
    Automate cleaning up a C: drive with low disk space
.DESCRIPTION
   Cleans the C: drive's Window Temporary files, Windows Software-distribution folder, `
   the local users Temporary folder, IIS logs(if applicable) and empties the recycling bin. `
   All deleted files will go into a log transcript in C:\Windows\Temp\. By default this `
   script leaves files that are newer than 7 days old however this variable can be edited.
.EXAMPLE
   PS C:\Users\mkerfoot\Desktop\Powershell> .\cleanup_log.ps1
   Save the file to your desktop with a .PS1 extension and run the file from an elevated PowerShell prompt.


   This script will typically clean up anywhere from 1GB up to 15GB of space from a C: drive.
.FUNCTIONALITY
   PowerShell v3
#>
function global:Write-Verbose ( [string]$Message )

# check $VerbosePreference variable, and turns -Verbose on
if ( $VerbosePreference -ne 'SilentlyContinue' )
Write-Host " $Message" -ForegroundColor 'Yellow' } }

$VerbosePreference = "Continue"
$DaysToDelete = 7
$LogDate = get-date -format "MM-d-yy-HH"
$objShell = New-Object -ComObject Shell.Application 
$objFolder = $objShell.Namespace(0xA)
$ErrorActionPreference = "silentlycontinue"
                    
Start-Transcript -Path C:\Windows\Temp\$LogDate.log

## Cleans all code off of the screen.
Clear-Host

$size = Get-ChildItem C:\Users\* -Include *.iso, *.vhd -Recurse -ErrorAction SilentlyContinue | 
Sort Length -Descending | 
Select-Object Name, Directory,
@{Name="Size (GB)";Expression="{0:N2}" -f ($_.Length / 1GB) }} |
Format-Table -AutoSize | Out-String

$Before = Get-WmiObject Win32_LogicalDisk | Where-Object { $_.DriveType -eq "3" } | Select-Object SystemName,
@{ Name = "Drive" ; Expression = { ( $_.DeviceID ) } },
@{ Name = "Size (GB)" ; Expression = {"{0:N1}" -f$_.Size / 1gb)}},
@{ Name = "FreeSpace (GB)" ; Expression = {"{0:N1}" -f$_.Freespace / 1gb ) } },
@{ Name = "PercentFree" ; Expression = {"{0:P1}" -f$_.FreeSpace / $_.Size ) } } |
Format-Table -AutoSize | Out-String                      
                    
## Stops the windows update service.
Get-Service -Name wuauserv | Stop-Service -Force -Verbose -ErrorAction SilentlyContinue
## Windows Update Service has been stopped successfully!

## Deletes the contents of windows software distribution.
Get-ChildItem "C:\Windows\SoftwareDistribution\*" -Recurse -Force -Verbose -ErrorAction SilentlyContinue |
Where-Object { ($_.CreationTime -lt $(Get-Date).AddDays(-$DaysToDelete)) } |
remove-item -force -Verbose -recurse -ErrorAction SilentlyContinue
## The Contents of Windows SoftwareDistribution have been removed successfully!

## Deletes the contents of the Windows Temp folder.
Get-ChildItem "C:\Windows\Temp\*" -Recurse -Force -Verbose -ErrorAction SilentlyContinue |
Where-Object { ($_.CreationTime -lt $(Get-Date).AddDays(-$DaysToDelete)) } |
remove-item -force -Verbose -recurse -ErrorAction SilentlyContinue
## The Contents of Windows Temp have been removed successfully!
             
## Delets all files and folders in user's Temp folder.
Get-ChildItem "C:\users\*\AppData\Local\Temp\*" -Recurse -Force -ErrorAction SilentlyContinue |
Where-Object { ($_.CreationTime -lt $(Get-Date).AddDays(-$DaysToDelete))} |
remove-item -force -Verbose -recurse -ErrorAction SilentlyContinue
## The contents of C:\users\$env:USERNAME\AppData\Local\Temp\ have been removed successfully!
                    
## Remove all files and folders in user's Temporary Internet Files.
Get-ChildItem "C:\users\*\AppData\Local\Microsoft\Windows\Temporary Internet Files\*" `
-Recurse -Force -Verbose -ErrorAction SilentlyContinue |
Where-Object {($_.CreationTime -le $(Get-Date).AddDays(-$DaysToDelete))} |
remove-item -force -recurse -ErrorAction SilentlyContinue
## All Temporary Internet Files have been removed successfully!
                    
## Cleans IIS Logs if applicable.
Get-ChildItem "C:\inetpub\logs\LogFiles\*" -Recurse -Force -ErrorAction SilentlyContinue |
Where-Object { ($_.CreationTime -le $(Get-Date).AddDays(-60)) } |
Remove-Item -Force -Verbose -Recurse -ErrorAction SilentlyContinue
## All IIS Logfiles over x days old have been removed Successfully!
                  
## deletes the contents of the recycling Bin.
## The Recycling Bin is now being emptied!
$objFolder.items() | ForEach-Object { Remove-Item $_.path -ErrorAction Ignore -Force -Verbose -Recurse }
## The Recycling Bin has been emptied!

## Starts the Windows Update Service
##Get-Service -Name wuauserv | Start-Service -Verbose

$After =  Get-WmiObject Win32_LogicalDisk | Where-Object { $_.DriveType -eq "3" } | Select-Object SystemName,
@{ Name = "Drive" ; Expression = { ( $_.DeviceID ) } },
@{ Name = "Size (GB)" ; Expression = {"{0:N1}" -f$_.Size / 1gb)}},
@{ Name = "FreeSpace (GB)" ; Expression = {"{0:N1}" -f$_.Freespace / 1gb ) } },
@{ Name = "PercentFree" ; Expression = {"{0:P1}" -f$_.FreeSpace / $_.Size ) } } |
Format-Table -AutoSize | Out-String

## Sends some before and after info for ticketing purposes
Hostname ; Get-Date | Select-Object DateTime
Write-Verbose "Before: $Before"
Write-Verbose "After: $After"
Write-Verbose $size

## Completed Successfully!
Stop-Transcript
}
Cleanup


retrieves a random and sometimes funny excuse.


001
002
003
004
005
006
007
008
009
010
011
012
013
014
function Get-Excuse
{
  $url = 'http://pages.cs.wisc.edu/~ballard/bofh/bofhserver.pl'
  $ProgressPreference = 'SilentlyContinue'
  $page = Invoke-WebRequest -Uri $url -UseBasicParsing
  $pattern = '<br><font size = "\+2">(.+)'

  if ($page.Content -match $pattern)
  {
    $matches[1]
  }
}
Get-Excuse


Gathers general CPU statistics


001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
Function Get-Cpu
{
<#
.CREATED BY:
    Matthew A. Kerfoot
.CREATED ON:
    10\ 1\2013
.Synopsis
   Gathers general CPU statistics
.DESCRIPTION
    Gathers Computername, Date, lists the top 10 CPU consuming processes and then `
    3 samples of the Average Processor time. and finally the average CPU usage.
.EXAMPLE
   Get-Cpu -Computername localhost | ConvertTo-Html | Out-File C:\
#>

                  [CmdletBinding()]
           Param ([Parameter(Mandatory=$false,
                  ValueFromPipelineByPropertyName=$true,
                  Position=0)]
                  $Computername
           )

         Begin {
                $Info = Get-Date ; Hostname
         }

     Process {
               $Start = Get-Process | Sort-Object -Descending cpu | Select-Object -First 10 | Format-Table -AutoSize
               $CpuTime = Get-Counter '\Processor(_Total)\% Processor Time' -SampleInterval 1 -MaxSamples 3
               $Cmd = wmic cpu get loadpercentage
     }

 End {
       $Info
       $Start | Format-Table -AutoSize
       $CpuTime
       $Cmd
 }
}
Get-Cpu

Output:

PS C:\> Get-Cpu
PSDSCPULLSERVER

Thursday, August 7, 2014 6:37:22 AM

Handles NPM(K)  PM(K)  WS(K) VM(M) CPU(s)   Id ProcessName
------- ------  -----  ----- ----- ------   -- -----------
    275    156 364148 407036   610  58.59  912 chrome
    178     56 272928 272204   454  33.77 3508 chrome
   1317     83  70336 133896   407  22.97 1588 chrome
    187     34 115120 136160   306   8.00 1828 chrome
    181     47 214652 219344   406   6.86 3716 chrome
    162     24  73820  68492   223   4.41 1844 chrome
    675     63 103012 141268   928   3.67 2364 powershell_ise
    222     27  72912  56480   241   3.17 2236 chrome
   1067     55  28832  98456   499   2.42 2148 explorer
    656     44  94256  95412   769   2.09 1796 ServerManager

Timestamp           CounterSamples
---------           --------------
8/7/2014 6:37:23 AM \\psdscpullserver\processor(_total)\% processor time :
                    3.1638990617469


8/7/2014 6:37:24 AM \\psdscpullserver\processor(_total)\% processor time :
                    1.58507638347763


8/7/2014 6:37:25 AM \\psdscpullserver\processor(_total)\% processor time :
                    9.39986973575754


LoadPercentage

4

PS C:\>

Queries Active Directory for all Server O\S's and outputs them to the console



001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
Function Get-AllServers
{
<#
.Synopsis
   Queries Active Directory for all Server O\S's and outputs them to the console.
.DESCRIPTION
   Creates Job to download my cleanup script every 5 min
.EXAMPLE
   PS C:\ > Get-AllServers
   This will output all servers on the current domain you are connected to.
.EXAMPLE
   PS C:\ > Get-AllServers | ConvertTo-Html | Out-File $env:USERPROFILE\Desktop\$env:COMPUTERNAME.htm
   This will output a list of the servers to a text file on the users desktop.
.NOTES
   Created By: Chad Hammond
.FUNCTIONALITY
   PowerShell v1.0+
#>
       [CmdletBinding()]
Param[Parameter( Mandatory = $False,
                   ValueFromPipelineByPropertyName = $true )]
                   $VerbosePreference = "Continue"
)
    
Begin$NewObj = New-Object System.DirectoryServices.DirectorySearcher }

Process$NewObj.Filter = "OperatingSystem=Window*Server*" ;
                "Name","canonicalname","distinguishedname" | 
                 Foreach-Object {$null = $NewObj.PropertiesToLoad.Add($_) } }

End { $NewObj.FindAll() | Select-Object @{ n = 'Name' ; e = { $_.properties['name'] } },
                                        @{ n = 'ParentOU' ; e = { $_.properties['distinguishedname'] -replace '^[^,]+,'} },
                                        @{ n = 'CanonicalName' ; e = { $_.properties['canonicalname'] } },
                                        @{ n = 'DN' ; e = { $_.properties['distinguishedname'] } } }

}
Get-AllServers

SampleOutput:
PS C:\> Get-AllServers

Name                          ParentOU                      CanonicalName                 DN
----                          --------                      -------------                 --
MKDC-01                       OU=Domain Controllers,DC=K... Kerfoot.com/Domain Control... CN=MKDC-01,OU=Domain Contr...
MKPSWA                        CN=Computers,DC=Kerfoot,DC... Kerfoot.com/Computers/MKPSWA  CN=MKPSWA,CN=Computers,DC=...
MKRODC-01                     CN=Computers,DC=Kerfoot,DC... Kerfoot.com/Computers/MKRO... CN=MKRODC-01,CN=Computers,...
MKDA                          CN=Computers,DC=Kerfoot,DC... Kerfoot.com/Computers/MKDA    CN=MKDA,CN=Computers,DC=Ke...
MKWSUS                        CN=Computers,DC=Kerfoot,DC... Kerfoot.com/Computers/MKWSUS  CN=MKWSUS,CN=Computers,DC=...
MKSQL-01                      CN=Computers,DC=Kerfoot,DC... Kerfoot.com/Computers/MKSQ... CN=MKSQL-01,CN=Computers,D...
MKFAP-02                      CN=Computers,DC=Kerfoot,DC... Kerfoot.com/Computers/MKFA... CN=MKFAP-02,CN=Computers,D...
MKFAP-01                      CN=Computers,DC=Kerfoot,DC... Kerfoot.com/Computers/MKFA... CN=MKFAP-01,CN=Computers,D...
MKWSUS-UPSTREAM               CN=Computers,DC=Kerfoot,DC... Kerfoot.com/Computers/MKWS... CN=MKWSUS-UPSTREAM,CN=Comp...
PSDSCPULLSERVER               CN=Computers,DC=Kerfoot,DC... Kerfoot.com/Computers/PSDS... CN=PSDSCPULLSERVER,CN=Comp...
SERVER2012R2-03               CN=Computers,DC=Kerfoot,DC... Kerfoot.com/Computers/SERV... CN=SERVER2012R2-03,CN=Comp...
DHCP-01                       CN=Computers,DC=Kerfoot,DC... Kerfoot.com/Computers/DHCP-01 CN=DHCP-01,CN=Computers,DC...
RODC                          CN=Computers,DC=Kerfoot,DC... Kerfoot.com/Computers/RODC    CN=RODC,CN=Computers,DC=Ke...
PSWA                          CN=Computers,DC=Kerfoot,DC... Kerfoot.com/Computers/PSWA    CN=PSWA,CN=Computers,DC=Ke...
DHCP-02                       CN=Computers,DC=Kerfoot,DC... Kerfoot.com/Computers/DHCP-02 CN=DHCP-02,CN=Computers,DC...
MKDC-02                       CN=Computers,DC=Kerfoot,DC... Kerfoot.com/Computers/MKDC-02 CN=MKDC-02,CN=Computers,DC...
SERVER2012R2-01               CN=Computers,DC=Kerfoot,DC... Kerfoot.com/Computers/SERV... CN=SERVER2012R2-01,CN=Comp...
SERVER2012R2-02               CN=Computers,DC=Kerfoot,DC... Kerfoot.com/Computers/SERV... CN=SERVER2012R2-02,CN=Comp...
PSWAW12                       CN=Computers,DC=Kerfoot,DC... Kerfoot.com/Computers/PSWAW12 CN=PSWAW12,CN=Computers,DC...


PS C:\>

Attach an Image to a users Outlook\Lync profile


001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
function Set-UserImage
{
<#
.CREATED BY:
    Matthew A. Kerfoot
.CREATED ON:
    11\11\2013
.Synopsis
   Attach an Image to a users Outlook\Lync profile.
.DESCRIPTION
   This script will prompt you for a username and then the image to assign to that user. once selected, the image will be uploaded.
.EXAMPLE
   PS C:\Users\mkerfoot\Desktop\Powershell> .\cleanup_log.ps1
   Save the file to your desktop with a .PS1 extention and run the file from an elavated PowerShell prompt.
.NOTES
   $root is the only line that will need to be edited.
.FUNCTIONALITY
   PowerShell v2
#>

    param[Parameter(Mandatory=$false,
                      ValueFromPipelineByPropertyName=$true)]
                      [string]$Title,
                      [string]$Directory,
                      [string]$Filter="All Files (*.*)|*.*")
                      [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms"|
                      Out-Null

    $root = [ADSI]'GC://dc=corp,dc=int'
    $SAMName=Read-Host "Please enter the AD username of the user whom you would like to add an image to for example: mkerfoot"
    $searcher = new-object System.DirectoryServices.DirectorySearcher($root)
    $searcher.filter = "(&(objectClass=user)(sAMAccountName=$SAMName))"
    $user = $searcher.findall()
    $userdn = $user[0].path
    $userdn = $userdn.trim("GC")
    $userdn = "LDAP" + $userdn
    $objForm = New-Object System.Windows.Forms.OpenFileDialog
    $objForm.InitialDirectory = $Directory
    $objForm.Filter = $Filter
    $objForm.Title = $Title
    $objForm.ShowHelp = $true
    $Show = $objForm.ShowDialog()
    $photo = Select-FileDialog -Title "Select a photo" -Directory "%userprofile%" -Filter "JPG Images (*.jpg)|*.jpg|PNG Images (*.png)|*.png"
    $user = [ADSI]($userdn)
    [byte[]]$file = Get-Content $photo -Encoding Byte
    $user.Properties["thumbnailPhoto"].Clear()
    $result = $user.Properties["thumbnailPhoto"].Add($file)
    $user.CommitChanges()

If ( $Show -eq "OK" ){ Return $objForm.FileName }
Else { Write-Error "Operation canceled by user." }

if ( $result -eq "0" ){ Write-Host "Photo successfully uploaded." -ForegroundColor Yellow }
elseWrite-Error "Photo was not uploaded." }

}
Set-UserImage


Creates a vertical list of computer names and saves it to your desktop.


001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
Function Get-ComputerList
{
<#
.CREATED BY:
    Matthew A. Kerfoot
.CREATED ON:
    2/19/2014
.Synopsis
   Creates a text file with a list of all computers and servers on the domain.
.DESCRIPTION
    This function gathers the names of all computers connected to you current Domain `
    and outputs the results to your Desktop by default.
.EXAMPLE
   Get-ComputerList | out
#>

        [CmdletBinding()]
    Param ([Parameter(Mandatory=$false,
        ValueFromPipelineByPropertyName=$true,
        Position=0)]
        $Save_File = "$env:USERPROFILE\Desktop\$env:USERDNSDOMAIN.txt",
        $ComputerList_spaces = "$env:USERPROFILE\Desktop\ComputerList_spaces.txt"
    )

        Import-Module activedirectory

     # Gather the name of all computer connected to the domain
     Get-ADComputer -filter * | select name | Out-File $ComputerList_spaces

  ## removes empty spaces from txt document
  $Comp = ( Get-Content "$ComputerList_spaces" | Select-Object -Skip 3 ).replace( " ","" )
  $Comp | Out-File "$Save_File"

## deletes the computerlist.txt document with whitespaces
del $ComputerList_spaces

}
Get-ComputerList


Creates and sets the IP Phone attribute in Active Directory per user specified.


001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
function Set-IPPhone
 {
 <#
.CREATED BY:
    Matthew A. Kerfoot
.CREATED ON:
    07/08/2014
.SYNOPSIS
   create and set IP Phone number in AD
.DESCRIPTION
   This function will create and set the IP Phone attribute in Active Directory per user specified.
.EXAMPLE
   Set-IPPhone -username mkerfoot -New_IP_Phone_Number 555-555-5555
#>

                        [CmdletBinding()]
                Param (
                        [Parameter(Mandatory=$true,
                        ValueFromPipelineByPropertyName=$true,
                        Position=0)]
                        $username,
                        [Parameter(Mandatory=$true,
                        ValueFromPipelineByPropertyName=$true,
                        Position=0)]
                        $New_IP_Phone_Number
               )

 Begin {

        import-module activedirectory

       }

 Process {

            $user = Get-ADUser -identity $username | Foreach-Object { $lookup = "LDAP://" + $_.DistinguishedName;[ADSI]$lookup}

            $user.put("IPPhone","$New_IP_Phone_Number")
         }

 End {

      $user.setinfo()

     }

 }
 Set-IPPhone


Crawls the web for anything desired


001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
function Search-Google
<#
.Synopsis
Searches the Googes
.DESCRIPTION
Lets you quickly start a search from within Powershell
.EXAMPLE
Search-Google Error code 5
--New google search results will open listing top entries for 'error code 5'

.EXAMPLE
search-google (gwmi win32_baseboard).Product maximum ram

#>

{
 Begin {
        $query='https://www.google.com/search?q='
       }
Process
       {
        if ($args.Count -eq 0)
       {
        "Args were empty, commiting `$input to `$args"
        Set-Variable -Name args -Value (@($input| % {$_})
        "Args now equals $args"
        $args = $args.Split()
       } ELSE {
               "Args had value, using them instead"
              }

            Write-Host $args.Count, "Arguments detected"
            "Parsing out Arguments: $args"
            for ($i=0;$i -le $args.Count;$i++){
            $args | % {"Arg $i `t $_ `t Length `t" + $_.Length, " characters"} }
            $args | % {$query = $query + "$_+"}
           }
    End
        {
         $url = $query.Substring(0,$query.Length-1)
         "Final Search will be $url `nInvoking..."
         start "$url"
        }
}


Changes the number of rows on Windows 8 metro desktop


001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
Function Bypass-WindowsMetro
{
<#
.Synopsis
   Changes the number of rows on Windows 8 metro desktop
.DESCRIPTION
   Changes the number of rows on Windows 8 metro desktop by modifying the registry
.EXAMPLE
   Set-MetroRows -Rows 3
   After loging out and back into windows you will have 3 rows on your Windows Metro desktop.
.EXAMPLE
   Set-MetroRows -Rows 1
   After loging out and back into windows you will have 1 row on your Windows Metro desktop.
.NOTES
   You must logout\sign out and back into Windows for the registry changes to take effect.
.FUNCTIONALITY
   PowerShell v3.0+
#>

[CmdletBinding()]
          Param ( [Parameter(Mandatory=$True,
                   ValueFromPipelineByPropertyName=$true,
                   Position=0)]
                   $Rows,
                   $VerbosePreference = "Continue" )

BeginRemove-ItemProperty "HKCU:\HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\ImmersiveShell\Grid" -Name "Layout_MaximumRowCount" }

ProcessNew-ItemProperty "HKCU:\HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\ImmersiveShell\Grid" -Name "Layout_MaximumRowCount" -Value $Rows -PropertyType "DWord" }

End { Write-Verbose "Please Press Enter to sign out of windows, once logged back in the changes will be in place!" ; Pause ; shutdown /l }

}