Click here to Skip to main content
15,881,803 members
Articles / Programming Languages / PowerShell

Custom CSharp Control for Powershell

Rate me:
Please Sign up or sign in to vote.
5.00/5 (1 vote)
7 Jan 2012CPOL2 min read 28.4K   597   6  
Customizable Custom CSharp Control for the Powershell New-PSDrive cmdlet
image001.jpg

Introduction

Powershell includes the capability for direct access to .NET and C# can be directly integrated. In this project, a custom C# control is created and accessed directly from powershell to enhance the functionality of the New-PSDrive cmdlet. Once the control is created with the appropriate sub-controls, it can be accessed from powershell via the namespace and classname (see the included powershell script for accessing the control). This is a simple example of creating a control and accessing it from powershell.

Powershell includes the capability to access Windows Presentation Foundations namespaces, and this is used in the powershell script to create a parent form that hosts the custom C# control. In this example, the custom control is loaded using reflection but in powershell 3, it is also possible to use the Add-Type cmdlet to load the assembly.

C#
namespace PSMap
{
    partial class MapControl
    {
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; 
        /// otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Component Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify 
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.DriveLetter = new System.Windows.Forms.ComboBox();
            this.ServerName = new System.Windows.Forms.ComboBox();
            this.ShareName = new System.Windows.Forms.ComboBox();
            this.Credentials = new System.Windows.Forms.ComboBox();
            this.lb_DriveLetter = new System.Windows.Forms.Label();
            this.lb_ServerName = new System.Windows.Forms.Label();
            this.lb_ShareName = new System.Windows.Forms.Label();
            this.lb_Credentials = new System.Windows.Forms.Label();
            this.lb_Title = new System.Windows.Forms.Label();
            this.lb_justcode = new System.Windows.Forms.Label();
            this.lb_About_PSMap = new System.Windows.Forms.Label();
            this.PSProvider = new System.Windows.Forms.ComboBox();
            this.lb_psprovider = new System.Windows.Forms.Label();
            this.SuspendLayout();
            // 
            // DriveLetter
            // 
            this.DriveLetter.FormattingEnabled = true;
            this.DriveLetter.Items.AddRange(new object[] {
            "HKLM",
            "G",
            "H",
            "I",
            "J",
            "K",
            "L",
            "M",
            "N",
            "O",
            "P",
            "Q",
            "R",
            "S",
            "T",
            "U",
            "V",
            "W",
            "X",
            "Y",
            "Z"});
            this.DriveLetter.Location = new System.Drawing.Point(6, 54);
            this.DriveLetter.Name = "DriveLetter";
            this.DriveLetter.Size = new System.Drawing.Size(96, 21);
            this.DriveLetter.TabIndex = 0;
            this.DriveLetter.SelectedIndexChanged += 
		new System.EventHandler(this.DriveLetter_SelectedIndexChanged);
            // 
            // ServerName
            // 
            
	     // … ( see included project )   
        }

        #endregion

        private System.Windows.Forms.ComboBox DriveLetter;
        private System.Windows.Forms.ComboBox ServerName;
        private System.Windows.Forms.ComboBox ShareName;
        private System.Windows.Forms.ComboBox Credentials;
        private System.Windows.Forms.Label lb_DriveLetter;
        private System.Windows.Forms.Label lb_ServerName;
        private System.Windows.Forms.Label lb_ShareName;
        private System.Windows.Forms.Label lb_Credentials;
        private System.Windows.Forms.Label lb_Title;
        private System.Windows.Forms.Label lb_justcode;
        private System.Windows.Forms.Label lb_About_PSMap;
        private System.Windows.Forms.ComboBox PSProvider;
        private System.Windows.Forms.Label lb_psprovider;
    }
}

In Visual Studio 2010, you can create a new project “Windows Forms Control Library” to create a custom Forms control.

image002.jpg

You will also want to set your .NET version to an appropriate version. In this case, I chose .NET Framework 3.5.

You will also need to generate a Strong Name for your assembly. A batch file is included in the deployment package (PSMapDll-Deploy.zip) which can be used to generate the Strong Name.

This customizable custom control for powershell allows you to easily enter parameters for the New-PSDrive cmdlet. Simply run the script below. I plan to create a module for it possibly.

IMPORTANT: You must set the correct powershell execution policy *AND* you will have to unblock the PSMap.dll file (C:\PSMapDll-Deploy\PSMap.dll – Click on Properties -> Unblock ) here below is the link to the complete Powershell package.

PSMapDll-Deploy

And here is the included sample powershell script to run the custom control (extract the package to C: or create the PSMapDll-Deploy directory and extact the files there). If for any reason, you have any trouble loading the DLL in the powershell script, you can use the inst-gac.bat file to install the assembly in your Global Assembly Cache.uninst-gac.bat is also included. The powershell script below is also included in the download package above.

The script will connect the drive you specify in the Custom Control above once you click ok. If Credentials are entered, it will use those, however alternate credentials are not required for normal operation (so leave that field blank in that case).

# load the customizable custom control
[Reflection.Assembly]::LoadFile('C:\PSMapDll-Deploy\PSMap.dll')  
 
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") 
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
 
# Setup the main forms
$objForm = New-Object System.Windows.Forms.Form 
$objForm.Text = "PSMapForm"
$objForm.Size = New-Object System.Drawing.Size(600,340) 
$objForm.StartPosition = "CenterScreen"
# add the PSMap custom control
$objCustom = New-Object PSMap.MapControl
$objCustom.Location = New-Object System.Drawing.Size(0,0)
$objCustom.Size = New-Object System.Drawing.Size(600,300)
 
#  add items as needed to the customize the controls of the PSMap custom control
$t = $objCustom.Controls.Item("ServerName")
$t.Items.Add("TestServer1")
$t.Items.Add("TestServer2")
 
$t = $objCustom.Controls.Item("ShareName")
$t.Items.Add("C$")
$t.Items.Add("MyShare")
 
$t = $objCustom.Controls.Item("Credentials")
$t.Items.Add("Computername\Username")
$t.Items.Add("DomainName\Username")
 
$t = $objCustom.Controls.Item("PSProvider")
$t.Items.Add("testprovider")
 
$t = $objCustom.Controls.Item("Credentials")
$t.Items.Add("domain\username")
 
#Add main form functionality and run form
$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Size(500,260)
$OKButton.Size = New-Object System.Drawing.Size(75,23)
$OKButton.Text = "OK"
$OKButton.Add_Click({$y = $objCustom;$objForm.Close()})
$objForm.Controls.Add($OKButton)$objForm.Controls.Add($objCustom)
$objForm.Topmost = $True
[void] $objForm.ShowDialog()
 
# create the UNC path variable from entered items
$z = "\\" + $y.Controls.Item("ServerName").Text + "\" + $y.Controls.Item("ShareName").Text
# create a test variable to test the credentials item
$x = $y.Controls.Item("Credentials")
# write out variables retrieved as an example for this sample script
$z$y.Controls.Item("DriveLetter").Text
$y.Controls.Item("Credentials").Text
 $y.Controls.Item("PSProvider").Text
$y.Controls.Item("ServerName").Text
$y.Controls.Item("ShareName").Text
$x.Text
 
# test the credentials variable and call the correct map command 
based on whether its present
if($x.Text -eq "") { 
 New-PSDrive -Name $y.Controls.Item("DriveLetter").Text 
 -PSProvider $y.Controls.Item("PSProvider").Text -Root $z
}
Else { 
 New-PSDrive -Name $y.Controls.Item("DriveLetter").Text 
 -PSProvider $y.Controls.Item("PSProvider").Text -Root $z -Credential $x.Text
}

History

  • 7th January, 2012: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Canada Canada
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
-- There are no messages in this forum --