Tag Cloud

CRM 2011 (161) CRM 4.0 (144) C# (116) JScript (109) Plugin (92) Registry (90) Techpedia (77) PyS60 (68) WScript (43) Plugin Message (31) Exploit (27) ShellCode (26) FAQ (22) JavaScript (21) Killer Codes (21) Hax (18) VB 6.0 (17) Commands (16) VBScript (16) Quotes (15) Turbo C++ (13) WMI (13) Security (11) 1337 (10) Tutorials (10) Asp.Net (9) Safe Boot (9) Python (8) Interview Questions (6) video (6) Ajax (5) VC++ (5) WebService (5) Workflow (5) Bat (4) Dorks (4) Sql Server (4) Aptitude (3) Picklist (3) Tweak (3) WCF (3) regex (3) Config (2) LINQ (2) PHP (2) Shell (2) Silverlight (2) TSql (2) flowchart (2) serialize (2) ASHX (1) CRM 4.0 Videos (1) Debug (1) FetchXml (1) GAC (1) General (1) Generics (1) HttpWebRequest (1) InputParameters (1) Lookup (1) Offline Plug-ins (1) OutputParameters (1) Plug-in Constructor (1) Protocol (1) RIA (1) Sharepoint (1) Walkthrough (1) Web.config (1) design patterns (1) generic (1) iframe (1) secure config (1) unsecure config (1) url (1)

Pages

Thursday, December 13, 2012

using pre & post images

using


System.Collections.Generic;

using


Microsoft.Xrm.Sdk;

using


Microsoft.Xrm.Sdk.Query;

using


System.ServiceModel;

namespace


TestCompany.CRM.Plugin

{

public


class officeUpdate : IPlugin

{



public void Execute(IServiceProvider serviceProvider)

{



IPluginExecutionContext context;

IOrganizationServiceFactory factory;

IOrganizationService service;

Entity PreImage;

Entity PostImage;



try

{

context = (

IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));

factory = (IOrganizationServiceFactory)serviceProvider.GetService(

typeof(IOrganizationServiceFactory));

service = factory.CreateOrganizationService(context.UserId);

PreImage = (Entity)context.PreEntityImages[

"PreUpdateImage"];

PostImage = (Entity)context.PostEntityImages[

"PostUpdateImage"];



int _preOfficestatusVal = 0;



int _postOfficestatusVal = 0;



if (PreImage.Contains("new_officestatus"))

{ _preOfficestatusVal = ((OptionSetValue)PreImage[

"new_officestatus"]).Value; }



if (PostImage.Contains("new_officestatus"))

{ _postOfficestatusVal = ((OptionSetValue)PostImage[

"new_officestatus"]).Value; }



if ((_preOfficestatusVal == 100000002) && (_postOfficestatusVal == 100000001))

{



// Logic for - Sub converted to Regional

}

}



catch (FaultException<OrganizationServiceFault> e)

{



throw e;

}



finally

{

service =
null;

factory =

null;

context =

null;

PreImage =

null;

PostImage =

null;

}

}

}

}

Debug a Plug-In

The following steps describe how to debug a plug-in executing on Microsoft Dynamics CRM 2011. To debug a plug-in that executes in the sandbox on Microsoft Dynamics CRM Online, you must using tracing as described later in this topic.
     

Debug a Plug-in

  1. Register and deploy the plug-in assembly.
    If there is another copy of the assembly at the same location and you cannot overwrite that copy because it is locked by Microsoft Dynamics CRM, you must restart the service process that was executing the plug-in. Refer to the table below for the correct service process. For more information, see Register and Deploy Plug-Ins.
  2. Configure the debugger.
    Attach the debugger to the process on the Microsoft Dynamics CRM server that will run your plug-in. Refer to the following table to identify the process.

     

    Plug-in Registration Configuration Service Process
    online
    w3wp.exe
    offline
    Microsoft.Crm.Application.Hoster.exe
    asynchronous registered plug-ins (or custom workflow assemblies)
    CrmAsyncService.exe
    sandbox (isolation mode)
    Microsoft.Crm.Sandbox.WorkerProcess.exe

    If there are multiple processes running the same executable, for example multiple w3wp.exe processes, attach the debugger to all instances of the running executable process. Next, set one or more breakpoints in your plug-in code.
  3. Test the plug-in.
    Run the Microsoft Dynamics CRM application, or other custom application that uses the SDK, and perform whatever action is required to cause the plug-in to execute. For example, if a plug-in is registered for an account creation event, create a new account.
  4. Debug your plug-in code.
    Make any needed changes to your code so that it performs as you want. If the code is changed, compile the code into an assembly and repeat steps 1 through 4 in this procedure as necessary. However, if you change the plug-in assembly's major or minor version numbers, you must unregister the earlier version of the assembly and register the new version. For more information, see Register and Deploy Plug-Ins.
  5. Register the plug-in in the database.
    After the edit/compile/deploy/test/debug cycle for your plug-in has been completed, unregister the (on-disk) plug-in assembly and then reregister the plug-in in the Microsoft Dynamics CRM database. For more information, see Register and Deploy Plug-Ins.
TipTip
It is possible to debug a database deployed plug-in. The compiled plug-in assembly's symbol file (.pdb) must be copied to the server's <crm-root>\Server\bin\assembly folder and Internet Information Services (IIS) must then be restarted. After debugging has been completed, you must remove the symbol file and reset IIS to prevent the process that was executing the plug-in from consuming additional memory.

For information on debugging a plug-in using the Plug-in Profiler tool, see Analyze Plug-in Performance.

Debug a Sandboxed Plug-in

It is important to perform these steps before the first execution of a sandboxed plug-in. If the plug-in has already been executed, either change the code of the assembly, causing the hash of the assembly to change on the server, or restart the Microsoft Dynamics CRM Sandbox Processing Service on the sandbox server.
Configure the Server
The sandbox host process monitors the sandbox worker process which is executing the plug-in. The host process checks if the plug-in stops responding, if it is exceeding memory thresholds, and more. If the worker process doesn't respond for than 30 seconds, it will be shutdown. In order to debug a sandbox plug-in, you must disable this shutdown feature. To disable the shutdown feature, set the following registry key to 1 (DWORD):
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSCRM\SandboxDebugPlugins 
Debug the Plug-in
Follow these steps to debug a sandboxed plug-in.
  1. Register the plug-in in the sandbox (isolation mode) and deploy it to the Microsoft Dynamics CRM server database.

  2. Copy the symbol file (.pdb) of the compiled plug-in assembly to the server\bin\assembly folder on the server running the sandbox worker process named Microsoft.Crm.Sandbox.WorkerProcess.exe. This is the server hosting the Sandbox Processing Service role.

  3. Follow the instructions in steps 2 through 4 presented at the beginning of this topic.

For information on debugging a plug-in using the Plug-in Profiler tool, see Analyze Plug-in Performance.

Logging and Tracing

An alternative method to debug a plug-in is to use tracing. Tracing assists developers in troubleshooting plug-ins by providing run-time plug-in information as an aid in diagnosing the cause of plug-in failure. Tracing is especially useful to debug Microsoft Dynamics CRM Online registered plug-ins as it is the only supported debugging method for that scenario.
The tracing discussed here is different from ASP.NET tracing. Tracing is implemented in the Microsoft Dynamics CRM SDK through the use of the tracing service ITracingService. Developers add Trace statements to their plug-in code, then build and deploy the plug-in. During execution and only when that plug-in passes an exception back to the platform at run-time, tracing information is displayed to the user. For a synchronous registered plug-in, the tracing information is displayed in a dialog of the Microsoft Dynamics CRM Web application. For an asynchronous registered plug-in, the tracing information is shown in the Details area of the System Job form in the Web application. The amount and nature of this information is up to you as a developer to code into your plug-ins.
The main reason for implementing this type of tracing is to support the isolated (sandboxed) plug-in capability in Microsoft Dynamics CRM. Sandboxed plug-ins are not able to write information to the system event log or the file system. The tracing service was implemented to provide sandboxed plug-ins with a means to output run-time information when an exception is thrown. In addition, tracing is also supported in plug-ins that are not sandboxed.
An important design feature of tracing is that the tracing information is only made available when an exception is passed from the plug-in back to the platform. When the error dialog is displayed in the Web application, the user must click the Download Log File button to view the log containing exception and trace output. If an exception is not thrown or is caught by the plug-in/custom activity code, any tracing information generated by your custom code is lost.
An alternate approach is to create a custom entity to track any run-time plug-in information that you want to record. When your plug-in executes, have the plug-in store its exception information in a record of your custom entity. In this way, you are logging your run-time plug-in information to the Microsoft Dynamics CRM database. This method works for any plug-in regardless of how it is registered. However, if the plug-in executes within the database transaction and an exception occurs that causes a transaction rollback, any entity data changes by the plug-in will be undone.
For more information about how to use tracing in plug-in code, see Sample: Azure Aware Custom Plug-In. For more information about platform (ASP.NET based) tracing, see the Microsoft Dynamics CRM 2011 Operating and Maintaining Guide, which is part of the Microsoft Dynamics CRM 2011 Implementation Guide.

Impersonate Another User

Impersonation is used to execute business logic (code) on behalf of another Microsoft Dynamics CRM user to provide a desired feature or service using the appropriate role and object-based security of that impersonated user. This is necessary because the Microsoft Dynamics CRM Web services can be called by various clients and services on behalf of a Microsoft Dynamics CRM user, for example, in a workflow or custom ISV solution. Impersonation involves two different user accounts: one user account (A) is used when executing code to perform some task on behalf of another user (B).

Required Privileges

User account (A) needs the privilege prvActOnBehalfOfAnotherUser, which is included in the Delegate role.
Alternately, for Active Directory directory service deployments only, user account (A) under which the impersonation code is to run can be added to the PrivUserGroup group in Active Directory. This group is created by Microsoft Dynamics CRM during installation and setup. User account (A) does not have to be associated with a licensed Microsoft Dynamics CRM user. However, the user who is being impersonated (B) must be a licensed Microsoft Dynamics CRM user.

Impersonate a User

To impersonate a user, set the CallerId property on an instance of OrganizationServiceProxy before calling the service's Web methods.

Impersonation in Plug-Ins

Impersonation is used to execute business logic (custom code) on behalf of a Microsoft Dynamics CRM system user to provide a desired feature or service for that user. Any business logic executed within a plug-in, including Web service method calls and data access, is governed by the security privileges of the impersonated user.
Plug-ins not executed by either the sandbox or asynchronous service execute under the security account that is specified on the Identity tab of the CRMAppPool Properties dialog box. The dialog box can be accessed by right-clicking the CRMAppPool application pool in Internet Information Services (IIS) Manager and then clicking Properties in the shortcut menu. By default, CRMAppPool uses the Network Service account identity but this can be changed by a system administrator during installation. If the CRMAppPool identity is changed to a system account other than Network Service, the new identity account must be added to the PrivUserGroup group in Active Directory. Refer to the "Change a Microsoft Dynamics CRM service account" topic in the Microsoft Dynamics CRM 2011 Implementation Guidefor complete and detailed instructions.
The two methods that can be employed to impersonate a user are discussed below.

Impersonation during plug-in registration

One method to impersonate a system user within a plug-in is by specifying the impersonated user during plug-in registration. When registering a plug-in programmatically, if the SdkMessageProcessingStep.ImpersonatingUserId attribute is set to a specific Microsoft Dynamics CRM system user, Web service calls made by the plug-in execute on behalf of the impersonated user. If ImpersonatingUserId is set to a value of null or Guid.Empty during plug-in registration, the calling/logged on user or the standard "system" user is the impersonated user.
Whether the calling/logged on user or "system" user is used for impersonation is dependent on the request being processed by the pipeline and is beyond the scope of the SDK documentation. For more information about the "system" user, refer to the next topic.
noteNote
When you register a plug-in using the sample plug-in registration tool that is provided in the SDK download, service methods invoked by the plug-in execute under the account of the calling or logged on user by default unless you select a different user in the Run in User's Context dropdown menu. For more information about the tool sample code, refer to the tool code under the SDK\Tools\PluginRegistration folder of the SDK download.

Impersonation during plug-in execution

Impersonation that was defined during plug-in registration can be altered in a plug-in at run time. Even if impersonation was not defined at plug-in registration, plug-in code can still use impersonation. The following discussion identifies the key properties and methods that play a role in impersonation when making Web service method calls in a plug-in.
The platform passes the impersonated user ID to a plug-in at run time through the UserId property. This property can have one of three different values as shown in the table below.

 

UserId Value Condition
Initiating user or "system" user
The SdkMessageProcessingStep.ImpersonatingUserId attribute is set to null or Guid.Empty at plug-in registration.
Impersonated user
The ImpersonatingUserId property is set to a valid system user ID at plug-in registration.
"system" user
The current pipeline was executed by the platform, not in direct response to a service method call.

The InitiatingUserId property of the execution context contains the ID of the system user that called the service method that ultimately caused the plug-in to execute.

ImportantImportant
For plug-ins executing offline, any entities created by the plug-in are owned by the logged on user. Impersonation in plug-ins is not supported while in offline mode.

Handle Exceptions in Plug-Ins

For synchronous plug-ins, the Microsoft Dynamics CRM platform handles exceptions passed back to the platform by displaying an error message in a dialog of the Web application user interface. The exception message for asynchronous registered plug-ins is written to a System Job (AsyncOperation) entity.
For plug-ins not registered in the sandbox, the exception message (System.Exception.Message) is also written to the Application event log on the server that runs the plug-in. The event log can be viewed by using the Event Viewer administrative tool. Since the Application event log is not available to sandboxed plug-ins, sandboxed plug-ins should use tracing. For more information, seeDebug a Plug-In.
You can optionally display a custom error message in a dialog of the Web application by having your plug-in throw an InvalidPluginExecutionException exception with the custom message as the Message property value. It is recommended that plug-ins only pass an InvalidPluginExecutionException back to the platform.

Pass Data Between Plug-Ins

The message pipeline model defines a parameter collection of custom data values in the execution context that is passed through the pipeline and shared among registered plug-ins, even from different 3rd party developers. This collection of data can be used by different plug-ins to communicate information between plug-ins and enable chain processing where data processed by one plug-in can be processed by the next plug-in in the sequence and so on. This feature is especially useful in pricing engine scenarios where multiple pricing plug-ins pass data between one another to calculate the total price for a sales order or invoice. Another potential use for this feature is to communicate information between a plug-in registered for a pre-event and a plug-in registered for a post-event.
The name of the parameter that is used for passing information between plug-ins is SharedVariables. This is a collection of key\value pairs. At run time, plug-ins can add, read, or modify properties in the SharedVariables collection. This provides a method of information communication among plug-ins.
This sample shows how to use SharedVariables to pass data from a pre-event registered plug-in to a post-event registered plug-in.
               
using System;  // Microsoft Dynamics CRM namespace(s) using Microsoft.Xrm.Sdk;  namespace Microsoft.Crm.Sdk.Samples {     /// <summary>     /// A plug-in that sends data to another plug-in through the SharedVariables     /// property of IPluginExecutionContext.     /// </summary>     /// <remarks>Register the PreEventPlugin for a pre-event and the      /// PostEventPlugin plug-in on a post-event.     /// </remarks>     public class PreEventPlugin : IPlugin     {         public void Execute(IServiceProvider serviceProvider)         {             // Obtain the execution context from the service provider.             Microsoft.Xrm.Sdk.IPluginExecutionContext context = (Microsoft.Xrm.Sdk.IPluginExecutionContext)                 serviceProvider.GetService(typeof(Microsoft.Xrm.Sdk.IPluginExecutionContext));              // Create or retrieve some data that will be needed by the post event             // plug-in. You could run a query, create an entity, or perform a calculation.             //In this sample, the data to be passed to the post plug-in is             // represented by a GUID.             Guid contact = new Guid("{74882D5C-381A-4863-A5B9-B8604615C2D0}");              // Pass the data to the post event plug-in in an execution context shared             // variable named PrimaryContact.             context.SharedVariables.Add("PrimaryContact", (Object)contact.ToString());         }     }      public class PostEventPlugin : IPlugin     {         public void Execute(IServiceProvider serviceProvider)         {             // Obtain the execution context from the service provider.             Microsoft.Xrm.Sdk.IPluginExecutionContext context = (Microsoft.Xrm.Sdk.IPluginExecutionContext)                 serviceProvider.GetService(typeof(Microsoft.Xrm.Sdk.IPluginExecutionContext));              // Obtain the contact from the execution context shared variables.             if (context.SharedVariables.Contains("PrimaryContact"))             {                 Guid contact =                     new Guid((string)context.SharedVariables["PrimaryContact"]);                  // Do something with the contact.             }         }     } } 
It is important that any type of data added to the shared variables collection be serializable otherwise the server will not know how to serialize the data and plug-in execution will fail.
For a plug-in registered in stage 20 or 40, to access the shared variables from a stage 10 registered plug-in that executes on create, update, delete, or by a RetrieveExchangeRateRequest, you must access the ParentContext.SharedVariables collection. For all other cases, IPluginExecutionContext.SharedVariables contains the collection.

IPluginExecutionContext

       
IPluginExecutionContext contains information that describes the run-time environment that the plug-in is executing in, information related to the execution pipeline, and entity business information. The context is contained in the System.IServiceProvider parameter that is passed at run-time to a plug-in through its Execute method.

// Obtain the execution context from the service provider. IPluginExecutionContext context = (IPluginExecutionContext)     serviceProvider.GetService(typeof(IPluginExecutionContext)); 

When a system event is fired for which a plug-in is registered, the system creates and populates the context and passes it to a plug-in through the above mentioned classes and methods. The execution context is passed to each registered plug-in in the pipeline when they are executed. Each plug-in in the execution pipeline is able to modify writable properties in the context. For example, given a plug-in registered for a pre-event and another plug-in registered for a post-event, the post-event plug-in can receive a context that has been modified by the pre-event plug-in. The same situation applies to plug-ins that are registered within the same stage.

All the properties in IPluginExecutionContext are read-only. However, your plug-in can modify the contents of those properties that are collections. For information on infinite loop prevention, refer to Depth.

CRM: Input and Output Parameters

The InputParameters property contains the data that is in the request message currently being processed by the event execution pipeline. Your plug-in code can access this data. The property is of type ParameterCollection where the keys to access the request data are the names of the actual public properties in the request. As an example, take a look at CreateRequest. One property of CreateRequest is named Target which is of type Entity. This is the entity currently being operated upon by the platform. To access the data of the entity you would use the name "Target" as the key in the input parameter collection. You also need to cast the returned instance.
// The InputParameters collection contains all the data passed in the message request.
if (context.InputParameters.Contains("Target") &&
context.InputParameters["Target"] is Entity)
{
// Obtain the target entity from the input parmameters.
Entity entity = (Entity)context.InputParameters["Target"];
Similarly, the OutputParameters property contains the data that is in the response message, for example CreateResponse, currently being passed through the event execution pipeline. However, only synchronous post-event and asynchronous registered plug-ins have OutputParameters populated as the response is the result of the core platform operation. The property is of type ParameterCollection where the keys to access the response data are the names of the actual public properties in the response.

CRM: Input and Output Parameters

The InputParameters property contains the data that is in the request message currently being processed by the event execution pipeline. Your plug-in code can access this data. The property is of type ParameterCollection where the keys to access the request data are the names of the actual public properties in the request. As an example, take a look at CreateRequest. One property of CreateRequest is named Target which is of type Entity. This is the entity currently being operated upon by the platform. To access the data of the entity you would use the name "Target" as the key in the input parameter collection. You also need to cast the returned instance.

C#

 

// The InputParameters collection contains all the data passed in the message request.

if (context.InputParameters.Contains("Target") &&

    context.InputParameters["Target"] is Entity)

{

    // Obtain the target entity from the input parmameters.

    Entity entity = (Entity)context.InputParameters["Target"];

Similarly, the OutputParameters property contains the data that is in the response message, for example CreateResponse, currently being passed through the event execution pipeline. However, only synchronous post-event and asynchronous registered plug-ins have OutputParameters populated as the response is the result of the core platform operation. The property is of type ParameterCollection where the keys to access the response data are the names of the actual public properties in the response.

CRM: Pre and Post Entity Images

PreEntityImages and PostEntityImages contain snapshots of the primary entity's attributes before (pre) and after (post) the core platform operation. Microsoft Dynamics CRM populates the pre-entity and post-entity images based on the security privileges of the impersonated system user. Only entity attributes that are set to a value or null are available in the pre or post entity images. You can specify to have the platform populate these PreEntityImages and PostEntityImages properties when you register your plug-in. The entity alias value you specify during plug-in registration is used as the key into the image collection in your plug-in code.
There are some events where images are not available. For example, only synchronous post-event and asynchronous registered plug-ins have PostEntityImages populated. In addition, the create operation does not support a pre-image and a delete operation does not support a post-image.