Phil's CRM Blog

Blog Related To Microsoft CRM

At last!! i have passed the MB2-876 - Extending Microsoft Dynamics® CRM 2011 Exam.

Now that WAS difficult, passed on second attempt Phil

CRM 2011 Full Screen

In CRM 3 and CRM 4 you could maximise a form to use full screen with the following:    window.moveTo(0,0);     window.resizeTo(screen.availWidth, screen.availHeight); In CRM 2011 this has changed you must add .top to your javascript as below:,0);, screen.availHeight);

Microsoft Dynamics CRM 2011 Released for On-Premises and Partner-Hosted Deployments

Microsoft Dynamics CRM 2011 Released for On-Premises and Partner-Hosted Deployments   Microsoft delivers the Power of Productivity for customers across all deployment models; raises bar for performance and scalability with 150,000-concurrent-user benchmark.     REDMOND, Wash. — Feb. 16, 2011 — Microsoft Corp. (Nasdaq “MSFT”) today announced that Microsoft Dynamics CRM 2011 for on-premises and partner-hosted deployments has been completed and released for customer download. This release complements the latest version of Microsoft Dynamics CRM Online, which delivers Microsoft Dynamics CRM 2011 as an on-demand service from Microsoft’s datacenters and was launched into 40 markets and 41 languages in January. With a single multitenant code base across cloud and on-premises deployment models, Microsoft Dynamics CRM 2011 delivers the Power of Productivity to sales, service and marketing organizations worldwide. Microsoft Dynamics CRM 2011 is now globally available and existing customers with active Microsoft Software Assurance agreements can access the new version immediately via the Microsoft Download Center. In addition, Microsoft announced the new release scaled to 150,000 concurrent users in a single instance while delivering sub-second response times, once again raising the bar for performance and scalability in the CRM industry. The new benchmark results will be detailed in a Microsoft Dynamics CRM performance and scalability white paper that will be delivered in the coming weeks. “The need to build deeper and more profitable relationships on a global scale remains a CIO top priority,” said Mark Barrett, senior vice president, CRM, Avanade. “The combination of Avanade’s deep experience in solution development and Microsoft Dynamics CRM 2011 enables us to deliver comprehensive CRM capabilities to our clients through on-premises deployments as well as a software-as-a-service offering. Microsoft Dynamics CRM 2011 provides a platform for us to help companies strengthen customer and partner relationships, increase productivity, and collaborate across the organization.” Microsoft Dynamics CRM 2011 provides customers and partners with a wide range of benefits, including point-and-click configurability, enterprise scalability, and easy interoperability to existing applications and databases. It delivers the Power of Productivity for users in organizations of all sizes through its focus on the following: • Familiar experiences through a next-generation native Microsoft Outlook client, browser-based and mobile access, RoleTailored design, and advanced user personalization, improving user adoption and giving users easy access to the information they need to be successful. • Intelligent experiences through guided process dialogs, inline business intelligence for performance and goal management, and real-time dashboards, providing the most up-to-date information critical to enabling sales, service and marketing professionals to do their jobs effectively. • Connected experiences through flexible cloud development, Windows Azure interoperability, contextual Microsoft SharePoint capabilities and the new Microsoft Dynamics Marketplace, making it easy for customers and partners to configure and customize Microsoft Dynamics CRM to meet specific business needs. “Microsoft Dynamics CRM 2011 brings a whole new level of productivity to sales, marketing and customer service departments,” said Terje Laugerud, CEO, CIBER International. “The focus on familiar, intelligent and connected experiences appeals to our customers and provides an ideal platform for CIBER to deliver innovative CRM solutions to customers in a range of industries.” Integrated within Microsoft Dynamics CRM 2011, the Microsoft Dynamics Marketplace is available today in 20 markets and currently offers more than 1,400 partner offerings for solutions and services. This online catalog is an easy way for partners to market and distribute solutions to Microsoft Dynamics customers, whether online, on-premises or partner-hosted. The marketplace enables customers to quickly search, discover and apply industry-specific applications and solution extensions from Microsoft and its partners to help them accelerate and extend their CRM and ERP implementations. Microsoft Dynamics Marketplace is available in Austria, Australia, Belgium, Brazil, Canada, Chile, Colombia, Denmark, Germany, France, India, Italy, Japan, Mexico, Netherlands, Portugal, Russia, Switzerland, the United Kingdom and the United States. More information about partners and customers deploying Microsoft Dynamics CRM 2011 can be found at Those who want to follow and engage with the Microsoft Dynamics CRM community can do so at @MSDynamicsCRM, #crm2011. About Microsoft Dynamics Microsoft Dynamics is a line of simple to learn and use ERP and CRM solutions that work with your existing technology and scale as you grow to give you long-term value. By using software and online services that work the way people and organizations work, businesses are better able to make informed decisions and adapt to rapid change. Microsoft Dynamics helps your people be more productive and your investments in existing systems last longer, while enabling your business to derive the insights necessary to respond quickly and have a competitive edge in an ever-changing world of business. Source

Disabling IPV6 On Windows Server - Affects CRM on IFD

Well for the past week i have been battling with an IFD Server that is not on the main CRM server, so i logged a call with Microsoft and managed to get to resolve the issue, but i was still having problems accessing the AD Side of the IFD..... I Checked all my IP Adresses by running IPCONFIG /allThis showed me that i had 6to4 Tunnel running, but i had unticked the IPv6 entries from the Adapters, so why was this still here?so i then pinged the server from itself e.g ping serverurlthis was trying to ping an IPv6 Address, so i edited the registry as below: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\tcpip6\ParametersCreate a DWORD 32 bit Value and rename it to "DisabledComponents"Double click it and type 255 in the value box, it will disable IPv6.Restart! Then when the server came back up i had no 6to4 tunenel and the ping was resolving to the IPv4 Address, then tried logging in from the server and hey presto!!!The main reason for getting the machine to be able to login to CRM from itself via AD is that when running server based code e.g. Plugins, ISV customisations were failing with Error 4.01 as the server was trying to connect via the IPv6 Address which was disabled. Hope this helps someone else !! Phil

How To Enable Remote Errors For SQL Server Reporting Services

Enabling remote errors for SQL Server Reporting Services means setting EnableRemoteErrors Reporting Services system property to True There are two ways to set the EnableRemoteErrors property to True for a Reporting Services instance.  Update ReportServer database Configuration table for EnableRemoteErrors The first way is updating the ConfigurationInfo table which is in the ReportServer database for configuration record named "EnableRemoteErrors".The default value for EnableRemoteErrors property in the ConfigurationInfo database table is "False". You can simply run an update sql statement to enable remote errors.But you may not be successfull to see the changes made on the ConfigurationInfo table on the Reporting Services application, if the application is being used intensely.    Enable EnableRemoteErrors property though running a script Second way to enable remote errors is using and running a script which updates the running configuration values of the Reporting Services.The codes of the script that will update configuration values for EnableRemoteErrors is given in the SQL Server 2005 Books Online.I chosed this method for solution in my problem. And this method successfully worked for my case.Here is the script codes : Public Sub Main()Dim P As New [Property]()P.Name = "EnableRemoteErrors"P.Value = TrueDim Properties(0) As [Property]Properties(0) = PTryrs.SetSystemProperties(Properties)Console.WriteLine("Remote errors enabled.")Catch SE As SoapExceptionConsole.WriteLine(SE.Detail.OuterXml)End TryEnd Sub Copy the above script code in an empty text file and as the script file as EnableRemoteErrors.rss on the root folder of your C drive.Of course you can select an other name for the script file name and an other folder to save your script. I chosed C drive to keep it easy to run the below command promt statement.Open the command promt window by running the "cmd" command in the "Run" box. Then run the below command after you have replaced the ReportServerName with the actual name of the Reporting Services server you want to configure and the ReportServer instance name. You can keep ReportServer unchanged if you use the default configurations. rs -i C:\EnableRemoteErrors.rss -s http://ReportServerName/ReportServer Enabling remote errors for a Reporting Services may help you to get more detailed information that may help for troubleshooting problems with Reporting Services applications and reports you are developing, but do not forget that this is against security rules or general security policies.Keep the times you enable remote errors for your Reporting Services server  short.You can then disable remote errors again by setting EnableRemoteErrors property to "False" by using any of the above methods. But this time set the EnableRemoteErrors to False instead of True. Other Reporting Services Properties kept in ConfigurationInfo table in ReportServer database Here you can find a list of all SQL Server Reporting Services properties and default values kept in ReportServer database ConfigurationInfo table •Name : EnableClientPrinting Value : True•Name : EnableExecutionLogging Value : True•Name : EnableIntegratedSecurity Value : true•Name : EnableLoadReportDefinition Value : True•Name : EnableMyReports Value : False•Name : EnableRemoteErrors Value : False•Name : EnableReportDesignClientDownload Value : True•Name : ExecutionLogDaysKept Value : 60•Name : ExternalImagesTimeout Value : 600•Name : MyReportsRole Value : My Reports•Name : SessionTimeout Value : 600•Name : SharePointIntegrated Value : False•Name : SiteName Value : SQL Server Reporting Services•Name : SnapshotCompression Value : SQL•Name : StoredParametersLifetime Value : 180•Name : StoredParametersThreshold Value : 1500•Name : SystemReportTimeout Value : 1800•Name : SystemSnapshotLimit Value : -1•Name : UseSessionCookies Value : true

Using Unresolved Email Recipients in CRM 4.0

Unresolved emails are useful in that you can send an email to someone without having them setup as a system record (contact, account, lead, queue, user, ect).  Unresolved email addresses are turned off by default.  They should be used with caution.  If you send an email to an unresolved address it will not track the email to that lead/contact since one does not exist.  It also does not leverage the email "Do not allow" flags to allow people to opt out of emails.  With those considerations, there are still cases where it is very useful to send an email to someone without having to create a contact record. I will show two example of sending emails to unresolved recipients.  The first will be sent from the email form using JavaScript.  The second will be done in a plugin.  We will add two unresolved email addresses as CC addresses on emails sent from a contact record. Before we begin.  You must flip the setting to allow unresolved recipients.  Go to Settings --> Administration --> System Settings --> Email Tab.  Set Allow messages with unresolved e-mail recipients to be sent to yes.  Second, we will add a couple of fields to the contact for secondary contacts email addresses.  These fields will contain our unresolved email addresses. JavaScript ImplementationWhen the user clicks "Send Email" from the contact form we want the CC field to default with the two unresolved email addresses.  To do this we add the following Jscript to the onload of the email form.  The code will check to see if the regarding object is of type contact since this form is used for all emails.  Then it adds each email address to an email object that follows the activityparty schema for unresolved email addresses.  It has a type of 9206 and the email is set in the data property.if (crmForm.FormType == 1 &&    crmForm.all.regardingobjectid.DataValue != null &&    crmForm.all.regardingobjectid.DataValue[0].typename == "contact" &&    window.opener != null &&    window.opener.document != null) {     var ar = new Array();    var emailObj = new Object();     if (window.opener.document.crmForm.all.new_secondarycontactemail1 != null &&            window.opener.document.crmForm.all.new_secondarycontactemail1.DataValue != null) {        emailObj = new Object();        emailObj['type'] = '9206';        emailObj['category'] = '3';        emailObj['data'] = window.opener.document.crmForm.all.new_secondarycontactemail1.DataValue;        emailObj['name'] = window.opener.document.crmForm.all.new_secondarycontactemail1.DataValue;        ar.push(emailObj);    }     if (window.opener.document.crmForm.all.new_secondarycontactemail2 != null &&            window.opener.document.crmForm.all.new_secondarycontactemail2.DataValue != null) {        emailObj = new Object();        emailObj['type'] = '9206';        emailObj['category'] = '3';        emailObj['data'] = window.opener.document.crmForm.all.new_secondarycontactemail2.DataValue;        emailObj['name'] = window.opener.document.crmForm.all.new_secondarycontactemail2.DataValue;        ar.push(emailObj);    } = ar; } Lastly, publish the customization.  When you click "Send Email" from the contact form your addresses will be added to the CC.      Plugin Implementation The same functionality can be added using a plugin.  The benefits of using a plugin versus a client side implementation is that you can implement consistent functionality regardless of whether the email send is triggered from a client portal, another plugin, or through the CRM UI.  The JavaScript implemenation is useful in that the user can see who the email is being sent to before they click Send.  Install the plugin using the registration tool as a pre-create step for email save.  This will add the CC on the initial save of the email.  It is triggered regardless of whether the user clicks save or send from the email form.  The code also includes duplicate checking logic. So, if the user adds the email address to the CC from the form it will not duplicate the same address in the plugin. using System.Web;using System.Net; using System;using System.Collections.Generic;using System.Linq;using System.Text;using Microsoft.Crm.Sdk;using Microsoft.Crm.SdkTypeProxy;using Microsoft.Crm.Sdk.Query;using System.Reflection;using System.Web.Services.Protocols;using Microsoft.Crm.SdkTypeProxy.Metadata;using Microsoft.Crm.Sdk.Metadata;using Inetium.CrmPlugins;using System.Collections; namespace Inetium.CrmPlugins.Plugins{    public class CaseUnresolvedEmailPlugin : IPlugin    {        public void Execute(IPluginExecutionContext context)        {            ICrmService service = null;            try            {                if (context.InputParameters.Properties.Contains("Target") &&                    context.InputParameters.Properties["Target"] is DynamicEntity)                {                    DynamicEntity entityInput = context.InputParameters.Properties["Target"] as DynamicEntity;                    if (entityInput.Properties.Contains("regardingobjectid"))                    {                        Lookup regardingObjectLookup = entityInput.Properties["regardingobjectid"] as Lookup;                        service = context.CreateCrmService(true);                                                // Only using this for contacts                        if (regardingObjectLookup.type ==                        {                            // Pull parent contact - using helper method                            DynamicEntity ctn = CRMUtilities.RetrieveById(service,, "contactid", regardingObjectLookup.Value, new ColumnSet(new string[]{"new_secondarycontactemail1", "new_secondarycontactemail2"}));                            if (!ctn.Properties.Contains("new_secondarycontactemail1") && !ctn.Properties.Contains("new_secondarycontactemail2"))                                return;                             string email1 = ctn.Properties.Contains("new_secondarycontactemail1") ? ctn.Properties["new_secondarycontactemail1"].ToString() : "";                            string email2 = ctn.Properties.Contains("new_secondarycontactemail2") ? ctn.Properties["new_secondarycontactemail2"].ToString() : "";                             DynamicEntity[] partyArrayExisting = entityInput.Properties.Contains("cc") ? entityInput.Properties["cc"] as DynamicEntity[] : new DynamicEntity[] { };                            List<DynamicEntity> partyList = new List<DynamicEntity>(partyArrayExisting);                             if (email1 != "" && !IsEmailAlreadyInCC(email1, partyList))                            {                                DynamicEntity party = new DynamicEntity();                                party.Name = EntityName.activityparty.ToString();                                party.Properties["addressused"] = email1;                                partyList.Add(party);                            }                             if (email2 != "" && !IsEmailAlreadyInCC(email2, partyList))                            {                                DynamicEntity party = new DynamicEntity();                                party.Name = EntityName.activityparty.ToString();                                party.Properties["addressused"] = email2;                                partyList.Add(party);                            }                             // Generate CC's list by adding in those from contacts                            if (partyList.Count > 0)                                entityInput.Properties["cc"] = partyList.ToArray();                         }                     }                }            }            catch (SoapException se)            {                throw new Exception(se.Detail.InnerText);            }            catch (Exception ex)            {                throw new Exception(ex.Message);            }            finally            {                if (service != null)                {                    service.Dispose();                    service = null;                }            }        }         private bool IsEmailAlreadyInCC(string email, List<DynamicEntity> activityPartyList)        {            bool bAlreadyExists = false;            foreach (DynamicEntity existingParty in activityPartyList)            {                // compare to existing CCs                if (existingParty.Properties.Contains("addressused") &&                    (existingParty.Properties["addressused"].ToString() == email))                {                    bAlreadyExists = true;                    break;                }            }            return bAlreadyExists;        }    }} Source: Andrew Zimmer

CRM 4 Install and SQL Error 15401

Last week i have had an issue where during the install of CRM 4, this is a fresh install the setup as follows: SQL Box - Windows 2008 R2 + SQL2008 SP1CRM Box - Windows 2008 R2 now both boxes have been freshly prepped and joined to the domain, all with out errors.for added installation proof both servers had their windows firewalls turned off. upon the Installation of CRM i encountered this error:14:41:37|  Error| System.Exception: Action Microsoft.Crm.Setup.Server.GrantConfigDBDatabaseAccessAction failed. ---> System.Data.SqlClient.SqlException: Windows NT user or group 'Domain\SQLAccessGroup {9e798758-54f6-44a6-93a6-51b6faf49928}' not found. Check the name again.    at Microsoft.Crm.Setup.Database.SharedDatabaseUtility.GrantDBAccess(String sqlServerName, String databaseName, String groupName, CrmDBConnectionType connectionType)    at Microsoft.Crm.Setup.Server.GrantConfigDBDatabaseAccessAction.Do(IDictionary parameters)    at Microsoft.Crm.Setup.Common.Action.ExecuteAction(Action action, IDictionary parameters, Boolean undo)    --- End of inner exception stack trace ---, Error, RetryCancel, Option1 Now its quite obvious at this stage that it is failing to Gannt Access to an account to the MSCRM_CONFIG Database on the SQL server. so i tried to add the SQLAccessGroup manually in the SQL Management Tools and the Error 15401: Windows NT user or group 'SCDC2003\SQLAccessGroup {9e798758-54f6-44a6-93a6-51b6faf49928}' not found. Check the name again. now this is strange as i could not add the account manually, So i thought is this just Group Related and tried add a domain user and the same problem reared it's ugly head. so a call to the Microsoft Support Team and some tests later, after running: (13.04 kb) via the command line:name2sid.exe domain\anyuser the real error appeared:LookupAccountName failed with error: The trust relationship between this workstation and the primary domain failed. (0x6fd/1789)Now this helps the Microsoft Guys a lot so they asked me run:netdom resetpwd /server:<DomainControllerName> /userd:<domain\domainadminuser> /passwordd:<password>This Command Replied with:The machine account password for the local machine has been successfully reset. The command completed the next thing to do is to put this new command into action by restarting the netlogon service:net stop netlogonnet start netlogonand clear the kerberos Tickets on the sql server:klist purge then i tried adding the group manually again and hey presto and shazzam, it was working. i hope this helps others having similar problems. Phil

Debugging Workflows and Plugins in Microsoft Dynamics CRM 4.0

The concept of debugging plugins and workflows has been blogged about in the past.  There is a lot of great information out there.  One thing I have noticed about debugging is that it involves a lot of steps.  These steps take time.  You end up waiting forever from the time you make a code change to the time that you are debugging again.  I wanted to share a couple things I have learned about debugging that have saved me a great deal of time. Time Wasters: Starting and stopping IIS and the async service Deploying your new assembly Attaching to processes Getting back to debugging after making a small code change Let’s get started… … Project Setup I like to start with a vanilla system on a virtual PC (VPC) that has CRM installed.  I import the customizations into my environment and set up some quick test data. Note:  I stay away from remote debugging when possible as it requires specific security privileges on the CRM server and you will affect users that are trying to access the system. From my VPC I open the project that includes my workflow or plugin.  Be sure to set the build path to the bin/assembly folder of your CRM instance.  On my machine it is C:\Program Files\Microsoft Dynamics CRM\server\bin\assembly\.  It varies from installation to installation.   Building to this location allows us to register the plugin to disk and make code changes quickly without having to move files around or re-register anything. Register Plugin Open the registration tool and register your plugin or workflow.  Be sure to register the plugin to disk. Note:  When you move to production I recommend registering to the database, but registering to disk works great for debugging. Attaching to Processes Now that you have the plugin registered, you are ready to start debugging.  You need to attach to W3WP.exe to attach to plugins since they run within IIS.  To attach to workflows you need to attach to the CRM async service which is Crmasyncservice.exe.   Select w3wp.exe and Crmasyncservice.exe and click “Attach.” To expedite the process I used a trick from Janne Mattila.  You leverage VS macros to attach to the processes by using a shortcut key. I have Ctrl+Shift+V tied to a script that attaches to both w3wp and crmasyncservice.   See my script below. Courtesy of Janne Mattila: Imports System Imports EnvDTE Imports EnvDTE80 Imports EnvDTE90 Imports System.Diagnostics Public Module AttachHelper     ' This subroutine attaches to w3wp.exe:     Sub Attach()         Dim attached As Boolean = False         Dim proc As EnvDTE.Process         For Each proc In DTE.Debugger.LocalProcesses             If (Right(proc.Name, 8) = "w3wp.exe") Then                 proc.Attach()                 attached = True             End If         Next         If attached = False Then             MsgBox("Couldn't find w3wp.exe")         End If         attached = False         For Each proc In DTE.Debugger.LocalProcesses             If (Right(proc.Name, 19) = "CrmAsyncService.exe") Then                 proc.Attach()                 attached = True             End If         Next         If attached = False Then             MsgBox("Couldn't find crmasyncservice.exe")         End If     End Sub End Module So we are now able to quickly attach to processes.  We can debug.  Awesome!!!   But wait!  Next, you discover you need to make a code change.  We don’t have edit-and-continue available in plugins yet.  So, you stop the your session, make your code change and you get the following error when you try to build.   This is because you are trying to build to a file location that is already locked by the async service and/or IIS.  To get around this I have a bat file on my desktop and I run it every time I want to rebuild.  It includes the following: iisreset net stop MSCRMAsyncService net start MSCRMAsyncService "C:\Program Files\Internet Explorer\iexplore.exe" http://andrewvpc:5555 This script restarts IIS to unlock w3wp.exe.  Second, it restarts the async service.  Lastly, I reopen the CRM website in IE, so IIS will re-spawn itself (replace andrewvpc with your servername).  Otherwise, when you try to attach to processes it won’t be able to find w3wp.exe.   Now that you have ran the script, try to rebuild.  You will be rid of your error message and it will build successfully.  Now re-run your macro using Ctrl+Shift+V.  You are back to debugging again. Enjoy!!! Source: Andrew Zimmer

Date field lookup cut off in IE8

This seemed strange to me, as I knew that I had used right hand date fields in CRM 4 previously, and it had worked.  I tested on another machine, this time with IE 7, and the calendar lookup was not cut off.     Internet Explorer 7                                          Internet Explorer 8 Turns out that it’s not really a bug in CRM, but rather a side effect from some changes in Internet Explorer 8.  The CRM team worked with the IE team and came back with a fix for this issue.  The fix is to install IE update 974455 and make the following registry change on the client: HKEY_LOCAL_MACHINE\Software\Microsoft\Internet Explorer\Main\FeatureControl Create a new Key, and name it as follows: FEATURE_FORCE_POPUPS_ONTO_MONITOR_KB974537 Within this key, point to New , and then click DWORD Value Type iexplore.exe for the name of the key Right-click iexplore.exe , click Modify and then type 1 in the Value data field Read more about this fix at the UK MSCRM Support Blog.

Determining CRM 4 ServicePack Level

Since Microsoft first released Microsoft CRM 4.0 (in early 2008) they have released several hotfix roll ups.  Each hotfix rollup fixes several problems that have been identified since the initial release.  It is generally recommended that you keep your CRM patched with the latest release.  However, it can often be difficult to know which hotfix has been applied to an installation of Microsoft CRM.  To determine which hotfix has been applied to your installation look at Help About (found on the top right hand side of the Internet Explorer window if using CRM via the browser or CRM > Help > About if using CRM via Outlook.  The Help About window will look similar to the following: The hotfix that has been applied to your installation is indicated by the number in brackets after the CRM 4.0, and in particular the final four digits. An explanation of the numbers and their corresponding release numbers is given below: RTM: 4.0.7333.3 Rollup 1: 4.0.7333.1213 Rollup 2: 4.0.7333.1312 Rollup 3: 4.0.7333.1408 Rollup 4: 4.0.7333.1551 Rollup 5: 4.0.7333.1644 Rollup 6: 4.0.7333.1750 Rollup 7: 4.0.7333.2138 Rollup 8: 4.0.7333.2542 Rollup 9: 4.0.7333.2644 Rollup 10: 4.0.7333.2741 Rollup 11: 4.0.7333.2861 Rollup 12: 4.0.7333.2935 One reason that it is important to be able to determine the hotfix version of an installation is when you want to import customisations from one version to another.  This is not always possible if the two installations are running different hotfixes.Another reason to upgrade your installation is to benefit from the latest security patches and optimisation improvements.  In particular, hotfix rollup 5 introduced a number of speed improvements.