Sunday, May 4, 2014

How to call custom cmdlet’s from PowerShell Script/How to create a custom cmdlet project in PowerShell

·         Open visual Studio

·         Create a Class library project

·         Add a new class file
The file will have be inheriting “System.Management.Automation.Cmdlet” .The file will also decorate the class file with the following verb [Cmdlet(VerbsCommon.Add, "NameOfYourFunctionality")]
Some sample code showing a sample powershell file


    [Cmdlet(VerbsCommon.Add, " NameOfYourFunctionality ")]
    public class MyClass : System.Management.Automation.Cmdlet
    {
        [Parameter(Position = 0, Mandatory = true)]
  public string para1;
   // define more parameters here
protected override void ProcessRecord()
        {

              //write your functionality here
 }

Add more class files if you need to build your functionality

·         Add a new installer file
Add the following code to the installer class
    [RunInstaller(true)]
    public class Installer : PSSnapIn
{
       public override string Name
        {
            get
            {
                return "NameWithWhichYouWantToRegisterWhenYouImportusing Add-PSSnapin";
            }
        }
}
}

·         Strong sign your assembly
·         In order to call this custom cmdlet from a script file you may have to first register this assembly in the GAC using the GACUTIL , once that is done you can use this custom cmdlet using the following commands in the script file

Add-PSSnapin NameWhichYoudefinedInTheNamePropertyOfinstallerFile -ErrorAction "Stop"

How to invoke/call custom cmdlet from another custom cmdlet in powershell

For example you have a requirement where you are writing custom cmdlet cmdLET1 which in turn needs to invoke cmdLET2.In such a scenario the challenge remains how to pass the parameters to the second cmdlet being invoked and also how exactly to invoke it.

Shown below is the sample code which shows how do we achieve such a scnerio

     PowerShell pShell = PowerShell.Create();
            Runspace runSpace = RunspaceFactory.CreateRunspace();
            runSpace.Open();
            Pipeline pipeline = Runspace.DefaultRunspace.CreateNestedPipeline();
            Command cmd = new Command("Add- cmdLET2");

            CommandParameter cmdPara1 = new CommandParameter("parameter1", value1);
            cmd.Parameters.Add(cmdPara1);

            CommandParameter cmdPara2 = new CommandParameter("parameter2", value2);
            cmd.Parameters.Add(cmdPara2);

            pipeline.Commands.Add(cmd);

            pShell.Commands.AddCommand("import-module").AddParameter("Name", "Add- cmdLET2");
            pipeline.Invoke();


The above code when called from cmdLET1 will invoke cmdLET2 with values passed in the CommandParameter’s

How to debug PowerShell custom Cmdlet project

In order to debug PowerShell go to the following path

Solution explorer à Right Click properties à debug

Here we need to configure the following three values

Start external program : mention the location of the powershell directory here usually it is “C:\WINDOWS\system32\WindowsPowerShell\v1.0\powershell.exe”

Next define Command line argument : -noexit -command Add-PSSnapin XXXX.PowerShell (replace  XXXX.PowerShell with the value you have defined in the “Name” property of the installer file )


Finally define the Working Directory : This is location where your project is building and placing the dlls, 

Note : In some cases you may require to copy dll from this location to the the GAC of the server, therefore every time you make a change in your code you may be required to update the dlls in the GAC. You may also need to sign your assembly with a strong name in case the same has to be copied to GAC.


Tuesday, December 10, 2013

remove an class object from a List in C# using IEqualityComparer

While removing simple datatypes(int, string, datetime etc) from List is quite simple it is not the case with Complex data types (some custom class) if it has to be removed from needs to be done using IEqualityComparer
 
I had this requirement where I needed to compare two set of Lists to identify which are the new sets of records to be created and which are the one already existing and therefore needs to be just updated.
 
A had a custom class called LookupNameValue which has certain name , value properties , now in order to compare two set of Lists in C# to find out I had to implement the IEqualityComparer for the LookupNameValue class
 
Sample code to implement IEqualityComparer : note that we have to implement method Equals and GetHashCode to use IEqualityComparer
public class ValueComparer : IEqualityComparer<LookupNameValue>
    {
 
        public bool Equals(LookupNameValue x,LookupNameValue y)
        {
            if (x.Value.Equals(y.Value))
                {
                    return true;
                }
                else
                {
                    return false;
                }
        }
        public int GetHashCode(LookupNameValue obj)
        {
            return obj.Name.GetHashCode();
        }
    }
 
Sample LookUpNameAndValue class
public class LookupNameValue : IComparable
    {
        private Guid _value;
        private string _name;
public string Name
        {
            get
            {
                return _name;
            }
            set
            {
                _name = value;
            }
        }
 
        public Guid Value
        {
            get
            {
                return _value;
            }
            set
            {
                _value = value;
            }
        }
}
 
Now once we have implemented the IEqualityComparer interface we need to use the same for filtering out the existing dataset.This is done by using Except method of the List
Sample Code to use the custom comparer
 
ValueComparer comparer = new ValueComparer();
IEnumerable<LookupNameValue> finalCreateTeamDataset = createTeamDatasetTemp.Except(updateDatasetToBeRemoved, comparer);
 
Where createTeamDatasetTemp and updateDatasetToBeRemoved are List of my generic class LookupNameValue
List<LookupNameValue> createTeamDatasetTemp = new List<LookupNameValue>();
List<LookupNameValue> updateDatasetToBeRemoved = new List<LookupNameValue>();
The filtered dataset could then be used as following
 
foreach (var data in finalCreateTeamDataset)
{
 //do ur job
}
 
Hope this is helpful to you all  

Thursday, June 13, 2013

How to write a Regular expression for case insensitive search for email with fixed domain in MVC4

I was trying to search for a way to write a regular expression which can validate my email string. My email string is something of the kind xxx@gmail.com which means while the first part of the string may change the later part is a fixed domain. I wanted this to be case insensitive validation so that an email XxXx@GmaIL.com is also validated properly.

To achieve the same we need to do it in three steps

First we need to define a custom attribute which will be used to validate the expression

Step 1 :

public class IgnorecaseRegularExpressionAttribute : RegularExpressionAttribute, IClientValidatable

 
 
{
 
public IgnoreCaseRegularExpressionAttribute(string pattern)

: base("(?i)" + pattern)
 
 

{ }
 
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
 
 

{
 
var rule = new ModelClientValidationRule

 
 
{
 
ValidationType = "ignorecaseregex",
 
 

ErrorMessage = ErrorMessage

};
 
 
rule.ValidationParameters.Add("pattern", Pattern.Substring(4));

yield return rule;
 
 

}

}

Step 2:
The validation mentioned in the step 1 need to be registered in a script file


jQuery.validator.unobtrusive.adapters.add('ignorecaseregex', ['pattern'], function (options) {

options.rules['icregex'] = options.params;

options.messages['icregex'] = options.message;



});
jQuery.validator.addMethod('ignorecaseregex', function (value, element, params) {

var match;

if (this.optional(element)) {

return true;



}
match = new RegExp(params.pattern, 'i').exec(value);

return (match && (match.index === 0) && (match[0].length === value.length));

}, '');

this script file needs to be loaded on the form where your property is used.

Step 3 :This is the final step where you are now ready to use the  IgnorecaseRegularExpressionAttribute attribute.This can be used on the property where we want to do a case insensitive validation for e.g.

[IgnorecaseRegularExpression("^[a-zA-Z0-9_-]+(\\.[a-zA-Z0-0_]+)*@gmail+(\\.com)", ErrorMessage = "Not a valid email.")]

public string DemoPropertyName { get; set; }


 



Wednesday, June 12, 2013

Case in-sensitive search in MSCRM 2011

To do a case insensitive search in MSCRM 2011 we need to tweak the query a little bit ,for e.g.

if (!String.IsNullOrEmpty(fieldname)) query.Criteria.AddCondition("fieldname".ToLower(), ConditionOperator.Equal, fieldname.ToLower());
EntityCollection col = service.RetrieveMultiple(query);
Here I am setting the schema name to ToLower() which actually does the trick, hope this help.Leave your comments.

Tuesday, June 4, 2013

Hitting backspace on the jquery datetime control hides it on MSCRM 2011 form/ How to capture the keypress event on a jquery control and overcome the default behavior


I have used jquery hour’s picker/Date picker control on the MSCRM form. It was working perfectly fine till the time I used to press the backspace. As soon as we press backspace it used to hide the control for some reason.

To overcome this we need to override the default behavior of the “backspace” and “delete” keys.

As shown below I am using the “keydown” event, please do not use KeyPress event as it does not gives the required result

$("#timepickerControl").keydown(function (e) {

            switch (e.keyCode) {

                case 46:  // delete

                    e.preventDefault();

                    alert("Del Key Pressed ,Please use slider to enter valid input");

                    break;

                case 8:  // backspace

                    e.preventDefault();

                    alert("Backspace Key Pressed ,Please use slider to enter valid input");

                    break;

            }

        });
The above code will stop the hiding if I click on the text box provided for the control.
In order to disable the backspace on the complete document and the parent document we need to have two extra pair of functions as below


 // Prevent the backspace key from navigating back on the webresource.

        $(document).unbind('keydown').bind('keydown', function (event) {

            var doPrevent = false;

            if (event.keyCode === 8) {

                var d = event.srcElement || event.target;

                if ((d.tagName.toUpperCase() === 'INPUT' && (d.type.toUpperCase() === 'TEXT' || d.type.toUpperCase() === 'PASSWORD'))

             || d.tagName.toUpperCase() === 'TEXTAREA') {

                    doPrevent = d.readOnly || d.disabled;

                }

                else {

                    doPrevent = true;

                }

            }

 

            if (doPrevent) {

                event.preventDefault();

            }

        });

 

    });

 

    //Prevent the backspace key from navigating back on the parent form containing the webresource.

    $(window.parent.document).unbind('keydown').bind('keydown', function (event) {

        var doPrevent = false;

        if (event.keyCode === 8) {

            var d = event.srcElement || event.target;

            if ((d.tagName.toUpperCase() === 'INPUT' && (d.type.toUpperCase() === 'TEXT' || d.type.toUpperCase() === 'PASSWORD'))

            || d.tagName.toUpperCase() === 'TEXTAREA') {

                doPrevent = d.readOnly || d.disabled;

            }

            else {

                doPrevent = true;

            }

        }

 

        if (doPrevent) {

            event.preventDefault();

        }

    });