Like any other application installed on Windows whenever we need to investigate and troubleshoot some issues event viewer and IIS logs (for web applications) are the first place to start.
But where developers and operations, in general, work together is when the cause is not obvious and for important application such as Microsoft Dynamics CRM is required to enable its tracing logs.
Trace files are helpful when you have to troubleshoot error messages or other issues in Microsoft CRM.
In this regards the Microsoft documentation is simple and straightforward to follow, the first method is via editing the windows registry settings, where I think will be for most system administrator feel comfortable to try, so this article is mainly for this audience and that are not comfortable with running a couple of powershell cmdlets that are safe and simple to understand.
Official Documentation
https://support.microsoft.com/en-au/help/907490/how-to-enable-tracing-in-microsoft-dynamics-crm
These changes made in Windows PowerShell do not update the Registry. These changes update the DeploymentProperties and ServerSettingsProperties tables in the MSCRM_CONFIG database.
Keep your recipe simple and share it
Create a simple script that we can re-use and run it and share with colleagues is the best foot in the door to start learning powershell for example, regardless of their previous knowledge or experience the learning curve can be very gentle.
The aim of using scripts to troubleshoot, document steps and solve issues is the best way to be able to reproduce problem and solutions. Starting with a simple script that enables tracing when we need it very effective and motivates colleagues to share and improve their practices.
Writing code requires technique and a lot of practice after few decades becomes a very refined form of art.
Starting with something that is small and fragile and not robust or reusable, is perfectly fine. Remember the aim is to start with something simple and stupid, keeping it simple until we feel confident that we can manage more complexity.
For this reason, modules and functions are too complicated and a script that accepts parameters as well. So If our requirements are enabling and disabling CRM Trace Logs with a script the simplest way for me is having 2 separate scripts that perform just one operation, that will reduce the number of lines of our scripts and will not require any parameter.
How To Enable CRM Tracing
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#Paolo Frigo, https://www.scriptinglibrary.com #https://support.microsoft.com/en-au/help/907490/how-to-enable-tracing-in-microsoft-dynamics-crm Add-PSSnapin Microsoft.Crm.PowerShell $setting = Get-CrmSetting TraceSettings $setting.Enabled = $True $setting.Directory = "D:\crmtrace\logs\" Set-CrmSetting $setting Get-CrmSetting TraceSettings Write-Output "The Crm Tracing is now ENABLED and the tracing logs will be available on this directory $($setting.Directory)" pause |
How To Disable CRM Tracing
1 2 3 4 5 6 7 8 9 10 11 12 13 |
#Paolo Frigo, https://www.scriptinglibrary.com #https://support.microsoft.com/en-au/help/907490/how-to-enable-tracing-in-microsoft-dynamics-crm Add-PSSnapin Microsoft.Crm.PowerShell $setting = Get-CrmSetting TraceSettings $setting.Enabled = $False Set-CrmSetting $setting Get-CrmSetting TraceSettings Write-OutPut "The Crm Tracing is now DISABLED" pause |
Single script with parameters and simple smarts
A variation of the scripts into 1 single one that accepts a parameter to turn CRM Tracing ON or OFF regardless the actual status, and throws an error if the path for the tracing logs is not valid (e.g. it doesn’t exist or the permission on that files aren’t correct).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
#Paolo Frigo, https://www.scriptinglibrary.com #This script need to run on the CRM Server #https://support.microsoft.com/en-au/help/907490/how-to-enable-tracing-in-microsoft-dynamics-crm #Add-PSSnapin Microsoft.Crm.PowerShell Param ( [Parameter(Mandatory=$true)] [ValidateSet("ON","OFF")] $Status ) #SETTINGS $TraceLogDirectory = "D:\crmtracelogs\" if (Test-Path $TraceLogDirectory){ Throw "This file path for Trace Logs is NOT valid `"$TraceLogDirectory`"" } $setting = Get-CrmSetting TraceSettings if ($Status -eq "ON"){ $setting.Directory = $TraceLogDirectory $setting.Enabled = $True } else { $setting.Enabled = $False } Set-CrmSetting $setting #Get-CrmSetting TraceSettings #Prints out the Settings Write-Output "The Crm Tracing is now $Status and the tracing logs will be available on this directory $($setting.Directory)" |
Ask yourself a couple of questions when you read your scripts
- Are the scripts above good scripts? Well.. these are all fit for purpose. There is always time to improve them and refactor if needed or required.
- Are they easy to read and everybody (even with less experience) can feel confident in running them? Yes, definitely.
Other Improvements
Restart CRM Services (lower environments)
There is no need for restarting all CRM services, but in case you wanted to perform a restart all in a simple oneliner will be extremely helpful and could be integrated into your script:
1 |
get-service *mscrm* | restart-service |
For DEV environments maybe it’s not an issue and could be done at any time.
As usual, all these scripts are available on my GitHub repository.
Nice Addition from Marty Diamond
As mentioned above, this comment worth to be quoted and added to this article using the code highlighting features’
Marty Diamond : I wrote a similar function for this back when I was doing CRM consulting. I included a switch for making the setting via the configuration database or the registry (for cases when you needed to grab tracing around SQL issues or just want to capture it from a single server). Thought it might be worth sharing!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
function Set-CrmTracing { [CmdletBinding()] Param ( [Parameter(Mandatory)] [ValidateSet(‘ConfigurationDatabase’, ‘Registry’)] [string]$Type, [Parameter(Mandatory)] [bool]$Enabled, [Parameter(Mandatory = $false)] [string]$TraceDirectory = “C:\Program Files\Microsoft Dynamics CRM\Trace”, [Parameter(Mandatory)] [ValidateSet(“Error”, “Verbose”)] [string]$Category, [Parameter(Mandatory = $false)] [bool]$CallStack ) switch ($Type) { ‘ConfigurationDatabase’ { # Define the setting type to be used and sets it as a variable $setting = Get-CrmSetting -SettingType TraceSettings # Set the tracing setting to Enabled $setting.Enabled = $Enabled $setting.CallStack = $CallStack $setting.Categories = “*:$Category” $setting.Directory = $TraceDirectory # Make the setting change if ($Enabled -eq 0) { Write-Warning “When disabling trace via configuration database, confirm that trace has actually stopped running!” Set-CrmSetting $setting } else { Write-Warning “Please confirm deployment-wide trace setting” Set-CrmSetting $setting -Confirm Write-Warning “Remember to disable tracing when finished!” } } ‘Registry’ { if (!(Test-Path $TraceDirectory)) { New-Item -ItemType Directory -Path $TraceDirectory -Force } if ($Enabled -eq 1) { Write-Warning “Remember to disable tracing when finished!” } New-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\MSCRM -Name TraceEnabled -Value $Enabled -PropertyType DWORD -Force New-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\MSCRM -Name TraceCallStack -Value $CallStack -PropertyType DWORD -Force New-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\MSCRM -Name TraceCategories -Value “*:$Category” -PropertyType String -Force New-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\MSCRM -Name TraceDirectory -Value $TraceDirectory -PropertyType String -Force # Change the TraceRefresh value $TraceRefreshValue = (Get-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\MSCRM -Name TraceRefresh).TraceRefresh if ($TraceRefreshValue -eq 0) { New-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\MSCRM -Name TraceRefresh -Value 1 -PropertyType DWORD -Force } else { New-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\MSCRM -Name TraceRefresh -Value 0 -PropertyType DWORD -Force } } } } |
This is really great! Nice to see people writing good PowerShell around CRM.
I wrote a similar function for this back when I was doing CRM consulting. I included a switch for making the setting via the configuration database or the registry (for cases when you needed to grab tracing around SQL issues or just want to capture it from a single server). Thought it might be worth sharing!
(…and apologies for how this might format!)
function Set-CrmTracing {
[CmdletBinding()]
Param
(
[Parameter(Mandatory)]
[ValidateSet(‘ConfigurationDatabase’, ‘Registry’)]
[string]$Type,
[Parameter(Mandatory)]
[bool]$Enabled,
[Parameter(Mandatory = $false)]
[string]$TraceDirectory = “C:\Program Files\Microsoft Dynamics CRM\Trace”,
[Parameter(Mandatory)]
[ValidateSet(“Error”, “Verbose”)]
[string]$Category,
[Parameter(Mandatory = $false)]
[bool]$CallStack
)
switch ($Type) {
‘ConfigurationDatabase’ {
# Define the setting type to be used and sets it as a variable
$setting = Get-CrmSetting -SettingType TraceSettings
# Set the tracing setting to Enabled
$setting.Enabled = $Enabled
$setting.CallStack = $CallStack
$setting.Categories = “*:$Category”
$setting.Directory = $TraceDirectory
# Make the setting change
if ($Enabled -eq 0) {
Write-Warning “When disabling trace via configuration database, confirm that trace has actually stopped running!”
Set-CrmSetting $setting
}
else {
Write-Warning “Please confirm deployment-wide trace setting”
Set-CrmSetting $setting -Confirm
Write-Warning “Remember to disable tracing when finished!”
}
}
‘Registry’ {
if (!(Test-Path $TraceDirectory)) {
New-Item -ItemType Directory -Path $TraceDirectory -Force
}
if ($Enabled -eq 1) {
Write-Warning “Remember to disable tracing when finished!”
}
New-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\MSCRM -Name TraceEnabled -Value $Enabled -PropertyType DWORD -Force
New-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\MSCRM -Name TraceCallStack -Value $CallStack -PropertyType DWORD -Force
New-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\MSCRM -Name TraceCategories -Value “*:$Category” -PropertyType String -Force
New-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\MSCRM -Name TraceDirectory -Value $TraceDirectory -PropertyType String -Force
# Change the TraceRefresh value
$TraceRefreshValue = (Get-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\MSCRM -Name TraceRefresh).TraceRefresh
if ($TraceRefreshValue -eq 0) {
New-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\MSCRM -Name TraceRefresh -Value 1 -PropertyType DWORD -Force
}
else {
New-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\MSCRM -Name TraceRefresh -Value 0 -PropertyType DWORD -Force
}
}
}
}
Hi Marty, thanks for your kind comment and I’ve added your script to the article. I really appreciate it!
Do you have a GitHub or Twitter handle that you want to add as well? Cheers!