Thursday, June 27, 2013
Wednesday, June 19, 2013
Lazy fix of Infinite Loops in Plugins
Got an error stating that CRM has identified an infinite loop?
This usually means that the number of iterations reaches a maximum of 8. We can fix this by adding a depth check at the beginning of our plugin code, just after we initialize each of the service objects:IPluginExecutionContext _context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
IOrganizationServiceFactory _factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
_sdk = _factory.CreateOrganizationService(context.UserId);
ITracingService _tracer = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
if (_context.Depth > 1) // if the plugin has run more than once
{
// if so, executes a return statement to cancel out of the plugin
return;
}
Now when we run the plugin, we shouldn’t run into an infinite loop.
NB: You must be careful when using the DEPTH property as there can be more complex scenarios that you may run into.
CRM 2011 Database Backup
How to easily automate CRM database backup?
You can do it with help of SQL command or own console app.
You’ll need to backup the following CRM databases:
with format, name ='Full backup of <database name>'
{
string path = Path.Combine("C:\Temp\backups\sql\", string.Format("{0}_{1:yyyyMMdd_HHmmss}.bak",this.DatabaseName, DateTime.Now));
SqlCommand cmd = new SqlCommand(
string.Format(@"backup database {0} to disk ='{1}' with format, name ='Full backup of {0}'",
this.DatabaseName, path), conn);
cmd.CommandTimeout = 120;
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
}
Done ;)
You can do it with help of SQL command or own console app.
You’ll need to backup the following CRM databases:
- MSCRM_CONFIG
- *_MSCRM
SQL command to backup a database is:
backup database <database name> to disk ='C:\Temp\backups\sql\<database name_timestamp>.bak'with format, name ='Full backup of <database name>'
To backup the database using a console program - use the code below:
using (SqlConnection conn = new SqlConnection(this.ConnectionString)){
string path = Path.Combine("C:\Temp\backups\sql\", string.Format("{0}_{1:yyyyMMdd_HHmmss}.bak",this.DatabaseName, DateTime.Now));
SqlCommand cmd = new SqlCommand(
string.Format(@"backup database {0} to disk ='{1}' with format, name ='Full backup of {0}'",
this.DatabaseName, path), conn);
cmd.CommandTimeout = 120;
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
}
Done ;)
Tuesday, June 18, 2013
What’s not supported in the next major release of Microsoft Dynamics CRM (2013?)
Removal of the 2007 Endpoint and Legacy Features
The 2007 service endpoint was deprecated in the Microsoft Dynamics CRM 2011 release. Extensions that use the 2007 endpoint will not be supported and will not work in the next major release of Microsoft Dynamics CRM. Note the following more detailed information:- Microsoft Dynamics CRM Online customers using the Microsoft account identity provider can continue to use extensions that require the 2007 endpoint after upgrade. However, prior to the transition of your organization to Microsoft online services (MOS), you will need to upgrade or remove those extensions that require the 2007 endpoint.
- Microsoft Dynamics CRM Online customers using the Microsoft online services (MOS) identity provider will see no change in service. The 2007 endpoint has not been supported in organizations using the MOS identity provider.
- When Microsoft Dynamics CRM 2011 on-premises and IFD customers try to upgrade their server to the next major release of Microsoft Dynamics CRM, the upgrade process will detect extensions that are using the 2007 endpoint or legacy Microsoft Dynamics CRM 4.0 features. If any of these extensions are found, the Environmental Diagnostic Wizard will report an error and you will not be able to continue the upgrade until those extensions are removed or upgraded to use the 2011 endpoint.
The following legacy Microsoft Dynamics CRM 4.0 features will be removed or will no longer be supported in the next major product release:
Thursday, January 24, 2013
How to improve CRMAsyncService.exe memory and CPU usage.
The Microsoft CRM web site if hosted on a multi-processor/core server will automatically be using server Garbage Collection mode, but for managed Microsoft .Net programs like the CRMAsyncService.exe, they will default to the workstation garbage collection mode. Note that this resolution will only apply if Microsoft Dynamics CRM is installed on a multi-processor or multi-core server since the crmasyncservice will aways be forced to use the Microsoft .Net workstation garbage collection mode on a single CPU (non multi-core) server.
In order to allow the CRMAsyncService.exe to take advantage of all the processors/cores on a server, you can add the following element to a CRMAsyncService.exe.config file and place it in the same directory as the CRMAsyncService.exe program, typically in the “C:\Program Files\Microsoft Dynamics CRM\Server\bin” directory if you haven’t changed the default installation location for the Microsoft CRM Server.
Note that these changes will take effect the next time that you restart the Microsoft CRM Async Service. Also note that if you already have a crmasyncservice.exe.config file, to place this information for the <gcServer enabled=”true”/> into the Runtime and configuration tags as seen below.
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<runtime>
<gcServer enabled="true"/>
</runtime>
</configuration>
As with any changes, although this can give much better throughput for the Microsoft CRM Async Service and workflows able to be executed in a given time frame, it is best to measure the changes before and after implementing this change. The CRM Async Service perfmon counters can be used for this as well as counters for Memory, .Net CLR Memory, and Processor. There are also other factors such as customizations, workflows, and SQL Server performance that plays a factor in overall Microsoft CRM Async Service performance, but enabling gcServer mode is a great way to improve performance on multi-processor servers with minimal effort.
Friday, October 19, 2012
Microsoft CRM 2011 Solution backups with help of Plugins.
This small plugin can save a lot of time and put things under control. Each time somebody press on Publish All button, it creates a backup of all user solutions (system solution is ignored) and creates a task in the system with attached backups. So you can easily find a right task with right backups of solutions.
Wednesday, August 29, 2012
Optimizing Microsoft .NET ThreadPool Settings for Microsoft CRM 2011
You can modify parameters in the Machine.config file to accommodate a specific environment. However, if each .aspx page makes a Web service call to a single IP address, it is recommended to adjust these parameters as shown in the following table:
Thursday, March 22, 2012
Some useful functions for MS CRM 2011 Reports
Here is a
couple of useful functions for MS CRM 2011 reports:
Function that used to remove the duplicate
records
Public Shared Function RemoveDups(ByVal
items As String) As String
Dim noDups As New System.Collections.ArrayList()
Dim SpStr
SpStr = Split(items ,",")
For i As Integer=0 To Ubound(Spstr)
If Not
noDups.Contains(SpStr(i).Trim()) Then
noDups.Add(SpStr(i).Trim())
End
If
Next
Dim uniqueItems As String() = New String(noDups.Count-1){}
noDups.CopyTo(uniqueItems)
Return String.Join(",", uniqueItems)
End Function
SharePoint 2010 Form Based authentication for MS CRM 2011 Plugins
Some time you need to add, delete, or update custom items in a list on the SharePoint 2010 when plugins in MS CRM is fired up. This simple function can save your time :)
Passing MS CRM 2011 CRMParameter from ribbon button to Silverlight application
It’s pretty cool when you can pass CRMParameters to Silverlight application. To do that we need to get “location” :
public static string GetCRMParametr()
{
if (HtmlPage.IsEnabled)
{
dynamic location = (ScriptObject)HtmlPage.Window.GetProperty("location");
string crmParametr = location.search;
if(!string.IsNullOrEmpty(crmParametr))
{
return crmParametr
}
}
return null;
}
You can add some kind of dummy parser to extract guid’s from passed parameters:
public static string GetCRMParametr()
{
if (HtmlPage.IsEnabled)
{
dynamic location = (ScriptObject)HtmlPage.Window.GetProperty("location");
string crmParametr = location.search;
if(!string.IsNullOrEmpty(crmParametr))
{
return crmParametr
}
}
return null;
}
You can add some kind of dummy parser to extract guid’s from passed parameters:
Monday, October 31, 2011
Useful JavaScript commands for Microsoft CRM 2011 - Part 2: Xrm.Page.data.entity.attributes
Useful JavaScript commands for Microsoft CRM 2011 - Part 2: Xrm.Page.data.entity.attributes
Xrm.Page.data.entity.attributes
– provides methods to retrieve information and perform actions on attributes.
Command
|
Description
|
.addOnChange()
|
Sets a function to
be called when the attribute value is changed.
|
.fireOnChange()
|
Causes the OnChange
event to occur on the attribute so that any script associated to that event
can execute.
Example:
Xrm.Page.getAttribute("CRMFieldSchemaName").fireOnChange(); |
.getAttributeType()
|
Returns a string
value that represents the type of attribute.
|
.getFormat()
|
Returns a string
value that represents formatting options for the attribute.
|
.getInitialValue()
|
Returns the initial
value for Boolean or optionset attributes.
Attribute Types: Boolean,
optionset
|
.getIsDirty()
|
Returns a Boolean
value indicating if there are unsaved changes to the attribute value.
|
.getMax()
|
Returns a number
indicating the maximum allowed value for an attribute.
Attribute Types:
money, decimal, integer, double
|
Useful JavaScript commands for Microsoft CRM 2011 - Part 1: Xrm.Page.context
Useful JavaScript commands for Microsoft CRM 2011 - Part 1:
Xrm.Page.context
Xrm.Page.context
– provides methods to obtain information specific to the organization, user or
parameters that were passed in the form of a query string.
Command
|
Description
|
.getAuthenticationHeader()
|
Returns the encoded header SOAP-request for Web service in the style
of MSCRM 4.0.
|
.getCurrentTheme()
|
Returns the current user's Outlook theme.
|
.getOrgLcid()
|
Returns the value of the LCID for the main language of the
organization.
Example:
Xrm.Page.context.
getOrgLcid();
|
.getOrgUniqueName()
|
Returns the unique name of the organization.
|
.getQueryStringParameters()
|
Returns an array of key-value pairs passed in the query string.
|
.getServerUrl()
|
Returns the base server URL. When a user is working offline with Microsoft Dynamics CRM for Microsoft Office Outlook, the URL is to the local Microsoft Dynamics CRM Web services.
|
.getUserId()
|
Returns the GUID value of the SystemUser.id value for the current user.
Example:
Xrm.Page.context.getUserId();
|
.getUserLcid()
|
Returns the LCID value that represents the Microsoft Dynamics CRM Language Pack that is the user selected as their preferred language.
Example:
Xrm.Page.context.getUserLcid();
|
.getUserRoles()
|
Returns an array of strings representing the GUID values of each of the security roles that the user is associated with.
Example:
Xrm.Page.context.getUserRoles();
|
.isOutlookClient()
|
Returns a Boolean value indicating if the user is using Microsoft Dynamics CRM for Microsoft Office Outlook.
Example:
Xrm.Page.context.isOutlookClient();
|
.isOutlookOnline()
|
Returns a Boolean value indicating whether the user is connected to the Microsoft Dynamics CRM server while using Microsoft Dynamics CRM for Microsoft Office Outlook with Offline Access. When this function returns false, the user is working offline without a connection to the server. They are interacting with an instance of Microsoft Dynamics CRM running on their local computer.
Example:
Xrm.Page.context.isOutlookOnline();
|
.prependOrgName()
|
Adds the name of the organization to the specified path.
|
Friday, September 23, 2011
How to add color to a Microsoft CRM 2011 Form Picklist
Add color to target picklist is a very simple task. I will show you an example on Task form, Priority Picklist.
It has three options: Low, Normal, High.
Let’s add colors for them: Yellow, Green and Red.
Simply add OnLoad event:
function AddColorToPriority()
{
crmForm.all["prioritycode"][0].style.background = "#FFF380"; // Low => Yellow
crmForm.all["prioritycode"][1].style.background = "#5EFB6E"; // Normal => Green
crmForm.all["prioritycode"][2].style.background = "#E55451"; // High => Red
}
It has three options: Low, Normal, High.
Let’s add colors for them: Yellow, Green and Red.
Simply add OnLoad event:
function AddColorToPriority()
{
crmForm.all["prioritycode"][0].style.background = "#FFF380"; // Low => Yellow
crmForm.all["prioritycode"][1].style.background = "#5EFB6E"; // Normal => Green
crmForm.all["prioritycode"][2].style.background = "#E55451"; // High => Red
}
Here is
other way to implement it:
function AddColorToPrioritySecond()
{
crmForm.all.prioritycode[0].style.background = "yellow"; // Low => Yellow
crmForm.all.prioritycode[1].style.background = "green"; // Normal => Green
crmForm.all.prioritycode[2].style.background = "red"; // High => Red
}
{
crmForm.all.prioritycode[0].style.background = "yellow"; // Low => Yellow
crmForm.all.prioritycode[1].style.background = "green"; // Normal => Green
crmForm.all.prioritycode[2].style.background = "red"; // High => Red
}
Monday, September 19, 2011
Get a list of System and User Dashboards in CRM 2011
You can get
a complete list of System and User Dashboard by:
public void InitializeDashboardList()
{
this.GetSystemDashboard();
this.GetUserDashboard();
}
private void GetSystemDashboard()
{
if (!User.HasPrivilege("systemform", AccessRights.ReadAccess, (IOrganizationContext)UserInformation.Current))
return;
var systemdashboard = this.RetrieveDashboard("systemform", new string[4]
{
"formid",
"name",
"isdefault",
"description"
});
}
private void GetUserDashboard()
{
if (!User.HasPrivilege("userform", AccessRights.ReadAccess, (IOrganizationContext)UserInformation.Current))
return;
var userdashboard = this.RetrieveDashboard("userform", new string[3]
{
"userformid",
"name",
"description"
});
}
private ApplicationEntityCollection RetrieveDashboard(string logicalName, string[] columns)
{
QueryExpression query = new QueryExpression(logicalName);
query.ColumnSet.AddColumns(columns);
query.Criteria.AddCondition("type", ConditionOperator.Equal, (object)0);
query.Orders.Add((object)new OrderExpression("name", OrderType.Ascending));
return DataSource.RetrieveMultiple(query, (IOrganizationContext)UserInformation.Current);
}
public void InitializeDashboardList()
{
this.GetSystemDashboard();
this.GetUserDashboard();
}
private void GetSystemDashboard()
{
if (!User.HasPrivilege("systemform", AccessRights.ReadAccess, (IOrganizationContext)UserInformation.Current))
return;
var systemdashboard = this.RetrieveDashboard("systemform", new string[4]
{
"formid",
"name",
"isdefault",
"description"
});
}
private void GetUserDashboard()
{
if (!User.HasPrivilege("userform", AccessRights.ReadAccess, (IOrganizationContext)UserInformation.Current))
return;
var userdashboard = this.RetrieveDashboard("userform", new string[3]
{
"userformid",
"name",
"description"
});
}
private ApplicationEntityCollection RetrieveDashboard(string logicalName, string[] columns)
{
QueryExpression query = new QueryExpression(logicalName);
query.ColumnSet.AddColumns(columns);
query.Criteria.AddCondition("type", ConditionOperator.Equal, (object)0);
query.Orders.Add((object)new OrderExpression("name", OrderType.Ascending));
return DataSource.RetrieveMultiple(query, (IOrganizationContext)UserInformation.Current);
}
List of Microsoft CRM 2011 Web Services
List of Web Services:
http://demo:7777/AppWebServices/ActivitiesWebService.asmx
http://demo:7777/AppWebServices/AdvancedFind.asmx
http://demo:7777/AppWebServices/Annotation.asmx
http://demo:7777/AppWebServices/AppGridWebService.asmx
http://demo:7777/AppWebServices/AssociateRecords.asmx
http://demo:7777/AppWebServices/ActivitiesWebService.asmx
http://demo:7777/AppWebServices/AdvancedFind.asmx
http://demo:7777/AppWebServices/Annotation.asmx
http://demo:7777/AppWebServices/AppGridWebService.asmx
http://demo:7777/AppWebServices/AssociateRecords.asmx
Wednesday, September 14, 2011
Search all columns of all tables in a MS CRM 2011 database for a keyword.
Here is the complete stored procedure code:
CREATE PROC SearchKeywordInAllCRMTables
(
@SearchKeyword nvarchar(100)
)
AS
BEGIN
CREATE TABLE #SearchResults (ColumnName nvarchar(370), ColumnValue nvarchar(3630))
SET NOCOUNT ON
DECLARE @TableName nvarchar(256), @ColumnName nvarchar(128), @TempKeyword nvarchar(110)
CREATE PROC SearchKeywordInAllCRMTables
(
@SearchKeyword nvarchar(100)
)
AS
BEGIN
CREATE TABLE #SearchResults (ColumnName nvarchar(370), ColumnValue nvarchar(3630))
SET NOCOUNT ON
DECLARE @TableName nvarchar(256), @ColumnName nvarchar(128), @TempKeyword nvarchar(110)
Wednesday, September 7, 2011
Thursday, August 25, 2011
Create first plugin with Development Toolkit CRM 2011 Part 1.
Before we begin, let's create some additional entities. I want to create “Meeting” and “Resources” entities.
Entity Meeting should represent information about meeting, invited participants and needed resources. Meeting form should include such fields:
- Meeting Name.
- Location.
- Start date.
- End date.
- Description.
- Priority.
- Send Email to participant.
Also it should have 1:N relation to Contacts and Resources.
Entity Resources describes information about resources that are involved in the meeting. (Example: Projector, Microphones, Speakers and etc.)
Resources form should include such fields:
- Name.
Get string value of OptionSet in CRM 2011
If you need to retrieve StateCode or StatusCode or other OptionSet of attribute, then simply use code bellow:
public static OptionMetadataCollection GetOptionsSetByAttribute(IOrganizationService service, string entityName, string attributeName)
{
var retrieveAttributeRequest = new RetrieveAttributeRequest();
retrieveAttributeRequest.EntityLogicalName = entityName;
retrieveAttributeRequest.LogicalName = attributeName;
retrieveAttributeRequest.RetrieveAsIfPublished = true;
var optionMetadataCollection = (((StatusAttributeMetadata) retrieveAttributeResponse.AttributeMetadata).OptionSet).Options;
//foreach (OptionMetadata optionMetadata in optionMetadataCollection)
//{
// Here you can add your advanced logic.....
// optionMetadata.Label.UserLocalizedLabel.Label = "Teset";
//}
// or simply return OptionMetadataCollection....
return optionMetadataCollection;
}
To use it just write:
OptionMetadataCollection metadatas = GetOptionsSetByAttribute(this.OrganizationService, "new_cars", "statuscode");
public static OptionMetadataCollection GetOptionsSetByAttribute(IOrganizationService service, string entityName, string attributeName)
{
var retrieveAttributeRequest = new RetrieveAttributeRequest();
retrieveAttributeRequest.EntityLogicalName = entityName;
retrieveAttributeRequest.LogicalName = attributeName;
retrieveAttributeRequest.RetrieveAsIfPublished = true;
var retrieveAttributeResponse = (RetrieveAttributeResponse)service.Execute(retrieveAttributeRequest);
var optionMetadataCollection = (((StatusAttributeMetadata) retrieveAttributeResponse.AttributeMetadata).OptionSet).Options;
//foreach (OptionMetadata optionMetadata in optionMetadataCollection)
//{
// Here you can add your advanced logic.....
// optionMetadata.Label.UserLocalizedLabel.Label = "Teset";
//}
// or simply return OptionMetadataCollection....
return optionMetadataCollection;
}
To use it just write:
OptionMetadataCollection metadatas = GetOptionsSetByAttribute(this.OrganizationService, "new_cars", "statuscode");
Subscribe to:
Posts (Atom)



