Outlook signature based on user information from Active Directory

To provide a consistent company image all users should use the same signature template in their Outlook profile. Ive created a Windows PowerShell-script to deploy a consistent Outlook signature to users, based on user information retrieved from Active Directory. Ive used the fields “Display name”, “Title, “E-mail” and “Telephone number”, however, additional fields may be added to suit your needs.

 

Step-by-step

1) Download the script from here. Save it to a UNC-path accessible for all users.

2) Adjust the custom variables:

image

3) From an Outlook client, create a signature based on your company template:

image

4) Copy the signature files from %appdata%MicrosoftSignatures to the UNC-path specified in the SigSource-variable in the script:

 

image

 

5) Open both Company Name.rtf and Company Name.htm in Microsoft Office Word and insert the following bookmarks:

image

Mark each word, e.g. “EmailAddress”, go to “Insert”, press the “Bookmark”-button and name the bookmark “EmailAddress”. It`s important that the names of the bookmarks are “DisplayName”, “Title”, “TelephoneNumber” and “EmailAddress”.
This is because these bookmarks are replaced by the information retrieved from Active Directory for the logged-on user.

6) When appropriately tested, deploy the script to end users. This may be accomplished by e.g. Group Policy:

image

 

Additional information

Sample signature created using Set-OutlookSignature.ps1:

image

Active Directory object for sample user:

image image

 

Settings are stored in HKCU in the registry:

image

A few notes:
-Existing signatures are preserved
-Users are allowed to make customizations to their signatures until a new version are deployed. Then the exisiting company-signature will be overwritten.

 

Update 21.11.2010: The script are improved by Darren Kattan. For details and updated instructions, see this blog-post.

56 thoughts on “Outlook signature based on user information from Active Directory

  1. Hi
    I’m evaluating this script but I find an error in following this. Can anyone confirm if the script is correct this way:

    #Stamp registry-values for Outlook Signature Settings if they doesnt match the initial script variables. Note that these will apply after the second script run when changes are made in the

    "Custom variables"-section.
    if ($ForcedSignatureNew -eq $ForceSignatureNew){}

    I make the following change and no longer showed me the error, but still not working:

    #Stamp registry-values for Outlook Signature Settings if they doesnt match the initial script variables. Note that these will apply after the second script run when changes are made in the “Custom variables”-section.
    if ($ForcedSignatureNew -eq $ForceSignatureNew){}

    Tks.

  2. I have rolled this script out in my office, it’s installed no problems on about 20 machines, but i have 7 that produce the following error:
    format-default : Error HRESULT E_FAIL has been returned from a call to a COM component.

    I assume this is an error when trying to open up Microsoft Word?

    There is no pattern as to what version of Windows and Office they are running, some use Vista Business with either Office 2003 or 2007, some use XP Pro with either Office 2003 or 2007.

    Have you encountered this problem before?

    • Hi there, i noticed some changes that needed to be made.
      1. The LDAP Names (pay attention to these as they might not bring back the required fields from AD)
      2. The error that you’re getting is probably because you have tried to run the script more than 2 times without chaing the version number.
      3. Just make sure all your Syntax is correct..

      Let me know if any of this helps or i’m just wasting ur time 😉

      • Hi there, I am not completely sure on what the problem was, but i downloaded a newer version of PowerShell for these machines and it now all works flawlessly.
        Thanks for getting back to me.

  3. Hi,

    Great script. Just having problems running. It gave me an error when I ran it through PowerShell,
    You must provide a value expression on the right-hand side of the ‘-‘ operator.
    At :line:140 char:20
    + “Custom variables”-s <<<< ection.

    I have edit the Custom Variables but still no good.

    thanks

  4. Hey Guys,

    I experiences a lot of the same problems as you with this script.

    I changed it considerably for the better:
    1. No need to use bookmarks. Just the words DisplayName, Title, and Email will be caught by a find and replace
    2. The Email address is generated as a link
    3. No need to copy and paste a ton of files from your local directory and then make identical changes to multiple files
    4. No need to create arbitrary version numbers. In my version it compares the last modified date of your .docx file to the last one that it copied from the server (date is stored in registry on successful import into Outlook). This prevents the script from running at every boot. It will only run fully when a change has been made.

    ###########################################################################”
    #
    # NAME: Set-OutlookSignature.ps1
    #
    # AUTHOR: Jan Egil Ring
    # Modifications by Darren Kattan
    #
    # COMMENT: Script to create an Outlook signature based on user information from Active Directory.
    # Adjust the variables in the “Custom variables”-section
    # Create an Outlook-signature from Microsoft Word (logo, fonts etc) and copy this signature to \domainNETLOGONsig_files$CompanyName$CompanyName.docx
    # This script supports the following keywords:
    # DisplayName
    # Title
    # Email
    # See the following blog-post for more information: http://blog.crayon.no/blogs/janegil/archive/2010/01/09/outlook-signature-based-on-user-information-from-active-directory.aspx
    #
    # Tested on Office 2003,2007 and 2010
    #
    # You have a royalty-free right to use, modify, reproduce, and
    # distribute this script file in any way you find useful, provided that
    # you agree that the creator, owner above has no warranty, obligations,
    # or liability for such use.
    #
    # VERSION HISTORY:
    # 1.0 09.01.2010 – Initial release
    # 1.1 11.09.2010 – Modified by Darren Kattan
    # – Removed bookmarks. Now uses simple find and replace for DisplayName, Title, and Email.
    # – Email address is generated as a link
    # – Signature is generated from a single .docx file
    # – Removed version numbers for script to run. Script runs at boot up when it sees a change in the “Date Modified” property of your signature template.
    #
    #
    ###########################################################################”

    #Custom variables
    $CompanyName = ‘Immense Networks’
    $DomainName = ‘IN.local’

    $SigSource = “\$DomainNamenetlogonsig_files$CompanyName”
    $ForceSignatureNew = ‘1’ #When the signature are forced the signature are enforced as default signature for new messages the next time the script runs. 0 = no force, 1 = force
    $ForceSignatureReplyForward = ‘1’ #When the signature are forced the signature are enforced as default signature for reply/forward messages the next time the script runs. 0 = no force, 1 = force

    #Environment variables
    $AppData=(Get-Item env:appdata).value
    $SigPath = ‘MicrosoftSignatures’
    $LocalSignaturePath = $AppData+$SigPath
    $RemoteSignaturePathFull = $SigSource+”+$CompanyName+’.docx’

    #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
    $ADTelePhoneNumber = $ADUser.TelephoneNumber

    #Setting registry information for the current user
    $CompanyRegPath = “HKCU:Software”+$CompanyName

    if (Test-Path $CompanyRegPath)
    {}
    else
    {New-Item -path “HKCU:Software” -name $CompanyName}

    if (Test-Path $CompanyRegPath’Outlook Signature Settings’)
    {}
    else
    {New-Item -path $CompanyRegPath -name “Outlook Signature Settings”}

    $SigVersion = (gci $RemoteSignaturePathFull).LastWriteTime #When was the last time the signature was written
    $ForcedSignatureNew = (Get-ItemProperty $CompanyRegPath’Outlook Signature Settings’).ForcedSignatureNew
    $ForcedSignatureReplyForward = (Get-ItemProperty $CompanyRegPath’Outlook Signature Settings’).ForcedSignatureReplyForward
    $SignatureVersion = (Get-ItemProperty $CompanyRegPath’Outlook Signature Settings’).SignatureVersion
    Set-ItemProperty $CompanyRegPath’Outlook Signature Settings’ -name SignatureSourceFiles -Value $SigSource
    $SignatureSourceFiles = (Get-ItemProperty $CompanyRegPath’Outlook Signature Settings’).SignatureSourceFiles

    #Forcing signature for new messages if enabled
    if ($ForcedSignatureNew -eq ‘1’)
    {
    #Set company signature as default for New messages
    $MSWord = New-Object -com word.application
    $EmailOptions = $MSWord.EmailOptions
    $EmailSignature = $EmailOptions.EmailSignature
    $EmailSignatureEntries = $EmailSignature.EmailSignatureEntries
    $EmailSignature.NewMessageSignature=$CompanyName
    $MSWord.Quit()
    }

    #Forcing signature for reply/forward messages if enabled
    if ($ForcedSignatureReplyForward -eq ‘1’)
    {
    #Set company signature as default for Reply/Forward messages
    $MSWord = New-Object -com word.application
    $EmailOptions = $MSWord.EmailOptions
    $EmailSignature = $EmailOptions.EmailSignature
    $EmailSignatureEntries = $EmailSignature.EmailSignatureEntries
    $EmailSignature.ReplyMessageSignature=$CompanyName
    $MSWord.Quit()
    }

    #Copying signature sourcefiles and creating signature if signature-version are different from local version
    if ($SignatureVersion -eq $SigVersion){}
    else
    {
    #Copy signature templates from domain to local Signature-folder
    Copy-Item “$SignatureSourceFiles*” $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 -com word.application
    $fullPath = $LocalSignaturePath+”+$CompanyName+’.docx’
    $MSWord.Documents.Open($fullPath)

    $FindText = “DisplayName”
    $ReplaceText = $ADDisplayName.ToString()
    $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord, $MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap, $Format, $ReplaceText, $ReplaceAll )

    $FindText = “Title”
    $ReplaceText = $ADTitle.ToString()
    $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord, $MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap, $Format, $ReplaceText, $ReplaceAll )

    $MSWord.Selection.Find.Execute(“Email”)

    $MSWord.ActiveDocument.Hyperlinks.Add($MSWord.Selection.Range, “mailto:”+$ADEmailAddress.ToString(), $missing, $missing, $ADEmailAddress.ToString())

    $MSWord.ActiveDocument.Save()
    $saveFormat = [Enum]::Parse([Microsoft.Office.Interop.Word.WdSaveFormat], “wdFormatHTML”);
    [ref]$BrowserLevel = “microsoft.office.interop.word.WdBrowserLevel” -as [type]

    $MSWord.ActiveDocument.WebOptions.OrganizeInFolder = $true
    $MSWord.ActiveDocument.WebOptions.UseLongFileNames = $true
    $MSWord.ActiveDocument.WebOptions.BrowserLevel = $BrowserLevel::wdBrowserLevelMicrosoftInternetExplorer6
    $path = $LocalSignaturePath+”+$CompanyName+”.htm”
    $MSWord.ActiveDocument.saveas([ref]$path, [ref]$saveFormat)

    $saveFormat = [Enum]::Parse([Microsoft.Office.Interop.Word.WdSaveFormat], “wdFormatRTF”);
    $path = $LocalSignaturePath+”+$CompanyName+”.rtf”
    $MSWord.ActiveDocument.SaveAs([ref] $path, [ref]$saveFormat)

    $saveFormat = [Enum]::Parse([Microsoft.Office.Interop.Word.WdSaveFormat], “wdFormatText”);
    $path = $LocalSignaturePath+”+$CompanyName+”.rtf”
    $MSWord.ActiveDocument.SaveAs([ref] $path, [ref]$saveFormat)

    $path = $LocalSignaturePath+”+$CompanyName+”.txt”
    $MSWord.ActiveDocument.SaveAs([ref] $path, [ref]$SaveFormat::wdFormatText)
    $MSWord.ActiveDocument.Close()

    $MSWord.Quit()

    }

    #Stamp registry-values for Outlook Signature Settings if they doesn`t match the initial script variables. Note that these will apply after the second script run when changes are made in the “Custom variables”-section.
    if ($ForcedSignatureNew -eq $ForceSignatureNew){}
    else
    {Set-ItemProperty $CompanyRegPath’Outlook Signature Settings’ -name ForcedSignatureNew -Value $ForceSignatureNew}

    if ($ForcedSignatureReplyForward -eq $ForceSignatureReplyForward){}
    else
    {Set-ItemProperty $CompanyRegPath’Outlook Signature Settings’ -name ForcedSignatureReplyForward -Value $ForceSignatureReplyForward}

    if ($SignatureVersion -eq $SigVersion){}
    else
    {Set-ItemProperty $CompanyRegPath’Outlook Signature Settings’ -name SignatureVersion -Value $SigVersion}

    All you do is create a single Company Name.docx file in your \domainNETLOGONsig_filesCompany Name directory

    Have this script run at logon and it will copy that file to the local user’s computer, perform the find a replace, then save as the 3 file types (HTML, RTF, and Text) automatically.

  5. Pingback: Deploying a Unified Email Signature Template in Outlook 2003/2007/2010 | Baton Rouge – Immense Networks

  6. Pingback: Outlook signature based on user information from Active Directory « .Insomnious

  7. Great script!! but I’m not there yet.. I receive the following error when execute the script on XP Pro SP3 with Office 2003:

    Unable to find type [Microsoft.Office.Interop.Word.WdSaveFormat]: make sure that the assembly containing this type is l
    oaded.
    At C:OutlookSignature2.ps1:141 char:74
    + $saveFormat = [Enum]::Parse([Microsoft.Office.Interop.Word.WdSaveFormat] <<<< , "wdFormatHTML");
    + CategoryInfo : InvalidOperation: (Microsoft.Offic…rd.WdSaveFormat:String) [], RuntimeException
    + FullyQualifiedErrorId : TypeNotFound

    It works flawless on Windows 7 with Office 2010. Hope you can help me!

    Remco

  8. Hello Jan,

    I’ve got it all working except one issue I hope you can help me with. In your script you use the following:
    $MSWord.Selection.Find.Execute(“Email”)

    $MSWord.ActiveDocument.Hyperlinks.Add($MSWord.Selection.Range, “mailto:”+$ADEmailAddress.ToString(), $missing, $missing, $ADEmailAddress.ToString())

    This works well. I added myself the following code:
    $MSWord.Selection.Find.Execute(“HomePage”)

    $MSWord.ActiveDocument.Hyperlinks.Add($MSWord.Selection.Range, “http://www.chasse.nl”, $missing, $missing, $ADwWWHomePage.ToString())

    This works well too provided I don’t use the 2 code’s in the same script, for some reason it joins the 2 links together. I think it has something to do with not clearing the range but so far found no solution.

    Do you have any?

    Thnx Remco

  9. When the script executes the line:

    $MSWord.Documents.Open($fullPath)

    Outlook.exe is also launched on my system (Windows 7 Pro, Office 2010). Anyone else experience this or know why that might be?

    • Hi – i have the same behaviour with outlook.exe, but it appears to start the process when

      “$EmailSignature.NewMessageSignature=$CompanyName” is executed.

      by the way, i have improved the script some more to include multiple signatures based on groups. Additionally, my version of the script will also re-sync on changes of user details, not just on changes of the template.Also added more AD details ( straightforward)
      Note that the group aspect will only work if executed under the user’s context as it uses the current security context to speed up group lookup. This also has the side-effect that only groups applicable at logon get taken into account. I use this as a logon script.

      Also note the last line which kicks the outlook process. This is a very dirty workaround but i cound’t get the process cleaned up propery by ReleaseComObject.

      This is the code:

      ###########################################################################”
      #
      # NAME: Set-OutlookSignature.ps1
      #
      # AUTHOR: Jan Egil Ring
      # Modifications by Darren Kattan
      #
      # COMMENT: Script to create an Outlook signature based on user information from Active Directory.
      # Adjust the variables in the “Custom variables”-section
      # Create an Outlook-signature from Microsoft Word (logo, fonts etc) and copy this signature to \domainNETLOGONsig_files$CompanyName$CompanyName.docx
      # This script supports the following keywords:
      # DisplayName
      # Title
      # Email
      # See the following blog-post for more information: http://blog.crayon.no/blogs/janegil/archive/2010/01/09/outlook-signature-based-on-user-information-from-active-directory.aspx
      #
      # Tested on Office 2003,2007 and 2010
      #
      # You have a royalty-free right to use, modify, reproduce, and
      # distribute this script file in any way you find useful, provided that
      # you agree that the creator, owner above has no warranty, obligations,
      # or liability for such use.
      #
      # VERSION HISTORY:
      # 1.0 09.01.2010 – Initial release
      # 1.1 11.09.2010 – Modified by Darren Kattan
      # – Removed bookmarks. Now uses simple find and replace for DisplayName, Title, and Email.
      # – Email address is generated as a link
      # – Signature is generated from a single .docx file
      # – Removed version numbers for script to run. Script runs at boot up when it sees a change in the “Date Modified” property of your signature template.
      # 1.11 11.15.2010 – Revised by Darren Kattan
      # – Fixed glitch with text signatures
      #
      #
      #####
      # Additional code by MAF for Sirl
      # Identified drawbacks: Will only re-create signature if the source file changes, not when user details change
      # Fixed: Now checks the registry for previousely synced values of display name, fax, mobile, phone, title, department and issues a re-sync if needed
      #
      # Problem: Will not perform right on new installations where the “sigantures” folder does not # exist yet
      # Fix: Explicit check and folder creation added
      #
      # Possible to-do’s : Add parameter to clean registry (force sig refresh)
      # Only set default sig if changed (Speedup?)
      ###########################################################################”
      #Custom variables

      $Companies = @(‘Sig1′,’Sig2′,’Sig3′,’Sig4′,’Sig5′)
      #Sig 1 will always be applied so the group field is empty
      $GrantingGroups = @(”,’GroupForSig2′,’GroupForSig3′,’GroupForSig4′,’GroupForSig5′)
      #A 1 sets the respective signature as standard for new mails.
      #Later Signatures overwrite previous ones
      $ForcedOnNew = @(1,1,0,1,0)
      #A 1 sets the respective signature as standard for replies.
      #Later Signatures overwrite previous ones
      $ForcedOnReply = @(1,1,0,1,0)

      $DomainName = ‘your.domain’

      #Environment variables
      $AppData=(Get-Item env:appdata).value
      $MSPath = $AppData+’Microsoft’
      $SigPath = ‘MicrosoftSignatures’
      $LocalSignaturePath = $AppData+$SigPath

      #took this out of technet – kindof doubles the lookup machnism but this gives a quick lookup mechanism for groups

      $CurrentUser = [System.Security.Principal.WindowsIdentity]::GetCurrent()
      $WindowsPrincipal = New-Object System.Security.Principal.WindowsPrincipal($CurrentUser)

      #Prerequisite: Check if Signatures Folder exists
      If(!(Test-Path $LocalSignaturePath))
      {
      New-Item -path $MsPath -name “Signatures” -itemType “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
      $ADDepartment = $ADUser.department
      $ADTelePhoneNumber = $ADUser.TelephoneNumber
      $ADFaxNumber = $ADUser.facsimileTelephoneNumber
      $ADMobileNumber = $ADUser.mobile

      #for loop from here

      for($i=0; $i -Lt $Companies.Count; ++$i)
      {
      #do we need to apply this?
      $Granting = $GrantingGroups[$i]

      if(($Granting -ne “”) -and !($WindowsPrincipal.IsInRole($Granting)))
      {
      #Write-Host $Companies[$i] not applicable
      continue
      }
      else
      {
      #Write-Host $Companies[$i] applies
      }

      #we use this to check if there is some need to update the signature
      #this may be a new template file or changed user information or a forced update by commandline
      $NeedToWriteSig = $False

      #Setting registry information for the current user
      $CompanyName = $Companies[$i]
      $ForceSignatureNew = $ForcedOnNew[$i]
      $ForceSignatureReplyForward = $ForcedOnReply[$i]
      $SigSource = “\$DomainNamenetlogonsig_files$CompanyName”
      $RemoteSignaturePathFull = $SigSource+”+$CompanyName+’.docx’
      $CompanyRegPath = “HKCU:Software”+$CompanyName

      if (Test-Path $CompanyRegPath)
      {}
      else
      {
      New-Item -path “HKCU:Software” -name $CompanyName
      }
      if (Test-Path $CompanyRegPath’Outlook Signature Settings’)
      {}
      else
      {
      New-Item -path $CompanyRegPath -name “Outlook Signature Settings”
      }

      $SigVersion = (gci $RemoteSignaturePathFull).LastWriteTime #When was the last time the signature was written
      $ForcedSignatureNew = (Get-ItemProperty $CompanyRegPath’Outlook Signature Settings’).ForcedSignatureNew
      $ForcedSignatureReplyForward = (Get-ItemProperty $CompanyRegPath’Outlook Signature Settings’).ForcedSignatureReplyForward

      $SignatureVersion = (Get-ItemProperty $CompanyRegPath’Outlook Signature Settings’).SignatureVersion

      Set-ItemProperty $CompanyRegPath’Outlook Signature Settings’ -name SignatureSourceFiles -Value $SigSource
      $SignatureSourceFiles = (Get-ItemProperty $CompanyRegPath’Outlook Signature Settings’).SignatureSourceFiles

      #Addition: Store current AD-Values to Registry to find out if we need to Re-Sync the Signature
      $StoredDisplayName = (Get-ItemProperty $CompanyRegPath’Outlook Signature Settings’).UserDisplayName
      if($ADDisplayName.ToString() -ne $StoredDisplayName)
      {
      Set-ItemProperty $CompanyRegPath’Outlook Signature Settings’ -name UserDisplayName -Value $ADDisplayName.ToString()
      $NeedToWriteSig = $True
      }
      $StoredEmailAddress = (Get-ItemProperty $CompanyRegPath’Outlook Signature Settings’).UserEmailAddress
      if($ADEmailAddress.ToString() -ne $StoredEmailAddress)
      {
      Set-ItemProperty $CompanyRegPath’Outlook Signature Settings’ -name UserEmailAddress -Value $ADEmailAddress.ToString()
      $NeedToWriteSig = $True
      }
      $StoredTitle= (Get-ItemProperty $CompanyRegPath’Outlook Signature Settings’).UserTitle
      if($ADTitle.ToString() -ne $StoredTitle)
      {
      Set-ItemProperty $CompanyRegPath’Outlook Signature Settings’ -name UserTitle -Value $ADTitle.ToString()
      $NeedToWriteSig = $True
      }
      $StoredDepartment = (Get-ItemProperty $CompanyRegPath’Outlook Signature Settings’).UserDepartment
      if($ADDepartment.ToString() -ne $StoredDepartment)
      {
      Set-ItemProperty $CompanyRegPath’Outlook Signature Settings’ -name UserDepartment -Value $ADDepartment.ToString()
      $NeedToWriteSig = $True
      }
      $StoredPhoneNumber = (Get-ItemProperty $CompanyRegPath’Outlook Signature Settings’).UserPhoneNumber
      if($ADTelePhoneNumber.ToString() -ne $StoredPhoneNumber)
      {
      Set-ItemProperty $CompanyRegPath’Outlook Signature Settings’ -name UserPhoneNumber -Value $ADTelePhoneNumber.ToString()
      $NeedToWriteSig = $True
      }
      $StoredFaxNumber = (Get-ItemProperty $CompanyRegPath’Outlook Signature Settings’).UserFaxNumber
      if($ADFaxNumber.ToString() -ne $StoredFaxNumber)
      {
      Set-ItemProperty $CompanyRegPath’Outlook Signature Settings’ -name UserFaxNumber -Value $ADFaxNumber.ToString()
      $NeedToWriteSig = $True
      }
      $StoredMobileNumber = (Get-ItemProperty $CompanyRegPath’Outlook Signature Settings’).UserMobileNumber
      if($ADMobileNumber.ToString() -ne $StoredMobileNumber)
      {
      Set-ItemProperty $CompanyRegPath’Outlook Signature Settings’ -name UserMobileNumber -Value $ADMobileNumber.ToString()
      $NeedToWriteSig = $True
      }
      #Addition ends

      #Forcing signature for new messages if enabled
      if (($ForceSignatureNew -eq ‘1’) -or ($ForceSignatureReplyForward -eq ‘1’))
      {
      #Set company signature as default for New messages
      $MSWord = New-Object -com word.application
      $EmailOptions = $MSWord.EmailOptions
      $EmailSignature = $EmailOptions.EmailSignature
      $EmailSignatureEntries = $EmailSignature.EmailSignatureEntries
      if($ForceSignatureNew -eq ‘1’) {$EmailSignature.NewMessageSignature=$CompanyName}
      if($ForceSignatureReplyForward -eq ‘1’) {$EmailSignature.ReplyMessageSignature=$CompanyName}
      $MSWord.Quit()
      #make sure the object is gone
      [System.Runtime.InteropServices.Marshal]::ReleaseComObject($EmailSignatureEntries)
      [System.Runtime.InteropServices.Marshal]::ReleaseComObject($EmailSignature)
      [System.Runtime.InteropServices.Marshal]::ReleaseComObject($EmailOptions)
      [System.Runtime.InteropServices.Marshal]::ReleaseComObject($MSWord)
      Remove-Variable MsWord
      }

      #Copying signature sourcefiles and creating signature if signature-version are different from local version
      if ($SignatureVersion -ne $SigVersion){$NeedToWriteSig = $True}

      #changed to accomodate more than just template change
      if ($NeedToWriteSig -eq $True)
      {
      Write-Host StartCopy
      #Copy signature templates from domain to local Signature-folder
      Copy-Item “$SignatureSourceFiles*” $LocalSignaturePath -Recurse -Force

      Write-Host EndCopy

      $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 -com word.application
      $fullPath = $LocalSignaturePath+”+$CompanyName+’.docx’
      $MSWord.Documents.Open($fullPath)
      $FindText = “adFullName”
      $ReplaceText = $ADDisplayName.ToString()
      $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord, $MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap, $Format, $ReplaceText, $ReplaceAll )
      $FindText = “adTitle”
      $ReplaceText = $ADTitle.ToString()
      $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord, $MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap, $Format, $ReplaceText, $ReplaceAll )
      $FindText = “adDepartment”
      $ReplaceText = $ADDepartment.ToString()
      $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord, $MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap, $Format, $ReplaceText, $ReplaceAll )
      $FindText = “adMobile”
      $ReplaceText = $ADMobileNumber.ToString()
      $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord, $MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap, $Format, $ReplaceText, $ReplaceAll )
      $FindText = “adFax”
      $ReplaceText = $ADFaxNumber.ToString()
      $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord, $MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap, $Format, $ReplaceText, $ReplaceAll )
      $FindText = “adPhone”
      $ReplaceText = $ADTelePhoneNumber.ToString()
      $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord, $MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap, $Format, $ReplaceText, $ReplaceAll )
      $MSWord.Selection.Find.Execute(“adEmail”)
      $MSWord.ActiveDocument.Hyperlinks.Add($MSWord.Selection.Range, “mailto:”+$ADEmailAddress.ToString(), $missing, $missing, $ADEmailAddress.ToString())
      $saveFormat = [Enum]::Parse([Microsoft.Office.Interop.Word.WdSaveFormat], “wdFormatHTML”);
      $path = $LocalSignaturePath+”+$CompanyName+”.htm”
      $MSWord.ActiveDocument.saveas([ref]$path, [ref]$saveFormat)
      $saveFormat = [Enum]::Parse([Microsoft.Office.Interop.Word.WdSaveFormat], “wdFormatRTF”);
      $path = $LocalSignaturePath+”+$CompanyName+”.rtf”
      $MSWord.ActiveDocument.SaveAs([ref] $path, [ref]$saveFormat)
      $saveFormat = [Enum]::Parse([Microsoft.Office.Interop.Word.WdSaveFormat], “wdFormatText”);
      $path = $LocalSignaturePath+”+$CompanyName+”.txt”
      $MSWord.ActiveDocument.SaveAs([ref] $path, [ref]$SaveFormat)
      $MSWord.ActiveDocument.Close()
      $MSWord.Quit()
      [System.Runtime.InteropServices.Marshal]::ReleaseComObject($MSWord)
      Remove-Variable MsWord
      }

      #Stamp registry-values for Outlook Signature Settings if they doesn`t match the initial script variables. Note that these will apply after the second script run when changes are made in the “Custom variables”-section.
      if ($ForcedSignatureNew -eq $ForceSignatureNew)
      {}
      else
      {
      Set-ItemProperty $CompanyRegPath’Outlook Signature Settings’ -name ForcedSignatureNew -Value $ForceSignatureNew
      }
      if ($ForcedSignatureReplyForward -eq $ForceSignatureReplyForward)
      {}
      else
      {
      Set-ItemProperty $CompanyRegPath’Outlook Signature Settings’ -name ForcedSignatureReplyForward -Value $ForceSignatureReplyForward
      }
      if ($SignatureVersion -eq $SigVersion)
      {}
      else
      {
      Set-ItemProperty $CompanyRegPath’Outlook Signature Settings’ -name SignatureVersion -Value $SigVersion
      }
      #This is not nice but needs to be done because the com-logic up there will most likely leave outlook running
      stop-process -Name outlook
      }

      • Excellent work :)

        I had also added the check for existence of the Signature directory and the line to kill Outlook at the end. You could vastly simplify the logic regarding changes to Active Directory by checking the $ADUser.whenChanged property;
        e.g. $ADModify = $ADUser.whenChanged [Source: http://gallery.technet.microsoft.com/ScriptCenter/6f7eee4b-1f42-499e-ae59-1aceb26100de/

        The issue I’m still having is Outlook launching. As you mentioned, the line

        “$EmailSignature.NewMessageSignature=$CompanyName”

        launches Outlook, as does

        $MSWord.Documents.Open($fullPath)

        Basically, it’s anything you try to do with Word after initializing the COM object ($MSWord = New-Object -com word.application). I’ve tested it with a simple script that opens a blank document and Outlook still launches.

        I’d really like to prevent Outlook from launching (or at least hide it), as this leads to confusion from the end user.

        Any experts on COM objects reading this? :)

      • Thanks for checking in Jan,

        $MSWord = New-Object -com word.application
        $MSWord.Visible = $False

        doesn’t affect things; Outlook still opens.

      • This outlook issue is really starting to become an issue for me as i have clients where the outlook kill command doesn’t seem to kill outlook so it keeps running in the background and the user can’t open a new instance before they kill the process via taskmanager.

  10. Here’s my simplified version (similar to Matthias’ but without the AD group stuff).

    Most importantly, it only needs to run once to make all changes. Subsequent runs are very quick in my testing.

    It also checks for changes to the signature template OR the Active Directory user (with less registry entries… it is controlled by the $ADVersion and $ADModify variables).

    [Admins need only change the four items under custom variables to suit their needs.]

    Still need to prevent the Outlook COM object launching…

    ###########################################################################”
    #
    # NAME: Set-OutlookSignature.ps1
    #
    # AUTHOR: Jan Egil Ring
    # Modifications by Darren Kattan
    #
    # COMMENT: Script to create an Outlook signature based on user information from Active Directory.
    # Adjust the variables in the “Custom variables”-section
    # Create an Outlook-signature from Microsoft Word (logo, fonts etc) and copy this signature to \domainNETLOGONsig_files$CompanyName$CompanyName.docx
    # This script supports the following keywords:
    # DisplayName
    # Title
    # Email
    # See the following blog-post for more information: http://blog.crayon.no/blogs/janegil/archive/2010/01/09/outlook-signature-based-on-user-information-from-active-directory.aspx
    #
    # Tested on Office 2003,2007 and 2010
    #
    # You have a royalty-free right to use, modify, reproduce, and
    # distribute this script file in any way you find useful, provided that
    # you agree that the creator, owner above has no warranty, obligations,
    # or liability for such use.
    #
    # VERSION HISTORY:
    # 1.0 09.01.2010 – Initial release
    # 1.1 11.09.2010 – Modified by Darren Kattan
    # – Removed bookmarks. Now uses simple find and replace for DisplayName, Title, and Email.
    # – Email address is generated as a link
    # – Signature is generated from a single .docx file
    # – Removed version numbers for script to run. Script runs at boot up when it sees a change in the “Date Modified” property of your signature template.
    # 1.11 11.15.2010 – Revised by Darren Kattan
    # – Fixed glitch with text signatures
    #
    #
    # 1.12 07.04.2011 – Modified by Philip Jeffrey
    # – revised script so that all settings are applied on first execution
    # – revised script to check for changes to the signature template OR the Active Directory user
    # – revised to include more Active Directory information fields
    # – added check for existence of Local Signature folder (explicit check and folder creation)
    # – added check for existence of registry values (explicit check and value creation, set to dummy value of 2 on first execution)
    #
    ###########################################################################”

    #Custom variables

    $CompanyName = ‘Immense Networks’
    $SigSource = “\domainNETLOGONsig_files$CompanyName”
    $ForceSignatureNew = ‘1’ #Enforce as default signature for new messages. (0 = no force, 1 = force)
    $ForceSignatureReplyForward = ‘1’ #Enforce as default signature for reply/forward messages. (0 = no force, 1 = force)

    #Environment variables

    $AppData=(Get-Item env:appdata).value
    $SigPath = ‘MicrosoftSignatures’
    $LocalSignaturePath = $AppData+$SigPath
    $RemoteSignaturePathFull = $SigSource+”+$CompanyName+’.docx’
    $SigVersion = (gci $RemoteSignaturePathFull).LastWriteTime #When was the last time the signature was written

    #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
    $ADDescription = $ADUser.description
    $ADTitle = $ADUser.title
    $ADCompany = $ADUser.Company
    $ADStreetAddress = $ADUser.StreetAddress
    $ADCity = $ADUser.l
    $ADState = $ADUser.st
    $ADZip = $ADUser.postalCode
    $ADTelephone = $ADUser.TelephoneNumber
    $ADFax = $ADUser.facsimiletelephonenumber
    $ADMobile = $ADUser.mobile
    $ADEmailAddress = $ADUser.mail
    $ADModify = $ADUser.whenChanged

    ###################################################################################################################

    #Set registry information for the current user

    $CompanyRegPath = “HKCU:Software”+$CompanyName

    if (Test-Path $CompanyRegPath)
    {}
    else
    {New-Item -path “HKCU:Software” -name $CompanyName}

    if (Test-Path $CompanyRegPath’Outlook Signature Settings’)
    {}
    else
    {New-Item -path $CompanyRegPath -name “Outlook Signature Settings”}

    if ((Get-ItemProperty $CompanyRegPath’Outlook Signature Settings’).SignatureVersion -eq $null)
    {
    Set-ItemProperty $CompanyRegPath’Outlook Signature Settings’ -name SignatureVersion -Value 2
    }

    if ((Get-ItemProperty $CompanyRegPath’Outlook Signature Settings’).ADVersion -eq $null)
    {
    Set-ItemProperty $CompanyRegPath’Outlook Signature Settings’ -name ADVersion -Value 2
    }

    if ((Get-ItemProperty $CompanyRegPath’Outlook Signature Settings’).ForcedSignatureNew -eq $null)
    {
    Set-ItemProperty $CompanyRegPath’Outlook Signature Settings’ -name ForcedSignatureNew -Value 2
    }

    if ((Get-ItemProperty $CompanyRegPath’Outlook Signature Settings’).ForcedSignatureReplyForward -eq $null)
    {
    Set-ItemProperty $CompanyRegPath’Outlook Signature Settings’ -name ForcedSignatureReplyForward -Value 2
    }

    ###################################################################################################################

    #Retrieve registry information for the current user

    $SignatureVersion = (Get-ItemProperty $CompanyRegPath’Outlook Signature Settings’).SignatureVersion
    $ADVersion = (Get-ItemProperty $CompanyRegPath’Outlook Signature Settings’).ADVersion
    $ForcedSignatureNew = (Get-ItemProperty $CompanyRegPath’Outlook Signature Settings’).ForcedSignatureNew
    $ForcedSignatureReplyForward = (Get-ItemProperty $CompanyRegPath’Outlook Signature Settings’).ForcedSignatureReplyForward

    ###################################################################################################################

    #Copy signature sourcefiles and creating signature if signature-version are different from local version
    #or if Active Directory information has been updated

    if (($SignatureVersion -eq $SigVersion) -and ($ADVersion -eq $ADModify))
    {}
    else
    {
    #Forcing signature for new messages if enabled
    if ($ForcedSignatureNew -eq ‘1’)
    {
    #Set company signature as default for New messages
    $MSWord = New-Object -com word.application
    $EmailOptions = $MSWord.EmailOptions
    $EmailSignature = $EmailOptions.EmailSignature
    $EmailSignatureEntries = $EmailSignature.EmailSignatureEntries
    $EmailSignature.NewMessageSignature=$CompanyName
    $MSWord.Quit()
    }

    #Forcing signature for reply/forward messages if enabled
    if ($ForcedSignatureReplyForward -eq ‘1’)
    {
    #Set company signature as default for Reply/Forward messages
    $MSWord = New-Object -com word.application
    $EmailOptions = $MSWord.EmailOptions
    $EmailSignature = $EmailOptions.EmailSignature
    $EmailSignatureEntries = $EmailSignature.EmailSignatureEntries
    $EmailSignature.ReplyMessageSignature=$CompanyName
    $MSWord.Quit()
    }

    #Create local signature directory if it doesn’t exist
    if (Test-Path $LocalSignaturePath)
    {}
    else
    {New-Item $LocalSignaturePath -itemType Directory}

    #Copy signature templates from domain to local Signature-folder
    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 -com word.application

    $fullPath = $LocalSignaturePath+”+$CompanyName+’.docx’
    $MSWord.Documents.Open($fullPath)

    $FindText = “DisplayName”
    $ReplaceText = $ADDisplayName.ToString()
    $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord, $MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap, $Format, $ReplaceText, $ReplaceAll )

    $FindText = “Description”
    $ReplaceText = $ADDescription.ToString()
    $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord, $MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap, $Format, $ReplaceText, $ReplaceAll )

    $FindText = “Title”
    $ReplaceText = $ADTitle.ToString()
    $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord, $MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap, $Format, $ReplaceText, $ReplaceAll )

    $FindText = “Company”
    $ReplaceText = $ADCompany.ToString()
    $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord, $MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap, $Format, $ReplaceText, $ReplaceAll )

    $FindText = “StreetAddress”
    $ReplaceText = $ADStreetAddress.ToString()
    $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord, $MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap, $Format, $ReplaceText, $ReplaceAll )

    $FindText = “City”
    $ReplaceText = $ADCity.ToString()
    $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord, $MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap, $Format, $ReplaceText, $ReplaceAll )

    $FindText = “State”
    $ReplaceText = $ADState.ToString()
    $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord, $MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap, $Format, $ReplaceText, $ReplaceAll )

    $FindText = “Zip”
    $ReplaceText = $ADZip.ToString()
    $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord, $MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap, $Format, $ReplaceText, $ReplaceAll )

    $FindText = “Telephone”
    $ReplaceText = $ADTelephone.ToString()
    $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord, $MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap, $Format, $ReplaceText, $ReplaceAll )

    $FindText = “Fax”
    $ReplaceText = $ADFax.ToString()
    $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord, $MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap, $Format, $ReplaceText, $ReplaceAll )

    $FindText = “Mobile”
    $ReplaceText = $ADMobile.ToString()
    $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord, $MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap, $Format, $ReplaceText, $ReplaceAll )

    $MSWord.Selection.Find.Execute(“Email”)
    $MSWord.ActiveDocument.Hyperlinks.Add($MSWord.Selection.Range, “mailto:”+$ADEmailAddress.ToString(), $missing, $missing, $ADEmailAddress.ToString())

    $saveFormat = [Enum]::Parse([Microsoft.Office.Interop.Word.WdSaveFormat], “wdFormatHTML”);
    $path = $LocalSignaturePath+”+$CompanyName+”.htm”
    $MSWord.ActiveDocument.saveas([ref]$path, [ref]$saveFormat)

    $saveFormat = [Enum]::Parse([Microsoft.Office.Interop.Word.WdSaveFormat], “wdFormatRTF”);
    $path = $LocalSignaturePath+”+$CompanyName+”.rtf”
    $MSWord.ActiveDocument.SaveAs([ref] $path, [ref]$saveFormat)

    $saveFormat = [Enum]::Parse([Microsoft.Office.Interop.Word.WdSaveFormat], “wdFormatText”);
    $path = $LocalSignaturePath+”+$CompanyName+”.txt”
    $MSWord.ActiveDocument.SaveAs([ref] $path, [ref]$SaveFormat)

    $MSWord.ActiveDocument.Close()
    $MSWord.Quit()

    #Stop Microsoft Outlook task spawned by Microsoft Word
    Stop-Process -name Outlook

    }

    ###################################################################################################################

    #Update registry values

    Set-ItemProperty $CompanyRegPath’Outlook Signature Settings’ -name SignatureVersion -Value $SigVersion
    Set-ItemProperty $CompanyRegPath’Outlook Signature Settings’ -name ADVersion -Value $ADModify
    Set-ItemProperty $CompanyRegPath’Outlook Signature Settings’ -name ForcedSignatureNew -Value $ForceSignatureNew
    Set-ItemProperty $CompanyRegPath’Outlook Signature Settings’ -name ForcedSignatureReplyForward -Value $ForceSignatureReplyForward

    ###################################################################################################################

  11. *** OOPS ***

    Please disregard my code above; in my haste I copied the errant “work-in-progress code” that does not force the default signature on first run.

    Please see corrected code below:

    ###########################################################################”
    #
    # NAME: Set-OutlookSignature.ps1
    #
    # AUTHOR: Jan Egil Ring
    # Modifications by Darren Kattan
    #
    # COMMENT: Script to create an Outlook signature based on user information from Active Directory.
    # Adjust the variables in the “Custom variables”-section
    # Create an Outlook-signature from Microsoft Word (logo, fonts etc) and copy this signature to \domainNETLOGONsig_files$CompanyName$CompanyName.docx
    # This script supports the following keywords:
    # DisplayName
    # Title
    # Email
    # See the following blog-post for more information: http://blog.crayon.no/blogs/janegil/archive/2010/01/09/outlook-signature-based-on-user-information-from-active-directory.aspx
    #
    # Tested on Office 2003,2007 and 2010
    #
    # You have a royalty-free right to use, modify, reproduce, and
    # distribute this script file in any way you find useful, provided that
    # you agree that the creator, owner above has no warranty, obligations,
    # or liability for such use.
    #
    # VERSION HISTORY:
    # 1.0 09.01.2010 – Initial release
    # 1.1 11.09.2010 – Modified by Darren Kattan
    # – Removed bookmarks. Now uses simple find and replace for DisplayName, Title, and Email.
    # – Email address is generated as a link
    # – Signature is generated from a single .docx file
    # – Removed version numbers for script to run. Script runs at boot up when it sees a change in the “Date Modified” property of your signature template.
    # 1.11 11.15.2010 – Revised by Darren Kattan
    # – Fixed glitch with text signatures
    #
    #
    # 1.12 07.04.2011 – Modified by Philip Jeffrey
    # – revised script so that all settings are applied on first execution
    # – revised script to check for changes to the signature template OR the Active Directory user
    # – revised to include more Active Directory information fields
    # – added check for existence of Local Signature folder (explicit check and folder creation)
    # – added check for existence of registry values (explicit check and value creation, set to dummy value of 2 on first execution)
    #
    ###########################################################################”

    #Custom variables

    $CompanyName = ‘Immense Networks’
    $SigSource = “\domainNETLOGONsig_files$CompanyName”
    $ForceSignatureNew = ‘1’ #Enforce as default signature for new messages. (0 = no force, 1 = force)
    $ForceSignatureReplyForward = ‘1’ #Enforce as default signature for reply/forward messages. (0 = no force, 1 = force)

    #Environment variables

    $AppData=(Get-Item env:appdata).value
    $SigPath = ‘MicrosoftSignatures’
    $LocalSignaturePath = $AppData+$SigPath
    $RemoteSignaturePathFull = $SigSource+”+$CompanyName+’.docx’
    $SigVersion = (gci $RemoteSignaturePathFull).LastWriteTime #When was the last time the signature was written

    #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
    $ADDescription = $ADUser.description
    $ADTitle = $ADUser.title
    $ADCompany = $ADUser.Company
    $ADStreetAddress = $ADUser.StreetAddress
    $ADCity = $ADUser.l
    $ADState = $ADUser.st
    $ADZip = $ADUser.postalCode
    $ADTelephone = $ADUser.TelephoneNumber
    $ADFax = $ADUser.facsimiletelephonenumber
    $ADMobile = $ADUser.mobile
    $ADEmailAddress = $ADUser.mail
    $ADModify = $ADUser.whenChanged

    ###################################################################################################################

    #Set registry information for the current user

    $CompanyRegPath = “HKCU:Software”+$CompanyName

    if (Test-Path $CompanyRegPath)
    {}
    else
    {New-Item -path “HKCU:Software” -name $CompanyName}

    if (Test-Path $CompanyRegPath’Outlook Signature Settings’)
    {}
    else
    {New-Item -path $CompanyRegPath -name “Outlook Signature Settings”}

    if ((Get-ItemProperty $CompanyRegPath’Outlook Signature Settings’).SignatureVersion -eq $null)
    {
    Set-ItemProperty $CompanyRegPath’Outlook Signature Settings’ -name SignatureVersion -Value 2
    }

    if ((Get-ItemProperty $CompanyRegPath’Outlook Signature Settings’).ADVersion -eq $null)
    {
    Set-ItemProperty $CompanyRegPath’Outlook Signature Settings’ -name ADVersion -Value 2
    }

    ###################################################################################################################

    #Retrieve registry information for the current user

    $SignatureVersion = (Get-ItemProperty $CompanyRegPath’Outlook Signature Settings’).SignatureVersion
    $ADVersion = (Get-ItemProperty $CompanyRegPath’Outlook Signature Settings’).ADVersion

    ###################################################################################################################

    #Copy signature sourcefiles and creating signature if signature-version are different from local version
    #or if Active Directory information has been updated

    if (($SignatureVersion -eq $SigVersion) -and ($ADVersion -eq $ADModify))
    {}
    else
    {
    #Create local signature directory if it doesn’t exist
    if (Test-Path $LocalSignaturePath)
    {}
    else
    {New-Item $LocalSignaturePath -itemType Directory}

    #Copy signature templates from domain to local Signature-folder
    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 -com word.application

    $fullPath = $LocalSignaturePath+”+$CompanyName+’.docx’
    $MSWord.Documents.Open($fullPath)

    $FindText = “DisplayName”
    $ReplaceText = $ADDisplayName.ToString()
    $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord, $MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap, $Format, $ReplaceText, $ReplaceAll )

    $FindText = “Description”
    $ReplaceText = $ADDescription.ToString()
    $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord, $MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap, $Format, $ReplaceText, $ReplaceAll )

    $FindText = “Title”
    $ReplaceText = $ADTitle.ToString()
    $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord, $MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap, $Format, $ReplaceText, $ReplaceAll )

    $FindText = “Company”
    $ReplaceText = $ADCompany.ToString()
    $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord, $MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap, $Format, $ReplaceText, $ReplaceAll )

    $FindText = “StreetAddress”
    $ReplaceText = $ADStreetAddress.ToString()
    $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord, $MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap, $Format, $ReplaceText, $ReplaceAll )

    $FindText = “City”
    $ReplaceText = $ADCity.ToString()
    $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord, $MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap, $Format, $ReplaceText, $ReplaceAll )

    $FindText = “State”
    $ReplaceText = $ADState.ToString()
    $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord, $MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap, $Format, $ReplaceText, $ReplaceAll )

    $FindText = “Zip”
    $ReplaceText = $ADZip.ToString()
    $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord, $MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap, $Format, $ReplaceText, $ReplaceAll )

    $FindText = “Telephone”
    $ReplaceText = $ADTelephone.ToString()
    $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord, $MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap, $Format, $ReplaceText, $ReplaceAll )

    $FindText = “Fax”
    $ReplaceText = $ADFax.ToString()
    $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord, $MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap, $Format, $ReplaceText, $ReplaceAll )

    $FindText = “Mobile”
    $ReplaceText = $ADMobile.ToString()
    $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord, $MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap, $Format, $ReplaceText, $ReplaceAll )

    $MSWord.Selection.Find.Execute(“Email”)
    $MSWord.ActiveDocument.Hyperlinks.Add($MSWord.Selection.Range, “mailto:”+$ADEmailAddress.ToString(), $missing, $missing, $ADEmailAddress.ToString())

    $saveFormat = [Enum]::Parse([Microsoft.Office.Interop.Word.WdSaveFormat], “wdFormatHTML”);
    $path = $LocalSignaturePath+”+$CompanyName+”.htm”
    $MSWord.ActiveDocument.saveas([ref]$path, [ref]$saveFormat)

    $saveFormat = [Enum]::Parse([Microsoft.Office.Interop.Word.WdSaveFormat], “wdFormatRTF”);
    $path = $LocalSignaturePath+”+$CompanyName+”.rtf”
    $MSWord.ActiveDocument.SaveAs([ref] $path, [ref]$saveFormat)

    $saveFormat = [Enum]::Parse([Microsoft.Office.Interop.Word.WdSaveFormat], “wdFormatText”);
    $path = $LocalSignaturePath+”+$CompanyName+”.txt”
    $MSWord.ActiveDocument.SaveAs([ref] $path, [ref]$SaveFormat)

    $MSWord.ActiveDocument.Close()
    $MSWord.Quit()

    #Forcing signature for new messages if enabled
    if ($ForceSignatureNew -eq ‘1’)
    {
    #Set company signature as default for New messages
    $MSWord = New-Object -com word.application
    $EmailOptions = $MSWord.EmailOptions
    $EmailSignature = $EmailOptions.EmailSignature
    $EmailSignatureEntries = $EmailSignature.EmailSignatureEntries
    $EmailSignature.NewMessageSignature=$CompanyName
    $MSWord.Quit()
    }

    #Forcing signature for reply/forward messages if enabled
    if ($ForceSignatureReplyForward -eq ‘1’)
    {
    #Set company signature as default for Reply/Forward messages
    $MSWord = New-Object -com word.application
    $EmailOptions = $MSWord.EmailOptions
    $EmailSignature = $EmailOptions.EmailSignature
    $EmailSignatureEntries = $EmailSignature.EmailSignatureEntries
    $EmailSignature.ReplyMessageSignature=$CompanyName
    $MSWord.Quit()
    }

    #Stop Microsoft Outlook task spawned by Microsoft Word
    Stop-Process -name Outlook

    }

    ###################################################################################################################

    #Update registry values

    Set-ItemProperty $CompanyRegPath’Outlook Signature Settings’ -name SignatureVersion -Value $SigVersion
    Set-ItemProperty $CompanyRegPath’Outlook Signature Settings’ -name ADVersion -Value $ADModify

    ###################################################################################################################

      • Yes, $AppData=(Get-Item env:appdata).value does not return anything in the XP clients I’ve tested with. Unless I’m doing something stupid, I’m contemplating a OS check to set the path manually.

        • Hmm, seems there are a couple of MS updates that fix the above issue. But I’m still finiding that the powershell script runs fine locally but not through GP. A bit anoying that Outlook gets triggered, but we’ll see what problems it causes in my test group. Running v1.11

  12. Hi Guys

    It’s working really good!
    But I have several ideas and dont know how them realized.
    1. Insert in signature photo from AD (shema expanded).
    2. Bind a certain picture in signature template to user’s sip address (algorithm).

    Thanks so much for your help.

  13. Hello Jan,

    I had an earlier issue where I couldn’t get your script to work. It turned out that I had to install the 2003 Primary Interop Assemblies at your suggestion and that worked voor XP + Office 2003. I’m now testing your script for Windows 7 + Office 2003 and am not able to get it to work. I’ve installed the 2003 Primary Interop Assemblies to no avail. It works with Windows 7 + Office 2010 so just to be sure I installed the 2010 Primary Interop Assemblies to no avail. I get a lot of messages like this:

    Exception calling “Open” with “1” argument(s): “Er is een fout opgetreden tijdens het openen van het bestand.”
    At C:TempOutlook-SignaturesSig-Standaard.ps1:137 char:23
    + $MSWord.Documents.Open <<<< ($fullPath)
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : ComMethodTargetInvocation

    You cannot call a method on a null-valued expression.
    At C:TempOutlook-SignaturesSig-Standaard.ps1:141 char:32
    + $MSWord.Selection.Find.Execute <<<< ($FindText, $MatchCase, $MatchWholeWord, $MatchWildcards, $MatchSoundsLike, $Mat
    chAllWordForms, $Forward, $Wrap, $Format, $ReplaceText, $ReplaceAll )
    + CategoryInfo : InvalidOperation: (Execute:String) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    Do you have any suggestions?

    Thnx Remco

  14. Pingback: PowerShell: Outlook unified signature based on Active Directory information « Bart's Weblog

  15. Seems the txt files only display

    PK

    as a signature repling to plain text emails

    but the txt looks like this

    K   ! >RHè| ¤  [Content_Types].xml ¢(   ´”ËNÃ0E÷HüCä-Jܲ@5í‚Ç*Q$¶Æ™´~Éž¾þžIÒFB‹ÝDJÆsïñ=£ÉÆèd!*gs6Ì,+]¡ì<g/³‡ôš%…-„vr¶…È&ãó³Ñlë!&ÔmcΈþ†ó(DÌœK•Ò#^Ãœ{!ßÅøåpÅ¥³S¬4Øxt¥XjLî7ô¹!  #Kn›…•W΄÷ZIDÊW¶øâ’î2ê¬×Ä…òñ‚0ït¨*?ìúž(š
    H¦"à£0„Á×.¼prihÙa™NW–JBÛ_©ùà$ÄH™µ#”ÝówqÈeDg^æ
    ÁLƒóqا­ô  ‚6Ã.†:‹ˆ[
    ±·õ·$ÝC4ö€Hѝ`§|a
    oÏ'£ø$~¤¤ 3oþÿo´ÒG!¦ ðúÙÿ@Ö2‡,é¾ÔgŸ¦Jøö÷c£êNé"þâзŽ4‘zç ÕÌ+ èðæõŒ ÿÿ PK   ! ‘·ó N _rels/.rels ¢( 

    Any help.

  16. ok fixed that issue

    I Changed

    $path = $LocalSignaturePath+’’+$CompanyName+”.txt”
    $MSWord.ActiveDocument.SaveAs([ref] $path, [ref]$SaveFormat::wdFormatText)

    To

    $saveFormat = [Enum]::Parse([Microsoft.Office.Interop.Word.WdSaveFormat], “wdFormatText”);
    $path = $LocalSignaturePath+’’+$CompanyName+”.txt”
    $MSWord.ActiveDocument.SaveAs([ref] $path, [ref]$saveFormat)

    now displays fine

  17. Hi,
    I have a very silly problem here.. I think it’s my problem but I couldn’t find a solution for it so far. I’m using Win2k3 server with SP2 but I can not find the tab of “Powershell scripts” in the logon properties in GPO.
    Can you please advise me what I’m missing?

    thanks in advance,

    • Hi,
      The PowerShell tab is available only on Windows Server 2008 R2. If you want to run a PowerShell script in 2003, you can call powershell.exe from a cmd-file. I.e. powershell.exe -File c:scriptsmyscript.ps1

    • I’m having the exact same problem, script runs without errors, but no files are created in the microsoft/signatures folder, and as a result no signatures appear in Outlook. Very confused now as to what’s going on.

  18. Hi,

    FYI there is a problem with the pasted code above, it seems a ‘ has converted to a ` in the $saveFormat section. Just something to watch out for.

    Cheers,
    Paul.

  19. Hi. Would anyone know how to add / modify the code so that the email address hyperlink is a different colour (grey). Our company colours requires the email address to be grey. New to Powershell. Thanks in advance. Paul.

  20. Hi,

    Our firm requires that the email address hyperlink is grey. The script creates the hyperlink as blue. I was wondering if anyone would be able to assist in how this could be implemented in the script? Thanks in advance. Paul. P.S. I have looking around on the Internet & have not had any luck in locating this thus far.

    • Hi Paul,

      I tried to do the same thing. Unfortunately, I think the hyperlink display format is set in the recipient’s email client, regardless of how you format the outbound signature.

      The setting for Outlook 2010 is under:

      Options…Mail…Spelling and Autocorrect…Proofing…Autocorrect Options…Autoformat…”Internet and Network Paths and Hyperlinks”.

      Clear the checkbox and re-open an email… you should see the address in its original format without the blue hyperlink.

  21. Hi Philip,

    Thanks very much for the reply & suggestion. Unfortunately that didn’t do the trick.

    I think it has to do with the part of the code where it writes the HTML for the hyperlink where we need to add in the style color for the hyperlink: “$MSWord.ActiveDocument.Hyperlinks.Add($MSWord.Selection.Range, “mailto:”+$ADEmailAddress.ToString”.

    That part I haven’t worked out yet as when we tell powershell to write to the HTML file: “style color:”black”> for example, it didn’t like the quotes. So that’s the path we are trying to go down to get that to work.

    Cheers
    Paul

  22. Thanks for the script, I used Philips modified version and it works great mostly, but for some users it runs very slow and this is the slow part of the script:

    $ReplaceAll = 2
    $FindContinue = 1
    $MatchCase = $False
    $MatchWholeWord = $True
    $MatchWildcards = $False
    $MatchSoundsLike = $False
    $MatchAllWordForms = $False
    $Forward = $True
    $Wrap = $FindContinue
    $Format = $False

    When running the script for these users, the output will appear very slow one by one (total runtime is about 5-8 min’s). So for instance, the output will show False…then 1 minute later True, then one minute later False…and so on. The script is running on a terminal server for all users, so it can’t be hardware related. I also can’t see any user specific differences regarding permissions or AD attributes.

    Anyone got a clue as to why this is happening?

    • A little update:

      I’ve been able to pinpoint the problematic code. It’s start with this one:

      $FindText = “DisplayName”
      $ReplaceText = $ADDisplayName.ToString()
      $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord, $MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap, $Format, $ReplaceText, $ReplaceAll )

      And then continues with all the other Findnext functions. For every function it takes about 30-60 sec’s to complete and move on to the next. The funny thing is that when I run the script in debug mode and set breakpoint after every function, I can walk through the functions instantly with F5.

      My Powershell knowlegde is crap, so any help here would be greatly appreciated! And again: same machine, different user…and it works fine! 😐

  23. When using this script and creating a new meeting appointment in your calendar you can not insert your signature from the signature button. The auto generated signature only works with emails and not calendar items.

  24. Any update with the Outlook process? It’s also a hindrance for me…
    Another thing is that at first run, it prompts to save the normal.dot file. Anybody saw that problem?

  25. Pingback: Outlook 2010 Signature Automation through Group policy | Niroshanezra's Exchange 2010 Blog

  26. Pingback: Find Outlook Version Powershell - ORG.org