Tuesday, November 17, 2015

PowerShell Tips: How to fix “split-path: Cannot find a provider with the name”


If we invoke PowerShell function from another PowerShell script and PowerShell function contains retrieve script path then it will gives this error.



The reason is function executes from another PowerShell and that function does not have knowledge of execution context of parent script.  To fix that we can retrieve the script path from PowerShell script which invoke the function and pass it to the function as a parameter.

Modified Function

function Deploy{

    param([string]$scriptPath)

    Process{
    $CrmCommanFile = join-path $scriptPath "\CRMCommand.exe"
    #Do what you want
    }
}


Modified PowerShell script which invoke the function

#$ErrorActionPreference = "stop"

# Find the current directory
$scriptPath = split-path -parent $MyInvocation.MyCommand.Definition

#Deploy CRM Customizations
. .\DeployScript.ps1
Deploy -scriptPath $scriptPath



Tuesday, November 10, 2015

CRM 2013 Tips: Set field read only/lock after save the record using CRM Business Rules

There are various ways to set field read only after saving record in CRM, most popular way is use JavaScript. However we can use Business Rule to set field read only based on the behavior of the other field or value of the same field. But there were no direct way to set field read only after saving the record. However we can utilize some behaviors of the Business Rule to set field read only after saving.

We can use “set field read only based on another field value” feature to set target field to read only. To do that we need a field which set value automatically after save the record and it should be read only by default. In CRM we have 4 fields which have those properties. Those fields are “Created By”, “Created On”, “Modified By” and “Modified On”. To set field read only after saving we need to add one of these fields to your target form (because Business Rules are working on the fields which available in the form). Then we can create business rule to set read only relevant field based on the value of previously mentioned fields.


For example:
I need to set read only field called “Identification Number” in the contact form after saving contact details.

Steps:
Add one of following fields in to the contact creation form.
  •     Crated On
  •     Created By
  •     Modified On
  •     Modified By

We choose “Created By” field as helping field to create business rule




Then create business rule to set “Identification Number” field to read only after set value to the “Crated By” field. We set business rule scope to form which we need to create contacts.



After activate business rule just create a contact record then you can see the Identification Number get locked because Created By field contains the data





Friday, November 6, 2015

C# - Fix Sequence contains no elements

This is very common error which can occur when you dealing with any kind of list/IQueryable etc. Root cause of this issue is when you apply filter/aggregate function (e.g. Max, Min etc.) to the list, it is empty. To avoid this kind of we can follow various ways to check list is empty or not. Otherwise we can fetch “FirstOrDefault” element rather than taking “First” element. 

Example

Exception:


-----------------------------System Exception Content-------------------------------
System.InvalidOperationException: Sequence contains no elements
   at System.Linq.Enumerable.Max(IEnumerable`1 source)
   at System.Linq.Enumerable.Max[TSource](IEnumerable`1 source, Func`2 selector)



 Code Snippet which cause this issue:


int compSteps=0;
if (appCompletedSteps.Count > 0)
{
compSteps = appCompletedSteps.Where(x => x.AppNumber == application.AppNumber).Max(y => y.StepID);
}


Code Fix: 

int compSteps=0;
if (appCompletedSteps.Count > 0 && appCompletedSteps.Where(x => x.AppNumber == app.AppNumber).Any())
{
compSteps = appCompletedSteps.Where(x => x.AppNumber == app.AppNumber).Max(y => y.StepID);
} 

Thursday, November 5, 2015

MSSQL: How to use “Link SQL” for query/sync databases in different database servers

Link SQL is very useful technique to connect database servers in same domain and querying them. Using Link SQL we can connect different databases and those details available in following article.

https://msdn.microsoft.com/en-us/library/ff772782.aspx?f=255&MSPPError=-2147217396 


In this we focus on link two SQL servers in same domain then querying and sync data between those two databases. We follow following steps to query two SQL databases in different database servers.



Step 1:

  • Make sure can access both database servers from each other.
  • Use SQL Management Studio to connect to the remote database server
  • If it unable to connect to the remote server then check it enabled named pipe and TCP/IP using SQL server configuration manager


Set TCP/IP enabled and Named Pipes Enabled - 32 bit mode

Set TCP/IP enabled and Named Pipes Enabled


  • If Management Studio still unable to access the SQL server remotely then check Windows firewall settings and gave necessary permission to access SQL server through. 
  • Setting Inbound Rule to access SQL server remotely

Create Inbound Rule in windows firewall

Set port which configured in SQL server


Step 2:




EXEC master.dbo.sp_addlinkedserver
   @server = N'XXX-UG07',
   @srvproduct=N'SQL Server' ;


  • After add database server as link server then all databases in that server available in current context. Following TSQL code shows how to execute stored procedure remotely then get data from SQL server and finally sync those data with target table.
  • Use “OPENQUERY” to execute stored procedure remotely and retrieve data.


DECLARE @BusinessUnit UNIQUEIDENTIFIER
DECLARE @CreatedBy UNIQUEIDENTIFIER
DECLARE @ModifiedBy UNIQUEIDENTIFIER
DECLARE @OwnerId UNIQUEIDENTIFIER
DECLARE @StateCode INT
DECLARE @StatusCode INT

set @BusinessUnit = '72921AD4-3025-E511-80BC-00155D156EA8'
set @CreatedBy = 'DDA81AD4-3025-E511-80BC-00155D156EA8'
set @ModifiedBy = 'DDA81AD4-3025-E511-80BC-00155D156EA8'
set @OwnerId = 'DDA81AD4-3025-E511-80BC-00155D156EA8'
set @StateCode = 0
set @StatusCode = 1


INSERT INTO [CC_MSCRM].[dbo].ContactBase
(Contactid,OwningBusinessUnit, CreatedBy, 
  CreatedOn, ModifiedBy, ModifiedOn,StateCode,StatusCode,
  FirstName,LastName,new_Number,OwnerId,OwnerIdType)

SELECT C1.contactid,@BusinessUnit,@CreatedBy,
    GETUTCDATE(),@ModifiedBy,GETUTCDATE(),@StateCode,@StatusCode,C1.FirstName, 
    C1.LastName, C1.new_AccountNumber,@OwnerId,8
FROM [XXX-UG07].CC_mscrm.dbo.contactbase C1
WHERE C1.contactid IN (SELECT contactid
FROM OPENQUERY([XXX-UG07],'CC_MSCRM.dbo.Test'))




Friday, October 30, 2015

Dynamic CRM Solution Deployment – Fix Access is Denied issue while importing CRM solutions



While importing CRM solution using Async service (CRM solution automated deployment), CRM copy the solution file (zip file) to the temporary directory with Guid (unique id). That temporary directory located inside of CRM installation directory. For example in our case it located in “C:\Program Files\Microsoft Dynamics CRM\CustomizationImport”. When we enable the trace using CRMDiag Tool it shows error in async service log like following. 

>Crm Exception: Message: Access is denied., ErrorCode: -2147187707, InnerException: System.UnauthorizedAccessException: Access to the path 'C:\Program Files\Microsoft Dynamics CRM\CustomizationImport\82c98e8896b34b2cb60e7741971a7921' is denied.
   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
   at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options, String msgPath, Boolean bFromProxy)
   at System.IO.FileStream..ctor(String path, FileMode mode)
   at Microsoft.Crm.CrmTemporaryFile..ctor(Byte[] fileData, String directoryName)
   at Microsoft.Crm.Tools.ImportExportPublish.RootImportHandler.ExtractFromCompressedFile(Byte[] compressedCustomizationFile, Boolean extractAllFiles)
   at Microsoft.Crm.Tools.ImportExportPublish.RootImportHandler..ctor(ImportXml parent, Boolean overwriteUnmanagedCustomizations, Boolean publishWorkflows, Byte[] compressedCustomizationFile, Boolean setup, Version existingDatabaseVersion, ExecutionContext context, Boolean extractAllFiles)
   at Microsoft.Crm.Tools.ImportExportPublish.ImportXml..ctor(Boolean overwriteUnmanagedCustomizations, Boolean publishWorkflows, Byte[] compressedCustomizationFile, Guid importJobId, Boolean convertToManaged, Boolean skipIntermediateImportJobUpdate, ExecutionContext context)
   at Microsoft.Crm.Tools.ImportExportPublish.ImportXml..ctor(Boolean overwriteUnmanagedCustomizations, Boolean publishWorkflows, Byte[] compressedCustomizationFile, Guid importJobId, Boolean convertToManaged, ExecutionContext context)
   at Microsoft.Crm.WebServices.ImportXmlService.ImportSolutionSkipCapable(Boolean overwriteUnmanagedCustomizations, Boolean publishWorkflows, Byte[] customizationFile, Guid importJobId, Boolean convertToManaged, Boolean skipProductUpdateDependencies, ExecutionContext context)
[2015-10-13 11:51:25.325] Process:CrmAsyncService |Organization:679a4ed3-4cb8-e411-940c-00155d6caa94 |Thread:    4 |Category: Platform.Sdk |User: d791b2fa-ce00-e011-903e-00155d6caa6a |Level: Error |ReqId: 6f0b3483-cfc9-42ae-b684-d9c141391f71 | VersionedPluginProxyStepBase.Execute  ilOffset = 0x65

 


How to fix:

The root cause of this issue is user who run the CRM Async service does not have write permission to the CRM Customization Import directory (in our case “C:\Program Files\Microsoft Dynamics CRM\CustomizationImport”). To fix this issue give necessary permission to the user who runs CRM Async service.



Identifying user who run CRM Async service

Navigate to Services -> Microsoft Dynamics CRM Asynchronous Processing Service, then check Log On As














Set permission to the user