Wednesday, November 18, 2009

Formatting output from CrmDiagTool4

I'm sure you know about the utility that will interrogate a CRM server and export CRM configuration details such as server details, Registry keys, CRM website details, TCP/IP, Active Directory settings, etc. The utility goes by the name "CrmDiagTool4".

To make the output of the utility more readable, I put together this short VBA script that you can run in Word 2003 or 2007.

First, run CrmDiagTool4.exe and export the system report. Then copy and paste the resulting report text into Word. You'll probably want to set the page orientation to Landscape, the margins to .25-inch, and the font for all text to Courier New 8pt.

Next, paste this script into the VBA editor and run it. It simply changes the formatting of the major report sections (lines beginning and ending with several dashes) to the Heading 1 format.


Sub FixDiagToolOutput()
   Dim headingText As String
   Dim range As range
   For Each para In ActiveDocument.Paragraphs
      If Mid(para.range.Text, 1, 10) = "----------" Then
         headingText = Replace(para.range.Text, "-", "")
         Set range = para.range
         range.Text = headingText
         range.Style = ActiveDocument.Styles("Heading 1")
      End If
   Next para
   MsgBox "Done"
End Sub


Cheers,

-Tim

Tuesday, October 27, 2009

CRM documentation tool: Fixing scripts

In a previous post I mentioned that the CRM 4.0 Documentation tool can export scripts from Dynamics CRM forms and attributes. One of the problems with the tool, though, is that it copies the JScript code verbatim from the exported CRM customizations xml file into Excel, complete with escaped greater-than and less-than characters. For example, a less-than character will appear in the script as &#60; instead of "<".

To fix the script code once it's in Excel, search and replace the following:

Replace &#60; with <

Replace &#62; with >

-Tim

Wednesday, August 26, 2009

NullReferenceException: Microsoft.Crm.ObjectModel.OrganizationUIService.LabelLoaderPublished.LoadMetadataLabel

WARNING: Back up your CRM database if you decide to follow the steps below!

If you see the following error in the CRM trace/log file (as I did today on a VPC… for no apparent reason):

Stack Trace Info: [NullReferenceException: Object reference not set to an instance of an object.]
at Microsoft.Crm.ObjectModel.OrganizationUIService.LabelLoaderPublished.LoadMetadataLabel(Int32 entityType, String attributeName, ExecutionContext context)


The problem might be that there’s an old attribute being referenced in the entity’s form. To determine this and remove the bad form from the form's xml definition, open the OrganizationUIBase table and look for the object type id for the problem entity (e.g., 10016). Copy the FormXml to notepad and save the file with an xml extension. Open the file in IE or other xml viewer/editor and look for an attribute that no longer exists. In notepad or in your xml editor, remove the problematic node, copy the new xml, and paste it into the FormXml in the OrganizationUIBase table. Restart IIS and then see if you can now export, publish, or do other work with the entity.

Of course, any direct change to the CRM database is not supported by Microsoft and should only be done as a last resort. Since I was working on a non-production VPC I went ahead and made the change... and it did the trick. Again, I have no idea how the problem occurred. The problem entity was fine the last time I loaded the VPC and today I couldn't publish, remove attributes, or export. Strange, very strange.

-Tim

Wednesday, August 12, 2009

Bingdown

I coined a new term today: Bingdown

Definition: A depressed state one reaches when Bing doesn't deliver what HAS to be out there.

Today's Bingdown: azure "dynamics crm" asp.net authentication token site:microsoft.com -faq

Another Bingdown (well, a partial Bingdown): "how to lose weight while programming"

Sunday, August 9, 2009

Enhancing the Dynamics CRM 4.0 Documentation Generator

Like me, Phil Edry (also with Altriva Solutions) is constantly on the lookout for Dynamics CRM development tools, blog posts, etc. that help us to become more productive for our clients. And we return the favor to the community by blogging, sharing code, and participating on forums.

Today, I want to share some code. But first you need to know about the gem of a CRM utility that Phil discovered last week on CodePlex: Microsoft Dynamics CRM 4.0 Documentation Generator.

After the 2 minute install of this tool and 2 minute export of your CRM application's customizations (XML), you can produce (in Excel) documentation that provides a list of all attributes on each form, the script of all objects on the forms, picklist values, and more. This can save hours in documentation time for anyone responsible for the configuration or maintenance of a Dynamics CRM 4.0 system.



One of the benefits of having this customization information in Excel is that it opens up the possibility to write VBA code to further analyze the information. That's what I've done with the code shown below.

This VBA code loops through each entity (listed on the Form worksheets) and for each attribute it determines whether the attribute is referenced in any of the JScript code on the form or any of the attribute onChange events. When the attribute is identified in a code line, it places the code line number(s) on the attribute's detail row. For many Dynamics CRM installations, this could save additional hours of work.

First, run the Documentation Generator tool. Then, open up the Excel VBA code editor, double-click the ThisWorkbook object, paste this code and click Run. Within 10 seconds you'll have additional details in your Excel entity/attribute report.

Sub IdentifyFieldsReferencedInScript()
Dim columnOrdinalForScriptLineNumbers As Integer
Dim formWorksheetName As String
Dim formWorksheetRowNumber As Integer
Dim formWorksheetAttribName As String
Dim scriptWorksheetName As String
Dim scriptWorksheet As Worksheet
Dim scriptWorksheetRowNumber As Integer
Dim scriptWorksheetBlankLineCounter As Integer
Dim scriptLineNumbersForAttribute As String
Dim scriptText As String
Dim currentEntityName As String

Application.ScreenUpdating = False

columnOrdinalForScriptLineNumbers = 6

'* Loop through each worksheet. Process worksheets that end with "-Form".
For Each xlSheet In ActiveWorkbook.Worksheets
If Right(xlSheet.Name, 5) = "-Form" Then

formWorksheetName = xlSheet.Name
currentEntityName = Left(formWorksheetName, (Len(formWorksheetName) - 5))
scriptWorksheetName = currentEntityName & "-Script"

'* Check for existence of a Script worksheet for the current entity.
On Error Resume Next
Err.Clear
Set scriptWorksheet = ActiveWorkbook.Worksheets(scriptWorksheetName)
If Err.Number <> 0 Then
MsgBox "At least one script worksheet is missing. Execution halted."
Exit For
End If

formWorksheetRowNumber = 5
scriptLineNumbersForAttribute = Empty

'* Loop through each attribute on the current form
Do
formWorksheetAttribName = xlSheet.Cells(formWorksheetRowNumber, 1)
If formWorksheetAttribName <> "Field" And Left(formWorksheetAttribName, 7) <> "Section" And formWorksheetAttribName <> Empty Then
scriptWorksheetRowNumber = 1
scriptLineNumbersForAttribute = Empty
scriptWorksheetBlankLineCounter = 0

Do
scriptText = scriptWorksheet.Cells(scriptWorksheetRowNumber, 6)
If InStr(1, scriptText, formWorksheetAttribName) Then
If scriptLineNumbersForAttribute = Empty Then
scriptLineNumbersForAttribute = CStr(scriptWorksheetRowNumber)
Else
scriptLineNumbersForAttribute = scriptLineNumbersForAttribute & "" & CStr(scriptWorksheetRowNumber)
End If
Else
If scriptText = Empty Then
scriptWorksheetBlankLineCounter = scriptWorksheetBlankLineCounter + 1
Else
scriptWorksheetBlankLineCounter = 0
End If
End If

scriptWorksheetRowNumber = scriptWorksheetRowNumber + 1
Loop While scriptWorksheetBlankLineCounter < formworksheetrownumber =" formWorksheetRowNumber"> Empty

End If
Next xlSheet

Application.ScreenUpdating = True

MsgBox "Process complete."

End Sub

There's lots more that can be built on top of the documentation generator utility. For example, VBA can be used to build a table of contents for easier access to the worksheets. Also, for a given attribute, you could run dynamic SQL queries to determine, for example, how often the attribute is populated (% utilization) and how often picklist options are selected. Or, through CRM API calls, it would be useful to know the names of attributes that are not on the entity's form -- this would help to provide a total picture of each entity.

If I build more functionality on top of the documentation tool's output I'll be sure to post the details here. Meanwhile, let me know if you have other ideas for how to make this tool's output more useful. It's great as it is, but there's definitely potential to make it even better.

Cheers,

-Tim

Wednesday, July 29, 2009

Custom calendar in CRM UI

While working on a project for a client at Altriva, a need emerged for a custom event calendar within the CRM UI. Using a pre-built calendar along with some custom code to store events (maintained in CRM) into an XML file, I was able to get this functionality in place pretty quickly.

Please read more about the options for implementing a custom calendar in Dynamics CRM 4.0 in the Altriva Blog.

Tuesday, March 17, 2009

MSCRMKeyGenerator - Expired key

Yesterday I mentioned that I received a working backup of customer's CRM 4.0 system in a VPC. This morning, when attempting to load the CRM Web UI I was confronted with an error, which led to this information in the Application Event Log:

Source: MSCRMKeyGenerator
Event ID: 18949
Error (partial): Current active key (KeyType : CrmWRPCTokenKey) is expired. This can indicate that a key is not being regenerated properly.

The most common fix for this problem is to restart the Microsoft CRM Asynchronous Processing Service but the service wouldn't start for me. Phil Edry, my esteemed colleague here at Altriva, said "try Rollup 2... that might fix it".

I owe him a beer... it worked.

Exactly why the "active key" expired and what Rollup 2 did to fix it still remains a mystery to me, but I have too much work to do to investigate it now. If you have some more details on this, though, please let us all know. Thanks, -TD