Show Picklist item in CRM 4.0

 
/* Jscript */

function ShowPickListItem(listID, value)
{
var objList = document.getElementById(listID);

if (objList.SavedList != null)
{
var selValue = null;
var indexInsertion = 0;

for (var i=0; i if (objList.SavedList[i].value == value)
objList.SavedList[i].Visible = true;

// Keep the selected value so we can reselect it after
if (objList.selectedIndex > -1)
selValue = objList.options[objList.selectedIndex].value;
// Remove all the items in the list
for (var i=objList.options.length - 1; i>=0; i--)
objList.options.remove(i);

// Add the items that must be visible
for (var i=0; i {
if (objList.SavedList[i].Visible)
{
var oOption = document.createElement('option');

oOption.text = objList.SavedList[i].Libelle;
oOption.value = objList.SavedList[i].value;

objList.options.add(oOption);
}
}

// Reselect the item that was selected
for (var i=0; i if (objList.options[i].value == selValue)
objList.selectedIndex = i;
}
}

Hide picklist item in CRM 4.0

 
/* Jscript */

function HidePickListItem(listID, value)
{
var objList = document.getElementById(listID);

// If the list has never been saved, save it now
if (objList.SavedList == null)
{
var arrListe = new Array();

for (var i=0; i {
arrListe[i] = new Object();
arrListe[i].value = objList.options[i].value;
arrListe[i].Libelle = objList.options[i].text;
arrListe[i].Visible = true;
}

objList.SavedList = arrListe;
}

for (var i=0; i if (objList.SavedList[i].value == value)
objList.SavedList[i].Visible = false;

for (var i=objList.options.length - 1; i>=0; i--)
if (objList.options[i].value == value)
objList.options.remove(i);
}

Route Message

Moves an entity instance from one queue to another.

Remarks

To use this message, pass an instance of the RouteRequest class as the request parameter in the Execute method.

There are three types of routing behavior as shown in the following table.

Route type        Description

User                 Routes the entity instance to the queue belonging to a user. The field EndpointId must be the ID of a user.

Queue              Routes the entity instance to a specific queue. The field EndpointId must be the ID of a queue.

Auto                Performs automatic routing using workflow. The field EndpointId is ignored. The field SourceQueueId specifies the ID of the queue that contains the entity instance specified in the Target field.

To perform this action, the caller must have access rights on the entity instance specified in the request class. For a list of required privileges, see Route Privileges.

  
//# The following code example shows how to use the Route message.

// Set up the CRM service.
CrmAuthenticationToken token = new CrmAuthenticationToken();
// You can use enums.cs from the SDK\Helpers folder to get the enumeration for Active Directory authentication.
token.AuthenticationType = 0;
token.OrganizationName = "AdventureWorksCycle";

CrmService service = new CrmService();
service.Url = "http://:/mscrmservices/2007/crmservice.asmx";
service.CrmAuthenticationTokenValue = token;
service.Credentials = System.Net.CredentialCache.DefaultCredentials;


// Create the target object for the request.
TargetQueuedAppointment target = new TargetQueuedAppointment();
// EntityId is the GUID of the appointment being routed.
target.EntityId = new Guid("7E91958D-C8A1-404C-AC2C-9C474FB2427B");

// Create the request object.
RouteRequest route = new RouteRequest();

// Set the properties of the request object.
route.Target = target;

// EndPointId is the GUID of the queue or user the appointment is being routed to.
// The queue cannot be a work in progress queue.
route.EndPointId = new Guid("44E05740-607B-47AA-ABD6-13A007E2DD85");

// RouteType indicates the EntityType of the endpoint.
route.RouteType = RouteType.Queue;

// SourceQueueId is the GUID of the queue that the appointment is coming from.
route.SourceQueueId = new Guid("BD0C1BDD-3310-4ECA-B2B1-131C2F5ED1B2");

// Execute the request.
RouteResponse routed = (RouteResponse)service.Execute(route);

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: 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.

CRM 4.0 Plug-in Stages, Pipelines and Execution Modes


 

Stage of Execution:
Pre-Stage: (synchronous) called before the write to the database.
The main reasons to use a Pre-Stage of Execution are synchronous in nature:
  • Modify data before it is written to the database.
  • Abort the action being taken
  • Server Side Validity checking
Post-Stage: (synchronous or asynchronous)
Use the Post-Stage of Execution whenever you don't need to use Pre-Stage.
If you don't want the user to wait for the process to finish and there is no race condition use asynchronous.
Triggering Pipeline:
The triggering pipeline is a little less obvious in nature and has an impact on what functionality that you can use in your plugin.
Parent Pipeline: This is the pipeline that is the most common and there are no restrictions imposed in a parent pipeline.
Child Pipeline: This is the pipeline that causes the most confusion and there are limitations that vary with Stage and Execution Mode.
Sometimes a child pipeline is required to trap the event you need, and sometimes you need to trap both the parent and child pipeline for the same entity, message and stage.
Example: Change the quotenumber in the Pre-Stage for the Create of a Quote.

The quotenumber is a field that the CRM web service will not allow you to change after it is written to the database so you need to use the Pre-Stage and modify the context Entity before the end of the Execute method as shown below.
var entity = (DynamicEntity)context.InputParameters.Properties[ParameterName.Target];  // . . . retrieve data to populate number . . .  // Set value before it is written to the database  if( entity.Properties.Contains(numberField)) {     entity.Properties.Remove(numberField); }  var prop = new StringProperty(numberField, newNumber); entity.Properties.Add(prop);
So far so good. This will work in any Pre-Create pipeline!
You can create a Quote in a few ways.
  • Sales -> Quotes -> New
  • (open an Account) -> Quotes -> New Quote
  • Sales -> Opportunities (open an opportunity) -> Quotes -> New Quote
Do you think that Creating a Quote always happens in the same pipeline?
Since you are an efficient plugin developer and are using the ICrmService and dynamic entities to access CRM data because it is pre-authenticated and fast. You retrieve some information to help create the number.
ICrmService service = context.CreateCrmService(true); retrieved = (RetrieveMultipleResponse)service.Execute(retrieve);
You register your plugin using the handy plugin registration tool for the Quote entity with the following settings:
  • Create
  • Pre Stage
  • Synchronous
  • Parent Pipeline
 CreateQuoteParent
You create your Quote from Sales -> Quotes -> New and it works!
However, in many business processes the user will create a Quote from an opportunity so it will inherit opportunityproduct information.
Now you create your quote from Sales -> Opportunities (open an opportunity) -> Quotes -> New Quote and for some reason your plugin did not fire. That is because this quote was created in a child pipeline.
The entire QOI chain also occurs in a child pipeline. If you create an order from a quote or invoice from an order it is happening in a child pipeline. There are other places that this occurs as well like creation of an account or contact from a lead.

You are in a child pipeline, now what ?

The first thing that you might try is to take your existing plugin and register it against the child pipeline, but it won't work. The ICrmService is not available to you in a child pipeline.
If you downloaded the plug-in template for CRM, you have probably seen the following method, which is what you need to use in a child pipeline.
/// <summary> /// Creates a CrmService proxy for plug-ins that execute in the child pipeline. /// </summary> /// <param name="context">The execution context that was passed to the plug-ins Execute method.</param> /// <param name="flag">Set to True to use impersontation.</param> /// <returns>A CrmServce instance.</returns> private static CrmService CreateCrmService(IPluginExecutionContext context, Boolean flag) {     var authToken = new CrmAuthenticationToken { AuthenticationType = 0, OrganizationName = context.OrganizationName, CallerId = (flag ? context.UserId : context.InitiatingUserId) };      var corToken = new CorrelationToken { CorrelationId = context.CorrelationId, CorrelationUpdatedTime = context.CorrelationUpdatedTime, Depth = context.Depth };      var regkey = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\MSCRM", false);      var service = new CrmService     {         CrmAuthenticationTokenValue = authToken,         UseDefaultCredentials = true,         Url = String.Concat(regkey.GetValue("ServerUrl").ToString(), "/2007/crmservice.asmx"),         CorrelationTokenValue = corToken     };      return service; }
You may find another method called GetCrmProxyUsingEndpointUrlInChildPipeline. It is essentially the same.
There is a comment in the plugin template that doesn't tell the whole story.
// For a plug-in running in the child pipeline, use this statement. // CrmService crmService = CreateCrmService(context, true);
What it doesn't mention is that what you are allowed to do with that service depends on what your execution mode is.
Hard Coded Restrictions:
A CrmService running Synchronously in a child pipeline is limited to the following:
  • Create
  • Delete
  • Update
  • RetrieveExchangeRate
However a child plugin running in Asynchronous Execution Mode is not limited this way.
Those 4 allowed actions are hard coded by MS whenever the plugin is executed inside a transaction, and it appears that all synchronous child pipeline events occur inside a transaction.
However you can do a query in child pipeline if it is registered as asynchronous.
In review:
  • Use ICrmService for all parent pipelines when at all possible.
  • Use CrmService for child pipelines in asynchronous execution mode.
  • There is very limited functionality allowed with CrmService for any plugin registered in a synchronous child pipeline
  • Querying CRM data in a plug-in registered as a synchronous Pre Create in a child process is currently very unsupported. (ie. direct SQL access)

How to add configuration parameters to plugins in CRM 2011



How to add configuration parameters to plugins in CRM 2011


When you design plugins, you often need an input parameter or a configuration for the plugin execution which can be easily updated without having to re-compile and/or re-register the plugin. For example, I have a plugin that sends a request to a SharePoint web service and I would like the endpoint URL for the web service to be configurable. In that case you have the following options:

1. Use a "Configuration" custom entity
This is perhaps the most popular method but it can be expensive to maintain. You can create a custom entity containing the configuration information so the plugin will read the data in the custom entity by retrieving the record each time it executes.

PROS:

  • Easy to update the value (can be done using the CRM UI).
  • Can configure privileges to control who has access to the configuration entity.
CONS:
  • Configuration is data instead of metadata, therefore, the configuration data cannot be transported with the solution. You will need to create the configuration record in each environment.
  • You might need to control that only one configuration entity can be created.


2. Use the plugin step "Configuration"
When you register a plugin step, there is a field where you can specify some configuration parameters for the plugin execution:
image
Then in the Constructor of your plugin class you will get the configuration value which you can use later in the Execute method:
public abstract class BasePlugin : IPlugin
{
    private string _secureConfig = null;
    private string _unsecureConfig = null;

    public BasePlugin(string unsecureConfig, string secureConfig)
    {
        _secureConfig = secureConfig;
        _unsecureConfig = unsecureConfig;
    }

    public void Execute()
    {
        // Use the configuration here
    }
}

PROS:
  • The step configuration is solution-aware so it will be automatically transported with the plugin step.
CONS:
  • You need to use the plugin registration tool or another application to update the step configuration.
  • The configuration is step-specific so you have to provide it and/or update it for every step even if the value is the same for all the steps (the configuration is on each step instead of the assembly or plugin type).
  • the configuration is just an attribute of the plugin step so you cannot control privileges on the configuration independently from privileges on plugin step entity.


3. Use the plugin step "Secure Configuration"
This is similar to the step Configuration except that the configuration data is stored in a separate entity which can be secured.
PROS:
  • The configuration data can be secured as any other entity using the CRM security model. This is useful when the configuration contains sensitive information such as passwords.
CONS:
  • Secure configuration is not solution aware so you will need to configure it for each environment.
  • You need to use the plugin registration tool or another application to update the step configuration.
  • The configuration is step-specific so you have to provide it and/or update it for every step even if the value is the same for all the steps (the configuration is on each step instead of the assembly or plugin type).


4. Use a Web Resource
You can store configuration information in web resources, for example you might have some XML configuration stored in a web resource and have your plugin read the web resource each time it executes.

PROS:
  • Web resources are solution aware and the GUID is preserved across environments so you can hardcode the web resource GUID in your plugin code. You can transport the web resource and the plugin in the same solution.
  • Can be easily updated using the CRM UI.
CONS:
  • You cannot secure the configuration since it depends on the web resource access privileges and most users will need at least read access to web resources.

Maximum of 5000 responses from a FetchXml

Edit the registry
  • Click Start, click Run, type regedit in the Open box, and then click OK.
  • Locate and then select the following registry subkey:

    HKEY_LOCAL_MACHINE\Software\Microsoft\MSCRM

  • On the Edit menu, point to New, and then click DWORD Value.
  • Type TurnOffFetchThrottling, and then press ENTER.
  • Right-click TurnOffFetchThrottling, and then click Modify.
  • Type a number other than 0 in the Value data box, and then click OK.Note Step 6 lets you retrieve the number of records specified in the Count attribute of your fetch statement.
  • On the File menu, click Exit.

  • Handle Message

    Moves an entity instance from a queue to the In Progress (WIPBin) queue of the user.

          
    //# The following code example demonstrates how to use the Handle message.
    // Set up the CRM service.
    CrmAuthenticationToken token = new CrmAuthenticationToken();
    // You can use enums.cs from the SDK\Helpers folder to get the enumeration for Active Directory authentication.
    token.AuthenticationType = 0;
    token.OrganizationName = "AdventureWorksCycle";

    CrmService service = new CrmService();
    service.Url = "http://:/mscrmservices/2007/crmservice.asmx";
    service.CrmAuthenticationTokenValue = token;
    service.Credentials = System.Net.CredentialCache.DefaultCredentials;

    // Create the Target Object for the Request
    TargetQueuedAppointment target = new TargetQueuedAppointment();

    // EntityId is the Guid of the appointment being handled
    target.EntityId = new Guid("7B222F98-F48A-4AED-9D09-77A19CB6EE82");

    // Create the Request Object
    HandleRequest handle = new HandleRequest();

    // Set the Request Object's Properties
    handle.Target = target;

    // SourceQueueId is the Guid of the queue the appointment is coming from
    handle.SourceQueueId = sourceQueue;

    // Execute the Request
    HandleResponse handled = (HandleResponse) service.Execute(handle);





    Start Microsoft Word using Jscript

    This is pretty old trick to use Active X Control to get an instance of application.
    // Start Microsoft Word using Jscript
    var createDoc = function (msg) {
        var MsWord = new ActiveXObject("Word.Application");
        MsWord.Documents.Add();
        MsWord.Selection.TypeParagraph();
        MsWord.Selection.TypeText("line 1 text1: " + msg);
        MsWord.Selection.TypeParagraph();
        MsWord.Selection.TypeParagraph();
        MsWord.Selection.TypeText("line2 text2: this is line two");
        MsWord.Visible = true;
    };
    

    Assign the queue to a team.

    This C# code assigns a queue to a team, we just need the Guid for team & queue.
    // ** Assign the queue to a team. **
    AssignRequest assignRequest = new AssignRequest()
    {
        Assignee = new EntityReference
        {
            LogicalName = "team",
            Id = new Guid("_teamGuId")
        },
     
        Target = new EntityReference("queue", new Guid("_queueGuid"))
    };
     
    _service.Execute(assignRequest);
     
    Console.WriteLine("The queue is owned by the team.");
     
    
    

    to UTC/JSON Date

     
    
    // to UTC/JSON Date
    Number.prototype.addZero = function () { return (this < 10) ? "0" +
    this : this; };
    var convertDate = function (d) {
    var d, s, u, uh, um, us;
    //d = new Date();
    s = d.getFullYear() + "-";
    s += (d.getMonth() + 1).addZero() + "-"; //getMonth returns an
    integer in the range 0-11
    s += d.getDate().addZero() + "T";
    s += d.getHours().addZero() + ":";
    s += d.getMinutes().addZero() + ":";
    s += d.getSeconds().addZero();
    u = 0 - d.getTimezoneOffset(); //getTimezoneOffset will
    be positive if you are behind UTC, and negative if you are ahead of
    UTC.
    us = (u >= 0) ? "+" : "-";
    u = Math.abs(u);
    uh = Math.floor(u / 60).addZero();
    um = (u % 60).addZero();
    s += us;
    s += uh + ":";
    s += um;
    alert(s);
    return (s);
    };

    // call
    convertDate(new Date());

    Parse XmlHttp Response

    // Parse XmlHttp Response
    function parseResponse(responseXML, attributename) {
    
        debugger;
        xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
        xmlDoc.async = "false";
        xmlDoc.loadXML(responseXML);
        x = xmlDoc.getElementsByTagName("a:KeyValuePairOfstringanyType");
        for (i = 0; i < x.length; i++) {
            if (x[i].childNodes[0].text == attributename) {
                //we decode the base 64 contents and alert the HTML of the Iframe
                alert(x[i].childNodes[1].text);
            }
    
        }
    }
    

    XmlHttp Request

    // XmlHttp Request
    var AjaxRequest = function (crmSvcUrl, soapString) {
    var XmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
    XmlHttp.open("POST", crmSvcUrl, false);
    XmlHttp.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
    XmlHttp.setRequestHeader("SOAPAction",
    "http://schemas.microsoft.com/crm/2007/WebServices/Fetch");
    XmlHttp.setRequestHeader("Content-Length", soapString.length);
    XmlHttp.send(soapString);
    var resultXml = XmlHttp.responseXML;
    return resultXml;
    };
    

    Create SOAP Envelop

    // Create SOAP Envelop
    var createSOAP = function (fxml) {
    var soap2 = "";
    soap2 += GenerateAuthenticationHeader();
    soap2 += "";
    soap2 += "";
    soap2 += "";
    soap2 += fxml;
    soap2 += "";
    soap2 += "";
    soap2 += "";
    soap2 += "";
    return soap2;
    };
    

    return if day is weekday

    // return if day is weekday
    var Weekday = function (chkDt) {
    if (chkDt.getDay() > 0 && chkDt.getDay() < 6) {
    //"Sorry, it's a weekday.";
    return true;
    }
    else {
    //"Hooray, it's a weekend!";
    return false;
    }
    }; //Ef
    

    JSON date fromat to date Object

    <pre class="brush: c#">
    //JSON date fromat to date Object
    var jsondtobj = function (txt) {
    var year, month, day;
    var filler = '.*?'; // Non-greedy match on filler
    var yre2 = '((?:(?:[1]{1}\\d{1}\\d{1}\\d{1})|(?:[2]{1}\\d{3})))(?![\\d])';
    // Year 1
    var yp = new RegExp(filler + yre2, ["i"]);
    var ym = yp.exec(txt);
    if (ym != null) {
    var year1 = ym[1];
    year = year1.replace(/</, "&lt;");
    }


    var mre2 = '(?:(?:[0-2]?\\d{1})|(?:[3][01]{1}))(?![\\d])'; //
    Uninteresting: day
    var mre4 = '((?:(?:[0-2]?\\d{1})|(?:[3][01]{1})))(?![\\d])'; // Month 1

    var mp = new RegExp(filler + mre2 + filler + mre4, ["i"]);
    var mm = mp.exec(txt);
    if (mm != null) {
    var mon1 = mm[1];
    month = mon1.replace(/</, "&lt;") - 1;
    }


    var dre2 = '(?:(?:[0-2]?\\d{1})|(?:[3][01]{1}))(?![\\d])'; //
    Uninteresting: day
    var dre4 = '(?:(?:[0-2]?\\d{1})|(?:[3][01]{1}))(?![\\d])'; //
    Uninteresting: day
    var dre6 = '((?:(?:[0-2]?\\d{1})|(?:[3][01]{1})))(?![\\d])'; // Day 1

    var dp = new RegExp(filler + dre2 + filler + dre4 + filler + dre6, ["i"]);
    var dm = dp.exec(txt);
    if (dm != null) {
    var day1 = dm[1];
    day = day1.replace(/</, "&lt;");
    }
    var dateObject = new Date(); dateObject.setDate(day);
    dateObject.setMonth(month); dateObject.setYear(year);
    return dateObject;
    }; //
    </pre>

    Extend Date Object with new function using Namespace

    // Extend Date Object with new function using Namespace
    //Date.prototype.daysBetween
    Date.prototype.daysBetween = function (date1, date2) {
        //Get 1 day in milliseconds
        var one_day = 1000 * 60 * 60 * 24;
    
        // Convert both dates to milliseconds
        var date1_ms = date1.getTime();
        var date2_ms = date2.getTime();
    
        // Calculate the difference in milliseconds
        var difference_ms = date2_ms - date1_ms;
        //take out milliseconds
        difference_ms = difference_ms / 1000;
        var seconds = Math.floor(difference_ms % 60);
        difference_ms = difference_ms / 60;
        var minutes = Math.floor(difference_ms % 60);
        difference_ms = difference_ms / 60;
        var hours = Math.floor(difference_ms % 24);
        var days = Math.floor(difference_ms / 24);
    
        return days + ' days, ' + hours + ' hours, ' + minutes + ' minutes, and ' + seconds + ' seconds';
    };
    
    

    Create new Queue using Early Bound

    // ** Create new Queue ** using Early Bound
    
    //Create new queues and store their returned GUIDs in variables for later use.
    
    Queue sourceQueue = new Queue
    
    {
    
        Name = "Example Queue 1",
    
        Description = "This is an example queue.",
    
    };
    
     
    
    Guid _QueueId = _service.Create(sourceQueue);
    
    Console.WriteLine("Created {0}", sourceQueue.Name);
    
    

    DeleteOptionSetRequest

    // ** DeleteOptionSetRequest **
    
    // deletes global option set
    
    DeleteOptionSetRequest deleteRequest = new DeleteOptionSetRequest
    
    {
    
        Name = "_globalOptionSetName"
    
    };
    
     
    
    _service.Execute(deleteRequest);
    
     
    
    

    DeleteEntityRequest

    // ** DeleteEntityRequest **
    
    // Deletes entity with logical name
    
    DeleteEntityRequest request = new DeleteEntityRequest()
    
    {
    
        LogicalName = "_customEntityName",
    
    };
    
    _service.Execute(request);
    

    DeleteAttributeRequest

    // ** DeleteAttributeRequest **
    
    // Delete attribute present in entity.
    
     
    
    // Create the request object
    
    DeleteAttributeRequest deleteAttribute = new DeleteAttributeRequest
    
    {
    
        // Set the request properties 
    
        EntityLogicalName = "EntityLogicalName",
    
        LogicalName = "anAttribute_SchemaName"
    
    };
    
    // Execute the request
    
    _service.Execute(deleteAttribute);
    
     
    

    create global option set

    // ** create global option set **
    
    // Define the request object and pass to the service.
    
    CreateOptionSetRequest createOptionSetRequest = new CreateOptionSetRequest
    
    {
    
        // Create a global option set (OptionSetMetadata).
    
        OptionSet = new OptionSetMetadata
    
        {
    
            Name = "_globalOptionSetName",
    
            DisplayName = new Label("Example Option Set", 1033),
    
            IsGlobal = true,
    
            OptionSetType = OptionSetType.Picklist,
    
            Options = 
    
        {
    
            new OptionMetadata(new Label("Open", 1033), null),
    
            new OptionMetadata(new Label("Suspended", 1033), null),
    
            new OptionMetadata(new Label("Cancelled", 1033), null),
    
            new OptionMetadata(new Label("Closed", 1033), null)
    
        }
    
        }
    
    };
    
     
    
    // Execute the request.
    
    CreateOptionSetResponse optionsResp =
    
        (CreateOptionSetResponse)_service.Execute(createOptionSetRequest);
    
    

    CRM 4.0 Form JScript

    // CRM 4.0 Form Scripts Example
    //Set Field Value
    crmForm.all.crmfieldscemaname.DataValue= "value";
    
    //Get Field Value
    var value = crmForm.all.crmfieldscemaname.DataValue;
    
    //Set Requirement Field
    crmForm.all.crmfieldscemaname.setAttribute( "req",0);
    //or
    crmForm.all.crmfieldscemaname_c.classname= "n";
    
    // Set Recommended
    crmForm.all.crmfieldscemaname.setAttribute( "req",1);
    //or
    crmForm.all.crmfieldscemaname_c.className= "rec";
    
    //Set Required
    crmForm.all.crmfieldscemaname.setAttribute( "req",2);
    //or
    crmForm.all.crmfieldscemaname_c.className= "req";
    
    //Disable a field
    crmForm.all.crmfieldscemaname.Disabled= true;
    
    //Enable a Field
    crmForm.all.crmfieldscemaname.Disabled= false;
    
    //hide a field
    crmForm.all.crmfieldscemaname.style.Display= "none";
    //or
    crmForm.all.crmfieldscemaname_c.style.Display= "none";
    
    //Show a field
    crmForm.all.crmfieldscemaname.style.Display= "block";
    //or
    crmForm.all.crmfieldscemaname_c.style.Display= "inline";
    
    //Set PickList Value
    crmForm.all.crmfieldscemaname.DataValue= "none";
    
    //Get PickList Value
    var value=crmForm.all.crmfieldscemaname.DataValue;
    
    

    Hide Tab using JScript

    //CRM 4.0
    crmForm.all.tabIndexTab.style.visibility = "hidden";
    
    // CRM 2011
    Xrm.Page.ui.tabs.get(TabIndex).setVisible(false);
    Xrm.Page.ui.tabs.get(TabIndex).setVisible(true);
    //Or
    Xrm.Page.ui.tabs.get(TabName).setVisible(false);
    

    CreateOneToManyRequest

    // ** CreateOneToManyRequest **
    
    // creates an entity relationship between Account and Campaign entities by using CreateOneToManyRequest
    
    CreateOneToManyRequest createOneToManyRelationshipRequest =
    
            new CreateOneToManyRequest
    
            {
    
                OneToManyRelationship =
    
                new OneToManyRelationshipMetadata
    
                {
    
                    ReferencedEntity = "account",
    
                    ReferencingEntity = "campaign",
    
                    SchemaName = "new_account_campaign",
    
                    AssociatedMenuConfiguration = new AssociatedMenuConfiguration
    
                    {
    
                        Behavior = AssociatedMenuBehavior.UseLabel,
    
                        Group = AssociatedMenuGroup.Details,
    
                        Label = new Label("Account", 1033),
    
                        Order = 10000
    
                    },
    
                    CascadeConfiguration = new CascadeConfiguration
    
                    {
    
                        Assign = CascadeType.Cascade,
    
                        Delete = CascadeType.Cascade,
    
                        Merge = CascadeType.Cascade,
    
                        Reparent = CascadeType.Cascade,
    
                        Share = CascadeType.Cascade,
    
                        Unshare = CascadeType.Cascade
    
                    }
    
                },
    
                Lookup = new LookupAttributeMetadata
    
                {
    
                    SchemaName = "new_parent_accountid",
    
                    DisplayName = new Label("Account Lookup", 1033),
    
                    RequiredLevel = new AttributeRequiredLevelManagedProperty(AttributeRequiredLevel.None),
    
                    Description = new Label("Sample Lookup", 1033)
    
                }
    
            };
    
     
    
     
    
    CreateOneToManyResponse createOneToManyRelationshipResponse =
    
        (CreateOneToManyResponse)_service.Execute(createOneToManyRelationshipRequest);
    
     
    

    Create a string attribute

    
    // ** Create a string attribute **
    
    StringAttributeMetadata stringAttribute = new StringAttributeMetadata
    
    {
    
        // Set base properties
    
        SchemaName = "new_string",
    
        DisplayName = new Label("Sample String", 1033),
    
        RequiredLevel = new AttributeRequiredLevelManagedProperty(AttributeRequiredLevel.None),
    
        Description = new Label("String Attribute", 1033),
    
        // Set extended properties
    
        MaxLength = 100
    
    };
    
     
    
     
    
     
    
    // Create the request.
    
    CreateAttributeRequest createAttributeRequest = new CreateAttributeRequest
    
    {
    
        EntityName = "EntityLogicalName",
    
        Attribute = stringAttribute
    
    };
    
     
    
    // Execute the request. Get Response
    
    CreateAttributeResponse resp = (CreateAttributeResponse)_service.Execute(createAttributeRequest); 
    
    

    Create a picklist attribute (Option set)

    
    // ** Create a picklist attribute (Option set) **
    
    PicklistAttributeMetadata pickListAttribute = new PicklistAttributeMetadata
    
    {
    
        // Set base properties
    
        SchemaName = "new_picklist",
    
        DisplayName = new Label("Sample Picklist", _languageCode),
    
        RequiredLevel = new AttributeRequiredLevelManagedProperty(AttributeRequiredLevel.None),
    
        Description = new Label("Picklist Attribute", _languageCode),
    
        // Set extended properties
    
        // Build local picklist options
    
        OptionSet = new OptionSetMetadata
    
        {
    
            IsGlobal = false,
    
            OptionSetType = OptionSetType.Picklist,
    
            Options = 
    
            {
    
            new OptionMetadata(
    
                new Label("Created", _languageCode), null),
    
            new OptionMetadata(
    
                new Label("Updated", _languageCode), null),
    
            new OptionMetadata(
    
                new Label("Deleted", _languageCode), null)
    
            }
    
        }
    
    };
    
     
    
    // Create the request.
    
    CreateAttributeRequest createAttributeRequest = new CreateAttributeRequest
    
    {
    
        EntityName = "EntityLogicalName",
    
        Attribute = pickListAttribute
    
    };
    
     
    
    // Execute the request. Get Response
    
    CreateAttributeResponse resp = (CreateAttributeResponse)_service.Execute(createAttributeRequest); 
    
    

    Hide Section in Tab on CRM 4.0 form

    crmForm.all..parentElement.parentElement.parentElement.style.display="none";
    //Another way from top down:
    document.getElementById("tab").childNodes[0].rows[].style.display = "none";
    //  is zero based tab number from left.  is zero based section number from top.
    //To show it back, simply replace "none" with "block".
    

    Hide Tab on CRM 4.0 form

    document.getElementById("tabTab").style.display = "none"; //  zero based tab number from left
    

    Hide Field / Attribute on CRM 4.0 form

    <


    pre class="brush: csharp">
    crmForm.all.


    <fieldname>_c.style.display = "none";
    crmForm.all.


    <fieldname>_d.style.display = "none";
    </


    pre>

    Create a integer attribute

    
    // ** Create a integer attribute **   
    
    IntegerAttributeMetadata integerAttribute = new IntegerAttributeMetadata
    
    {
    
        // Set base properties
    
        SchemaName = "new_integer",
    
        DisplayName = new Label("Sample Integer", 1033),
    
        RequiredLevel = new AttributeRequiredLevelManagedProperty(AttributeRequiredLevel.None),
    
        Description = new Label("Integer Attribute", 1033),
    
        // Set extended properties
    
        Format = IntegerFormat.None,
    
        MaxValue = 100,
    
        MinValue = 0
    
    };
    
     
    
     
    
     
    
     
    
    // Create the request.
    
    CreateAttributeRequest createAttributeRequest = new CreateAttributeRequest
    
    {
    
        EntityName = "EntityLogicalName",
    
        Attribute = integerAttribute
    
    };
    
     
    
    // Execute the request. Get Response
    
    CreateAttributeResponse resp = (CreateAttributeResponse)_service.Execute(createAttributeRequest); 
    
     
    
    

    ModifyAccess Message

    Remarks

    To use this message, pass an instance of the ModifyAccessRequest class as the request parameter in the Execute method.

    This action applies to all child instances of the target entity instance. For all child instances, if the caller does not have share privileges for those entity types, or share rights to the instances, the child instances are not shared. As a result, the owner of the entity instance, or a user who shares the instance with share rights, automatically has share rights to all child instances of the target entity instance. In this case, only the lack of privileges to a particular entity type prevents the child instances from being shared.

    For a description of how actions on a parent instance affect child instances, see Cascading Rules.

    To perform this action, the caller must have access rights on the entity instance specified in the request class. For a list of required privileges, see ModifyAccess Privileges.

        
    //# The following code example shows how to use the ModifyAccess message.

    // Set up the CRM service.
    CrmAuthenticationToken token = new CrmAuthenticationToken();
    // You can use enums.cs from the SDK\Helpers folder to get the enumeration for Active Directory authentication.
    token.AuthenticationType = 0;
    token.OrganizationName = "AdventureWorksCycle";

    CrmService service = new CrmService();
    service.Url = "http://:/mscrmservices/2007/crmservice.asmx";
    service.CrmAuthenticationTokenValue = token;
    service.Credentials = System.Net.CredentialCache.DefaultCredentials;

    // Create the Security Principal Object
    SecurityPrincipal principal = new SecurityPrincipal();
    principal.Type = SecurityPrincipalType.User;

    // PrincipalId is the Guid of the user whose access is being modified
    principal.PrincipalId = new Guid("7B222F98-F48A-4AED-9D09-77A19CB6EE82");

    // Create the PrincipalAccess
    PrincipalAccess principalAccess = new PrincipalAccess();

    // Set the PrincipalAccess Object's Properties
    principalAccess.Principal = principal;

    // gives the principal access to read
    principalAccess.AccessMask = AccessRights.ReadAccess;

    // Create the Target Object for the Request
    TargetOwnedAccount target = new TargetOwnedAccount();

    // EntityId is the Guid of the account whose access is being modified
    target.EntityId = new Guid("2B951FBC-1C56-4430-B23B-20A1349068F3");

    // Create the Request Object
    ModifyAccessRequest modify = new ModifyAccessRequest();

    // Set the Request Object's Properties
    modify.PrincipalAccess = principalAccess;
    modify.Target = target;

    // Execute the Request
    ModifyAccessResponse modified = (ModifyAccessResponse)service.Execute(modify);

    Create a decimal attribute

    // ** Create a decimal attribute **   
    
    DecimalAttributeMetadata decimalAttribute = new DecimalAttributeMetadata
    
    {
    
        // Set base properties
    
        SchemaName = "new_decimal",
    
        DisplayName = new Label("Sample Decimal", 1033),
    
        RequiredLevel = new AttributeRequiredLevelManagedProperty(AttributeRequiredLevel.None),
    
        Description = new Label("Decimal Attribute", 1033),
    
        // Set extended properties
    
        MaxValue = 100,
    
        MinValue = 0,
    
        Precision = 1
    
    };
    
     
    
     
    
     
    
    // Create the request.
    
    CreateAttributeRequest createAttributeRequest = new CreateAttributeRequest
    
    {
    
        EntityName = "EntityLogicalName",
    
        Attribute = decimalAttribute
    
    };
    
     
    
    // Execute the request. Get Response
    
    CreateAttributeResponse resp = (CreateAttributeResponse)_service.Execute(createAttributeRequest); 
    
     
    

    Create a date time attribute

    // ** Create a date time attribute **
    
    DateTimeAttributeMetadata dtAttribute = new DateTimeAttributeMetadata
    
    {
    
        // Set base properties
    
        SchemaName = "new_datetime",
    
        DisplayName = new Label("Sample DateTime", 1033),
    
        RequiredLevel = new AttributeRequiredLevelManagedProperty(AttributeRequiredLevel.None),
    
        Description = new Label("DateTime Attribute", 1033),
    
        // Set extended properties
    
        Format = DateTimeFormat.DateOnly,
    
        ImeMode = ImeMode.Disabled
    
    };
    
     
    
     
    
    // Create the request.
    
    CreateAttributeRequest createAttributeRequest = new CreateAttributeRequest
    
    {
    
        EntityName = "EntityLogicalName",
    
        Attribute = dtAttribute
    
    };
    
     
    
    // Execute the request. Get Response
    
    CreateAttributeResponse resp = (CreateAttributeResponse)_service.Execute(createAttributeRequest); 
    
    

    Create a boolean attribute

    // ** Create a boolean attribute **
    
    // Boolean attribute
    
    BooleanAttributeMetadata boolAttribute = new BooleanAttributeMetadata
    
    {
    
        // Set base properties
    
        SchemaName = "new_boolean",
    
        DisplayName = new Label("Sample Boolean", 1033),
    
        RequiredLevel = new AttributeRequiredLevelManagedProperty(AttributeRequiredLevel.None),
    
        Description = new Label("Boolean Attribute", 1033),
    
        // Set extended properties
    
        OptionSet = new BooleanOptionSetMetadata(
    
            new OptionMetadata(new Label("True", 1033), 1),
    
            new OptionMetadata(new Label("False", 1033), 0)
    
            )
    
    };
    
     
    
    // Create the request.
    
    CreateAttributeRequest createAttributeRequest = new CreateAttributeRequest
    
    {
    
        EntityName = "EntityLogicalName",
    
        Attribute = boolAttribute
    
    };
    
     
    
    // Execute the request.
    
    _service.Execute(createAttributeRequest);
    
     
    

    Create a money attribute

    // ** Create a money attribute **
    
    MoneyAttributeMetadata moneyAttribute = new MoneyAttributeMetadata
    
    {
    
        // Set base properties
    
        SchemaName = "new_money",
    
        DisplayName = new Label("Money Picklist", 1033),
    
        RequiredLevel = new AttributeRequiredLevelManagedProperty(AttributeRequiredLevel.None),
    
        Description = new Label("Money Attribue", 1033),
    
        // Set extended properties
    
        MaxValue = 1000.00,
    
        MinValue = 0.00,
    
        Precision = 1,
    
        PrecisionSource = 1,
    
        ImeMode = ImeMode.Disabled
    
    };
    
     
    
     
    
     
    
    // Create the request.
    
    CreateAttributeRequest createAttributeRequest = new CreateAttributeRequest
    
    {
    
        EntityName = "EntityLogicalName",
    
        Attribute = moneyAttribute
    
    };
    
     
    
    // Execute the request. Get Response
    
    CreateAttributeResponse resp = (CreateAttributeResponse)_service.Execute(createAttributeRequest); 
    
     
    

    CanManyTomanyRequest

    // ** CanManyTomanyRequest **
    
    // Determines whether the entity can participate in a many-to-many relationship.
    
    CanManyToManyRequest canManyToManyRequest = new CanManyToManyRequest
    
    {
    
        EntityName = "entity_logicalname"
    
    };
    
     
    
    CanManyToManyResponse canManyToManyResponse =
    
        (CanManyToManyResponse)_service.Execute(canManyToManyRequest);
    
     
    
    if (!canManyToManyResponse.CanManyToMany)
    
    {
    
        Console.WriteLine(
    
            "Entity {0} can't participate in a many-to-many relationship.", 
    
            "entity_logicalname");
    
    }
    

    GetProcessInfo using WMI

    Sub GetProcess()
      Set objWMI = GetObject("winmgmts:")
      Set instanzen = objWMI.InstancesOf("Win32_Process")
      'MakeTabH "Instance","CommandLine"
      For Each objInstance In instanzen
        'MakeTabD objInstance.Name , objInstance.CommandLine
      write objInstance.Name  & " : " & objInstance.CommandLine & ""
      'document.frames.myiframe.document.body.style.font="arial"
      Next
    End Sub
    

    DeleteOptionValueRequest

    // ** DeleteOptionValueRequest **
    
    // to remove the newly inserted label.
    
    DeleteOptionValueRequest deleteOptionValueRequest =
    
        new DeleteOptionValueRequest
    
        {
    
            OptionSetName = "_globalOptionSetName",
    
            Value = 100011
    
        };
    
     
    
    // Execute the request.
    
    _service.Execute(deleteOptionValueRequest
    
    

    CreateManyToManyRequest

    // ** CreateManyToManyRequest **
    
    //Ex: creates the entity relationship between the Account and Contact entities by using CreateManyToManyRequest.
    
     
    
    CreateManyToManyRequest createManyToManyRelationshipRequest = new CreateManyToManyRequest
    
        {
    
            IntersectEntitySchemaName = "new_accounts_campaigns",
    
            ManyToManyRelationship = new ManyToManyRelationshipMetadata
    
            {
    
                SchemaName = "new_accounts_campaigns",
    
                Entity1LogicalName = "account",
    
                Entity1AssociatedMenuConfiguration =
    
                new AssociatedMenuConfiguration
    
                {
    
                    Behavior = AssociatedMenuBehavior.UseLabel,
    
                    Group = AssociatedMenuGroup.Details,
    
                    Label = new Label("Account", 1033),
    
                    Order = 10000
    
                },
    
                Entity2LogicalName = "campaign",
    
                Entity2AssociatedMenuConfiguration =
    
                new AssociatedMenuConfiguration
    
                {
    
                    Behavior = AssociatedMenuBehavior.UseLabel,
    
                    Group = AssociatedMenuGroup.Details,
    
                    Label = new Label("Campaign", 1033),
    
                    Order = 10000
    
                }
    
            }
    
        };
    
     
    
    CreateManyToManyResponse createManytoManyRelationshipResponse =
    
        (CreateManyToManyResponse)_service.Execute(
    
        createManyToManyRelationshipRequest);
    
     
    
    
    

    Complete DateDiff() Function

    Perhaps the above function looks like the Visual Basic function of the same name. In fact it is loosely based on it. I was planning on recreating it in its complete form for your enjoyment, but, thankfully someone has already beat me to it. That someone is Rob Eberhardt of Slingshot Solutions. It's part of his excellent jsDate script. It's free to use as long as you give credit where credit is due. His function offers a lot of advantages over the simple one presented above. For starters, his can calculate the month interval, which cannot be done by dividing into the number of milliseconds since month lengths differ. It also supports setting the first day of the week to something other than Sunday. Finally, it adjusts for Daylight Savings Time, which affects intervals of a day ("d") and larger:
    Date.DateDiff = function(p_Interval, p_Date1, p_Date2, p_FirstDayOfWeek){
     p_FirstDayOfWeek = (isNaN(p_FirstDayOfWeek) || p_FirstDayOfWeek==0) ? vbSunday : parseInt(p_FirstDayOfWeek);
    
     var dt1 = Date.CDate(p_Date1);
     var dt2 = Date.CDate(p_Date2);
    
     //correct Daylight Savings Ttime (DST)-affected intervals ("d" & bigger)
     if("h,n,s,ms".indexOf(p_Interval.toLowerCase())==-1){
      if(p_Date1.toString().indexOf(":") ==-1){ dt1.setUTCHours(0,0,0,0) }; // no time, assume 12am
      if(p_Date2.toString().indexOf(":") ==-1){ dt2.setUTCHours(0,0,0,0) }; // no time, assume 12am
     }
    
    
     // get ms between UTC dates and make into "difference" date
     var iDiffMS = dt2.valueOf() - dt1.valueOf();
     var dtDiff = new Date(iDiffMS);
    
     // calc various diffs
     var nYears  = dt2.getUTCFullYear() - dt1.getUTCFullYear();
     var nMonths = dt2.getUTCMonth() - dt1.getUTCMonth() + (nYears!=0 ? nYears*12 : 0);
     var nQuarters = parseInt(nMonths / 3);
     
     var nMilliseconds = iDiffMS;
     var nSeconds = parseInt(iDiffMS / 1000);
     var nMinutes = parseInt(nSeconds / 60);
     var nHours = parseInt(nMinutes / 60);
     var nDays  = parseInt(nHours / 24); //now fixed for DST switch days
     var nWeeks = parseInt(nDays / 7);
    
     if(p_Interval.toLowerCase()=='ww'){
       // set dates to 1st & last FirstDayOfWeek
       var offset = Date.DatePart("w", dt1, p_FirstDayOfWeek)-1;
       if(offset){ dt1.setDate(dt1.getDate() +7 -offset); }
       var offset = Date.DatePart("w", dt2, p_FirstDayOfWeek)-1;
       if(offset){ dt2.setDate(dt2.getDate() -offset); }
       // recurse to "w" with adjusted dates
       var nCalWeeks = Date.DateDiff("w", dt1, dt2) + 1;
     }
     
     // return difference
     switch(p_Interval.toLowerCase()){
      case "yyyy": return nYears;
      case "q": return nQuarters;
      case "m": return nMonths;
      case "y": // day of year
      case "d": return nDays;
      case "w": return nWeeks;
      case "ww":return nCalWeeks; // week of year 
      case "h": return nHours;
      case "n": return nMinutes;
      case "s": return nSeconds;
      case "ms":return nMilliseconds;
      default : return "invalid interval: '" + p_Interval + "'";
     }
    }
    var y2k  = new Date(2000, 0, 1) //Month is 0-11 in JavaScript!
    var today= new Date();
    console.log('Months since the new millenium: ' + Date.DateDiff('m', y2k, today)); //displays 143
    

    A Simple dateDiff() Function

    There is no reason to write a function for each date/time interval; one function can contain all of the required intervals and return the correct value for the one we want. In the following function, the datepart argument tells it what interval we are after, where 'w' is a week, 'd' a day, 'h' hours, 'n' for minutes, and 's' for seconds:
    
    // datepart: 'y', 'm', 'w', 'd', 'h', 'n', 's'
    Date.dateDiff = function(datepart, fromdate, todate) { 
      datepart = datepart.toLowerCase(); 
      var diff = todate - fromdate; 
      var divideBy = { w:604800000, 
                       d:86400000, 
                       h:3600000, 
                       n:60000, 
                       s:1000 }; 
      
      return Math.floor( diff/divideBy[datepart]);
    }
    //Set the two dates
    var y2k  = new Date(2000, 0, 1);
    var today= new Date();
    console.log('Weeks since the new millenium: ' + Date.dateDiff('w', y2k, today)); //displays 625
    

    Converting Milliseconds to other Intervals

    As long as you can calculate the number of milliseconds in an interval, you can come up with a number by dividing the total number of milliseconds by the number of milliseconds in the desired interval. What's more, we can apply the modulus (%) operator to strip out that value to determine the next larger interval. The key is to always go from the smallest interval - milliseconds - to the largest - days:
    
    Date.daysBetween = function( date1, date2 ) {
      //Get 1 day in milliseconds
      var one_day=1000*60*60*24;
    
      // Convert both dates to milliseconds
      var date1_ms = date1.getTime();
      var date2_ms = date2.getTime();
    
      // Calculate the difference in milliseconds
      var difference_ms = date2_ms - date1_ms;
      //take out milliseconds
      difference_ms = difference_ms/1000;
      var seconds = Math.floor(difference_ms % 60);
      difference_ms = difference_ms/60; 
      var minutes = Math.floor(difference_ms % 60);
      difference_ms = difference_ms/60; 
      var hours = Math.floor(difference_ms % 24);  
      var days = Math.floor(difference_ms/24);
      
      return days + ' days, ' + hours + ' hours, ' + minutes + ' minutes, and ' + seconds + ' seconds';
    }
    
    //Set the two dates
    var y2k  = new Date(2000, 0, 1);
    var Jan1st2010 = new Date(y2k.getYear() + 10, y2k.getMonth(), y2k.getDate());
    var today= new Date();
    //displays "Days from Wed Jan 01 0110 00:00:00 GMT-0500 (Eastern Standard Time) to Tue Dec 27 2011 12:14:02 GMT-0500 (Eastern Standard Time): 694686 days, 12 hours, 14 minutes, and 2 seconds"
    console.log('Days from ' + Jan1st2010 + ' to ' + today + ': ' + Date.daysBetween(Jan1st2010, today));
    
    

    Calculating the Difference between Two Known Dates

    Unfortunately, calculating a date interval such as days, weeks, or months between two known dates is not as easy because you can't just add Date objects together. In order to use a Date object in any sort of calculation, we must first retrieve the Date's internal millisecond value, which is stored as a large integer. The function to do that is Date.getTime(). Once both Dates have been converted, subtracting the later one from the earlier one returns the difference in milliseconds. The desired interval can then be determined by dividing that number by the corresponding number of milliseconds. For instance, to obtain the number of days for a given number of milliseconds, we would divide by 86,400,000, the number of milliseconds in a day (1000 x 60 seconds x 60 minutes x 24 hours):
     
    Date.daysBetween = function( date1, date2 ) {
      //Get 1 day in milliseconds
      var one_day=1000*60*60*24;
    
      // Convert both dates to milliseconds
      var date1_ms = date1.getTime();
      var date2_ms = date2.getTime();
    
      // Calculate the difference in milliseconds
      var difference_ms = date2_ms - date1_ms;
        
      // Convert back to days and return
      return Math.round(difference_ms/one_day); 
    }
    
    //Set the two dates
    var y2k  = new Date(2000, 0, 1); 
    var Jan1st2010 = new Date(y2k.getFullYear() + 10, y2k.getMonth(), y2k.getDate());
    var today= new Date();
    //displays 726
    console.log( 'Days since ' 
               + Jan1st2010.toLocaleDateString() + ': ' 
               + Date.daysBetween(Jan1st2010, today));
    
    The rounding is optional, depending on whether you want partial days or not.

    jsDate: VBScript native Date functions emulated for Javascript

    /*
    Name: jsDate
    Desc: VBScript native Date functions emulated for Javascript
    Author: Rob Eberhardt, Slingshot Solutions - http://slingfive.com/
    Note: see jsDate.txt for more info
    */
    
    // constants
    vbGeneralDate=0; vbLongDate=1; vbShortDate=2; vbLongTime=3; vbShortTime=4;  // NamedFormat
    vbUseSystemDayOfWeek=0; vbSunday=1; vbMonday=2; vbTuesday=3; vbWednesday=4; vbThursday=5; vbFriday=6; vbSaturday=7; // FirstDayOfWeek
    vbUseSystem=0; vbFirstJan1=1; vbFirstFourDays=2; vbFirstFullWeek=3; // FirstWeekOfYear
    
    // arrays (1-based)
    Date.MonthNames = [null,'January','February','March','April','May','June','July','August','September','October','November','December'];
    Date.WeekdayNames = [null,'Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];
    
    
    
    
    Date.IsDate = function(p_Expression){
     return !isNaN(new Date(p_Expression));  // <-- review further
    }
    
    Date.CDate = function(p_Date){
     if(Date.IsDate(p_Date)){ return new Date(p_Date); }
    
     var strTry = p_Date.replace(/\-/g, '/').replace(/\./g, '/').replace(/ /g, '/'); // fix separators
     strTry = strTry.replace(/pm$/i, " pm").replace(/am$/i, " am"); // and meridian spacing
     if(Date.IsDate(strTry)){ return new Date(strTry); }
    
     var strTryYear = strTry + '/' + new Date().getFullYear(); // append year
     if(Date.IsDate(strTryYear)){ return new Date(strTryYear); }
     
    
     if(strTry.indexOf(":")){ // if appears to have time
      var strTryYear2 = strTry.replace(/ /, '/' + new Date().getFullYear() + ' '); // insert year
      if(Date.IsDate(strTryYear2)){ return new Date(strTryYear2); }
    
      var strTryDate = new Date().toDateString() + ' ' + p_Date; // pre-pend current date
      if(Date.IsDate(strTryDate)){ return new Date(strTryDate); }
     }
     
     return false; // double as looser IsDate
     //throw("Error #13 - Type mismatch"); // or is this better? 
    }
     
    
    
    Date.DateAdd = function(p_Interval, p_Number, p_Date){
     if(!Date.CDate(p_Date)){ return "invalid date: '" + p_Date + "'"; }
     if(isNaN(p_Number)){ return "invalid number: '" + p_Number + "'"; } 
    
     p_Number = new Number(p_Number);
     var dt = Date.CDate(p_Date);
     
     switch(p_Interval.toLowerCase()){
      case "yyyy": {
       dt.setFullYear(dt.getFullYear() + p_Number);
       break;
      }
      case "q": {
       dt.setMonth(dt.getMonth() + (p_Number*3));
       break;
      }
      case "m": {
       dt.setMonth(dt.getMonth() + p_Number);
       break;
      }
      case "y":   // day of year
      case "d":   // day
      case "w": {  // weekday
       dt.setDate(dt.getDate() + p_Number);
       break;
      }
      case "ww": { // week of year
       dt.setDate(dt.getDate() + (p_Number*7));
       break;
      }
      case "h": {
       dt.setHours(dt.getHours() + p_Number);
       break;
      }
      case "n": {  // minute
       dt.setMinutes(dt.getMinutes() + p_Number);
       break;
      }
      case "s": {
       dt.setSeconds(dt.getSeconds() + p_Number);
       break;
      }
      case "ms": { // JS extension
       dt.setMilliseconds(dt.getMilliseconds() + p_Number);
       break;
      }
      default: {
       return "invalid interval: '" + p_Interval + "'";
      }
     }
     return dt;
    }
    
    
    
    Date.DateDiff = function(p_Interval, p_Date1, p_Date2, p_FirstDayOfWeek){
     if(!Date.CDate(p_Date1)){ return "invalid date: '" + p_Date1 + "'"; }
     if(!Date.CDate(p_Date2)){ return "invalid date: '" + p_Date2 + "'"; }
     p_FirstDayOfWeek = (isNaN(p_FirstDayOfWeek) || p_FirstDayOfWeek==0) ? vbSunday : parseInt(p_FirstDayOfWeek); // set default & cast
    
     var dt1 = Date.CDate(p_Date1);
     var dt2 = Date.CDate(p_Date2);
    
     // correct DST-affected intervals ("d" & bigger)
     if("h,n,s,ms".indexOf(p_Interval.toLowerCase())==-1){
      if(p_Date1.toString().indexOf(":") ==-1){ dt1.setUTCHours(0,0,0,0) }; // no time, assume 12am
      if(p_Date2.toString().indexOf(":") ==-1){ dt2.setUTCHours(0,0,0,0) }; // no time, assume 12am
     }
    
    
     // get ms between UTC dates and make into "difference" date
     var iDiffMS = dt2.valueOf() - dt1.valueOf();
     var dtDiff = new Date(iDiffMS);
    
     // calc various diffs
     var nYears  = dt2.getUTCFullYear() - dt1.getUTCFullYear();
     var nMonths = dt2.getUTCMonth() - dt1.getUTCMonth() + (nYears!=0 ? nYears*12 : 0);
     var nQuarters = parseInt(nMonths / 3); //<<-- different than VBScript, which watches rollover not completion
     
     var nMilliseconds = iDiffMS;
     var nSeconds = parseInt(iDiffMS / 1000);
     var nMinutes = parseInt(nSeconds / 60);
     var nHours = parseInt(nMinutes / 60);
     var nDays  = parseInt(nHours / 24); // <-- now fixed for DST switch days
     var nWeeks = parseInt(nDays / 7);
    
    
     if(p_Interval.toLowerCase()=='ww'){
       // set dates to 1st & last FirstDayOfWeek
       var offset = Date.DatePart("w", dt1, p_FirstDayOfWeek)-1;
       if(offset){ dt1.setDate(dt1.getDate() +7 -offset); }
       var offset = Date.DatePart("w", dt2, p_FirstDayOfWeek)-1;
       if(offset){ dt2.setDate(dt2.getDate() -offset); }
       // recurse to "w" with adjusted dates
       var nCalWeeks = Date.DateDiff("w", dt1, dt2) + 1;
     }
     // TODO: similar for 'w'?
     
     
     // return difference
     switch(p_Interval.toLowerCase()){
      case "yyyy": return nYears;
      case "q": return nQuarters;
      case "m": return nMonths;
      case "y":   // day of year
      case "d": return nDays;
      case "w": return nWeeks;
      case "ww":return nCalWeeks; // week of year 
      case "h": return nHours;
      case "n": return nMinutes;
      case "s": return nSeconds;
      case "ms":return nMilliseconds; // not in VBScript
      default : return "invalid interval: '" + p_Interval + "'";
     }
    }
    
    
    
    
    Date.DatePart = function(p_Interval, p_Date, p_FirstDayOfWeek){
     if(!Date.CDate(p_Date)){ return "invalid date: '" + p_Date + "'"; }
    
     var dtPart = Date.CDate(p_Date);
     
     switch(p_Interval.toLowerCase()){
      case "yyyy": return dtPart.getFullYear();
      case "q": return parseInt(dtPart.getMonth() / 3) + 1;
      case "m": return dtPart.getMonth() + 1;
      case "y": return Date.DateDiff("y", "1/1/" + dtPart.getFullYear(), dtPart) + 1; // day of year
      case "d": return dtPart.getDate();
      case "w": return Date.Weekday(dtPart.getDay()+1, p_FirstDayOfWeek);  // weekday
      case "ww":return Date.DateDiff("ww", "1/1/" + dtPart.getFullYear(), dtPart, p_FirstDayOfWeek) + 1; // week of year
      case "h": return dtPart.getHours();
      case "n": return dtPart.getMinutes();
      case "s": return dtPart.getSeconds();
      case "ms":return dtPart.getMilliseconds(); // <-- JS extension, NOT in VBScript
      default : return "invalid interval: '" + p_Interval + "'";
     }
    }
    
    
    
    Date.MonthName = function(p_Month, p_Abbreviate){
     if(isNaN(p_Month)){ // v0.94- compat: extract real param from passed date
      if(!Date.CDate(p_Month)){ return "invalid month: '" + p_Month + "'"; }
      p_Month = DatePart("m", Date.CDate(p_Month));
     }
    
     var retVal = Date.MonthNames[p_Month];
     if(p_Abbreviate==true){ retVal = retVal.substring(0, 3) } // abbr to 3 chars
     return retVal;
    }
    
    
    Date.WeekdayName = function(p_Weekday, p_Abbreviate, p_FirstDayOfWeek){
     if(isNaN(p_Weekday)){ // v0.94- compat: extract real param from passed date
      if(!Date.CDate(p_Weekday)){ return "invalid weekday: '" + p_Weekday + "'"; }
      p_Weekday = DatePart("w", Date.CDate(p_Weekday));
     }
     p_FirstDayOfWeek = (isNaN(p_FirstDayOfWeek) || p_FirstDayOfWeek==0) ? vbSunday : parseInt(p_FirstDayOfWeek); // set default & cast
    
     var nWeekdayNameIdx = ((p_FirstDayOfWeek-1 + parseInt(p_Weekday)-1 +7) % 7) + 1; // compensate nWeekdayNameIdx for p_FirstDayOfWeek
     var retVal = Date.WeekdayNames[nWeekdayNameIdx];
     if(p_Abbreviate==true){ retVal = retVal.substring(0, 3) } // abbr to 3 chars
     return retVal;
    }
    
    
    // adjusts weekday for week starting on p_FirstDayOfWeek
    Date.Weekday=function(p_Weekday, p_FirstDayOfWeek){ 
     p_FirstDayOfWeek = (isNaN(p_FirstDayOfWeek) || p_FirstDayOfWeek==0) ? vbSunday : parseInt(p_FirstDayOfWeek); // set default & cast
    
     return ((parseInt(p_Weekday) - p_FirstDayOfWeek +7) % 7) + 1;
    }
    
    
    
    
    
    Date.FormatDateTime = function(p_Date, p_NamedFormat){
     if(p_Date.toUpperCase().substring(0,3) == "NOW"){ p_Date = new Date() };
     if(!Date.CDate(p_Date)){ return "invalid date: '" + p_Date + "'"; }
     if(isNaN(p_NamedFormat)){ p_NamedFormat = vbGeneralDate };
    
     var dt = Date.CDate(p_Date);
    
     switch(parseInt(p_NamedFormat)){
      case vbGeneralDate: return dt.toString();
      case vbLongDate:  return Format(p_Date, 'DDDD, MMMM D, YYYY');
      case vbShortDate:  return Format(p_Date, 'MM/DD/YYYY');
      case vbLongTime:  return dt.toLocaleTimeString();
      case vbShortTime:  return Format(p_Date, 'HH:MM:SS');
      default: return "invalid NamedFormat: '" + p_NamedFormat + "'";
     }
    }
    
    
    Date.Format = function(p_Date, p_Format, p_FirstDayOfWeek, p_firstweekofyear) {
     if(!Date.CDate(p_Date)){ return "invalid date: '" + p_Date + "'"; }
     if(!p_Format || p_Format==''){ return dt.toString() };
    
     var dt = Date.CDate(p_Date);
    
     // Zero-padding formatter
     this.pad = function(p_str){
      if(p_str.toString().length==1){p_str = '0' + p_str}
      return p_str;
     }
    
     var ampm = dt.getHours()>=12 ? 'PM' : 'AM'
     var hr = dt.getHours();
     if (hr == 0){hr = 12};
     if (hr > 12) {hr -= 12};
     var strShortTime = hr +':'+ this.pad(dt.getMinutes()) +':'+ this.pad(dt.getSeconds()) +' '+ ampm;
     var strShortDate = (dt.getMonth()+1) +'/'+ dt.getDate() +'/'+ new String( dt.getFullYear() ).substring(2,4);
     var strLongDate = Date.MonthName(dt.getMonth()+1) +' '+ dt.getDate() +', '+ dt.getFullYear();  //
    
     var retVal = p_Format;
     
     // switch tokens whose alpha replacements could be accidentally captured
     retVal = retVal.replace( new RegExp('C', 'gi'), 'CCCC' ); 
     retVal = retVal.replace( new RegExp('mmmm', 'gi'), 'XXXX' );
     retVal = retVal.replace( new RegExp('mmm', 'gi'), 'XXX' );
     retVal = retVal.replace( new RegExp('dddddd', 'gi'), 'AAAAAA' ); 
     retVal = retVal.replace( new RegExp('ddddd', 'gi'), 'AAAAA' ); 
     retVal = retVal.replace( new RegExp('dddd', 'gi'), 'AAAA' );
     retVal = retVal.replace( new RegExp('ddd', 'gi'), 'AAA' );
     retVal = retVal.replace( new RegExp('timezone', 'gi'), 'ZZZZ' );
     retVal = retVal.replace( new RegExp('time24', 'gi'), 'TTTT' );
     retVal = retVal.replace( new RegExp('time', 'gi'), 'TTT' );
    
     // now do simple token replacements
     retVal = retVal.replace( new RegExp('yyyy', 'gi'), dt.getFullYear() );
     retVal = retVal.replace( new RegExp('yy', 'gi'), new String( dt.getFullYear() ).substring(2,4) );
     retVal = retVal.replace( new RegExp('y', 'gi'), Date.DatePart("y", dt) );
     retVal = retVal.replace( new RegExp('q', 'gi'), Date.DatePart("q", dt) );
     retVal = retVal.replace( new RegExp('mm', 'gi'), (dt.getMonth() + 1) ); 
     retVal = retVal.replace( new RegExp('m', 'gi'), (dt.getMonth() + 1) ); 
     retVal = retVal.replace( new RegExp('dd', 'gi'), this.pad(dt.getDate()) );
     retVal = retVal.replace( new RegExp('d', 'gi'), dt.getDate() );
     retVal = retVal.replace( new RegExp('hh', 'gi'), this.pad(dt.getHours()) );
     retVal = retVal.replace( new RegExp('h', 'gi'), dt.getHours() );
     retVal = retVal.replace( new RegExp('nn', 'gi'), this.pad(dt.getMinutes()) );
     retVal = retVal.replace( new RegExp('n', 'gi'), dt.getMinutes() );
     retVal = retVal.replace( new RegExp('ss', 'gi'), this.pad(dt.getSeconds()) ); 
     retVal = retVal.replace( new RegExp('s', 'gi'), dt.getSeconds() ); 
     retVal = retVal.replace( new RegExp('t t t t t', 'gi'), strShortTime ); 
     retVal = retVal.replace( new RegExp('am/pm', 'g'), dt.getHours()>=12 ? 'pm' : 'am');
     retVal = retVal.replace( new RegExp('AM/PM', 'g'), dt.getHours()>=12 ? 'PM' : 'AM');
     retVal = retVal.replace( new RegExp('a/p', 'g'), dt.getHours()>=12 ? 'p' : 'a');
     retVal = retVal.replace( new RegExp('A/P', 'g'), dt.getHours()>=12 ? 'P' : 'A');
     retVal = retVal.replace( new RegExp('AMPM', 'g'), dt.getHours()>=12 ? 'pm' : 'am');
     // (always proceed largest same-lettered token to smallest)
    
     // now finish the previously set-aside tokens 
     retVal = retVal.replace( new RegExp('XXXX', 'gi'), Date.MonthName(dt.getMonth()+1, false) ); //
     retVal = retVal.replace( new RegExp('XXX',  'gi'), Date.MonthName(dt.getMonth()+1, true ) ); //
     retVal = retVal.replace( new RegExp('AAAAAA', 'gi'), strLongDate ); 
     retVal = retVal.replace( new RegExp('AAAAA', 'gi'), strShortDate ); 
     retVal = retVal.replace( new RegExp('AAAA', 'gi'), Date.WeekdayName(dt.getDay()+1, false, p_FirstDayOfWeek) ); // 
     retVal = retVal.replace( new RegExp('AAA',  'gi'), Date.WeekdayName(dt.getDay()+1, true,  p_FirstDayOfWeek) ); // 
     retVal = retVal.replace( new RegExp('TTTT', 'gi'), dt.getHours() + ':' + this.pad(dt.getMinutes()) );
     retVal = retVal.replace( new RegExp('TTT',  'gi'), hr +':'+ this.pad(dt.getMinutes()) +' '+ ampm );
     retVal = retVal.replace( new RegExp('CCCC', 'gi'), strShortDate +' '+ strShortTime ); 
    
     // finally timezone
     tz = dt.getTimezoneOffset();
     timezone = (tz<0) ? ('GMT-' + tz/60) : (tz==0) ? ('GMT') : ('GMT+' + tz/60);
     retVal = retVal.replace( new RegExp('ZZZZ', 'gi'), timezone );
    
     return retVal;
    }
    
    
    
    // ====================================
    
    /* if desired, map new methods to direct functions
    */
    IsDate = Date.IsDate;
    CDate = Date.CDate;
    DateAdd = Date.DateAdd;
    DateDiff = Date.DateDiff;
    DatePart = Date.DatePart;
    MonthName = Date.MonthName;
    WeekdayName = Date.WeekdayName;
    Weekday = Date.Weekday;
    FormatDateTime = Date.FormatDateTime;
    Format = Date.Format;
    
    
    
    /* and other capitalizations for easier porting
    isDate = IsDate;
    dateAdd = DateAdd;
    dateDiff = DateDiff;
    datePart = DatePart;
    monthName = MonthName;
    weekdayName = WeekdayName;
    formatDateTime = FormatDateTime;
    format = Format;
    
    isdate = IsDate;
    dateadd = DateAdd;
    datediff = DateDiff;
    datepart = DatePart;
    monthname = MonthName;
    weekdayname = WeekdayName;
    formatdatetime = FormatDateTime;
    
    ISDATE = IsDate;
    DATEADD = DateAdd;
    DATEDIFF = DateDiff;
    DATEPART = DatePart;
    MONTHNAME = MonthName;
    WEEKDAYNAME = WeekdayName;
    FORMATDATETIME = FormatDateTime;
    FORMAT = Format;
    */