Powershell: Script to set Outlook 2010/2013 signature using information populated from Active Directory

Powershell Logo<

The other week I needed a script to set an Outlook signature on all machines in the environment. I had a look around, and found some old VBScript solutions, but also a few using Powershell.
The only script that came close to my needs was the one provided by Jan Egil: http://gallery.technet.microsoft.com/office/6f7eee4b-1f42-499e-ae59-1aceb26100de, but it returned quite a few errors, was missing some functions I needed, but also had other functions, that was not needed in my case.

This script will gather information from AD and automatically populate the fields in the signature.

Here is my script, and thanks again to Jan Egil for providing the original functionality :)

Download: set_outlook_signature_1_0.zip

Script to set Outlook signature for Outlook 2010 or Outlook 2013
Script to set Outlook signature as either available or forced. Tested on Office 2010/2013 for Windows 7/8/8.1. Provided AS IS with no warranty.
This script is a modified version of Jan Egil's script: http://gallery.technet.microsoft.com/office/6f7eee4b-1f42-499e-ae59-1aceb26100de
Some of the modifications made:
- Removed signature version stamp in registry
- Ability to set the signature version
- When setting the signature as available, the COM object is used and when forced, a registry change is applied
- Removed a lot of things removed that did not fulfill my needs
- A lot of other things that I don't remember :)
Author: Daniel Classon
Version: 1.0
1.0 2014-09-24 - First version released
1. Create a *.docx file
2. Edit the file so it looks the way you want the signature to look and edit text to correspond with the AD properties
further down in the script. For example the test "Title" corresponds to the AD property "title".
3. Edit the section #Custom variables 
4. Run the script
5. Done!
#Custom variables
$SignatureName = '' #Insert desired name of signature. This will name will appear in Outlook.
$SigSource = "" #Provide full path to the *.docx signature file
$SignatureVersion = "1.0" #Change this if you have updated the signature. If you do not change it, the script will quit after checking if signature is up to date.
$ForceSignature = '0' #If set to '0', the signature will be editable in Outlook and if set to '1' will be non-editable and forced.
$DefaultAddress = ''
$DefaultCity = ''
$DefaultTelephone = ''
#Environment variables
$AppData=(Get-Item env:appdata).value
$SigPath = '\Microsoft\Signaturer'
$LocalSignaturePath = $AppData+$SigPath
$RemoteSignaturePathFull = $SigSource
#Copy version file
If (!(Test-Path -Path $LocalSignaturePath\$SignatureVersion))
New-Item -Path $LocalSignaturePath\$SignatureVersion -Type Directory
Elseif (Test-Path -Path $LocalSignaturePath\$SignatureVersion)
Write-Output "Latest signature already exists"
#Check signature path (needs to be created if a signature has never been created for the profile
if (!(Test-Path -path $LocalSignaturePath)) {
	New-Item $LocalSignaturePath -Type Directory
#Get Active Directory information for current user
$UserName = $env:username
$Filter = "(&(objectCategory=User)(samAccountName=$UserName))"
$Searcher = New-Object System.DirectoryServices.DirectorySearcher
$Searcher.Filter = $Filter
$ADUserPath = $Searcher.FindOne()
$ADUser = $ADUserPath.GetDirectoryEntry()
$ADDisplayName = $ADUser.DisplayName
$ADEmailAddress = $ADUser.mail
$ADTitle = $ADUser.title
$ADDescription = $ADUser.description
$ADTelePhoneNumber = $ADUser.TelephoneNumber
$ADFax = $ADUser.facsimileTelephoneNumber
$ADMobile = $ADUser.mobile
$ADStreetAddress = $ADUser.streetaddress
$ADCity = $ADUser.l
$ADPOBox = $ADUser.postofficebox
$ADCustomAttribute1 = $ADUser.extensionAttribute1
$ADModify = $ADUser.whenChanged
#Copy signature templates from domain to local Signature-folder
Write-Output "Copying Signatures"
Copy-Item "$Sigsource" $LocalSignaturePath -Recurse -Force
$ReplaceAll = 2
$FindContinue = 1
$MatchCase = $False
$MatchWholeWord = $True
$MatchWildcards = $False
$MatchSoundsLike = $False
$MatchAllWordForms = $False
$Forward = $True
$Wrap = $FindContinue
$Format = $False
#Insert variables from Active Directory to rtf signature-file
$MSWord = New-Object -ComObject word.application
$fullPath = $LocalSignaturePath+'\'+$SignatureName+'.docx'
#User Name $ Designation 
$FindText = "DisplayName" 
$Designation = $ADCustomAttribute1.ToString() #designations in Exchange custom attribute 1
If ($Designation -ne '') { 
	$Name = $ADDisplayName.ToString()
	$ReplaceText = $Name+', '+$Designation
Else {
	$ReplaceText = $ADDisplayName.ToString() 
$MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord,	$MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap,	$Format, $ReplaceText, $ReplaceAll	)
$LogInfo += $NL+'Username: '+$ReplaceText	
$FindText = "Title"
$ReplaceText = $ADTitle.ToString()
$MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord,	$MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap,	$Format, $ReplaceText, $ReplaceAll	)
$LogInfo += $NL+'Title: '+$ReplaceText
If ($ADDescription -ne '') { 
   	$FindText = "Description"
   	$ReplaceText = $ADDescription.ToString()
Else {
	$FindText = " | Description "
   	$ReplaceText = "".ToString()
	$MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord,	$MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap,	$Format, $ReplaceText, $ReplaceAll	)
	$LogInfo += $NL+'Description: '+$ReplaceText
#Street Address
If ($ADStreetAddress -ne '') { 
    $FindText = "StreetAddress"
    $ReplaceText = $ADStreetAddress.ToString()
Else {
    $FindText = "StreetAddress"
    $ReplaceText = $DefaultAddress
	$MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord,	$MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap,	$Format, $ReplaceText, $ReplaceAll	)
	$LogInfo += $NL+'Street Address: '+$ReplaceText
If ($ADCity -ne '') { 
    $FindText = "City"
    $ReplaceText = $ADCity.ToString()
Else {
    $FindText = "City"
    $ReplaceText = $DefaultCity 
	$MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord,	$MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap,	$Format, $ReplaceText, $ReplaceAll	)
	$LogInfo += $NL+'City: '+$ReplaceText
If ($ADTelephoneNumber -ne "") { 
	$FindText = "TelephoneNumber"
	$ReplaceText = $ADTelephoneNumber.ToString()
Else {
    $FindText = "TelephoneNumber"
	$ReplaceText = $DefaultTelephone
	$MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord,	$MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap,	$Format, $ReplaceText, $ReplaceAll	)
	$LogInfo += $NL+'Telephone: '+$ReplaceText
If ($ADMobile -ne "") { 
	$FindText = "MobileNumber"
	$ReplaceText = $ADMobile.ToString()
Else {
	$FindText = "| Mob MobileNumber "
    $ReplaceText = "".ToString()
	$MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord,	$MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap,	$Format, $ReplaceText, $ReplaceAll	)
    $LogInfo += $NL+'MobileNumber: '+$ReplaceText
#Save new message signature 
Write-Output "Saving Signatures"
#Save HTML
$saveFormat = [Enum]::Parse([Microsoft.Office.Interop.Word.WdSaveFormat], "wdFormatHTML");
$path = $LocalSignaturePath+'\'+$SignatureName+".htm"
$MSWord.ActiveDocument.saveas([ref]$path, [ref]$saveFormat)
#Save RTF 
$saveFormat = [Enum]::Parse([Microsoft.Office.Interop.Word.WdSaveFormat], "wdFormatRTF");
$path = $LocalSignaturePath+'\'+$SignatureName+".rtf"
$MSWord.ActiveDocument.SaveAs([ref] $path, [ref]$saveFormat)
#Save TXT    
$saveFormat = [Enum]::Parse([Microsoft.Office.Interop.Word.WdSaveFormat], "wdFormatText");
$path = $LocalSignaturePath+'\'+$SignatureName+".txt"
$MSWord.ActiveDocument.SaveAs([ref] $path, [ref]$SaveFormat)
#Office 2010
If (Test-Path HKCU:'\Software\Microsoft\Office\14.0')
Write-Output "Setting signature for Office 2010"
    If (Get-ItemProperty -Name 'ReplySignature' -Path HKCU:'\Software\Microsoft\Office\14.0\Common\MailSettings' -ErrorAction SilentlyContinue) 
    Write-Output "Signature already exists"
    Else { 
    New-ItemProperty HKCU:'\Software\Microsoft\Office\14.0\Common\MailSettings' -Name 'ReplySignature' -Value $SignatureName -PropertyType 'String' -Force
    New-ItemProperty HKCU:'\Software\Microsoft\Office\14.0\Common\MailSettings' -Name 'NewSignature' -Value $SignatureName -PropertyType 'String' -Force
If ((Test-Path HKCU:'\Software\Microsoft\Office\14.0') -eq $False)
Write-Output "Office 2010 is not installed"
#Office 2013 
If (Test-Path HKCU:'\Software\Microsoft\Office\15.0')
Write-Output "Setting signature for Office 2013"
If ($ForceSignature -eq '0')
Write-Output "Setting signature for Office 2013 as available"
$Outlook = "Outlook"
if ($Outlook -ne $null)
Stop-Process -Name $Outlook -Force
$MSWord = New-Object -comobject word.application
$EmailOptions = $MSWord.EmailOptions
$EmailSignature = $EmailOptions.EmailSignature
$EmailSignatureEntries = $EmailSignature.EmailSignatureEntries
Stop-Process -Name $Outlook
If ($ForceSignature -eq '1')
Write-Output "Setting signature for Office 2013 as forced"
    If (Get-ItemProperty -Name 'NewSignature' -Path HKCU:'\Software\Microsoft\Office\15.0\Common\MailSettings' -ErrorAction SilentlyContinue) { } 
    Else { 
    New-ItemProperty HKCU:'\Software\Microsoft\Office\15.0\Common\MailSettings' -Name 'NewSignature' -Value $SignatureName -PropertyType 'String' -Force 
    If (Get-ItemProperty -Name 'ReplySignature' -Path HKCU:'\Software\Microsoft\Office\15.0\Common\MailSettings' -ErrorAction SilentlyContinue) { } 
    Else { 
    New-ItemProperty HKCU:'\Software\Microsoft\Office\15.0\Common\MailSettings' -Name 'ReplySignature' -Value $SignatureName -PropertyType 'String' -Force
If ((Test-Path HKCU:'\Software\Microsoft\Office\15.0') -eq $False)
Write-Output "Office 2013 is not installed"
Tagged with: , , , , ,
Posted in Blog, Microsoft, Microsoft Office, Powershell

Microsoft Best Practice guide for Task Sequences in Configuration Manager 2012 R2

System Center Configuration Manager

Download the guide in Word format here:


Tagged with: , , , , , , ,
Posted in Blog, Microsoft, OS Deployment, SCCM 2012

Guide: How to create an MDT 2013 Task Sequence template

If you are working with MDT, you are most likely creating new task sequences every now and then. When doing this, you might either create a new task sequence from scratch or maybe you are copying another task sequence.
I have run in to numerous issues with copying task sequences in MDT, so what I do is that I create a template instead, that has all the basic steps that I want there.

Creating a template in MDT is very simple:

1. Create a task sequence that you will use as a template.

2. Browse to your deployment share and locate the Control folder.

3. In the Control folder there should be a subfolder with the name of the task sequence

4. In The subfolder, there should be a file called ts.xml, which is the task sequence

How to create an MDT 2013 Task Sequence template

5. Copy the ts.xml and rename it to ts_template.xml or similar:

Copy Task Sequence template MDT 2013

6. Go to the installation folder for MDT, typically C:\Program Files\Microsoft Deployment Toolkit and go to the folder called “Templates”.

7. Paste the ts_template.xml here:

Copy task sequence template MDT 2013

8. Open up the ts_template.xml in notepad and edit the top row, with a suitable name and description for your task sequence template:

Edit Task Sequence template MDT 2013

9. Open Deployment Workbench, and create a new Task Sequence:

New Task Sequence MDT 2013

10. Give your new Task Sequence a name:

Task Sequence name MDT 2013

11. Select your newly created Task Sequence template :)

Select Task Sequence template MDT 2013

Tagged with: , , , , , , , ,
Posted in Blog, Guides, MDT 2012, MDT 2013, MDT 2013, SCCM 2007, SCCM 2007, SCCM 2012, SCCM 2012, System Center

How to force an SCCM 2012 client out of Provisioing Mode during OSD

The other day I had an issue at a customer, where the installations of new computers ran without any errors, but once logging in, it was obvious that everything was not right.
The reason why we noticed that something was wrong, was that all new computers that had been installed, were missing the SCEP client. Looking at the server side, everything looked fine, so it had to be something on the client side.

Issues that were present:
1. SCEP was not being installed
2. Fewer Actions than usually for the Configuration Manager client
3. There was no Client Certificate for the client

I’ve seen this before with SCCM 2007, and then the problem was the client was still in Provisioning Mode.
Provisioning Mode is a mode that the client is in during OSD, which blocks policies from being applied during the installation. Once the task sequence is complete, the client should have been brought out of this mode, and get its policies correctly.
One easy way to check this is opening the Registry Editor and checking this value:


Regedit Provisioing mode SCCM 2012 client

Sure enough, the client was still in Provisioning Mode.

So, how should we solve this?

One way is to change the value in the registry and then reinstall the client, but since this happens on almost all new installations, this would be some seriously tedious work.

The easiest solution is to add these two registry changes as seperate command line steps in your Task Sequence after the “Setup Windows and ConfigMgr” step:

REG ADD HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\CCM\CcmExec /v ProvisioningMode /t REG_SZ /d false /f
REG ADD HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\CCM\CcmExec /v SystemTaskExcludes /t REG_SZ /d “” /f

Force SCCM 2012 client out of Provisioning Mode Task Sequence

Do a new installation now and it should work!

Note: This does not actually solve the underlying issue why the client is still left in Provisioning Mode. It does however get your deployment solution up and running again.

Tagged with: , , , , , , , , , , ,
Posted in Blog, Guides, Microsoft, OS Deployment, SCCM 2007, SCCM 2007, SCCM 2012, SCCM 2012, System Center

New OS Deployment resources on TechNet

TechNet has put together a collection of new resources for those interested in OS deployment.

Some of the topics that are covered:

– Creating an image with MDT 2013
– Deploying Windows 8.1 with MDT 2013
– Deploying Windows 8.1 with MDT 2013 and Configuration Manager 2012 R2
– Deploying Windows to Go
– Making additional customizations with Windows ADK

Here is the link:

Tagged with: , , , , , , , ,
Posted in Blog, MDT 2013, Microsoft, OS Deployment, SCCM 2012, System Center, Windows 8.1

Location of CMTrace after installation of Configuration Manager 2012

System Center Configuration Manager

CMTrace, as most of you know is a great log viewer to use for viewing your SCCM logs in real time.

I did a previous blog post on where to find CMTrace during OSD, but where is it located on the Configuration Manager 2012 server?

It is located here:

“CM12 installation dir”\tools

Tagged with: , , , , , , ,
Posted in Blog, Microsoft, SCCM 2012, System Center

Guide: Updating Flash Player using Powershell App Deployment Toolkit and SCCM 2007

Powershell App Deployment Toolkit

This guide assumes that Internet Explorer is the only browser being used in your organization.

1. Download the Powershell App Deployment Toolkit here:

2. Use this template for Deploy-Application.ps1:

    This script performs the installation or uninstallation of an application(s).  
    The script is provided as a template to perform an install or uninstall of an application(s). 
    The script either performs an "Install" deployment type or an "Uninstall" deployment type.
    The install deployment type is broken down in to 3 main sections/phases: Pre-Install, Install, and Post-Install.
    The script dot-sources the AppDeployToolkitMain.ps1 script which contains the logic and functions required to install or uninstall an application.
    To access the help section,
    Deploy-Application.ps1 -DeploymentType "Silent"
    Deploy-Application.ps1 -AllowRebootPassThru -AllowDefer
    Deploy-Application.ps1 -Uninstall 
.PARAMETER DeploymentType
    The type of deployment to perform. [Default is "Install"]
    Specifies whether the installation should be run in Interactive, Silent or NonInteractive mode.
    Interactive = Default mode
    Silent = No dialogs
    NonInteractive = Very silent, i.e. no blocking apps. Noninteractive mode is automatically set if an SCCM task sequence or session 0 is detected.
.PARAMETER AllowRebootPassThru
    Allows the 3010 return code (requires restart) to be passed back to the parent process (e.g. SCCM) if detected from an installation. 
    If 3010 is passed back to SCCM a reboot prompt will be triggered.
Param (
    [string] $DeploymentType = "Install",
    [string] $DeployMode = "Interactive",
    [switch] $AllowRebootPassThru = $false
Try {
# Variables: Application
$appVendor = "Adobe"
$appName = "Flash Player"
$appVersion = ""
$appArch = ""
$appLang = "EN"
$appRevision = "01"
$appScriptVersion = "1.0.1"
$appScriptDate = "02/28/2014"
$appScriptAuthor = "Daniel Classon"
# Variables: Script - Do not modify this section
$deployAppScriptFriendlyName = "Deploy Application"
$deployAppScriptVersion = "3.0.7"
$deployAppScriptDate = "10/24/2013"
$deployAppScriptParameters = $psBoundParameters
# Variables: Environment
$scriptDirectory = Split-Path -Parent $MyInvocation.MyCommand.Definition
# Dot source the App Deploy Toolkit Functions
If ($deploymentType -ne "uninstall") { $installPhase = "Pre-Installation"
    # Show Welcome Message, close Internet Explorer if required, allow up to 3 deferrals, verify there is enough disk space to complete the install and persist the prompt
    Show-InstallationWelcome -CloseApps "iexplore" -AllowDefer -DeferTimes 3 -CheckDiskSpace -PersistPrompt
    # Show Progress Message (with the default message)
    # Perform pre-installation tasks here
    # Uninstall Previous versions of Adobe Flash Player
    Remove-MSIApplications "Adobe Flash Player"
$installPhase = "Installation"
    # Get the Internet Explorer version
    $ieVersion = Get-Item "HKLM:Software\Microsoft\Internet Explorer" -ErrorAction SilentlyContinue | Get-ItemProperty | Select "svcVersion" -ExpandProperty "svcVersion"
    $ieSubstringPos = $ieVersion.IndexOf(".")
    [int]$ieShortVersion = $ieVersion.Substring(0, $ieSubstringPos)
    # Install Flash Player ActiveX Control for IE versions prior to IE10 
    If ($ieShortVersion -lt 10) { 
        Execute-MSI -Action Install -Path "install_flash_player_12_active_x.msi"
    # Set Adobe Flash Config file to stop Auto-Updates (32-bit)
    Copy-File -Path "$dirSupportFiles\mms.cfg" -Destination "$envWindir\system32\Macromed\Flash\mms.cfg"
    # Set Adobe Flash Config file to stop Auto-Updates (64-bit)
    Copy-File -Path "$dirSupportFiles\mms.cfg" -Destination "$envWindir\SysWOW64\Macromed\Flash\mms.cfg"
$installPhase = "Post-Installation"
    # Perform post-installation tasks here
    # Display a message at the end of the install
    # Show-InstallationPrompt -Message "You can customise text to appear at the end of an install, or remove it completely for unattended installations." -ButtonRightText "Ok" -Icon Information -NoWait
} ElseIf ($deploymentType -eq "uninstall") { $installPhase = "Uninstallation"
    # Show Welcome Message, close Internet Explorer if required with a 60 second countdown before automatically closing
    Show-InstallationWelcome -CloseApps "iexplore" 
    # -CloseAppsCountdown "60"
    # Show Progress Message (with the default message)
    # Perform uninstallation tasks here
    # Uninstall Flash Player Plug-in for Active-X (IE) Browsers
    Execute-MSI -Action Uninstall -Path "{A10EE46B-C2E8-4FAB-A8F8-3E80D0662BA9}"
} } Catch {$exceptionMessage = "$($_.Exception.Message) `($($_.ScriptStackTrace)`)"; Write-Log "$exceptionMessage"; Show-DialogBox -Text $exceptionMessage -Icon "Stop"; Exit-Script -ExitCode 1} # Catch any errors in this script 
Exit-Script -ExitCode 0 # Otherwise call the Exit-Script function to perform final cleanup operations

3. If you want to turn off Automatic Updates, create a file called “mms.cfg” containing this:


Place it in the folder “SupportFiles”

4. Continue from step 3 in the previous guide I wrote about Updating Java using Powershell App Deployment Toolkit
5. Done!

Tagged with: , , , ,
Posted in Blog, Guides, Microsoft, Powershell, Powershell, SCCM 2007, SCCM 2007, Windows 7, Windows 8, Windows 8, Windows 8.1, Windows 8.1

Powershell: How to read contents from all text files in a directory and add them to a single text file

Powershell Logo
Here’s a short Powershell tip that can be useful. If you have a directory with text files and want to add the content to a single text file, you can use this command:

Get-Content "directory path"\*.txt -Force | Set-Content "directory path"\results.txt
Tagged with: , , , , , , ,
Posted in Blog, Guides, Microsoft, Powershell, Powershell

Powershell: Script to add users from a text file to an Active Directory group using alternate credentials

Here is a short script which you can use to add users to an Active Directory Group. Just add a list of users in a text file, in this case called “users.txt”. Run the script and enter the credentials that has the appropriate permissions. Replace “Test_Group” with the group that you want to add the users to.

A tip is to add the -WhatIf statement after “Add-ADGroupMember -Credential $cred -Identity Test_Group -Member $_”, just to make sure that the script does what you want it do, before putting it in production. So, like this:

Add-ADGroupMember -Credential $cred -Identity Test_Group -Member $_ -WhatIf

Import-module ActiveDirectory 
$cred = Get-Credential
Get-Content ".\users.txt" | % { 
Add-ADGroupMember -Credential $cred -Identity Test_Group -Member $_
Tagged with: , , , ,
Posted in Active Directory, Blog, Microsoft, Powershell

System Center Configuration Manager 2012 and Windows Server 2012 Data Deduplication

System Center Configuration Manager

Deduplication is one of the coolest features in Windows Server 2012. The System Center Configuration Manager Team just posted a blog post on how you can use it to save space on your Configuration Manager 2012 Distribution Points.

Very interesting! Read about it here:


Tagged with: , , , , ,
Posted in Blog, Microsoft, SCCM 2012, Windows Server 2012, Windows Server 2012 R2
Daniel Classon