Tuesday, July 07, 2009

One of my managers is number 9!

I read David Jennaway's blog today (http://mscrmuk.blogspot.com/) and he was happy that he was listed at 100 on the list of the most influential Dynamics Professionals in the World. I had a look through the list and found that the head of our "Microsoft Empowering Team" at Logica (I represent Dynamics CRM in this team) and also the head of our Dynamics Practice globaly, Thomas Olfsson at position nr 9 in the entire world!

Have a look at the list you self here: http://dynamicsworld.co.uk/index.html

Gustaf Westerlund
Microsoft Dynamics CRM Architect

Logica
www.logica.com

Friday, June 05, 2009

Workflow scope and security roles

When creating workflows there are some things that have to be taken into account. One thing that you might not know the details about is the Scope in "Options for Automatic Workflows". There are four options that are very similar to the options used for setting up security roles. They are:


- User
- Business Unit
- Parent: Child Business Unit
- Organization

Bellow the selection of the scope, there are some workflow triggering options, like starting the workflow when on create or when an attribute has changed.

The meaning of this is that dependent on the scope you have selected, the triggering will be set up, based on the user who owns the workflow.

So, for instance, if I select "User" in scope and then select triggering on attribute change, and I am the owner of the workflow, then it will only trigger when I make a change to the object.

If scope is set to Organization, it will trigger for all users in the tennant which is why this is most often used. Note however that user is set as default, so you'll have to change this when creating the workflow if you want it to work for someone else than yourself.

This is a useful tool since it can allow powerusers to create their own workflows to help them with their work without actually enabling this for everyone else.

As I have mentioned earlier, the workflow functionality is very powerful, and even thought there are protections agains infinite recursions and such, there is still the risk that semi skilled powerusers creating workflows that put a heavy load on the asyncservice, so I would be a bit reluctant on letting them use this. Thorough training is a must before and try to teach them to keep the workflows simple. If you have several custom workflow activities, for instance, activities for integrating with other systems, I would be very careful since it is hard, if not impossible to restrict a custom workflow activity to just a selected amount of users.

Gustaf Westerlund
Microsoft Dynamics CRM Architect

Logica
www.logica.com

Monday, June 01, 2009

Internet Facing Deployment

As many of you know, one of the integral and unique parts of Dynamics CRM 4.0 is it's ability to be Internet facing. This does not only mean that you have to choose between the ameneties of a normal AD logon and the grace of IFD, you can have both. So, even if you are just a small company with just a small business version of CRM 4.0 and not a larger corporation, there is no reason why you shouldn't use Dynamics CRM 4.0 with the IFD technology.





So, how do you do it?





There are some good documents provided by Microsoft on how to do it(like this one: http://www.microsoft.com/downloads/thankyou.aspx?familyId=3861e56d-b5ed-4f7f-b2fd-5a53bc71dafc&displayLang=en) but there are some parts of it that are a bit tricky and depend on some of the infrastructure components you have, like DNS, and that might not be Microsoft, or even hosted. So I thought I'd describe a bit about how it works and give an example of how to do it.

First of all you have to do a normal installation of CRM 4.0. You can install on port 5555, 80 or any other TCP port. It doesn't matter for IFD deployment, however, port 80 or 443 have to be made available from the Internet so the physical placement of the CRM server is critical. You can use normal redirect techniques or reverse proxy lookup (as in ISA-server). The important fact is that the server must be placed so that it can be reached from the outside.


The next thing you have to set up is an external name that you can use when adressing the server from Internet, hence it has to be a real name and not just an internal name. If you have registered a domainname you could set a hostname to point to the organizations you want to access.

I used dyndns.com and registered a name like "mydomain" and my CRM organization was mycrm, when using IFD that would make the address for this org:

http://mycrm.mydomain.dyndns.com

Make sure that everything bellow mydomain.dyndns.com also gets redirected to you CRM servers external URL (port 80 or 443 depending on if you are using SSL or not)

The next step is to run the IFD Tool as referenced in the Microsoft Document. It can be downloaded from here.

Use it to set up CRM by setting the right stuff in the web.config and setting some keys in the registry. It is a lot easier than doing it yourself. You have to set it up to the external name you have chosen.

Now the final step is to add a host header in the IIS website for CRM for *.mydomain.dyndns.com or explicitly for mycrm.mydomain.dyndns.com for port 80 or 443 depending on your setup.

Now you should be able to browse to mycompany.mydomain.dyndns.com and get to the logon screen.

To get reports working you have to install the report connector software found on the CRM CD/DVD.

There are of course lot of variations to this, using reverse proxy of ISA Server and all the options of setting up certificates for SSL but I'll leave that out of this posting to keep it simple.

Menno has recently published a posting on this as well (http://www.tekoppele.com/Blog/post/2009/05/30/How-to-configure-an-Internet-Facing-Deployment-for-Microsoft-Dynamics-CRM-40.aspx, and there are several other blogs and MS KB articles concerning this. If you have problems, try taking it a step at a time and analyse and design the setup first so that you have got it figgured before you start configuring!

Good luck!



Gustaf Westerlund
Microsoft Dynamics CRM Architect

Logica
www.logica.com

Friday, May 08, 2009

Enhancing performance in virtual machines

I follow the blog Microsoft Dynamics CRM UK Blog which is very good and they had an interesting posting today concerning performance issues in virtual PC 2007 on laptops. As most consultants, I use one (a lenovo T61p). You can read more about it here: http://blogs.msdn.com/ukcrm/archive/2009/05/07/virtual-pc-2007-performance-tweaks.aspx

When I tried to apply the change to the file they mentioned (%appdata%\Microsoft\Virtual PC\options.xml) I had a problem since I didn't have the parent tag in my file. I checked around a bit and found that it could just be added to the main structure. So, after modifications, my file looked like this:

----
</virtual_network>
<virtual_machines>
<enable_idle_thread type="boolean">true</enable_idle_thread>
</virtual_machines>
<window>
---

I would recommend adding it, if you most of the time have the computer connected to the power outlet, since it will probably increase the performance of your virtual machines!

Gustaf Westerlund
Microsoft Dynamics CRM Architect

Logica
www.logica.com

Monday, April 20, 2009

Importing large customization files to vanilla system

Sometimes you will need to import large customization files from one system to a vanilla system (no customizations). This file will often include workflows as well as new entities and attributes.

Since the workflows are dependant on the entities of the CRM system, a workflow cannot be imported if the entities it depends on do not exist.

This is usually not a problem in English based systems since Workflow starts with the letter "W" and hence is quite far down the list. In Swedish it is named "Arbetsflöde" and hence will be placed at the top. So, when importing the customization file, if importing everything, the system might give you an error if any workflow is dependant on an entitiy with a displayname after "A".

The solution is simple, just import everything but workflows first and then import workflows.

Gustaf Westerlund
Microsoft Dynamics CRM Architect

Logica
www.logica.com

Monday, February 23, 2009

Errors when programmatically attaching events in forms

Today I had a very weird error. I had two datetime fields on a form, one on the first tab and one one the second. Let's call them date1 and date2 to make it easier.

I attached an event in the onload by using

crmForm.all.date1.attachEvent("onchange", myFunc1);

and for the date2 field:

crmForm.all.date2.attachEvent("onchange", myFunc2);

The weird part was that if I changed date1 first and then date2, myFunc2 didn't fire. But if I first changed date2 and then date1, both fired as they should.

So I tried just adding an alert instead using the normal onchange method via the form editor in CRM and that triggered every time, just as it should, so something is different.

The simple solution seemed to be to move date2 from the second tab to the first. That got everything working just as it should.

I havn't tried it but I think that one could also write a method that confirms all the event attachments and then calling this at the end of every onchange triggering function and perhaps some extra time when the tabs are changed to make sure the events are bound correctly.

I have checked the documentation in CRM for if this kind of runtime event attachment might not be supported but my interpretation of the text is that is should be all right according to it. The closest paragraph in the unsupported customization section is the following:

"The use of custom HttpModules to inject HTML/DHTML into the Microsoft Dynamics CRM Forms. "

As I wrote, my interpretation is that attaching events (not even overwriting the onchange), should be ok according to this since we arn't injecting anything, just adding an event listener. Hence I feel that this must be interpreted as a bugg in CRM.

Gustaf Westerlund
Microsoft Dynamics CRM Architect

Logica
www.logica.com

Tuesday, February 17, 2009

Unicode conversion

When writing javascripts with alerts or similar when not working with english, special characters like the swedish åäö might not be shown correctly. I found this helpful page where you can enter the string you want to convert and then copy paste the result. Simple and nice.

http://rishida.net/scripts/uniview/conversion.php

Gustaf Westerlund
Microsoft Dynamics CRM Architect

Logica
www.logica.com

Really cool way of getting FetchXML from advanced find

I've been having some problems with my blogs in Outlook but today I fixed it and started checked if there was anything special and found this very interesting article on Ronald Lemmens blog.
http://ronaldlemmen.blogspot.com/2009/02/using-advanced-find-for-fetchxml.html

He describes how to, without any code or customizations to a system, easily get the fetchxml code from an advanced find by just putting some javascriptcode in the url of the window. Beautiful in all it simplicity!


Gustaf Westerlund
Microsoft Dynamics CRM Architect

Logica
www.logica.com

Force update of Report

The project I am currently involved in uses Reporting Services reports that are shown as PDF:s as quotes that are sent to the customer. It is implemented by creating a custom report that takes the object id (like quote) which is called from an isv.config button and by using querystring parameters, the output is directed to PDF.

However, I got a puzzeling bug. The data in the quote is of course based on data in some CRM entities and when a quote was generated and the user found something was wrong, changed this in CRM, saved and then tried to regenerate the PDF, the change didn't show. I restared Internet Explorer, and regenerated the quote-pdf and now it showed correctly. Hence some sort of caching error.

I looked around the internet a bit and found that by adding the following parameter to the querystring, I could refresh the sessions variables and I would get a fresh and correct report.´

&rs:ClearSession=true

So, the entire url was (except for the report id etc.):

&rs:Command=Render&rs:ClearSession=true&objid={D1F1FD5D-D7F8-DD11-967B-005056AA29F5}&rs:Format=PDF

So, if you get a similar error, just try setting this.

It is also possible that IE caches the pdf and then you'll have to add some variable to the querystring, like a tick or datetime that is unique for every call (from that client) and that will bypass IE:s caching.

Gustaf Westerlund
Microsoft Dynamics CRM Architect

Logica
www.logica.com

Tuesday, February 03, 2009

Workflow warning

Today I was troubleshooting a CRM server which had the CRMAsycnService and w3wp service totally hogging the machine. It was quite obvious that it was CRM that was the cause for this and since CRMAsyncService was involved, probably workflows or perhaps the deletionservice.

After a bit of looking around I found a workflow that was set to trigger on attribute change on an entity and then later in that same entity, changed some attributes. This caused an infinite loop which was the cause for the hogging. By first unpublishing the workflow and then removing all started systemjobs, I got the machine back up to speed.

My conclusion from this is that even though the workflow GUI seems easy it is deceitfully powerfull and you quite easily create workflows that hogg the server (the server hosting the async-service anyway). This should be taken into consideration when putting this tool into the hands of non-programmers since the risk for the entire system stability is large. This can be either application consultants or power users at the customer.

There is also no standard way of locking some of the triggers on workflows so that you can eliminate this risk. I you know of any, please leave a comment!


Gustaf Westerlund
Microsoft Dynamics CRM Architect

Logica
www.logica.com

Monday, February 02, 2009

Process implementation strategy

When implementing a business process in Dynamics CRM there are several different implementation paths to choose from. There are advantages and disadvantages to the different techniques but there are some goals that I feel the implementations should meet, mainly:



1. Fully supported customizations only

2. Flexible and non-static.

3. Power user modifiable

4. Movable from environment to environment (dev-test-production)



I will discuss the different aspects bellow and why I feel they are important.



Fully supported customizations only

This is almost so self-evident that it doesn't even need mentioning but I have seen several CRM implementations that not only nudge this paradigm in the corner, but bite big large chunks out of it. For me, the number one reason why this is so important is that all customers will sooner or later want a hotfix or upgrade to a later version and when Microsoft, in their greatest foresight and benevolence definied the concept of supported customizations, they made this possible without costly maintanance agreements or hostile customer relationships. So, not following it should be punishable by death or something close to it.



I would presume that you CRM implementations are meant to last for your customers and that you want a long a fruitfull relationship with your customer, why you just cannot underestimate this point. If you have to make unsupported customizations, make sure they are as light weight as possible, document them thouroghly and how to validate them when installing a hotfix or upgrade.



A business process must hence be made as supported as possible.



Flexible and non-static

The solution has to be flexible and non-static. We, and our customers live in an ever changing world and to cope with this, business processes have to change as the world around a company changes. Just imagine the changes the telecom industry has gone through the latest 20 years. To fully accomodate this the customer implementations have to be flexible and changable. Microsoft Dynamics CRM is one of the most versatile and flexible systems available, especially now that it incorporates windows workflow foundation. Implementing a business process in code entirly, locks the processes down, and builds a dependance on the CRM delivering partner, something every customer-value focused consultant must despise. I do not need to force my customers to use my services when I can get them to choose me because of the value I deliver to them every hour of every day.



Instead, use the power of Windows Workflow Foundation combined with custom workflow activities. If needed, trigger these workflows using plug-ins and isv.config customizations.



Power user modifiable

A business process often involves users of different sorts and communicates with these using emails, tasks and other activites. The content of these and the recipients, sometimes dynamically set, sometimes static (like the CFO), might need to be changed. Therefore it is not very flexible for the customer if code has to be re-written everytime a mail has to be changed. It is a lot more flexible to create a workflow that creates the activity and then just execute the workflow from code, apart from the fact that it is a lot quicker to implement. Just write a method that enables you to execute the workflow by name instead of Guid.



Movable from environment to environment (dev-test-production)

All implementations of any notable size always includes at least three environements, not seldom up to 5 or 6 depending on how you count (local dev, central dev, test, training, production). Business process implementations have to be easy to move between solutions without any or with as little as possible environement specifics. Hence, try to use names (or some other environment indpendant value) instead of guids since guids are environment specifics when relating to workflows and other similar things. Try to get all environement specific settings in one place, one file or create an entity for them. This can be a challange but try, it will pay off in the long run.


These are my thoughts on the business processes implementation stategy concerning Dynamics CRM 4. I would be happy to discuss the topic so please leave comments!

Gustaf Westerlund
Microsoft Dynamics CRM Architect

Logica
www.logica.com

Thursday, January 29, 2009

Problem opening workflows in CRM GUI

Currently I am working on a project with a quite complex sales process and part of it is managed by workflows (for flexibility) and to be able to do what is needed, I have developed several custom workflow activities.

However, today I had just installed some stuff and was going to review one of the workflows, and the CRM GUI crashed with the Exception "System.NullReferenceException" in a really nasty way when I tried to open it. By looking at the stack trace I got a feeling it had something to do with my custom activities so I just reregistered them and then everything started working again. So if you come across this error, this might be the problem. I couldn't find any reference to this error on the net why I thought it might be a good idea to blog about it.

Gustaf Westerlund
Microsoft Dynamics CRM Architect

Logica
www.logica.com

Wednesday, January 28, 2009

Workflow activity development and file locking

As some of you might have noticed, the dll:s containing the custom workflow activities might get locked and hence the compilation fails in it's final stage.

To handle this, I tried a good program called Unlocker 1.8.7 which you can find here: http://ccollomb.free.fr/unlocker/ - it is freeware and it will tell you which processes are locking a file and can help you kill them.

So, what is locking my dll? Well, actually several processes are involved both the MSCRMAsyncService and the IIS worker process (w3wp).

The most obvious way of handling it is just restarting the two services and that will work. However, restarting the w3wp process will require the entire CRM application to be recompiled which will create extra long and annoying waits. Instead, just recycle the applicationpool involved (CRMAppPool).

There are no problems restarting the MSCRMAsyncService.

And if you want to do it all in the pre-build event just add the following lines:

net stop "MSCRMAsyncService"
net start "MSCRMAsyncService"
cscript C:\Inetpub\AdminScripts\adsutil.vbs stop_server W3svc/AppPools/CRMAppPool cscript C:\Inetpub\AdminScripts\adsutil.vbs start_server W3svc/AppPools/CRMAppPool

And if you are still having problems, use the unlocker program!

Gustaf Westerlund
Microsoft Dynamics CRM Architect

Logica
www.logica.com

Tuesday, January 13, 2009

List Web Part for Dynamics CRM 4.0

Finally Microsoft have release the List Web Part for Dynamics CRM 4.0. I havn't had the opportunity to test it yet but the previous version (for CRM 3) had problems with non-english versions of SharePoint so be aware, especially if you are running CRM and SharePoint in different base languages.

If you have any experience of it, please let me know.

Gustaf Westerlund
Microsoft Dynamics CRM Architect

Logica
www.logica.com

Thursday, December 18, 2008

How to make a workflow wait until a certain date

How to make a workflow wait until a certain date might seem trivial but it isn't all that clear when using the GUI, but I found a nice blog with good pictures explaining how to do it so instead of reinventing the wheel, I'll just give you the link: http://www.askcrm.com/Default.aspx?tabid=866&EntryID=55

Gustaf Westerlund
Microsoft Dynamics CRM Architect

Logica
www.logica.com

Sunday, November 23, 2008

AT&T Wireless self destructs...

It's actually an old story by now but I just recently heard of it from my new staff manager and it is a very interesting story of just how bad a CRM implementation can get. It concerns Siebel and my analysis of the story is that the reson for the crash was mostly due to bad management and a lock on both timeframe and functionallity, something I believe is impossible if you want to achieve any kind of quality. This case being the perfect example.

Please read it and leave a comment here if you want to discuss it!
http://www.cio.com/article/32228/Project_Management_AT_T_Wireless_Self_Destructs

Gustaf Westerlund
Microsoft Dynamics CRM Architect

Logica
www.logica.com

Wednesday, November 19, 2008

Automatic restart of Async Service

When developing new workflow activities for CRM 4.0 you need to release the filelocks on the dll to be able to copy the new dll to the assembly directory. This can of course be done manually by restarting the service in the service manager but can be scripted into the prebuild events aswell, so that it is more automatic. Add the following two lines to the Pre-build events of your workflow activity project to make it restart the MSCRMAsyncService:

net stop "MSCRMAsyncService"
net start "MSCRMAsyncService"

Please note that you might inflict any ongoing workflows by doing this so take care if it is a live production server.

Gustaf Westerlund
Microsoft Dynamics CRM Architect

Logica
www.logica.com

Friday, November 14, 2008

Quick create

As many of you know, in CRM 3 there is a special view of an entity form called quickcreate. This is used when you press "New" in a lookup window. For instance, on an account you can press: select primary contact, when the search dialog shows you can instead of selecting an existing contact press the new button and a "slimline" version of the contact form show with just the must-have and should-have fields available.

In CRM 4 this feature is not used any more and the complete form will always be shown in this case, however, the functionality hasn't been removed. I tried to find some kind of reference to it in the SDK but couldn't so I had a look in the original CRM code in CRM 3 and found how to do it.

To open a form as quick create, find the object type code (1 = account etc) and go to the URL:
http://[server:port]/[organisation]/_forms/QuickCreateReturn/quickcreate.aspx?crmFormSubmitObjectType=[objecttypecode].

For example, for account on the local machine when CRM is installed on port 5555 and the company is named "company":
http://localhost:5555/company/_forms/QuickCreateReturn/quickcreate.aspx?crmFormSubmitObjectType=1

Since I couldn't find any official reference to this in the SDK it is very possibly unsupported to do this but it works for now. Any hotfixes or similar might, but are not very likely to change this functionality, new versions of CRM like v.next are more likely to change/remove this functionality.

Gustaf Westerlund
Microsoft Dynamics CRM Architect

Logica
www.logica.com

Tuesday, November 11, 2008

Putting all javascript code in external files

Dynamics CRM is great. It has some really nice functions like being able to add javascripts to different event in the form to handle special needs of the GUI.

However, it is only fine as long as these scripts arn't that many and not too complex. When they start getting more and more complex, bigger and their numbers start increasing it soon becomes an impossible tast of maintaining them all and there is no built in function to handle javascript includes without special code. It also takes a long time developing more complex code in the javascript form window in CRM and then running the preview or publishing it each time before testing.

There is light in the tunnel however, by using the technique specified bellow, you can both
get global javascript files, save and refresh only to see you changes, and keeping all scripts for one entity in one file (and not one for onLoad, one for onSave and one for each onChange that is needed).

A lot of credit for this has to go to Michael Höhne at Stunnware since he added a posting on his blog on how to manage javascript includes in runtime.

So, first of all we have to put some standard code in the onLoad. This should only be done once and it shouldn't really be changed until you need to publish it for release (switching of the caching).

var LoadFile = function(url, cache)
{
var httpRequest = new ActiveXObject("Msxml2.XMLHTTP");
httpRequest.open("GET", url, false);
if (!cache)

{
httpRequest.setRequestHeader("If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT");
}

httpRequest.send(null);
return httpRequest.responseText;
}

eval(LoadFile("/isv/mycrmext/javascripts/MyGlobal.js", false));
eval(LoadFile("/isv/mycrmext/javascripts/Account_onload.js", false));

This code simply loads and executes the two files MyGlobal.js and Account_onload.js located in the directory C:\Program Files\Microsoft Dynamics CRM\CRMWeb\ISV\myCRMEXT\JavaScripts
and can be found at the url: :port/isv/mycrmext/javascripts/">http://:port/isv/mycrmext/javascripts/.

So, copy-paste it into the onload event form in the account form editor in CRM. Activate the event, save and publish.

Then you can create the two .js-files at the specified directory. Start with just some test code like:
alert("This is the MyGlobal.js-file");
or something similar.

The next step is to try to avoid using the onsave and onchange events. This is quite easy when you know how but it is sort of in the gray area of supported customizations so be aware of this.

In the file Account_onload.js add the following code:
var MyOnSave = function()
{
alert("onSave");
}

var MyOnChange = function()
{
alert("onChange");
}


alert("onload)

crmForm.attachEvent("onsave", MyOnSave);
crmForm.all.name("onchange", MyOnChange);

This attaches a simple function to the onsave event of the form and another to the onchange event of the attribute "name".

The functional defintions/declarations can be put into any of the includefiles.

Now, just save the file, and open an account to see the magic! (It should show a dialog when loading with the text "onload", when the accountname is changed, it should show "onchange" and when saved, it should show "onsave".

Please note that I would advise you to put the javascript files in the same "host" from a IE perspective since you will get less problems with cross domain scripting and similar IE related security issues. This doesn't however mean that you cannot put the js-files anywhere on the internet where the clients can access it.

Gustaf Westerlund
Microsoft Dynamics CRM Architect

Logica
www.logica.com

Wednesday, November 05, 2008

How to get the URL to the reportserver programmatically

I was searching the net the other day to try to find a way to programmatically get the reporting server url from CRM. I thought that there must be some way to find it using the standard CRM webservice and I really looked throught the SDK and all the blogs I could find to see if anyone knew.



Finally I gave up and tried to find some other way to get it and I remembered that it is set in the registry so I wrote some code to get it from there and here it is in all it's simple glory:



RegistryKey regkey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\MSCRM");
string reportserver = regkey.GetValue("SQLRSServerURL").ToString();




And it worked but only just since it uses the server name and my VPN connection to the customers environment didn't bother with sending it to me why I have to manually add it to the hosts file.



The host file can be found at the path: C:\WINDOWS\system32\drivers\etc\hosts



and I added the row:

192.168.0.100 CRMTESTSRV



Now my button which point to my aspx that redirects to a the report in pdf-format works just fine and is independant of the CRM server it is installed on.



The solution isn't supported as far as I know since you never know if they might change the registry value in the future (not very likely in an update but might happen in an upgrade). If anyone has any supported way of getting this URL, please comment this post.



This could also be done using javascripts but I find it easier to manage server side code and it doesn't add that much overhead considering the report has to be generated independantly of if I use aspx or javascript to open the report.



Gustaf Westerlund
Microsoft Dynamics CRM Architect

Logica
www.logica.com