Sunday, December 29, 2013

Make PowerShell startup blazing fast!!

If you use PowerShell...You HAVE to run this script! This will cut the time it takes PowerShell to start in half!

Function Improve-GAC { Set-Alias ngen (Join-Path ([System.Runtime.InteropServices.RuntimeEnvironment]::GetRuntimeDirectory()) ngen.exe)
 [AppDomain]::CurrentDomain.GetAssemblies() |
    sort {Split-path $_.location -leaf} |
    %{
        $Name = (Split-Path $_.location -leaf)
        if ([System.Runtime.InteropServices.RuntimeEnvironment]::FromGlobalAccessCache($_))
        {
            Write-Host "Already GACed: $Name"
        }else
        {
            Write-Host -ForegroundColor Yellow "NGENing      : $Name"
            ngen $_.location | %{"`t$_"}
         }
      }
}Improve-GAC


referance: http://blogs.msdn.com/b/powershell/archive/2007/11/08/update-gac-ps1.aspx

Saturday, December 28, 2013

Backup Windows 8.1

Here is a short little PowerShell Function that I use to create a scheduled job that runs every night at midnight that backups my C:\ drive to my E:\ drive.

The code used to backup Windows 8.1:
wbAdmin start backup -backupTarget:E: -include:C: -quiet

Function Create-ScheduledJob {
<#
.Synopsis
   schedules nightly backups.
.FUNCTIONALITY
   PowerShell v3.0+
#>
[CmdletBinding()]
    Param( [Parameter( Mandatory = $True )]
           $JobName,
           [Parameter( Mandatory = $True )]
           $ScriptToRun,
           $VerbosePreference = "Continue" )

Begin{ $Trigger = (New-JobTrigger -Daily -At 12:01AM) }

Process{ Register-ScheduledJob -Name $JobName -Trigger $Trigger -ScriptBlock { "& wbAdmin start backup -backupTarget:E: -include:C: -quiet" } }

End { Write-Verbose "Your new ScheduledJob has been created successfully!" }

}Create-ScheduledJob


Monday, December 23, 2013

Skip Windows Metro UI at boot

Here is a short PowerShell function that will make Windows boot right to the Desktop; skipping the Metro UI!

Function Disable-MetroAtBoot {
<#
.Synopsis
   Disables Windows booting to the Metro Desktop.
.DESCRIPTION
   Disables Windows booting to the Metro Desktop by modifying the registry. Windows will boot to the Desktop after running this function.
.EXAMPLE
   Disable-MetroAtBoot
   After loging out and back into windows you will have 3 rows on your Windows Metro desktop.
.EXAMPLE
   Disable-MetroAtBoot -Verbose
   After loging out and back into windows you will have 1 row on your Windows Metro desktop.
.NOTES
   After running this script the next time you log into Windows, the first thing you will see is the desktop and not the Metro desktop.
.FUNCTIONALITY
   Windows 8, Windows 8.1
#>
[CmdletBinding()]
          Param ( $VerbosePreference = "Continue" )
    
Begin{ $RegLocation = "HKCU:\HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\StartPage" }

Process{ New-ItemProperty $RegLocation -Name "OpenAtLogon" -Value 0 -PropertyType "DWord" }

End { Write-Verbose "Next time you log into Windows; Windows will boot right to the Desktop!" }

}Disable-MetroAtBoot -Verbose


Tuesday, December 10, 2013

Change number of rows on Windows 8 metro desktop

Do you have Windows 8 installed? Would you like to customize your Computers Desktop? Download this short PowerShell function to modify the amount of rows you Windows Metro Desktop will display.

I've got some good new, some not so good news and some bad news;

       

Good:

If you have Windows 8 this opens up an awesome ability to customize your Metro Desktop.

       

Not so good:

I have yet to get this to work in Windows 8.1. There is however a possible workaround as in some copies of Windows 8.1 you are able to Charms Bar > Settings > Tiles > Show More Tiles Change to 'Yes'. This option is only found in specific Versions of  Windows 8.1, sadly I have not came to a defiant reasoning to what allows this option

       

Bad:

You must sign out of your Windows account and back in for the change to take effect.

Simply copy the below code into an Administrative PowerShell console by right clicking on PowerShell.exe and then left clicking on 'Run as an Administrator.'

Function Set-MetroRows {
<#
.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" )
    
Begin{ Remove-ItemProperty "HKCU:\HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\ImmersiveShell\Grid" -Name "Layout_MaximumRowCount" }

Process{ New-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 }

} Set-MetroRows -Rows 3
The amount of rows that you can have is determined by your screen resolution.(see chart below)
Screen Resolution (HxV)DefaultMaxMin
800 x 600331
1024 x 768441
1152 x 864551
1280 x 720441
1280 x 900551
1280 x 960561
1280 x 1024561
1440 x 900551
1600 x 900551
1680 x 1050661
1900 x 1080561
1920 x 1080661
1920 x 1200671
2560 x 19206101
Examples:





Wednesday, December 4, 2013

Cleanup a C: drive with Windows PowerShell

title

Being an overnight Administrator I get a lot of low disk space alerts when drives hit their thresholds. Tonight I’m going to put an end to all this work. I wrote the following script to help automate the cleaning of C:\ drives or any drives that have a Windows operating system installed.

What Does this Script do?

  1. Clears all code off the screen
  2. Stops the Windows Update Service
  3. Deletes the contents of Windows Software Distribution
  4. Deletes the contents of windows temp folder
  5. Deletes files in users temp folder
  6. Deletes temporary internet files
  7. Cleans IIS logs
  8. Empties the Recycling Bin
  9. Starts Windows update service
  10. Outputs disk space before and after.
 
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
<#
.CREATED BY:
    Matthew A. Kerfoot
.CREATED ON:
    10\17\2013
.Synopsis
   automate cleaning up a C: drive with low disk space
.DESCRIPTION
   Cleans up the C: drives temp files and other misc. unneeded files.
.EXAMPLE
   .\cleanup_log.ps1
#>
function global:Write-Verbose
   (
    [string]$Message
   )
    # check $VerbosePreference variable
   { if ( $VerbosePreference -ne 'SilentlyContinue' )
       { Write-Host " $Message" -ForegroundColor 'Yellow' } }
         Write-Verbose  
          $DaysToDelete = 7
          $LogDate = get-date -format "MM-d-yy-HH"
          $objShell = New-Object -ComObject Shell.Application 
          $objFolder = $objShell.Namespace(0xA) 
                    
            Start-Transcript -Path C:\Windows\Temp\$LogDate.log

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

          $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!

            ## Deletes all files and folders in user's Temp folder.
            Get-ChildItem "C:\users\$env:USERNAME\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\$env:USERNAME\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.
            $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-Host "Before: $Before"
     Write-Host "After: $After"

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

 ## Completed Successfully!
 Stop-Transcript
Now just open an elevated command prompt and run the this script.
 
Sample Output:

VT-MKERFOOT-W8
nbsp;
DateTime
--------
Thursday, December 04, 2014 5:00:15 MATTHEW
Before:
SystemName     Drive Size (GB) FreeSpace (GB) PercentFree
----------     ----- --------- -------------- -----------
VT-MKERFOOT-W8 C:    223.2     41.8           18.7 %
After:
SystemName     Drive Size (GB) FreeSpace (GB) PercentFree
----------     ----- --------- -------------- -----------
VT-MKERFOOT-W8 C:    223.2     45.9           20.5 %
VT-MKERFOOT-W8 C:    223.2     29.2           13.1 %

Transcript stopped, output file is C:\Windows\Temp\12-04-14-9.log
 
 
Note this would have cleaned up more files and given a long verbose string of files removed except I just ran this against my computer and it brought it from 18% free to 20% free(which was shown above). Now all you have to do is Download my script here!

Wednesday, November 13, 2013

Find neighbor cache with PowerShell

Have you ever wanted to view the neighbor cache or possibly the IP address of a friend or family members networked device? New with PowerShell 3.0 is the cmdlet Get-NetNeighbor which will retrieve all neighbor cache information for IPv4 and IPv6 by default.

To get the neighbor cache we used to have to:


Type netsh, and then press ENTER.

Type interface ipv6, and then press ENTER.

Type show neighbors, and then press ENTER.


 Now don't get me wrong that method still works......however with PowerShell 3.0 we can just type        Get-NetNeighbor (as shown below).

PS [www.matthewkerfoot.com]> Get-NetNeighbor

ifIndex IPAddress                                        LinkLayerAddress   State       PolicyStore
------- ---------                                        ----------------   -----       -----------
100     ff02::1:ffv5:307b                                333ffff3ffa5       Permanent   ActiveStore
100     ff02::5:2                                        33ff33000100       Permanent   ActiveStore
100     ff02::12                                         33ff33000000       Permanent   ActiveStore
100     ff02::2                                          3ff333000000       Permanent   ActiveStore
100     fe80::f93b:d3e4:eccc:7b6b                        000000000000       Unreachable ActiveStore
100     fe80::eccc:af83:398f:a1a8                        000000000000       Unreachable ActiveStore
100     fe80::eccc:6ab0:eccc:136e                        000000000000       Unreachable ActiveStore
100     fe80::a53e:5e59:1aaa:469b                        000000000000       Unreachable ActiveStore
100     fe80::95c4:eccc:fa9c:eccc                        000000000000       Unreachable ActiveStore
100     fe80::810b:9551:eccc:8f76                        000000000000       Unreachable ActiveStore
100     fe80::eccc:af1d:592d:bb91                        000000000000       Unreachable ActiveStore
100     fe80::790f:eccc:8c2:39fd                         000000000000       Unreachable ActiveStore
100     fe80::6882:eccc:7d16:c810                        000000000000       Unreachable ActiveStore
100     fe80::eccc:8044:2eb2:efca                        000000000000       Unreachable ActiveStore
100     fe80::55e9:284a:8568:a20d                        000000000000       Unreachable ActiveStore
100     fe80::25f4:8f34:2ccb:3da5                        000000000000       Unreachable ActiveStore
100     fe80::1822:5444:6ba5:eccc                        000000000000       Unreachable ActiveStore
100     fe80::1b5:b466:8065:eccc                         000000000000       Unreachable ActiveStore
97      ff02::1:eccc:307b                                3333ffa5307b       Permanent   ActiveStore
97      ff02::1:eccc:5663                                3333ffff5663       Permanent   ActiveStore
97      ff02::1:3                                        33330ff00100       Permanent   ActiveStore
97      ff02::2:8                                        3333000ff100       Permanent   ActiveStore
Actual Data has been manipulated

The Get-NetNeighbor cmdlet is an awesome addition to PowerShell, this cmdlet allows us to have the same capabilities as we always could before with netsh and just like a Cisco network device by running the command show CDP Neighbor. I like to modify this cmdlet at little bit to show me only IPv4 address' that I have recently talked to.
Get-NetNeighbor -AddressFamily IPv4 | Where-Object { $_.State -ne "Permanent" } | Sort-Object State,IPAddress -Descending
I find the output of the above cmdlets ussually gives me everything I want to know.
PS [www.matthewkerfoot.com]> Get-NetNeighbor -AddressFamily IPv4 | Where-Object { $_.State -ne "Permanent" } | Sort-Object State,IPAddress -Descending

ifIndex IPAddress                                        LinkLayerAddress   State       PolicyStore
------- ---------                                        ----------------   -----       -----------
95      10.10.10.1                                      50eef56fede2       Reachable   ActiveStore
95      10.10.10.100                                    eab56ef256a2       Stale       ActiveStore
95      10.10.10.101                                    000000000000       Unreachable ActiveStore
95      10.10.10.254                                    000000000000       Unreachable ActiveStore

PS [www.matthewkerfoot.com]>

Monday, November 11, 2013

Open an .HTML file with PowerShell

Have you ever wanted to open a .HTML file with PowerShell, either in a script or just because you were already in a PS console? There is actually a really easy way to do this in your default browser via PowerShell. The cmdlet "Invoke-Expression" will run the any command or expression.

Lets take a look at Invoke-Expression's help file by running the command help Invoke-Expression -full I prefer to run the cmdlet Help instead of the full cmdlet Get-Help because help will only show you a page at a time, so by default typing help is the equivalent to Get-Help command | more
PS [www.matthewkerfoot.com]> help Invoke-Expression -full

NAME
    Invoke-Expression

SYNOPSIS
    Runs commands or expressions on the local computer.

SYNTAX
    Invoke-Expression [-Command]  []


DESCRIPTION
    The Invoke-Expression cmdlet evaluates or runs a specified string as a command and returns the results of the
    expression or command. Without Invoke-Expression, a string submitted at the command line would be returned
    (echoed) unchanged.


PARAMETERS
    -Command 
        Specifies the command or expression to run. Type the command or expression or enter a variable that
        contains the command or expression. The Command parameter is required.
In order to open an .HTML file from PowerShell you must first know the location of the file, then simply type, "Invoke-Expression .\filename.html"
PS [www.matthewkerfoot.com]> Invoke-Expression C:\Users\mkerfoot\Desktop\HTML_report.html
Invoke-Expression can also be used to open an image or any filepath applicable.
PS [www.matthewkerfoot.com]> Invoke-Expression C:\Users\mkerfoot\Desktop\Icon.PNG
The Following command will open up the file I specified in your default browser.


Wednesday, October 30, 2013

Find amount of time since Windows started

Whether you need to find out the time since a computer was turned on for ticketing purposes, just out of curiosity or to show off how long your server has been online to a friend, you have come to the right place. Here is a PowerShell function to find out how many Days, Hours, and Minutes since the machine was started.

Copy the below code into a PowerShell window.
<#
.CREATED BY:
    Chris Davis
.MODIFIED BY:
    Matthew A. Kerfoot
.MODIFIED ON:
    10\30\2013
.Synopsis
   Outputs how long since the last reboot
.DESCRIPTION
    This function gathers information regarding when $ComputeName was last rebooted. `
.EXAMPLE
   Get-Uptime localhost | ConvertTo-Html | Out-File C:\
   Referance - http://pc-addicts.com/my-powershell-scripts/
#>

function Get-Uptime { [CmdletBinding()]

param ( [Parameter(Mandatory=$false,
                   ValueFromPipelineByPropertyName=$true,
                   Position=0)]
           [string]$ComputerName = "$env:COMPUTERNAME" )

Begin { $OS = Get-WmiObject -Class Win32_OperatingSystem -ComputerName $Computername
        $diff = $OS.ConvertToDateTime($OS.LocalDateTime) - $OS.ConvertToDateTime($OS.LastBootUpTime) }

Process { foreach ( $_ in $ComputerName ){ 
                   @{ "ComputerName" = $Computername
                      "Days" = $diff.Days
                      "Hours" = $diff.Hours
                      "Minutes" = $diff.Minutes } } }

End { New-Object -TypeName PSObject -Property $properties | Format-Table -AutoSize }}

Once the above code is pasted into a PowerShell prompt hit enter a couple times and type, 'Get-Uptime'.
[www.matthewkerfoot.com]> Get-Uptime
Name                           Value
----                           -----
Hours                          5
Days                           0
ComputerName                   VT-MKERFOOT-W8
Minutes                        52

PS [www.matthewkerfoot.com]>