# this script lets you send an sms to 2 users at the same time import appuifw import messaging
data = appuifw.query(u"Type your name:", "text") nbr1 = "123456"
# change the mobile number here nbr2 = "234567"
# change the mobile number here txt = u"Greetings from:" +data
if appuifw.query(u"Send message to your 2 friends","query") == True:
messaging.sms_send(nbr1, txt)
messaging.sms_send(nbr2, txt)
appuifw.note(u"Messages sent", "info") else:
appuifw.note(u"Well, your Messages are not sent then", "info")
Send SMS to two users @ same time
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.
| 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.
using pre & post images
using System.Collections.Generic;
//# CRM 2011: Using PRe & Post Images
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 (FaultExceptione)
{
throw e;
}
finally
{
service = null;
factory = null;
context = null;
PreImage = null;
PostImage = null;
}
}
}
}
Extend 5000 limit on data retrieval
With CRM 4.0 and Microsoft CRM 2011 there is a default limit for the number items that can be retrieved when making various types of web service calls into the CRM.
Typically this limit is set to 5000 but with some types of calls it will return 7000. In any case, the process to remove the limit and set it to 20,000 is very easy.
On the server running CRM
- 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.
hooker.py
# hooker.py
# deals with hooking of win32 APIs.
# public domain code.
from patcher import *
from tramper import tramper
from win32api import *
from pytcc import pytcc
def create_hook (duplicate_api, cparam_types='', prelogic="", postlogic="", restype="int"):
""" create_hook (pat, duplicate_api, cparam_types='', prelogic="", postlogic="", restype="int"):
"""
c_code =\
"""
%s function (int caller, %s)
{
%s
%s RET = DUPE ( %s );
%s
return RET;
}"""
cargs = ''
symbols = ''
for arg, char in zip (cparam_types, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"):
symbols += "%s, " % char
cargs += "%s %s, " % (arg, char)
symbols = symbols [:-2]
cargs = cargs [:-2]
c_code = c_code % (restype, cargs, prelogic, restype, symbols, postlogic)
ccompiler = pytcc ()
ccompiler.add_lib_proc ("msvcrt.dll", "memset")
ccompiler.add_symbol ("DUPE", duplicate_api)
ccompiler.compile (c_code)
ccompiler.relocate ()
hook = ccompiler.get_symbol ("function")
return (c_code, hook)
def hooker (apiname, cparam_types=list(), restype="int", prelogic='', postlogic='', pid=GetCurrentProcessId(), dllname="kernel32"):
"""hooker (apiname, cparam_types=list(), restype="int", prelogic='', postlogic='', pid=GetCurrentProcessId(), dllname="kernel32"):
"""
pat = patcher ()
params_size = get_cparams_size (cparam_types)
pat.set_params_size (params_size)
pat.set_source_as_api (apiname, dllname)
hook_size = len (get_patch (pat.destination, pat.params_size))
tramp = tramper (pat.source, hook_size)
pat.duplicate_api = tramp
hook_ccode, hooks = create_hook (tramp, cparam_types, prelogic, postlogic, restype)
pat.c_code = hook_ccode
pat.set_destination (hooks)
return pat
if __name__ == '__main__':
# Test.
hook = hooker (\
# API to hook
apiname="OpenProcess",
# the DLL the API is in. (defaults to kernel32)
dllname="kernel32",
# (required) API parameter types. In our hook these get translated to the names A,B,C...respectively.
cparam_types=["int", "int", "int"],
# (required) the API return type.
restype="int",
# (optional) this is the code in our hook wich is executed Before the real API.
prelogic="if (C==1) {return 1111;}",
# (optional) this is the code in our hook wich is executed After the real API. The real API's return value is named RET.
postlogic="if (RET) {return 0;}"
)
# hook API.
# hook automatically unhooks itself and cleans up when it isnt refered to anymore.
hook.patch ()
print "Calling hooked OpenProcess api with process id as 1."
ret = windll.kernel32.OpenProcess (0x1f0fff, 0, 1)
print "Return value: %s" % ret
if ret == 1111: print "This test was sucesful."
else: print "Return value is unexpected."
# unhook API.
# hook.unpatch ()
#cad
How to hide and show left navigation items in CRM 4.0
The first you need to do when you want to manipulate the left navigation section is to create a general function to get a reference to a navigation block. The reason is because each time you want to hide or show a block or nav item you need the DOM reference of the navigation block so instead of copying the code every time, you write a function and you call it everywhere.
Get the DOM reference to a left navigation block in CRM 4.0
/* Jscript: Get the DOM reference */
function GetNavBlock(block)
{
var objBlockDetails = document.getElementById("_NA_Info");
var objBlockSales = document.getElementById("_NA_SFA");
var objBlockService = document.getElementById("_NA_CS");
var objBlockMarketing = document.getElementById("_NA_MA");
var objNavBlock = null;
if (objBlockDetails.innerText.substr(0, objBlockDetails.innerText.indexOf(":")).toLowerCase() == block.toLowerCase())
objNavBlock = objBlockDetails;
else if (objBlockSales.innerText.substr(0, objBlockSales.innerText.indexOf(":")).toLowerCase() == block.toLowerCase())
objNavBlock = objBlockSales;
else if (objBlockService.innerText.substr(0, objBlockService.innerText.indexOf(":")).toLowerCase() == block.toLowerCase())
objNavBlock = objBlockService;
else if (objBlockMarketing.innerText.substr(0, objBlockMarketing.innerText.indexOf(":")).toLowerCase() == block.toLowerCase())
objNavBlock = objBlockMarketing;
else
throw "The navigation block '" + block + "' doesn't exists.";
return objNavBlock;
}
Hide a navigation block in CRM 4.0
/* Jscript: Hide a navigation block */
function HideNavBlock(block){
var objNavBlock = GetNavBlock(block);
objNavBlock.parentElement.style.display = "none";
}
Show a navigation block in CRM 4.0
/* Jscript: Show a navigation block */
function ShowNavBlock(block){
var objNavBlock = GetNavBlock(block);
objNavBlock.parentElement.style.display = "";
}
Hide a navigation item in a navigation block in CRM 4.0
/* Jscript: Hide a navigation item in a navigation block */
function HideNavItem(block, item){
var objNavBlock = GetNavBlock(block);
for (var i=0; i{
var menuItem = objNavBlock.nextSibling.childNodes[i];
if (menuItem.childNodes[0].childNodes[1].innerText == item)
menuItem.style.display = "none";
}
}
Show a navigation item in a navigation block in CRM 4.0
/* Jscript: Show a navigation item in a navigation block */
function ShowNavItem(block, item)
{
var objNavBlock = GetNavBlock(block);
for (var i=0; i{
var menuItem = objNavBlock.nextSibling.childNodes[i];
if (menuItem.childNodes[0].childNodes[1].innerText == item)
menuItem.style.display = "";
}
}
Retrieves all the CRM Organizations available on the server
///
/// Retrieves all the CRM Organizations available on the server
///
private void GetOrganizations()
{
//Authenticate with the DiscoveryService using
// Active Directory Windows Integrated Security
CrmDiscoveryService.CrmDiscoveryService discoveryService = new CrmDiscoveryService.CrmDiscoveryService();
discoveryService.Credentials = System.Net.CredentialCache.DefaultCredentials;
//Make request for organization information
RetrieveOrganizationsRequest orgsRequest = new RetrieveOrganizationsRequest();
RetrieveOrganizationsResponse orgsResponse = (RetrieveOrganizationsResponse)discoveryService.Execute(orgsRequest);
//Populate the organizations
for (int i = 0; i < orgsResponse.OrganizationDetails.Length; i++)
{
ddlOrganizations.Items.Add(new ListItem(orgsResponse.OrganizationDetails[i].OrganizationName, orgsResponse.OrganizationDetails[i].OrganizationId.ToString()));
}
}
Get the CrmService reference by Organization
///
/// Get the CrmService reference by Organization
///
///
///
private CrmSdk.CrmService GetCrmService(string organizationName)
{
// Setup the Authentication Token
CrmSdk.CrmAuthenticationToken token = new CrmAuthenticationToken();
token.OrganizationName = organizationName;
CrmSdk.CrmService crmService = new CrmSdk.CrmService();
crmService.Credentials = System.Net.CredentialCache.DefaultCredentials;
crmService.CrmAuthenticationTokenValue = token;
return crmService;
}
Obtaining a license key from the Microsoft Dynamics CRM database
If all of a sudden it happened that you lost your LicenseKey for MS CRM , it can peep in the database MS SQL.
It should do the following query to your database MS CRM :
SELECT * from License
SELECT LicenseKey from License
select * from sys.databases
select * from sys.databases;
If the caller of sys.databases is not the owner of the database and the database is not master
or tempdb, the minimum permissions required to see the corresponding row are
ALTER ANY DATABASE or VIEW ANY DATABASE server-level permission,
or CREATE DATABASE permission in the master database. If a database is not ONLINE
or AUTO_CLOSE is set to ON, the values of some columns may be NULL. If a database is
OFFLINE, the corresponding row is not visible to low-privileged users.
To see the corresponding row if the database is OFFLINE, a user must have at least the
ALTER ANY DATABASE server-level permission or the CREATE DATABASE permission
in the master database.
name
Name of database, unique within an instance of SQL Server.
database_id
ID of the database, unique within an instance of SQL Server.
source_database_id
Non-NULL = ID of the source database of this database snapshot.
owner_sid
SID (Security-Identifier) of the external owner of the database, as registered to the server.
create_date
Date the database was created or renamed. For tempdb, this value changes every time the server restarts.
compatibility_level
Integer corresponding to the version of SQL Server for which behavior is compatible:
collation_name
Collation for the database. Acts as the default collation in the database.
user_access
User-access setting:
user_access_desc
Description of user-access setting:
is_trustworthy_on
1 = Database has been marked trustworthy.
0 = Database has not been marked trustworthy.
is_db_chaining_on
1 = Cross-database ownership chaining is ON.
0 = Cross-database ownership chaining is OFF.
is_parameterization_forced
1 = Parameterization is FORCED.
0 = Parameterization is SIMPLE.
is_master_key_encrypted_by_server
1 = Database has an encrypted master key.
0 = Database does not have an encrypted master key.
is_read_only
1 = Database is READ_ONLY.
0 = Database is READ_WRITE.
is_auto_close_on
1 = AUTO_CLOSE is ON.
0 = AUTO_CLOSE is OFF.
is_auto_shrink_on
1 = AUTO_SHRINK is ON.
0 = AUTO_SHRINK is OFF.
state
Database state:
0 = ONLINE
1 = RESTORING
2 = RECOVERING
3 = RECOVERY_PENDING
4 = SUSPECT
5 = EMERGENCY
6 = OFFLINE
state_desc
Description of the database state:
ONLINE
RESTORING
RECOVERING
RECOVERY_PENDING
SUSPECT
EMERGENCY
OFFLINE
is_in_standby
Database is read-only for restore log.
is_cleanly_shutdown
1 = Database shutdown cleanly; no recovery required on startup.
0 = Database did not shutdown cleanly; recovery is required on startup.
snapshot_isolation_state
State of snapshot-isolation transactions being allowed, as set by the ALLOW_SNAPSHOT_ISOLATION option:
0 = Snapshot isolation state is OFF (default). Snapshot isolation is disallowed.
1 = Snapshot isolation state ON. Snapshot isolation is allowed.
2 = Snapshot isolation state is in transition to OFF state. All transactions have their modifications versioned. Cannot start new transactions using snapshot isolation. The database remains in the transition to OFF state until all transactions that were active when ALTER DATABASE was run can be completed.
3 = Snapshot isolation state is in transition to ON state. New transactions have their modifications versioned. Transactions cannot use snapshot isolation until the snapshot isolation state becomes 1 (ON). The database remains in the transition to ON state until all update transactions that were active when ALTER DATABASE was run can be completed.
snapshot_isolation_state_desc
Description of state of snapshot-isolation transactions being allowed, as set by the ALLOW_SNAPSHOT_ISOLATION option:
OFF
ON
IN_TRANSITION_TO_ON
IN_TRANSITION_TO_OFF
is_read_committed_snapshot_on
1 = Read-committed-snapshot option is ON. Read operations under the read-committed isolation level are based on snapshot scans and do not acquire locks.
0 = Read-committed-snapshot option is OFF (default). Read operations under the read-committed isolation level use share locks.
recovery_model
Recovery model selected:
1 = FULL
2 = BULK_LOGGED
3 = SIMPLE
recovery_model_desc
Description of recovery model selected:
FULL
BULK_LOGGED
SIMPLE
page_verify_option
Setting of PAGE_VERIFY option:
0 = NONE
1 = TORN_PAGE_DETECTION
2 = CHECKSUM
page_verify_option_desc
Description of PAGE_VERIFY option setting:
NONE.TORN_PAGE_DETECTION
CHECKSUM
is_date_correlation_on
1 = DATE_CORRELATION_OPTIMIZATION is ON.
0 = DATE_CORRELATION_OPTIMIZATION is OFF.
is_auto_create_stats_on
1 = AUTO_CREATE_STATISTICS is ON.
0 = AUTO_CREATE_STATISTICS is OFF.
is_auto_update_stats_on
1 = AUTO_UPDATE_STATISTICS is ON.
0 = AUTO_UPDATE_STATISTICS is OFF.
is_auto_update_stats_async_on
1 = AUTO_UPDATE_STATISTICS_ASYNC is ON.
0 = AUTO_UPDATE_STATISTICS_ASYNC is OFF.
is_ansi_null_default_on
1 = ANSI_NULL_DEFAULT is ON.
0 = ANSI_NULL_DEFAULT is OFF.
is_ansi_nulls_on
1 = ANSI_NULLS is ON.
0 = ANSI_NULLS is OFF.
is_ansi_padding_on
1 = ANSI_PADDING is ON.
0 = ANSI_PADDING is OFF.
is_ansi_warnings_on
1 = ANSI_WARNINGS is ON.
0 = ANSI_WARNINGS is OFF.
is_arithabort_on
1 = ARITHABORT is ON.
0 = ARITHABORT is OFF.
is_concat_null_yields_null_on
1 = CONCAT_NULL_YIELDS_NULL is ON.
0 = CONCAT_NULL_YIELDS_NULL is OFF.
is_numeric_roundabort_on
1 = NUMERIC_ROUNDABORT is ON.
0 = NUMERIC_ROUNDABORT is OFF.
is_quoted_identifier_on
1 = QUOTED_IDENTIFIER is ON.
0 = QUOTED_IDENTIFIER is OFF.
is_recursive_triggers_on
1 = RECURSIVE_TRIGGERS is ON.
0 = RECURSIVE_TRIGGERS is OFF.
is_cursor_close_on_commit_on
1 = CURSOR_CLOSE_ON_COMMIT is ON.
0 = CURSOR_CLOSE_ON_COMMIT is OFF.
is_local_cursor_default
1 = CURSOR_DEFAULT is local.
0 = CURSOR_DEFAULT is global.
is_fulltext_enabled
1 = Full-text is enabled for the database.
0 = Full-text is disabled for the database.
is_supplemental_logging_enabled
1 = SUPPLEMENTAL_LOGGING is ON.
0 = SUPPLEMENTAL_LOGGING is OFF.
is_published
1 = Database is a publication database in a transactional or snapshot replication topology.
0 = Is not a publication database.
is_subscribed
1 = Database is a subscription database in a replication topology.
0 = Is not a subscription database.
is_merge_published
1 = Database is a publication database in a merge replication topology.
0 = Is not a publication database in a merge replication topology.
is_distributor
1 = Database is the distribution database for a replication topology.
0 = Is not the distribution database for a replication topology.
is_sync_with_backup
1 = Database is marked for replication synchronization with backup.
0 = Is not marked for replication synchronization with backup.
service_broker_guid
Identifier of the service broker for this database. Used as the broker_instance of the target in the routing table.
is_broker_enabled
1 = The broker in this database is currently sending and receiving messages.
0 = All sent messages will stay on the transmission queue and received messages will not be put on queues in this database.
By default, restored or attached databases have the broker disabled.
log_reuse_wait
Reuse of transaction log space is currently waiting on one of the following:
0 = Nothing
1 = Checkpoint
2 = Log backup
3 = Active backup or restore
4 = Active transaction
6 = Replication
7 = database snapshot Creation
8 = Log Scan
9 = Other (transient)
If the reason is LOG_BACKUP, it may take two backups to actually free the space.
log_reuse_wait_desc
Description of reuse of transaction log space is currently waiting on one of the following:
NOTHING
CHECKPOINT
LOG_BACKUP
ACTIVE_BACKUP_OR_RESTORE
ACTIVE_TRANSACTION
DATABASE_MIRRORING
REPLICATION
DATABASE_SNAPSHOT_CREATION
LOG_SCAN
OTHER_TRANSIENT