none
PowerShell Signature script

    Pertanyaan

  • Hi all, 

    I have a "little" big problem with a part of the my script.

    All parts of the script works well except setting the signature generated as default and only if the script is deployed by GPO 

    If I run the script from desktop works fine and set the new signature as default

    Instead, If the script are deployed by GPO works in all parts but is unable to set the new signature as default.

    WHY? :-(

    ###########################################################################”
    #
    # 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 \\domain\NETLOGON\sig_files\$CompanyName\$CompanyName.docx
    #	 This script supports the following keywords:
    #	 DisplayName
    #	 Title
    #	 Email
    #
    # VERSION HISTORY:
    # 1.0 – Initial release
    #
    #
    # 
    ###########################################################################”
    
    #Custom variables
    $CompanyName = ‘iQuad’
    $DomainName = ‘iqd.local’
    
    #test path and crete folder
    $TARGETDIR = $env:APPDATA + "\Microsoft\Signatures"
    if(!(Test-Path -Path $TARGETDIR )){
        New-Item -ItemType directory -Path $TARGETDIR
    }
    
    
    $SigSource = “\\$DomainName\netlogon\sig_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 = ‘\Microsoft\Signatures’
    $LocalSignaturePath = $AppData+$SigPath
    $RemoteSignaturePathFull = $SigSource+’\'+$CompanyName+’.docx’
    $ExchPath = '\\EX1\Signatures\'
    
    
    #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
    $ADdescription = $ADuser.description
    $ADFax = $ADuser.facsimileTelephoneNumber
    $ADMobile = $ADuser.mobile
    $ADDepartment = $ADuser.department
    
    
    #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(“PostaEL”)
    $FindText = “PostaEL”
    $ReplaceText = $ADEmailAddress.ToString()
    $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord,	$MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap,	$Format, $ReplaceText, $ReplaceAll	)
    
    
    $FindText = “TelePhoneNumber”
    $ReplaceText = $ADTelePhoneNumber.ToString()
    $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord,	$MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap,	$Format, $ReplaceText, $ReplaceAll	)
    
    $FindText = “facsimileTelephoneNumber”
    $ReplaceText = $ADFax.ToString()
    $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord,	$MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap,	$Format, $ReplaceText, $ReplaceAll	)
    
    $FindText = “BlogIQ”
    $ReplaceText = $ADDepartment.ToString()
    $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord,	$MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap,	$Format, $ReplaceText, $ReplaceAll	)
    
    
    # $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], “wdFormatFilteredHTML”);
    [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)
    
    # Save html file with username from AD (OWA)
    $pathOWA = $LocalSignaturePath+’\'+$UserName+”.htm”
    $MSWord.ActiveDocument.saveas([ref]$pathOWA, [ref]$saveFormat)
    Copy-Item “$LocalSignaturePath\$UserName.htm” "$ExchPath" -Recurse -Force
    
    
    
    # Saving rtf and txt 
    
    $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)
    
    $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()
    
    }
    
    #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}
    
    $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


    Andrea Gallazzi
    windowserver.it - blog: andreagx.blogspot.com
    This posting is provided AS IS with no warranties, and confers no rights.



    • Diedit oleh Andrea, Gallazzi Rabu, 19 Februari 2014 15.59
    • Dipindahkan oleh Bill_Stewart Jumat, 04 Juli 2014 01.25 Unanswerable drive-by question
    Rabu, 19 Februari 2014 15.58

Semua Balasan

  • Word does not like to run under a GPO in Vista and later  Have users run manually or schedule it to run periodically under task scheduler

    Exchange can now generate signatures. 


    ¯\_(ツ)_/¯

    Rabu, 19 Februari 2014 16.26
  • Hi jrv,

    thank you for your reply

    My idea was the deployment by GPO. Create a task sheduler for each user is crazy in case of undreds of users. 


    Andrea Gallazzi
    windowserver.it - blog: andreagx.blogspot.com
    This posting is provided AS IS with no warranties, and confers no rights.

    Rabu, 19 Februari 2014 17.08
  • There are many issues with that signature including not cleaning up the Word objects.  That will keep the signature from being updated.

    You are continuing to create a signature repeatedly and it wil lbe attempted on every logon. This is a very bad design.

    There is method in the Word object model that sets the default signature.  You should not be using the registry.

    Forget about the version.  Set the sig file create time to the same as the template and use that.

    Look in the Gallery here.  There are a number of signature generators that do not have the issues that yours does.


    ¯\_(ツ)_/¯

    Rabu, 19 Februari 2014 17.09
  • Here is a partially fixed version.  I eliminated a lot of the code that will cause trouble.  You also had a large amount of "smart" quotes which will not work correctly under all circumstances.

    You really don't need to generate individual files.  They are auto-generated when you create the signature. 

    ###########################################################################”
    #
    # 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 \\domain\NETLOGON\sig_files\$CompanyName\$CompanyName.docx
    #	 This script supports the following keywords:
    #	 DisplayName
    #	 Title
    #	 Email
    #
    # VERSION HISTORY:
    # 1.0 – Initial release
    #
    #
    # 
    ###########################################################################”
    
    #Custom variables
    $CompanyName='iQuad'
    $DomainName='iqd.local'
    
    #test path and crete folder
    $TARGETDIR = $env:APPDATA + "\Microsoft\Signatures"
    if(!(Test-Path -Path $TARGETDIR )){
        New-Item -ItemType directory -Path $TARGETDIR
    }
    
    $SigSource ="\\$DomainName\netlogon\sig_files\$CompanyName"
    $ForceSignatureNew=$true #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=$true #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=$env:appdata
    $SigPath='\Microsoft\Signatures'
    $LocalSignaturePath=$AppData+$SigPath
    $RemoteSignaturePathFull="$SigSource\$CompanyName.docx"
    $ExchPath='\\EX1\Signatures\'
    
    
    #Get Active Directory information for current user
    $UserName = $env:username
    $Searcher=[adsisearcher]"(&(objectCategory=User)(samAccountName=$UserName))"
    $ADUserPath=$Searcher.FindOne()
    $ADUser=$ADUserPath.GetDirectoryEntry()
    $ADDisplayName = $ADUser.DisplayName
    $ADEmailAddress = $ADUser.mail
    $ADTitle = $ADUser.title
    $ADTelePhoneNumber = $ADUser.telephoneNumber
    $ADdescription = $ADuser.description
    $ADFax = $ADuser.facsimileTelephoneNumber
    $ADMobile = $ADuser.mobile
    $ADDepartment = $ADuser.department
    
    
    #Setting registry information for the current user
    $CompanyRegPath="HKCU:\Software\$CompanyName"
    
    if(-not(Test-Path $CompanyRegPath)){
        New-Item -path “HKCU:\Software” -name $CompanyName
    }
    
    if(-not(Test-Path "$CompanyRegPath\Outlook Signature Settings")){
        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
    
    # create this once to make release easier
    $MSWord = New-Object -com word.application
    
    #Forcing signature for new messages if enabled
    if ($ForcedSignatureNew){
        #Set company signature as default for New messages
        $MSWord.EmailOptions.EmailSignature.NewMessageSignature=$CompanyName
    }
    
    #Forcing signature for reply/forward messages if enabled
    if ($ForcedSignatureReplyForward){
        #Set company signature as default for Reply/Forward messages
        $MSWord.EmailOptions.EmailSignature.ReplyMessageSignature=$CompanyName
    }
    
    #Copying signature sourcefiles and creating signature if signature-version are different from local version
    if ($SignatureVersion -ne $SigVersion){
        #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
        $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(“PostaEL”)
        $FindText = “PostaEL”
        $ReplaceText = $ADEmailAddress.ToString()
        $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord,	$MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap,	$Format, $ReplaceText, $ReplaceAll	)
    
    
        $FindText = “TelePhoneNumber”
        $ReplaceText = $ADTelePhoneNumber.ToString()
        $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord,	$MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap,	$Format, $ReplaceText, $ReplaceAll	)
    
        $FindText = “facsimileTelephoneNumber”
        $ReplaceText = $ADFax.ToString()
        $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord,	$MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap,	$Format, $ReplaceText, $ReplaceAll	)
    
        $FindText = “BlogIQ”
        $ReplaceText = $ADDepartment.ToString()
        $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord,	$MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap,	$Format, $ReplaceText, $ReplaceAll	)
    
        $MSWord.ActiveDocument.Save()
        $MSWord.ActiveDocument.WebOptions.OrganizeInFolder = $true
        $MSWord.ActiveDocument.WebOptions.UseLongFileNames = $true
        $MSWord.ActiveDocument.WebOptions.BrowserLevel = [microsoft.office.interop.word.WdBrowserLevel]::wdBrowserLevelMicrosoftInternetExplorer6
        $path="$LocalSignaturePath\$CompanyName.htm"
        $MSWord.ActiveDocument.saveas([ref]$path, [ref][Microsoft.Office.Interop.Word.WdSaveFormat]::wdFormatFilteredHTML)
    
        # Save html file with username from AD (OWA)
        $pathOWA="$LocalSignaturePat\$UserName.htm"
        $MSWord.ActiveDocument.saveas([ref]$pathOWA, [ref][Microsoft.Office.Interop.Word.WdSaveFormat]::wdFormatFilteredHTML)
        Copy-Item $pathOWA $ExchPath -Recurse -Force
    
    
    
        # Saving rtf and txt 
        $path = "$LocalSignaturePath\$CompanyName+”.rtf"
        $MSWord.ActiveDocument.SaveAs([ref]$path, [ref][Microsoft.Office.Interop.Word.WdSaveFormat]::wdFormatRTF)
    
        $path = "$LocalSignaturePath\$CompanyName.rtf"
        $MSWord.ActiveDocument.SaveAs([ref]$path, [ref][Microsoft.Office.Interop.Word.WdSaveFormat]::wdFormatText)
    
        $path = "$LocalSignaturePath\$CompanyName.txt"
        $MSWord.ActiveDocument.SaveAs([ref] $path, [ref][Microsoft.Office.Interop.Word.WdSaveFormat]::wdFormatText)
    
    }
    
    $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){
        Set-ItemProperty $CompanyRegPath’\Outlook Signature Settings’ -name ForcedSignatureNew -Value $ForceSignatureNew
    }
    
    if ($ForcedSignatureReplyForward -ne $ForceSignatureReplyForward){
        Set-ItemProperty "$CompanyRegPath\Outlook Signature Settings" -name ForcedSignatureReplyForward -Value $ForceSignatureReplyForward
    }
    
    if($SignatureVersion -ne $SigVersion){
        Set-ItemProperty "$CompanyRegPath\Outlook Signature Settings" -name SignatureVersion -Value $SigVersion
    }
    

    By not constantly recreating the objects and by never crating reference objects we can just release MSWord once.  Also opening and closing word like that will create file locks that may corrupt the document.  You really should start by turning off document recovery and all alerts and messages.

    Somewhere I have a simple and well tested version that uses a template.  We can set it once and then just distribute the word template.   It is much easier to manage.

    Exchange signatures are the best and easiest.


    ¯\_(ツ)_/¯

    Rabu, 19 Februari 2014 17.45
  • If you use it under GP it will be a headache until you get it well tested and remove any excess code.  Office products do not like to run with no UI.  GP can execute before the UI is shown.  This can be an issue.

    The order you were doing things in was the likely cause of the defaults not getting set.


    ¯\_(ツ)_/¯

    Rabu, 19 Februari 2014 17.51
  • Here is a good article on how to set up corporate signatures using Exchange Rules.

    http://www.howto-outlook.com/howto/corporatesignatures.htm


    ¯\_(ツ)_/¯

    Kamis, 20 Februari 2014 01.22
  • OMG!

    Use the transport rules for signature is the worst design ever!

    BTW this is the solution:

    powershell -noexit -file \\domain\NETLOGON\sig_files\signature.ps1 (in a batch file)


    Andrea Gallazzi
    windowserver.it - blog: andreagx.blogspot.com
    This posting is provided AS IS with no warranties, and confers no rights.

    Kamis, 20 Februari 2014 10.09
  • Anything that changes the execution environment is apt to make yours work partially.

    You still have a huge memory leak  that will cause issues in the future.


    ¯\_(ツ)_/¯

    Kamis, 20 Februari 2014 12.59
  • Anything that changes the execution environment is apt to make yours work partially.

    You still have a huge memory leak  that will cause issues in the future.


    ¯\_(ツ)_/¯


    So is there any better way or updated PowerShell script for creating the Outlook email signature?

    /* Server Support Specialist */

    Selasa, 08 Mei 2018 03.34