Microsoft Dynamics CRM supports an offline API, allowing you to develop solutions that work when disconnected from the Microsoft Dynamics CRM Web server. When deploying an integrated solution that runs using the Microsoft Dynamics CRM for Outlook with Offline Access, you need to take additional considerations into account.
We recommend that you create a separate installer for offline applications, even if the contents of the installers are symmetrical between the server and the client. The client installer typically requires less overhead, and you should find it easier to manage as a separate executable.
Remember that any custom Web pages that you load on the Microsoft Dynamics CRM server will not be accessible when the user works in a disconnected (offline) state. Microsoft Dynamics CRM uses a locally installed Cassini Web server to serve its Web pages. As discussed further in Chapter 10, your custom Web pages need to be accessible from the client’s computer, which means you must deploy versions of your Web pages to the Cassini Web server.
You will use the same techniques to deploy your custom Web files to the Offline Client that you use for the Microsoft Dynamics CRM server. However, the file location of the Offline Client Web site is slightly different. You can locate the Web site directory from the following registry value:
HKEY_CURRENT_USERSoftwareMicrosoftMSCRMClientInstallPath
The InstallPath value will typically be C:Program FilesMicrosoft Dynamics CRMClient. The Web site is stored in the resweb folders underneath this directory. For example, the Web site path might be C:Program FilesMicrosoft Dynamics CRMClient esweb.
As you learned in Chapter 5, plug-ins can execute when a user is offline. Each plug-in used by the Offline Client must have its public key token placed in the registry of the local computer. Microsoft Dynamics CRM instituted this requirement to prevent a "man-in-the-middle" attack during offline synchronization. This type of attack involves the interception of the plug-in assembly (which is stored as a Base64-encoded string) during offline synchronization. The assembly is then changed to a malicious assembly. The Offline Client then runs that assembly when the plug-in is triggered while in the offline state. However, an attacker cannot easily forge the public key token on the assembly (you require the original certificate file) when compiling the malicious assembly. So Microsoft Dynamics CRM compares all offline plug-in assemblies to a allow list stored in the client computer’s registry. The registry is used because it must be updated via a mechanism separate from offline synchronization. (Otherwise the attacker would simply change the allow list as well.)
Because the registry key used to store the allow list is user-specific, you may want to place the key in the registry during the configuration step.
The code sample in Example 9-1 shows how to read your public key token from your plug-in assemblies:
Example 9-1. Reading a registry key
using System; using System.IO; using System.Reflection; namespace ReadPublicKey { class Program { static void Main(string[] args) { //Get the paths from the Console Applications Arguments //Eg. ReadPublicKey.exe c:myplugin.dll //Ensure absolute paths are provided. string path = args[0]; //Load the Assembly Assembly assembly = Assembly.LoadFile(path); string[] properties = assembly.GetName().FullName.Split(",= ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); string publicKeyToken = properties[6]; //Write the Key to the Console Console.WriteLine(publicKeyToken); Console.ReadLine(); } } }
You should ensure that this value is added as a registry key in the following registry location: HKEY_CURRENT_USERSoftwareMicrosoftMSCRMClientAllowList.
The code in Example 9-2 demonstrates how to add this key to the registry:
Example 9-2. Creating a registry key
using System; using System.Text; using Microsoft.Win32; namespace AddPublicKey { class Program { static void Main(string[] args) { //Get PublicKey Token from Args //eg. AddPublicKey.exe 84d2d3539f7d7390 string publicKey = args[0]; string path = @"SoftwareMicrosoftMSCRMClientAllowList" + publicKey; RegistryKey registrykey = Registry.CurrentUser.CreateSubKey(path); registrykey.Close(); } } }
Figure 9-7 shows the registry key after being added.