Monday, June 29, 2009

Adding a Custom Button to Advanced Find in CRM 4.0

Have you ever observed how powerful Advanced Find dialogue can be in the right hands? Well apart from looking at the customized result set and providing total control to filter the data Advanced Find can be used for some really cool tricks. Recently, I had to face a situation where I needed to turn Advanced Find into some bit simpler find by removing some functionalist and by adding a simple button on the Grid Toolbar.

I managed it somehow in few hours and thought to share it with you, just in case you also fall in the same trap some day. So here it goes, just note that, modifying Advanced Find is NOT at all supported and I DO NOT take any responsibility what so ever if you follow the steps I've mentioned below and end up with any kind of damage[mental\physical\financial\social\...].

Here are steps to add a button to advanced find window
1. Go to CRM Installation directory and navigate to \CRMWeb\AdvancedFind\. Mostly you will have to go to C:\Program Files\Microsoft Dynamics CRM\CRMWeb\AdvancedFind.
2. Take a back up of AdvFind.aspx.
3. Open AdvFind.aspx in any text editor. [Visual Studio is recommended though].
4. locate the first </form> tag.
5. Copy-paste the following line : <input type="button" onclick="Alert('Hey!!!... I am in Advanced Find Window...')" value="Click Me!!!" />
6. Save and Close the file.
7. Go to CRM and click on Advanced Find... Dialogue. You will see a long ugly button on top. Click on it to see the message.
This is a simple approach I've followed. There can be tons of things you can do. You can skin it to look like the real CRM buttons and then replace the alert message with some really useful and complex logic.

Anyways, I took it little further and added the following script and removed the button from the previous step.

<script language="javascript" type="text/javascript">
function DoIt() {
var template = document.getElementById("btnEditProperties");
var newNode = document.createElement(template.tagName);
newNode.setAttribute("class", "ms-crm-Menu");
newNode.setAttribute("tabIndex", "-1");
newNode.setAttribute("title", "Visit Metrix...");
var magic = "<SPAN class=ms-crm-Menu-Label><A class=ms-crm-Menu-Label tabIndex=-1 onclick='return false;' href='javascript:onclick();' target=_self><IMG class=ms-crm-Menu-ButtonFirst tabIndex=-1 alt='Visit Metrix....' src='/_imgs/vieweditor/16_viewProps.gif'><SPAN class=ms-crm-MenuItem-TextRTL tabIndex=0>http:\\\\
metrix.blogspot.com</SPAN></A></SPAN>";
newNode.insertAdjacentHTML("afterBegin", magic);
template.parentNode.appendChild(newNode);
}
DoIt();
</script>

and I got this :

Also you might want to add a little delay in the execution of the script by using window.setTimeout method otherwise it will give error in case the grid is not loaded by the time script is called.

Monday, June 22, 2009

Hide Elements on OnLoad in CRM 4.0/CRM 3.0

I know it is pretty simple to do but I see there are posts popping up here and there for the same. So here it is, a very simple script to hide form elements in CRM during page load. You can call the function from any where any time once you have put it on OnLoad event of the page.

document.HideElement = function(elementId) {
if (document.getElementById(elementId))
document.getElementById(elementId).style.display = 'none';
}

And here how you can use this function to hide various elements when CRM form loads

document.HideElement("_MBcrmFormSave"); // Hides Save button
document.HideElement("_MBcrmFormSaveAndClose"); // Hides Save And Close button

to hide an element say for example : AccountValue, following will be the code snippet

document.HideElement("skynet_AccountValue_c");
document.HideElement("skynet_AccountValue_d");
document.HideElement("skynet_AccountValue");

Wednesday, June 17, 2009

Will The Real GAC Folder Structure Please Show Up?

Just in case the above mentioned blogpost is gone, here is the command to 'mount' GAC as a drive.
subst x: "c:\windows\assembly\gac"
It solves the universal problem for the developers who wants to dissemble .net assemblies which are registered in GAC. Enjoy!!!

Tuesday, June 16, 2009

Disable Page Close Confirmation in CRM 4.0

If you have worked with CRM, then you must have observed an annoying popup message whenever you try to close a form once you have made any changes to it. In certain cases, you might like to avoid showing that dialogue. In one of the recent engagements, I had to change some values on the form when it loads but then users started complaining that even if they don't change anything they are presented with the dialogue box asking to save the record. And then what I had to put a crmForm.Save(); statement after I've changed the values[That's lame I know...]. However, I stumbled upon on this unsupported and undocumented function that helps you get rid of that irritating popup. Use it wisely and you will be good to go :

crmForm.detachCloseAlert()

Wednesday, June 03, 2009

Scrolling Announcements on Home Page for CRM 4.0

Lately, I've started looking into problems people face when dealing with CRM. Well it is a part of my job and provides me a great learning opportunity.

A day or two before I got this requirement : The end user wanted to scroll Announcements[CRM entity : newsarticle] on top of home page. I made a simple script which can be used. This one fetches all Announcements so you might want to set some filters like expiry date or active on date.

Here are the steps to scroll announcement on CRM Home page. Kindly note that I do not take any responsibility if something goes wrong with this approach.
1. Go to CRMWeb\_root\ and take backup of bar_top.aspx and keep it safe somewhere. In case things goes wrong, you will need it to restore things back.
2. Open bar_top.aspx in Visual Studio
3. Add the following code snippet at the end of the file.

<!-- SCRIPT BEGIN : Scroll Announcements -->

<script type="text/javascript" language="javascript">
window.attachEvent('onload', ScrollAnnouncement);

function ScrollAnnouncement() {
var xml = "" +
"<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
"<soap:Envelope xmlns:soap=\"
http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">"
+ GenerateAuthenticationHeader()
+
" <soap:Body>" +
" <Execute xmlns=\"
http://schemas.microsoft.com/crm/2007/WebServices\">" +
" <Request xsi:type=\"RetrieveMultipleRequest\" ReturnDynamicEntities=\"true\">" +
" <Query xmlns:q1=\"
http://schemas.microsoft.com/crm/2006/Query\" xsi:type=\"q1:QueryExpression\">" +
" <q1:EntityName>businessunitnewsarticle</q1:EntityName>" +
" <q1:ColumnSet xsi:type=\"q1:ColumnSet\">" +
" <q1:Attributes>" +
" <q1:Attribute>articletitle</q1:Attribute>" +
" </q1:Attributes>" +
" </q1:ColumnSet>" +
" <q1:Distinct>false</q1:Distinct>" +
" </Query>" +
" </Request>" +
" </Execute>" +
" </soap:Body>" +
"</soap:Envelope>" +
"";

var xmlHttpRequest = new ActiveXObject("Msxml2.XMLHTTP");

xmlHttpRequest.Open("POST", "/mscrmservices/2007/CrmService.asmx", false);
xmlHttpRequest.setRequestHeader("SOAPAction", "
http://schemas.microsoft.com/crm/2007/WebServices/Execute");
xmlHttpRequest.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
xmlHttpRequest.setRequestHeader("Content-Length", xml.length);
xmlHttpRequest.send(xml);

var resultXml = xmlHttpRequest.responseXML;

var entityNode = resultXml.selectNodes("//BusinessEntities")[0];
var marqueeHTML = "<marquee class='ms-crm-MastHead-SignIn-User'>";
for (var i = 0; i < entityNode.childNodes.length; i++) {
if (i == 0) {
marqueeHTML += entityNode.childNodes[i].childNodes[0].childNodes[0].text
} else {
marqueeHTML += "&nbsp; &nbsp; " + entityNode.childNodes[i].childNodes[0].childNodes[0].text;
}
}
marqueeHTML += "<marquee>";

var headerTD = document.getElementById("tdLogoMastHeadBar");
headerTD.innerHTML += marqueeHTML;
}
</script>

<!-- SCRIPT END : Scroll Announcements -->


4. Check on home page.
You will see a scrolling marquee of the announcements title on CRM Header.

Monday, June 01, 2009

Hiding Menu Items from top menu bar in CRM 4.0

Here is a little script which you can call to hide menu item from top menu.
Put this script on page load or on any other event where you would like it.
You might also wanna add it as document.HideMenuItem = new function(targetMenu, targetMenuItem) {//code goes here};

function HideMenuItem(targetMenu, targetMenuItem) {
var menuLIs = document.getElementById("mnuBar1").getElementsByTagName("LI");
for (var i = 0; i < menuLIs.length; i++) {
if (menuLIs[i].title && menuLIs[i].title.indexOf(targetMenu) > -1) {
var targetDivs = menuLIs[i].getElementsByTagName("DIV");
for (var j = 0; j < targetDivs.length; j++) {
var targetLIs = targetDivs[j].getElementsByTagName("LI");
for (var k = 0; k < targetLIs.length; k++) {
if (targetLIs[k].innerHTML.indexOf(targetMenuItem) > -1) {
targetLIs[k].style.display = "none";
return;
}
}
}
}
}
}

All you have to do is call it with two parameters first parameter is the text without space so if you have root menu named Sub Test, you should call it SubTest. And the second parameter is the whole text of the menu item you need to hide.

HideMenuItem("ISV.NEW", "Coming Soon...");
HideMenuItem("SubTest", "Test Sub 1");
HideMenuItem("ISV.NEW", "Web Only");

Let me know if you need any more info on the same.
PS: Thanks to Andrew, there was a bug in the previous version of script, which didn't work with all the menus but now it has been fixed.

Friday, May 29, 2009

Hiding Notes Section from Notes tab from CRM Form

If you hit this post, then most probably you were looking to hide Notes Section/Notes Tab. However there is a CRM limitation of having only 8 tabs per form[It can be overridden though].
So sometimes you might want to use that notorious Notes tab but then you don't want users to see Notes field in there.
So here is a one line of code which takes care of it. Just copy paste it on the Form Load of your entity form and it should do the rest
document.getElementById("notescontrol_d").parentNode.parentNode.parentNode.parentNode.style.display
= "none";

Thursday, May 28, 2009

Removing System Locked Section from CRM Form

This is one interesting and as usual unsupported solution that will help you to remove a system locked section from CRM form. Kindly note that I do not take any responsibility if something goes wrong with this approach.

Please take backup of your customization before you try this. Here is a step by step guide to remove a system locked section.

1. Export Service Appointment entity.[Take a backup of the zip file you just exported].
2. Extract content of the zip file -> customization.xml.
3. Open the xml in your favourite xml editor. You can use Notepad or Visual Studio to keep it simple.
4. locate the following section "scheduling information"
<section name="scheduling information" showlabel="true" showbar="true" locklevel="1" id="<GUID>" IsUserDefined="0" layout="varwidth" columns="11">change locklevel 1 to 0.
5. Once you have done it, import the customization back to CRM.
6. Open the Form.
7. Move Start Time and End Time to a choice of your section. You can Duration and All Day Event as well.
8. Remove the section.
9. Preview and Test.

In case things do not work as expected, use the backup and restore the entity.

Tuesday, March 03, 2009

Dependent Picklist for CRM 4.0

It's been a while since I posted anything on this blog and there are good reasons for that. Lately I've been quite busy with an integration project which involves a WCF Proxy and a lot of troubleshooting here and there. It's definitely fun but then I don't get time nor I've energy to do anything once I am home.

Anyways today I could steal some time 'cause of a request to share the code of Dynamic or chained Picklists in CRM 4.0 There is not much rocket science in here just easy to use scriptlets and pure DHTML fun.

I have uploaded it here : https://cid-b6a90e5b5092759c.skydrive.live.com/self.aspx/BlogStore/Chained%20Picklists.zip

The zip has the script file and a helper excel that will make it easier for you to create the Picklist arrays.

If you give it a try kindly let me know how it goes for you.

Monday, January 19, 2009

Dirty Fox... heading the risky business apps list

Ah... I thought I will give company to Mrinal.. and here it is.. a link to the article... check it out ... http://www.insidetech.com/news/articles/3605-firefox-heads-risky-business-app-list oh.. hi.. L(inux)users... where are yo?

VS2008SP1 on Win7

As you all know.. Win7 is out.. and my god it is.. faster beyond my expectations.. and definitely.. faster than my XPSP3(Oh I was so proud... about it :(). And just yesterday, I installed VS2008 SP1 on it nad it works like a charm.. not a single glitch in compiling my existing code and on top of that it looks better than Vista. It has got soft UI elements and somehow.. I felt really comfortable working with them when compared to Vista. Check out the sample running a demo WPF application.

And no matter... what they are saying, it was piece of cake to install VS2008 it took less than 10 minutes and YES I don't want to talk about how long it took to install SP1(I was running some heavy processes in background.. eh.. :P)

Sunday, January 18, 2009

Microsoft .NET Framework 2.0 Service Pack 2

Link:
Download Overview:
The .NET Framework 2.0 Service Pack 2 provides cumulative roll-up updates for customer reported issues found after the release of the .NET Framework 2.0. In addition, this release provides performance improvements, and prerequisite feature support for the .NET Framework 3.5 Service Pack 1.

Please review the supported operating systems for this deployment package in the System Requirements section. The corresponding updates for Windows Vista and Microsoft Windows 2008 are deployed via the full .NET Framework 3.5 service pack 1.
Just be careful, there is a follow up update patch - KB959209 needed, once you install .Net Framework 2.0 SP2.

Saturday, January 17, 2009

CircuitCity short-circuited

I just came to know about this... very very sad :(
http://www.circuitcity.com/closed.html

Wednesday, December 24, 2008

Opera... you too?

Today is a bad day.. really really bad day.. I didn't expect this from Opera.. at least.. if Google does it.. it is in their nature... but Opera you too?
Microsoft has done the same thing in early 90s but they changed and they paid a lot of money for what they did earlier.
What happened is, I got an "There is a new version of Opera available for download." message, and as a die hard fan of Opera, I immediately click on Download and once it downloaded, I started installation. I love my existing settings and customizations in Opera, so I always upgrade rather than clean install. And as usual I was about to click on Next when I noticed a small, pre-checked check box at bottom of the installer. And my instincts told me.... HEY!!!! STOP!!!... and I looked at it.. the check box read ... Make Opera Default Browser..and I was like : Oh my lord.. did Microsoft(Old days) took over or what? or it is Google now? Well.. for those who didn't get it.. that check box will make Opera my default browser.. and yes.. I am no idiot who doesn't understand flexibility of IE.. most of the sites I look at looks the BEST on IE.. and most of the good sites works fine.. with IE.. no problem so far...while Opera.. is the best browser.. for the sites which normal users might not want to give a look.. for me it works.. but Opera as my default browser.. NO NO.. BIG NO!!!... anyways.. I survived the attack(This is a kindda browser replacement attack.. aahh I coined a new term... :P)
This was definitely a dirty move.. and well thought and.. yes.. I can tell it was no accident.. Opera did the same the Microsoft was used to do earlier. But that was a different time.. but now? NO NO!!!! Opera.. 5 cents down.. you guys are.. so next time you install Opera..just be careful.. they are not as good as they were used to be.. anymore..

Google.. does it again...

I dunno what kind of idiot some one has to be to push an update to a product.. which just changes the version number... I wish I could be that idiot.. and then.. google would have hired me as a Product Manager(Phew.. thank god.. I am smart.. and I won't have to be that guy..)
According to this blog as well as few other trusted resources I just came to know, Google pushed a product update on iPhone that changes the version number... YA... just the version number.. that's it..

Wednesday, December 17, 2008

Killing a Process running on Remote Computer(The batch file way..)

This morning when I came to office, I had a set of tasks which needed to be completed ASAP. My current engagement requires me to work on customer server via RDP. Now RDP has an interesting behavior, in certain cases if the server has a limited resources, it will simply refuse to allow RDP access. And unfortunately, it happened to me today. One of my colleague ran a time-consuming, resource-hungry custom code over the weekend so we can work smoothly during the weekdays, however the application could not complete its work during the weekend and was still running and consuming whatever resources were available and in turn caused a DoS (Denial Of Service). I thought to use VBScript/WMI to kill the remote process as I had the name of the process to be killed and have had used it in past effectively. I started working with the script but, I felt it will take too much time to figure out the script that will help me so I decided to search on my favorite search engine for easier and faster options. Within a few minutes I got the pointers to use tasklist.exe and taskkill.exe. I killed the process manually and easily got my access restored. However at end of the day, spending some time one this and making a batch file will come handy as we run into this situation more often. So I spent few minutes in notepad and here is the batch file that I got. This batch file is not polished but should get the job done in time of needs. And as usual I don't take any responsibility of any kind if you use this script and get into some trouble. So use it at your own risk...

@ECHO OFF
@ECHO WARNING : This script will forcefully kill the process and will not ask for confirmation before killing the process.

SET MESSAGE=
SET SYSTEMNAME=
SET USERNAME=
SET PASSWORD=
SET PID=

SET /P MESSAGE=Press any key to continue...

SET /P SYSTEMNAME=Enter target computer name or IP :
SET /P USERNAME=Enter User Name (domain\username) :
SET /P PASSWORD=Enter Password :

@ECHO Please wait while we get the list of processes...

TASKLIST.EXE /S %SYSTEMNAME% /U %USERNAME% /P %PASSWORD%

SET /P PID=Enter PID(Process ID) of the process you want to kill :

TASKKILL.EXE /F /S %SYSTEMNAME% /U %USERNAME% /P %PASSWORD% /PID %PID%

SET /P MESSAGE=Press any key to continue...

Generic Serializer-Deserializer

Around one and half year back, I was handling an interesting situation. There were few different systems sending in XML messages, and my component had to accept the message, interpret it and take appropriate actions.

It was easy till I came to know about XML message and its elements and alternate messages. The possibilities were unlimited, and it sounded stupid to hand code/hard code XML elements. Rather than that the solution was designed so that we converted XML -> XSD -> CS. After few changes made here and there to fine tune the CS files with XML, we faced another challenge, we had to serialize/deserialize incoming/outgoing messages. After few minutes of R&D I could pull out this. I've listed the method signature and minor code implementation. It is so simple that you can easily get it working in few minutes.

public static string Serialize<T>(
T data
)
{

//Create the Serializer

XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));

//Use the serializer we have just created and serialize the object.

}

the same goes with the Deserializer

public static T Deserialize<T>(
string serializedData
)
{

//check whether the incoming data is not a null string
if (string.IsNullOrEmpty(serializedData))
return default(T); //This can be controversial, so handle with care and as per your requirements, in certain cases you can return null as well, kindly let me know if you have anything that can improvise this code

//create a serializer
XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));

//Use the deserializer we have just created and deserialize the object.

}

I must thank my friend Sidhartha http://IamJunk.spaces.live.com, as he helped me a lot to enhance the code. I've not published the whole code, in case you need it, drop me an email/comment. I will be more than happy to help you out.

All In One Entity for CRM 4.0

Sometimes back I was doing a research on a script(It is coming soon.. just wait and watch...) and that script required me to try all the CRM datatypes one by one on the form. And trust me, it was a pretty boring job to create the element on a CRM form and then check compatibility of that script with it. Anyway, I thought I can help out my friends out there just in case they face the similar situation. So here is a SkyDrive link :

https://cid-b6a90e5b5092759c.skydrive.live.com/self.aspx/BlogStore/AllInOneEntity.zip
If you find that I've missed out something, kindly drop me a note. Thanks in advance.

Friday, November 21, 2008

Google Launches Themes for Gmail

Well.. Google's flagship beta(err... hmm.. ya.. for a while..or forever?) product has just got another feature(well.. you can add 31 features a month and remove 17 of them if you are in beta.. ain't it?). It is themes...(Oh and I was thinking they will get me free land line/cell calling from Gmail browser interface :D). Anyways.. I tried.. one and it looks good.. :D.. check out the screenshot below..

My Gmail Inbox...after applying Terminal theme