Tuesday, 24 July 2012

The found version is 'C.0.8.40'. The expected version is '162'. (rsInvalidReportServerDatabase) - SSRS 2012

This morning I was trying to create the first organization in a MS Dynamics CRM 2011 deployment and when it tried to validate the SSRS URL, it failed with this error:
The version of the report server database is either in a format that is not valid or it cannot be read. The found version is 'C.0.8.40'.  The expected version is '162'. (rsInvalidReportServerDatabase)
I navigated to the SSRS URL and I got the same error.

It turns out that the error is fairly well known and can be easily resolved. All you need to do is recreate the reports database.
  1. Open Reporting Service Configuration Manager. [Start | All Programs | Microsoft SQL Server 2012 | Configuration Tools | Reporting Service Configuration Manager]
  2.  Connect to the report service instance that is giving you the problem
  3. Click Database.
  4. Click Change Database.
  5. Select Create a new report server database and follow the wizard.
This should get rid of this issue.

It would be a good idea to get rid of the old report database, to prevent any confusion, after you've backed it up, of course.

Monday, 23 July 2012

An unexpected error occurred. (Fault Detail is equal to Microsoft.Xrm.Sdk.OrganizationServiceFault).

In my previous post, I described how to import a solution programmatically, one thing I did not do was show how I instantiated the OrganizationServiceProxy nor how I had configured the Application Pools for the MS Dynamics website.

This is the method I used to instantiate the OrganizationServiceProxy:
 private OrganizationServiceProxy InstantiateOrgService(OrganizationServiceProxy service, string OrgName, string FQDN, int port = 80, int TimeOut = 600)
 {
     try
     {
         ClientCredentials creds = new ClientCredentials();
         creds.Windows.ClientCredential = (NetworkCredential)CredentialCache.DefaultCredentials;
 
         service = new OrganizationServiceProxy(new Uri(string.Format(Constants.OrgURL, FQDN, port, OrgName)), null, creds, null);
         service.Timeout = new TimeSpan(0, 0, TimeOut);
 
         return service;
     }
     catch (Exception ex)
     {
         MessageBox.Show(string.Format("Unable to instatiate the Org Service. Exception {0}", ex));
 
         return null;
     }
 }
I had another method that I had used where I passed in an specific set of credentials, rather than using default credentials, and that method had worked fine, but when I changed to the method above, it would not work and I would get this rather helpful message:
An unexpected error occurred.
(Fault Detail is equal to Microsoft.Xrm.Sdk.OrganizationServiceFault).
After a lot of hair pulling and useless Google searches (sorry my esteemed friend) I realized what I had changed, I was using Default Credentials, but the Application pool was not configured to use a domain account, so I changed the account running the CRM Application Pool to a domain account and this resolved the issue:


Saturday, 21 July 2012

Import solution programmatically in Microsoft Dynamics CRM 2011 (ImportSolutionRequest)

I've been working in trying to automate as much of our build as possible and one of the first things to try to automate was importing solutions.

The ImportSolutions method is designed to be invoked from a WPF application. SolutionsDirectory is entered through the GUI and should only contain solution files.

Not shown is the PublishSolution method, which is, hopefully, fairly self explanatory and only tries to publish the solution if the import was successful.

 private bool ImportSolutions(OrganizationServiceProxy OrgService, string SolutionsDirectory)
 {
    ImportSolutionRequest SolutionRequest;
    byte[] Solution;
 
    string[] files = Directory.GetFiles(SolutionsDirectory, Constants.ZipExtension);
 
    foreach (string file in files)
    {
        Solution = File.ReadAllBytes(file);
 
        SolutionRequest = new ImportSolutionRequest();
        SolutionRequest.CustomizationFile = Solution;
        SolutionRequest.ImportJobId = Guid.NewGuid();
        SolutionRequest.ConvertToManaged = true; //does this actually work?
 
        try
        {
            OrgService.Execute(SolutionRequest);
 
            Entity ImportJob = new Entity("importjob");
 
            ImportJob = OrgService.Retrieve(ImportJob.LogicalName, SolutionRequest.ImportJobId, new ColumnSet(true));
 
            XDocument xdoc = XDocument.Parse(ImportJob["data"].ToString());
 
            String ImportedSolutionName = xdoc.Descendants("solutionManifest").Descendants("UniqueName").First().Value;
            bool SolutionImportResult = xdoc.Descendants("solutionManifest").Descendants("result").First().FirstAttribute.Value
                == "success" ? true : false;
 
            Guid? SolutionId = GetSolutionGuid(OrgService, ImportedSolutionName);
 
            if (SolutionImportResult && SolutionId != null)
            {
                PublishSolution(OrgService, file, (Guid)SolutionId);
            }
 
        }
        catch (Exception ex)
        {
            MessageBox.Show(string.Format("An error occurred while uploading solution {0}.{1}Exception:{2}", file, Environment.NewLine, ex));
 
            return false;
        }
 
    }
 
    return true;
 }

Saturday, 14 July 2012

Create organization programmatically in Microsoft Dynamics CRM 2011

I've been working on automating various parts of the deployment of our new project and one of them is the creation of organizations. As I mentioned in a previous post, we are not doing a full install in any one server, which means that an organization is NOT created during the install and this is where the SDK comes in.

The method below, designed to be invoked from a WPF application, will create an Organization in MS Dynamics CRM 2011. Do bear in mind that creating an organization is a long process, it took a good 15 minutes in our development server when I tested it.

 private void CreateOrganization(DeploymentServiceClient service, string DisplayName, string UniqueName, string SqlServerName, string SrsUrl)
 {
     DeferredOperationStatus createOrgStatus;
 
     using (service)
     {
         Organization organization = new Organization
         {
             FriendlyName = DisplayName,
             UniqueName = UniqueName,
             SqlServerName = SqlServerName,
             SrsUrl = SrsUrl
         };
 
         try
         {
             BeginCreateOrganizationRequest request = new BeginCreateOrganizationRequest();
 
             request.Organization = organization;
 
             BeginCreateOrganizationResponse response = (BeginCreateOrganizationResponse)service.Execute(request);
 
             EntityInstanceId operationid = new EntityInstanceId()
             {
                 Id = response.OperationId
             };
 
             createOrgStatus = service.Retrieve(DeploymentEntityType.DeferredOperationStatus, operationid) as DeferredOperationStatus;
 
             //The process of creating new ORG is quite slow, thus the status is not checked regularly
 
             while (createOrgStatus.State != DeferredOperationState.Completed)
             {
                 Thread.Sleep(Constants.WaitInterval);
 
                 createOrgStatus = service.Retrieve(DeploymentEntityType.DeferredOperationStatus, operationid) as DeferredOperationStatus;
             }
 
             MessageBox.Show(string.Format("Organization {0} has been created.", UniqueName));
         }
         catch (Exception ex)
         {
             MessageBox.Show(string.Format("An exception has occurred while creating Organization {0}.{1}{2}.", UniqueName, Environment.NewLine, ex));
         }
 
     }
 }

The method below is used to instantiate the deployment service client with default credentials:

 private DeploymentServiceClient InstantiateDeploymentService(DeploymentServiceClient service, string FQDN, int port = 80, int TimeOut = 600)
 {
     try
     {
         service = ProxyClientHelper.CreateClient(new Uri(string.Format(Constants.DeploymentURL, FQDN, port)));
   
         service.Endpoint.Binding.SendTimeout = new TimeSpan(0, 0, TimeOut);
   
         return service;
     }
     catch (Exception ex)
     {
         MessageBox.Show(string.Format("Unable to instatiate Deployment Service. Exception {0}", ex));
   
         return null;
     }
 }

Note that you can use the PowerShell cmdlet Get-CrmOperationStatus to check the status of the import if you are really impatient (Remember to load the CRM Snap-in first: Add-PSSnapin Microsoft.Crm.PowerShell).

Friday, 13 July 2012

Install multiple roles of Microsoft Dynamics CRM 2011 from the command line

I finally had a chance to give installing Microsoft Dynamics CRM 2011 using the command line a go yesterday and I must say it wasn't plain sailing. One of the reasons was that we weren't doing a complete installation, which coupled with Microsoft deficient documentation resulted in a bit of grief.

We installed all front end roles and the deployment roles apart from the tools because the documentation is incorrect, it says the role name should be DeploymentManagerTool but in actual fact the role name is DeploymentTools, which meant that it uninstalled MS Dynamics CRM the second time we tried as it did not recognize the role, so it assumed that we wanted to uninstall.

Also, for some reason the documentation, see here, surrounds the value for the reboot clause with quotes, e.g. "true" which is wrong.

If you edit the configuration file with notepad, make sure that you save it as unicode, you can check this by opening the configuration file with Internet Explorer. If it opens it, then you are OK. Otherwise, open the file with notepad and ensure that it is save as unicode, see below:


For some reason, the Windows Process Activation Service was disabled in our servers, so we enabled it ( It was preventing IIS from starting halfway through the install).

The command to install from the command line is as follows
setupserver.exe /QR /L c:\logs\log.log /config c:\configfile.xml
We used two different config files, one for the Front End Server and Deployment and the another one for the Back End Server. The former was deployed first and the latter second on different servers. 

A few things to bear in mind:
  • The License key is the evaluation license
  • I think that the Reporting URL tag is not needed.
  • On the back end configuration database creation is set to false as this was created during Front end install.

Front End Server and Deployment configuration file:

  <CRMSetup>
  <Server>
  <Patch update="false" />
  <!--Evaluation License Key 90 Days 12/07/2012-->
  <LicenseKey>MQM2H-JYYRB-RRD6J-8WBBC-CVBD3</LicenseKey>
  <SqlServer>TEST008</SqlServer>
  <Database create="true"/>
  <Reporting URL="http://TEST008/ReportServer"/>
  <OU>OU=PSW,DC=CU,DC=ORG</OU>
  <InstallDir>C:\Program Files\Microsoft Dynamics CRM</InstallDir>
  
  <!--CRM Server Roles-->
  <Roles>
  <Role name="WebApplicationServer"/>
  <Role name="DeploymentWebService"/>
  <Role name="DiscoveryWebService"/>
  <Role name="OrganizationWebService"/>
  <Role name="HelpServer"/>
  <Role name="DeploymentTools"/>
  </Roles>
  
  <CrmServiceAccount type="DomainUser">
  <ServiceAccountLogin>cu\psw_svc</ServiceAccountLogin>
  <ServiceAccountPassword>P@ssw0rd123</ServiceAccountPassword>
  </CrmServiceAccount>
  
  <DeploymentServiceAccount type="DomainUser">
  <ServiceAccountLogin>cu\psw_svc</ServiceAccountLogin>
  <ServiceAccountPassword>P@ssw0rd123</ServiceAccountPassword>
  </DeploymentServiceAccount>
  
  <SQM optin="false"/>
  <muoptin optin="false"/>
  
  <Reboot>true</Reboot>
  </Server>
  </CRMSetup>

And the Back End Server configuration file:

 <CRMSetup>
 <Server>
 <Patch update="false" />
 <!--Evaluation License Key 90 Days 12/07/2012-->
 <LicenseKey>MQM2H-JYYRB-RRD6J-8WBBC-CVBD3</LicenseKey>
 <SqlServer>TEST008</SqlServer>
 <Database create="false"/>
 <Reporting URL="http://TEST008/ReportServer"/>
 <OU>OU=PSW,DC=CU,DC=ORG</OU>
 <InstallDir>C:\Program Files\Microsoft Dynamics CRM</InstallDir>
 
 <!--CRM Server Roles-->
 <Roles>
 <Role name="AsynchronousProcessingService"/>
 <Role name="SandboxProcessingService"/>
 </Roles>
 
 <CrmServiceAccount type="DomainUser">
 <ServiceAccountLogin>cu\psw_svc</ServiceAccountLogin>
 <ServiceAccountPassword>P@ssw0rd123</ServiceAccountPassword>
 </CrmServiceAccount>
 
 <DeploymentServiceAccount type="DomainUser">
 <ServiceAccountLogin>cu\psw_svc</ServiceAccountLogin>
 <ServiceAccountPassword>P@ssw0rd123</ServiceAccountPassword>
 </DeploymentServiceAccount>
 
 <SQM optin="false"/>
 <muoptin optin="false"/>
 
 <Reboot>true</Reboot>
 </Server>
 </CRMSetup>

Thursday, 12 July 2012

Date Parsing issues in C# (Regional Settings in Windows 2008)


A while ago I posted about some issues we had while parsing dates in a .NET application, well it was a MS Dynamics CRM application, but the code itself was a simple, run of the mill, web method.

Imagine my surprise when yesterday I had to sort out a similar issue for a new project I'm working on, though this time there were a couple of differences:
  1. No domain account was being used for the application pools.
  2. Operating System was Windows 2008 R2 Enterprise edition.
  3. Everybody concerned was convinced that it had been working up until now.
In all likelihood, it had only worked, because they had not looked far enough in to the future, i.e. they were parsing 10/07/2012, (i.e. 10th July) which would be parsed as 7th October, so when they tried 13/07/2012 the system stopped working.

The source of the problem as well as the solution were the same as last time:
  • The source: Using US version of Windows.
  • The solution: Set all users to UK settings.
This is accomplished like this (I assume that you have set up your current user with the local settings that you want, in my case UK):
  1. Open Region and Language section of Control Panel (Start | Control Panel | Region and Language)


  2. Select Administrative tab.


  3. Click Copy Settings.


  4. Tick as per screenshot.


  5. Click OK twice.
This sets all user and system accounts to use the same regional settings and solved all of our date parsing problems.

Wednesday, 11 July 2012

Extend Logical Volume RHEL/CentOS 6.x

In a previous post, I discussed how to generally manipulate logical volumes, the one thing I forgot to do was to do a real life test. What do I mean by a real life test?

We had an old box with a single hard drive and RHEL 6 installed on it. Unfortunately, it was a very small hard drive and we wanted to dump a database on that server to do a few tests, so we added another hard drive then did the following, hopefully self-explanatory:
  1. pvcreate /dev/sdb1
  2. vgextend VolGroup /dev/sdb1
  3. lvextend -l +100%FREE /dev/mapper/VolGroup-lv_root
  4. resize2fs /dev/mapper/VolGroup-lv_root
Now the root filesystem is a ginormous 38 GB, which is big enough for our purposes.

It's crucial that step 4 is carried out, as otherwise the filesystem will not extend to the totality of the logical volume, which is what was missing from my previous post.

Tuesday, 10 July 2012

Optional and Named Parameters in C#

As I mentioned a my previous post, I've recently started work in a new project that uses Microsoft Dynamics CRM 2011 and one of the first things I was asked to do was to write a method with a number of mandatory  [3] and optional [6] arguments/parameters of different types.

I thought to myself, this is great, now I have to write a lot of pointless logic to check whether the arguments/parameters have been passed in or use params and an object array plus a lot of logic to check what is being passed in. I dismissed passing in a complex object as there were too many permutations, which would require many many constructors and this is where I remembered reading about the new features of .NET Framework 4.0, which supports Optional and Named arguments/parameters.

The former are as their name would suggest optional and the latter are simply a way of calling optional parameters, so here is my method's signature, I won't explain the details as they are not relevant:

public AppointmentProposal[] GetAppointmentProposals(Guid SiteId, 

Guid ServiceId, int Duration, Guid? UserId = null, DateTime? Earliest = null,

DateTime? Latest = null, int MaxRows = 15, int SearchWindowRange = 7, 

int UserTimeZoneCode = 1)

The optional arguments/parameters have been give a default value, which means that if they are not passed in the default value will be used. This means that to a certain extent you still have to do some checking but it's a lot less checking that if you have to check whether the parameter is there.

In order to call the above method with mandatory parameters only, this is what you need, where SiteId and ServiceId are of type Guid.

GetAppointmentProposals(SiteId,ServiceId,60)

When invoked like this, GetAppointmentProposals will have the UserId, Earliest and Latest parameters set to null and the other three parameters will have their default values, namely: MaxRows will equal 15, SearchWindowRange will equal 7 and UserTimeZoneCode will equal 1.

If you want to change the MaxRows parameter, then you would invoke it like this:

GetAppointmentProposals(SiteId,ServiceId,60, MaxRows: 10)

When invoked like this, GetAppointmentProposals will have the UserId, Earliest and Latest parameters set to null and the other two parameters not specifically mentioned will have their default values, namely: SearchWindowRange will equal 7 and UserTimeZoneCode will equal 1 where MaxRows will equal 10.

Hopefully, that should clarify why they are called named parameters.

Monday, 9 July 2012

The type or namespace name 'Crm' does not exist in the namespace 'Microsoft'

I started working in a new project that uses Microsoft Dynamics CRM 2011 recently and I was trying to compile a console application to quickly test a method but no matter what I did, I kept getting a few of these errors:

The type or namespace name 'Crm' does not exist in the namespace 'Microsoft'
The type or namespace name 'Xrm' does not exist in the namespace 'Microsoft'

This despite the fact that I had added the SDK references to the project and then re-added them for good measure, but to no avail.  Then I remembered (actually, somebody pointed it out) that by default the Target Framework is set to the Client Profile rather than the Full Profile, so I changed it to the Full profile, like this:
  1. On the Project menu, click ProjectName Properties.
  2. Click the Application tab (selected by default).


  3. In the Target framework list, select .NET Framework 4.0.


  4. You'll see this dialog: Press Yes (The project properties will close).




  5. You can now compile your project.

Tuesday, 3 July 2012

Computer History Museum and HP Garage

I've away for a few weeks visiting relatives in sunny California and one of the places I visited was the Computer History Museum in Mountain View, CA.

It's a must for Geeks like me, for normal people like my girlfriend, I'm not so sure. Actually, that is not true, she found it really interesting, but had had enough after a few hours, I, on the other hand would have stayed all day and not only because I got this:
It took me a bit to work out that it spelt CHM in binary, because two of the ones are very close together and I was counting them as a single digit rather than two. Technically, it spells 67, 72 & 77 in Binary, which converted to its ASCII values is CHM.

I can recommend the Tour, or experience (the guide's own words), as the guide was very knowledgeable and because of this: 

Oh, yes, it's a punch card, a real one (at least the guide said so, so it must be true).

We also looked at a demonstration of the only working Babbage engine in the world, a very impressive machine, indeed.

The only disappointment was that flash photography was not allowed anywhere, which meant that taking pictures was tricky at the best of times, which is a shame. I did manage to take a few which can be seen below. All in all, it was a great experience at a fairly reasonable price

Xerox Alto - Probably the first ever personal Computer

Google Server Rack. All Google Searches were originally served from these servers

Finally, since we were in the neighbourhood, we thought we stopped by the birth of Silicon Valley, which is this little garage at 367 Addison Avenue in Palo Alto, where HP was founded.