Advanced Windows PowerShell Scripting Video Training

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

Thursday, February 27, 2014

Get the PowerShell V3–ShowWindow in PowerShell V2

This week I’m delivering a PowerShell class in Virginia to an audience who will be using PowerShell V2 for a while longer.  I noticed that one of the features of V3 that they like is the –ShowWindow parameter of Get-Help.  Since this class is a 10 day tool making course, I decided to just create the tool for them.  What I decided to do was to have Notepad display the help file information for me.  This provides the critical “Search” capability that they are looking for.  I also decided to address one of the short comings of Get-Help –ShowWindow and that is it’s inability to open multiple help windows at the same time.  Below is the code.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

Function Show-V2ShowWindow

{

[cmdletBinding()]

Param(

    [Parameter(Mandatory=$True,

    ValueFromPipeline=$true)]

    [String[]]$Cmdlet

    )

 

    Begin {}

 

    Process

    {

        # Generate a full path to the currently logged in user's "Documents"

        # Folder

        $Path = "$($Env:HomeDrive)$($env:HOMEPATH)\Documents\PSHelpFile.txt"

       

        ForEach ($C in $Cmdlet)

        {

            Try

            {

                # Collect the full Help File information for the cmdlet.

                Get-Help $C -Full -ErrorAction Stop |

                    Out-File -FilePath $Path

       

                # Open the txt file in Notepad

                Invoke-Expression -Command "Notepad.exe $Path"

               

                #Pause to allow Notepad to load before loading the next help file.

                Start-Sleep -Milliseconds 250

               

                # Remove the temporary txt file.

                Remove-Item -Path $Path

            }

 

            Catch

            {

                # If no help file exists for this cmdlet, then display a warning.

                Write-Warning "No Help file Available"

            }

        } # END: ForEach ($C in $Cmdlet)

    } # END: Process

 

    End {}

 

<#

.SYNOPSIS

Displays the full help file in notepad.

 

.DESCRIPTION

Displays the full help file in notepad.  This allows for multiple help files

to be open for users in PowerShell V2 environments to simulate

the functionality of -ShowWindow in PowerShell V3

 

.PARAMETER Cmdlet

The Cmdlet or ABOUT_ file that you want to display.

 

.EXAMPLE

Get-V2ShowWindow Get-Date

 

Displays the full help file for Get-Date in Notepad.

 

.EXAMPLE

Show-V2ShowWindow -cmdlet Get-date, Get-Command

 

Opens two help files at the same time.

 

.EXAMPLE

"Get-date", "Get-Command" | Show-V2ShowWindow

 

Opens two help files at the same time.  When piping cmdlets in from the command line,

they must be enclosed in quotation marks.

 

.NOTES

==============================================================================

Author: Jason A. Yoder

Company: MCTExpert of Arizona

 

User assumes are risk and liability for executing this code.  As with

all PowerShell code, read and understand it before executing it in your

environment.

 

Licensing: This code may not be republished or utilized in part or in full

for any for profit product or publication without the expressed written

consent of MCTExpert of Arizona. 

 

Copyright © 2014 MCTExpert of Arizona.  All rights reserved.

==============================================================================

#>  

} # End: Function Show-V2ShowWindow 

Here are a few areas of interest.

Line Comments
16 I need to store a txt file temporarily so I need a location where I know the user will have write access so I’m going to use there “My Documents” folder.  To find it, I’m using two variables from PowerShell’s Environment PSProvider, Homedrive and HomePath.  The value of these two variables help me correctly create the path to the temporary file.
18 Line 18 starts the ForEach loop that gives the cmdlet the ability to open multiple help files at one.
23 Get the help information and saves it to the temporary txt file.
27 This line will open Notepad.exe with the temporary file.
30 One problem that I noticed in testing is that if I am opening multiple files, the next command to remove the file executes before Notepad reads it.  To solve this problem, I pause the script for .25 seconds before allowing Remove-Item to clean up the txt file.
33 Removes the txt file.
36 Just in case the user asks for a help file that does not exists, this will prevent a blank Notepad window from opening and displays a warning message.

 

At the very least, I recommend that the script writer upgrades to at least PowerShell V3.  The ISE makes it work it and has features that are not available in the V2 ISE.  Remember that PowerShell V2 code is 100% compatible with V3 and V4 so if you are in an environment that has to wait to implement the newer versions of PowerShell, your tool making efforts will not be in vein.  Go ahead and script away.  They will work when you finally get to upgrade.

Thursday, February 20, 2014

Adding Some Code Templates to the PowerShell ISE

Today I’m sitting at the car dealership waiting on my wife’s car to get a recall fixed.  Luckily I can carry my entire office on my laptop (I’ve been here for 3 hours).  I’m working on finalizing my code for the 2014 PowerShell Summit in April so of course I keep finding better and better ways of writing my own code.  (BTW, my session at the summit is on Tuesday)  What I am focused on is to take my HelpDesk module code to the next level, but also to be able to do it quickly and easily.  This has finally given me a reason to use the Snippets functionality in the PowerShell ISE.

I wrote up some code that will help me a lot and saved it as a PowerShell script called HDSnippet.ps1.  This code will be my template.

Now, before we begin, you need to be on PowerShell V3.  I know that a lot of you who are going to be taking my PowerShell classes over then next few months are still in a V2 environment.  That is OK.  Copy and Paste still work.  For those of you on PowerShell V3, open the ISE and press Ctrl-J.  We are going to be adding to this list.

I’m going to do this as a User-Defined snippet. My default folder for my snippets is C:\Users\JASON\Documents\WindowsPowerShell\Snippets.  Since the Snippets folder does not yet exist, you will want to create it.  This is also where the cmdlet New-IseSnippet will automatically place your new snippet file.

I’m now going to create a little script to help reduce my typing.

$Text = (Get-Content -Raw -Path "C:\Users\JASON\Documents\WIndowsPowerShell\Snippets\HDSnippet.ps1")

 

$Props = @{

    "Title" = "NewHDCmdlet";

    "Description" = "Default code for a new HD module cmdlet";

    "Author" = "Jason A. Yoder"

    "Text" = $Text

 

}

 

New-IseSnippet @Props

 

Since my Snippet is actually code, I have to use the –Raw switch with the Get-Content cmdlet so the Text property of New-IseSnippet processes it correctly.

This will create a new file in the Snippets folder called NewHDCmdlet.snippets.ps1xml.  If you press Ctrl-J now, you will have access to your snippet.  If you decided that you no longer need one of your templates, just delete it from the Snippets folder.

If you want to stop displaying the default snippets and see just yours, in the ISE click Tools –> Options.  Click the General Settings tab and uncheck the Use default snippets.

image

Monday, February 10, 2014

SMB Nation Emerging Technology Tour is Coming to Toronto

This is just a reminder that I’ll be up in Toronto talking about PowerShell  with SMB Nation on March 7th.  You can find out more information about the conference and the other speakers and topics here (http://tour.smbnation.com/toronto/). 

I look forward to meeting as many of my neighbors to the north as possible.

Testing if a Resource is online

I was sitting in the USO at the San Jose airport a few months ago after teaching a class when I got a call from a friend who had an issue.  Apparently, his company’s email server went down.  It had been down for about 24 hours.  Of course the first person to take note of this was the big boss her self.  He asked me if PowerShell could tell him when a serve is down.

This reminded me of a script that I ran years ago that would test connectivity to all of my resources (servers, printers, routers, etc.) and then dropped me an email to let me know if I had work to do.  This email would say something like “Have a nice day” if nothing was wrong in the subject line.  It would say something else if there was a problem and then I would have to open it.

I spent about an hour building a test environment and rebuilt that script in PowerShell for my friend.  He was very happy to receive it. For this years SMB Nation Emerging Technology Tour, I decided build a simplified version of it.  I also set it up as a scheduled job to make life a bit easier on him.  Here is the simplified version:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

Function Test-Network

{

Param ($ComputerName)

   

    ForEach ($Name in $ComputerName)

    {

        $Hash = @{'Quiet' = $True;

                  'Count' = 1;

                  'ComputerName' = $Name}

        If (!(Test-Connection @Hash))

        {

            $MailHash = @{'To' = "Administrator@TechTour.com";

                          'From' = "LittleGreenMen@Mars.Planet";

                          'Subject' = "Sever $Name is offline";

                          'Body' = "Have a nice day";

                          'SMTPServer' = "Tech-ex1"}

            Send-MailMessage @MailHash

        }

    }

}

Test-Network -ComputerName Tech-EX1, Tech-EX11

The first thing to notice is that this is a function.  Ok, I like to make things functions.  Line 21 is where you place the names or IP addresses of all the resources that you want to test a connection to in a comma separated list.  You may also want to adjust the following values in the hash table in lines 12 – 16.  To is the email address to send to.  Notice that this code only supports sending to one email address.  From:  I doubt that you would want to receive an email form Mars.  You may want to give this a name like ResourceConnectivityTest@YourDomain.com.  Otherwise your Exchange server may send the message to the Phantom Zone.  Also the SMTPServer should be the name of your SMTP Server.

Once this is done, save this script to a server that will always be on.  No point on putting this on your laptop.  You want something that will have persistent connectivity to your network.  We are now going to set this script up as a scheduled job.

First we are going to create a DateTime object that species the time that this code will run.  Let’s say that we want this report to run at 7:45 AM everyday.  That way it is in our inbox when we get to work at 8.

PS C:\psworks> Get-Date -hour 7 -Minute 45

 

Thursday, February 6, 2014 7:45:06 AM

 

The time right now is actually 4:49 PM.  The date does not matter, we just need to save this DateTime object to a variable.

PS C:\psworks> $Time = Get-Date -hour 7 -Minute 45

 

We will use this variable with the New-JobTrigger cmdlet.  This will determine what triggers this scheduled task.  The New-JobTrigger cmdlet also sets the frequency that the task will run.  The following options are available to schedule the task to repeat.

 

-AtLogOn Starts when the user logs on.
-AtStartUp Starts when Windows boots.
-Daily Every day at the specified time.
-DaysOfWeek This allows you to select the day of the week that the task runs.  You can provide a comma separated list of either strings or integers to represent the days of the week.
String Integer
“Sunday” 0
“Monday” 1
“Tuesday” 2
“Wednesday” 3
“Thursday” 4
“Friday” 5
“Saturday” 6
-Once Only runs once.
-Weekly Runs once a week
-WeeksInterval Used in conjunction with –Weekly, this integer specifies the number of weeks to skip.

For this task, we want it to run daily.  We will save the trigger object in the variable $Trigger.

$Trigger = New-JobTrigger -At $Time -Daily

 

Now we are ready to register the job.  Remember that the script and the scheduled job needs to be on a server that is always on and connected to the network. 

PS C:\psworks> Register-ScheduledJob -Name "Server Check" -FilePath "C:\PS\ServerTest.ps1" -Trigger $Trigger -Credential "TechTour\Administrator"

 

Id         Name            JobTriggers     Command                            

--         ----            -----------     -------                            

1          Server Check    1               C:\PS\ServerTest.ps1 

 

You will be prompted for the credentials of the user or service account that will be running this script.  In this example, I used a user account but in practice, I would assign a service account to avoid problems with password changes and also with security on your Exchange Server so you are not permitting it to send emails from outside domain.

image

Open the Task Scheduler and take a look at your scheduled task.  it is located at: Task Scheduler Library / Microsoft / Windows / PowerShell / Scheduled Jobs

image

 

You are all done.  Just check your email in the morning.