Advanced Windows PowerShell Scripting Video Training

Advanced Windows PowerShell Scripting Video Training
Advanced Windows PowerShell Scripting Video Training

Friday, January 29, 2016

How to copy a Portion of an Image and Paste it into a Section of a PictureBox Control vwith PowerShell

This one has been a thorn in my side for a long time.  As a matter of fact, it has stopped several projects while I figure it out.  We are all familiar with the concept of selecting part of an image and then pasting that selection where we want.  The problem that I have been facing is how to do that in code with PowerShell.

I’m utilizing SAPIEN PowerShell Studio 2015 for a project involving images.  I need to take parts of multiple images and assemble them into a single PictureBox control.  Even my most beloved search engine was not helping me much. Let’s start off with making a copy of part of an image.
To set this up I created a form with 3 PictureBox controls.


The red box is P1, the green is P2, and the blue is P3.  I colorized them so we can see what is going on in each as we progress through the code. Each PictureBox is 256, 256 in size.

# Load the image into P1
$P1.ImageLocation = "E:\PowerShell\InDev\Graphics1\a-0320.jpg"
$P1.Load()




Next we will create a bitmap in memory and store the image from P1 into it.

# Create a new empty bitmap in memory and store the contents of P1.
$BMP0 = [System.Drawing.Bitmap]::New($P1.Image)

We need to create a System.Drawing.Rectangle structure and give it the initial location and the height and width.  Here is the link to MSDN to describe this object: https://msdn.microsoft.com/en-us/library/system.drawing.rectangle(v=vs.110).aspx

# Create a rectangle representing to portion of the image to capture
$SourceRec = [System.Drawing.Rectangle]::New(51, 101, 100, 100)

The first two numbers are the x and y coordinates of where the upper left of the rectangle will be.  Remember, (0, 0) is in the upper left.  The third number is the number of pixels in width and the fourth is the number of pixels in height.  This rectangle will be used to capture an area of the image that starts at (51, 101) and is both 100 pixels wide and high.  The lower right hand corner of this rectangle will be at location (151, 201).

Now paste the copied image into P2.

# Paste this image into P2.
$P2.Image = $BMP0.clone($SourceRec, $BMP0.PixelFormat)


By default, the image is pasted into the upper left corner of the image.  Our next task is to paste this image anywhere we want.

We need to create another image object in memory.  This time make it the size of the PictureBox P3.

# Create a new bitmap to hold the new image.
$BMP1 = [System.Drawing.Bitmap]::New(256, 256)

Next create another rectangle structure.  This time the first two values are the upper left corner of the rectangle in the new image where you want to paste.  In this case, (10, 40).  The rectangle will be 100 x 100 in size. This is the same size as the captured image.

# Create a rectangle to represent the area to paste the image.
$DestRec = [System.Drawing.Rectangle]::New(10, 40, 100, 100)

Using P2 as our source image, we are going to draw it into $BMP1.  Notice that we use the $DestRec structure to specify where to draw it in the image.

# Draw the contents of $P2 to the location specified in $DestRec.
$P2.DrawToBitmap($BMP1, $DestRec)

Next we draw the image $BMP1 into PictureBox P3. 

# Display the image $BMP1 in P3.
$P3.Image = $BMP1



You can call the Dispose method on $BMP0 since we are not using it, but you cannot call Dispose on $BMP1 since it is being referenced as the image for $P3.

Here is the full code that is inserted into the $Form1_Load event.

# Load the image into P1
$P1.ImageLocation = "E:\PowerShell\InDev\Graphics1\a-0320.jpg"
$P1.Load()
      
# Create a new empty bitmap in memory and store the contents of P1.
$BMP0 = [System.Drawing.Bitmap]::New($P1.Image)
      
# Create a rectangle representing to portion of the image to capture
$SourceRec = [System.Drawing.Rectangle]::New(51, 101, 100, 100)
      
# Paste this image into P2.
$P2.Image = $BMP0.clone($SourceRec, $BMP0.PixelFormat)
      
# Create a new bitmap to hold the new image.
$BMP1 = [System.Drawing.Bitmap]::New(256, 256)
      
# Create a rectangle to represent the area to paste the image.
$DestRec = [System.Drawing.Rectangle]::New(10, 40, 100, 100)
             
# Draw the contents of $P2 to the location specified in $DestRec.
$P2.DrawToBitmap($BMP1, $DestRec)
      
# Display the image $BMP1 in P3.
$P3.Image = $BMP1

 You can set the Visible property on P1 and P2 to $False if you want to hide them and only display the final image.


As we continue to watch PowerShell evolve, you will be tasked to come up with more user friendly ways for our non-technical users to take advantage of PowerShell.  This should help in the creation of effective GUIs for the end user. 

Thursday, January 28, 2016

How to Extract all of the Cmdlets used in a Script

How to Extract all of the Cmdlets used in a Script
This idea actually came from a member of my class.  He compiled all of the code that we created over the past week and wanted to know every unique cmdlet that we used.  He was attempting to work with the –Match comparison operator and had a good query.  I thought this was a good idea so I wrote some code to help him out.
This is a good way to inventory your cmdlets so you can find out which modules you need to have available when running your code on other nodes.

# How to extract all of the unique cmdlets used in a script.

Function Get-UsedCommands
{
Param (
    [Switch]
    $Count,

    [String]
    $Path
)

    Try
    {

        $Data = Get-Content -Path $Path -ErrorAction Stop
        $Ary = @()
        $Output = @()

        ForEach ($D in $Data)
        {

                $Ary += Select-String "\w+-\w+" -input $D -AllMatches |
                Foreach {$_.matches}

        }

        # Verify that each cmdlet starts with a PowerShell verb.
        # This is to prevent false positives.
        $Verbs = (Get-Verb).Verb
            ForEach ($A in $Ary)
            {
                $Value = ($A.Value).Remove(($A.Value).IndexOf("-"),$A.length-($A.Value).IndexOf("-"))
                If ($Value -in $Verbs)
                {
                    $Output += $A.Value.trim()
                }
            }

        If ($Count)
        {
            $Obj = New-Object -TypeName PSObject -Property @{
                Count = ($Output | Sort-Object -Unique | Measure-Object).Count
                }
            Write-Output $Obj
        }
        Else {$Output | Sort-Object -Unique}
    }
    Catch
    {Write-Warning "File not found"}

<#
.SYNOPSIS
Reads a file and gets all of the cmdlets used.

.DESCRIPTION
Reads the contents of a file and either displays all of the unique
cmdlets used in the file or counts them.  Only cmdlets that use
approved PowerShell verbs will be counted.

.PARAMETER Count
Returns the number of unique PowerShell Commands used.

.PARAMETER Path
The path to the script.

.Example
Get-UsedCommands -Path "E:\One Drive\ChangeUsers.ps1"
Reads the ChangeUsers.ps1 file and returns the unique cmdlets used in that script.

.Example
Get-UsedCommands -Path "E:\One Drive\ChangeUsers.ps1" -Count
Reads the ChangeUsers.ps1 file and counts the unique cmdlets used in that script.

.NOTES
===============================================================================
== Cmdlet: Get-UsedCommands                                                  ==
== Author: Jason A. Yoder                                                    ==
== Company: MCTExpert of Arizona                                             ==
== Date: January 15, 2016                                                    ==
== Copyright: All rights reserved.                                           ==
== Version: 1.0.0.0                                                          ==
== Legal: The user assumes all responsibility and liability for the usage of ==
== this PowerShell code.  MCTExpert of Arizona, Its officers, shareholders,  ==
== owners, and their relatives are not liable for any damages.  As with all  ==
== code, review it and understand it prior to usage.  It is recommended that ==
== this code be fully tested and validated in a test environment prior to    ==
== usage in a production environment.                                        ==
==                                                                           ==
== Does this code make changes: NO                                           ==
===============================================================================
#>

}


Wednesday, January 27, 2016

Using TAB Completion with CIM Commands

One of the items that my PowerShell class this past week has noticed is that there is some TAB completion capability with Get-CIMInstance.  This is true for both the –NameSpace and –ClassName parameters. To use the TAB completion, just press space after the parameter and press TAB.  The list of Class Libraries are not loaded by default.  This means that the Shell/ISE may pause for loading when it comes to big namespaces like the default Root\CIMv2.  This pause will only be for the first usage in the current namespace.
Notice the ISE is loading after I pressed TAB.









To get a list of CIM cmdlets that support some type of TAB completion:
Function Find-TabCompletion
{
PAram ($String)

    # Set up the search string.
    $S = "*"+"$String"+"*"

    Get-Command -noun "$S" |
        Select-Object -ExpandProperty Name |
        ForEach-Object {
            $Obj = New-Object -TypeName psobject -Property @{
            Cmdlet = $Null
            Parameters = $Null
              }
            $String = $Null
            $Data = (Get-Help -Name $_ -Full).Parameters
            ForEach ($D in $Data.parameter)
            {
                If ($D.Description -match "You can use tab completion to browse")
                {
                    $String = $String + ", " + "$($D.Name)"
                }
            }
           
            # Write to the pipeline only if one of the
            # commands parameters has TAB completion in
            # its description.
            If ($String -ne $Null)
            {
                $Obj.Cmdlet = $_
                $Obj.Parameters = $String.Remove(0,1).Trim()
      
                Write-Output $Obj
            }
        }
}

Here is what it the output looks like when you look for TAB completion being listed in the CIM cmdlets’ help files:
Find-TabCompletion -String "CIM"

Cmdlet                    Parameters         
------                    ----------         
Get-CimAssociatedInstance Namespace          
Get-CimClass              ClassName, Namespace
Get-CimInstance           ClassName, Namespace
Invoke-CimMethod          ClassName, Namespace
New-CimInstance           ClassName, Namespace
Register-CimIndication... ClassName, Namespace
Remove-CimInstance        Namespace          
Set-CimInstance           Namespace          




You will get nothing for WMI. This is just another good reason to switch to the CIM cmdlets.





Tuesday, January 26, 2016

How to Read Help Files (Part 7 of 7)

This is it!  The last in this series on how to read PowerShell Help Files.

Help files are available for more than just cmdlets.  PowerShell actually has an entire book of material to help you learn PowerShell built it.  Type this command:
Get-Help About_*

What you see are help files about various aspects of using PowerShell.  You will see help on programming constructs, PowerShell features, and different elements of the syntax. 
The help concerning programming such as About_IF and About_Switch start off very basic and adds in additional elements as you go.  I’ve used the About files many times to solve problems and discover why technologies are not working.

You also have help files for the PowerShell Providers.  The PSProviders give you easy access to data that would otherwise be difficult to access, such as the registry.  To see all of your PSProviders:

Get-PSProvider

PS C:\> Get-PSProvider

Name                 Capabilities                            Drives                                                             
----                 ------------                            ------                                                              
Registry             ShouldProcess, Transactions             {HKLM, HKCU}                                                       
Alias                ShouldProcess                           {Alias}                                                            
Environment          ShouldProcess                           {Env}                                                              
FileSystem           Filter, ShouldProcess, Credentials      {C, D, E}                                                          
Function             ShouldProcess                           {Function}                                                         
Variable             ShouldProcess                           {Variable}                                                          
Certificate          ShouldProcess                           {Cert}                                                             
WSMan                Credentials                             {WSMan}                                                            


To get help on each provider, just ask for it by name.  For example: Get-Help Registry or Get-Help FileSystem.

That is it on reading the Help Files.  I encourage you to invest in reading the help files for cmdlets as you start using them.  This initial investment will slow you down at first, but it will pay in dividends later.  Not only in saving you time because you know how to use a cmdlet, but also in extra coding.  One of the coding errors that my PowerShell students make is they write a lot of extra code to do something that is already built into a cmdlet.  By investing in reading the help files up front, you will have to code less and produce your scripts faster and more efficiently.

Monday, January 25, 2016

How to Read Help Files (Part 6 of 7)

As I promised yesterday, here are a few tips and tricks for help files based on cmdlets.

As you invest more heavily into PowerShell and you read the help files, you may get to the point that you will realize which cmdlet to use and what the parameter is you need, but you cannot remember how to use the parameter.  Get-Help can focus on the specific parameter of a cmdlet.

Get-Help Stop-Process –Parameter ID

 PS C:\> Get-Help Stop-Process –Parameter ID

-Id
    Specifies the process IDs of the processes to be stopped. To specify multiple IDs, use commas to separate the IDs. To find the PID of a process, type
    "get-process". The parameter name ("Id") is optional.
   
    Required?                    true
    Position?                    1
    Default value                none
    Accept pipeline input?       true (ByPropertyName)
    Accept wildcard characters?  false

This displays the full help file for the –ID parameter of Stop-Process.  If you just want the parameter section of the help file type:

Get-Help Stop-Process –Parameter *

If you want just the examples:
Get-Help Stop-Process –Examples

If you would like to keep multiple help files open in a searchable window, try this:
Get-Help Stop-Process –ShowWindow

Also, if you prefer and online help file in a web browser:
Get-Help Stop-Process –Online

This is it for help on cmdlets.  Tomorrow we will look at more ways to use Get-Help


Sunday, January 24, 2016

Reading Help Files (Part 5 of 7)

The full help file for any cmdlet is the golden ticket to getting the PowerShell pipeline to work.  Go ahead and get the full help file for Stop-Process.

Get-Help Stop-Process –Full

The full help file contains everything.  Let’s look at some of the differences between Full and Detailed help.

The first difference is with the parameters section.  Extra data is displayed for each parameter.

     -Id
        Specifies the process IDs of the processes to be stopped. To specify multiple IDs, use commas to separate the IDs. To find the PID of a process, type
        "get-process". The parameter name ("Id") is optional.
       
        Required?                    true
        Position?                    1
        Default value                none
        Accept pipeline input?       true (ByPropertyName)
        Accept wildcard characters?  false

The Required attribute tells us if this is a mandatory parameter.

Position will let you know if this is a positional parameter or a named parameter.  In this case, let’s stop the process with an ID of 6944.  Since the ID parameter is positional, we can accomplish this in one of two ways.

Stop-Process –ID 6924
Stop-Process 6924

With positional parameters, you can omit the parameter name as long as you provide a value of the correct data type.  If the parameter is named, you must provide the parameters name to use it.  In this case, -ID­ is in position #1.

The Default value will tell me if a default value is provided if I do not specify one.  Ypu will find that many cmdlets with a –ComputerName parameter has a default value of LocalHost.

We use the Accept pipeline input attribute to determine if we can use the PowerShell pipeline with this parameter.  In this case, we can.

The final attribute tells us if a wild card is accepted for the argument of this parameter.  In this case, no it is not.

Next is the INPUTS and OUTPUTS:
INPUTS
    System.Diagnostics.Process
       
       
   
        You can pipe a process object to Stop-Process.
   
   
OUTPUTS
    None or System.Diagnostics.Process
       
       
   
        When you use the PassThru parameter, Stop-Process returns a System.Diagnostics.Process object that represents the stopped process. Otherwise, this
        cmdlet does not generate any output.

This section tells us what kind of object can be passed to this cmdlet and what we should expect out of it.

The NOTES section provides extra information that may not fall under any of the other categories.
    
NOTES
   
   
        You can also refer to Stop-Process by its built-in aliases, "kill" and "spps". For more information, see about_Aliases.
       
        You can also use the properties and methods of the Windows Management Instrumentation (WMI) Win32_Process object in Windows PowerShell. For more
        information, see Get-WmiObject and the WMI SDK.
       
        When stopping processes, be aware that stopping a process can stop process and services that depend on the process. In an extreme case, stopping a
        process can stop Windows.
        


Tomorrow we will wrap things up with regards to cmdlets with a few extra tips.