Thursday, October 9, 2014

Update Existing PST file path for Users

Replaced an aging file server, and ran into the issue of Terminal Services users not being able to load their Outlook pst data files. After much surfing, searching, and a call to Microsoft, I still had nothing. Thanks to a co-worker and mucho caffeine, we finally located the reg keys (in binary) that stored the pst location.

The script below is tested against Outlook 2010, but has been successful in my testing. Set the $oldpath and $newpath to fit your environment. Test it against a few accounts before deploying. I take no responsibility for the use of this in any org. :D

$encodingType = [Text.Encoding]::Default.HeaderName
$oldPath = "" #Old fileserver/path name here
$newPath = "" #New fileserver/path name here


function bin2string{
    Param(
        $thispath, #Path to the Key
        [string]$thisProperty #Name of the property (typically in HEX)
    )
    $binary = Get-ItemProperty -path $thisPath.pspath | select -expand $thisProperty
    $string = [Text.Encoding]::GetEncoding($encodingType).GetString( $binary )
    return $string
}

function string2bin{
    param(
        [string]$thisString
    )
    $newBinary = [Text.Encoding]::GetEncoding($encodingType).GetBytes( $thisString )
    return $newBinary
}


set-location "HKCU:\Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles\Default Outlook Profile"
$path = get-location


$keys = get-childitem $path

foreach($key in $keys){
    #write-host $key -ForegroundColor DarkCyan
    $properties = get-itemproperty -path $key.pspath
    #$properties | where {$_ -match "01020fff"}
    if (($properties | where {$_ -match "01020fff"}).count -ne 0 -AND ($properties | where {$_ -match "001f3006"}).count -ne 0){
        #Make sure this is an Outlook Data File Key
        if ((bin2string $key "001f3006") -match "O\WU\WT\WL\WO\WO\WK\W+D\WA\WT\WA\W+F\WI\WL\WE"){
            Write-Host "Found $(bin2string $key "001f3006") in $Key" -ForegroundColor Yellow

            #Get string from Property 01020fff, the functional Path property
            $nowString = bin2string $key "01020fff"
            #Fix string in Property 01020fff, the functional Path property
            $nowString = $nowString -replace $oldPath,$newPath
            #Convert Fixed String Back into Binary
            $newBinary = string2bin $nowString
            #Set the Bin as the Value of Property 01020fff, the functional Path property
            Set-ItemProperty -path $key.pspath  -name "01020fff" -value $newBinary

            #Get string from Property 001f6700
            $nowString2 = bin2string $key "001f6700"
            $nowString2
            #Fix string in Property 001f6700
            $nowString2 = $nowString2 -replace ($oldPath.ToCharArray() -join "\W"),($newPath.ToCharArray() -join " ")
            $nowString2
            #Convert Fixed String Back into Binary
            $newBinary2 = string2bin $nowString2
            #Set the Bin as the Value of Property 001f6700
            Set-ItemProperty -path $key.pspath  -name "001f6700" -value $newBinary2

            }
        }
    }

Wednesday, October 1, 2014

Updating Shortcuts for a File Server replacement

When retiring an older File Server, one has to account for the many possible uses and references to the old file server name. Shortcuts is one that can be addressed via Powershell. The following script finds all shortcuts that have the $from server, and update the references to point to the $to server (these are set in the script beforehand). The only catch is that I didn't build in long file name support, so if you have paths over 255 characters, some additions will be required.
<# 
 .NOTES
 ===========================================================================
  Author: Jared Shippy
  Created: 09/19/2014
 ===========================================================================
 .DESCRIPTION
  Script for updating shortcuts for new file server location
 .PARAMETER Path
  Path to target folder.
 .PARAMETER Recurse
  Updates shortcuts through subfolders if used.
 .PARAMETER Whatif
  Writes no changes, displays files that would be affected.
 .EXAMPLE
  # See which shortcuts would be affected in c:\testFolder (subfolders included)
  lnkUpdate -path c:\testFolder -recurse -whatif
 .EXAMPLE
  # Make the perform the change in c:\testfolder ONLY (no subfolders)
  lnkUpdate -path c:\testfolder
#>

param (
 # Path to root of Targeted Folder
 [Parameter(Mandatory=$true)]
 [string]$path,
 # Perform Recursive?
 [switch]$recurse,
 # Does nothing, shows what it *would* do
 [switch]$whatif
)

# Initialization Variables
$shell = New-Object -ComObject wscript.shell
$from = "oldServer" #The name of the old file server
$to = "newServer" #The name of the new file server

# Targeting Logic - To recurse or not recurse
$lnkFiles = $null
if ($recurse -eq $true)
 {
  $lnkFiles = Get-ChildItem -Recurse (Join-Path $path \*.lnk)
 }
 else
 {
  $lnkFiles = Get-ChildItem (Join-Path $path \*.lnk)
}
foreach ($file in $lnkFiles)
{
 
 if (($shell.createShortcut($file.fullname)).targetPath -match "$from" -or ($shell.createShortcut($file.fullname)).workingdirectory -match "$from" -or ($shell.createShortcut($file.fullname)).arguements -match "$from")
 
 {
  Write-Host "Match on $($file.fullname)" -ForegroundColor 'DarkCyan'
  if ($whatif -eq $true)
  {
   Write-Host "WHATIF: WOULD replace path here"
  }
  else
  {
   $fixThis = $shell.createShortcut($file.fullname)
   $fixThis.targetPath = $fixThis.targetPath -replace "$from", "$to"
   $fixThis.workingDirectory = $fixThis.workingDirectory -replace "$from", "$to"
   $fixThis.arguments = $fixThis.arguments -replace "$from", "$to"
   $fixThis.Save()
  }
  
 }
}



# check and update links
foreach ($shortcut in $shortcuts)
{
 # Find the correct property for the next line:
 If ($shortcut.property -match "$from")
 {
  $shortcut.property -replace "$from", "$to"
 }
 else
 {
  Write-Host "No $from in this Shortcut" -ForegroundColor Green
  
 }
}