PowerShell ISE AddOn ModuleMenu

Recently I did an online presentation on ISE Addons. As I was preparing for the talk one thing led to another, as they usually do when I’m working in PowerShell, and before I knew it I had a new add-on for the PowerShell ISE. This addon creates a menu for all of the modules in your module path.

The module looks at the $env:PSModulePath environmental variable and creates a submenu for each module. I came up with a nice two level Write-Progress command because at least on my desktop I have a lot of modules.

My script creates a sub menu for each discovered module.

You can import the module directly from the menu, and when you do, my module dynamically updates the menu with options to look at all the commands in the module and to remove it.

The module menu uses Out-Gridview quite a bit to keep things graphical, but it is view only. However, I added a nice module summary.

To try this out, download ModuleMenu.zip and extract to your modules folder. Then in the ISE, import module ModuleMenu. Everything is contained in a single .psm1 file which you can edit directly from the menu! Perhaps you might not need the module, but it offers some nice examples of creating ISE add-on menu items. Once PowerShell v3 is released, much of this will probably be irrelevant. I’ll worry about that later.

Enjoy!

Post to Twitter Post to Plurk Post to Yahoo Buzz Post to Delicious Post to Digg Post to Facebook Post to FriendFeed Post to Google Buzz Post to Ping.fm Post to Reddit Post to Slashdot Post to StumbleUpon Post to Technorati

Posted in PowerShell ISE, Scripting | Tagged , , , , | Leave a comment

Create HTML Bar Charts from PowerShell

I saw a very nice mention on Twitter today where someone had taken an idea of mine and created something practical and in production. It is always nice to hear. The inspiring article was something I worked up that showed using the PowerShell console as a graphing tool. Of course someone immediately wanted to know about turning this into HTML. Actually he wanted this in a web page that would automatically refresh. I don’t think I can manage that, but I came up with a demo script that will create a colorized bar graph in ah HTML page. If you want to update it, simply re-run your command.

Here’s the demo code.

#requires -version 2.0

Param (
[string[]]$computers=@($env:computername),
[string]$Path="drivereport.htm"
)

$Title="Drive Report"

#embed a stylesheet in the html header
$head = @"
<style>
body { background-color:#FFFFCC;
       font-family:Tahoma;
       font-size:12pt; }
td, th { border:1px solid #000033;
         border-collapse:collapse; }
th { color:white;
     background-color:#000033; }
table, tr, td, th { padding: 0px; margin: 0px }
table { margin-left:10px; }
</style>
<Title>$Title</Title>
<br>
"
@

#define an array for html fragments
$fragments=@()

#get the drive data
$data=get-wmiobject -Class Win32_logicaldisk -filter "drivetype=3" -computer $computers

#group data by computername
$groups=$Data | Group-Object -Property SystemName

#this is the graph character
[string]$g=[char]9608

#create html fragments for each computer
#iterate through each group object
       
ForEach ($computer in $groups) {
   
    $fragments+="<H2>$($computer.Name)</H2>"
   
    #define a collection of drives from the group object
    $Drives=$computer.group
   
    #create an html fragment
    $html=$drives | Select @{Name="Drive";Expression={$_.DeviceID}},
    @{Name="SizeGB";Expression={$_.Size/1GB  -as [int]}},
    @{Name="UsedGB";Expression={"{0:N2}" -f (($_.Size - $_.Freespace)/1GB) }},
    @{Name="FreeGB";Expression={"{0:N2}" -f ($_.FreeSpace/1GB) }},
    @{Name="Usage";Expression={
      $UsedPer= (($_.Size - $_.Freespace)/$_.Size)*100
      $UsedGraph=$g * ($UsedPer/2)
      $FreeGraph=$g* ((100-$UsedPer)/2)
      #I'm using place holders for the < and > characters
      "xopenFont color=Redxclose{0}xopen/FontxclosexopenFont Color=Greenxclose{1}xopen/fontxclose" -f $usedGraph,$FreeGraph
    }} | ConvertTo-Html -Fragment
   
    #replace the tag place holders. It is a hack but it works.
    $html=$html -replace "xopen","<"
    $html=$html -replace "xclose",">"
   
    #add to fragments
    $Fragments+=$html
   
    #insert a return between each computer
    $fragments+="<br>"
   
} #foreach computer

#add a footer
$footer=("<br><I>Report run {0} by {1}\{2}<I>" -f (Get-Date -displayhint date),$env:userdomain,$env:username)
$fragments+=$footer

#write the result to a file
ConvertTo-Html -head $head -body $fragments  | Out-File $Path

The key concept here is that I’m building a final HTML file from a collection of HTML fragments. I think most of the script should be self-explanatory. The core part of the script takes the collection of drives for a computer, selects some custom properties and converts it into an HTML fragment.

#create an html fragment
    $html=$drives | Select @{Name="Drive";Expression={$_.DeviceID}},
    @{Name="SizeGB";Expression={$_.Size/1GB  -as [int]}},
    @{Name="UsedGB";Expression={"{0:N2}" -f (($_.Size - $_.Freespace)/1GB) }},
    @{Name="FreeGB";Expression={"{0:N2}" -f ($_.FreeSpace/1GB) }},
    @{Name="Usage";Expression={
      $UsedPer= (($_.Size - $_.Freespace)/$_.Size)*100
      $UsedGraph=$g * ($UsedPer/2)
      $FreeGraph=$g* ((100-$UsedPer)/2)
      #I'm using place holders for the < and > characters
      "xopenFont color=Redxclose{0}xopen/FontxclosexopenFont Color=Greenxclose{1}xopen/fontxclose" -f $usedGraph,$FreeGraph
    }} | ConvertTo-Html -Fragment

The tricky part is the value for “Usage” In the Expression scriptblock I’m calculating a value for how much disk space is used and how much is free. I then create a string that is my graphing character ([CHAR]9608) times a value. The value is the corresponding percentage divided by 2 because I want to put the used graphic right next to the free graphic. And this leads me to the hack: I want the used graph to be in Red and the free graph string to be in Green. I’m taking the easy way and using a FONT tag. But, I can’t use the < and > characters because Convertto-HTML “translates” them. I couldn’t find anyway around this. So instead I use a place holder.

 "xopenFont color=Redxclose{0}xopen/FontxclosexopenFont Color=Greenxclose{1}xopen/fontxclose" -f $usedGraph,$FreeGraph

All I need to do is replace the placeholders from the HTML output.

    #replace the tag place holders. It is a hack but it works.
    $html=$html -replace "xopen","<"
    $html=$html -replace "xclose",">"
   
    #add to fragments
    $Fragments+=$html

Perhaps not the most elegant solution, but it works. The script wraps up by taking all of the HTML code and creates the final file.

ConvertTo-Html -head $head -body $fragments  | Out-File $Path

To run this for a group of computers I can run a command like:

PS C:\scripts> .\demo-HtmlBarChart.ps1 "jdhit-dc01","serenity","quark"

Here is the result:

I haven’t found a way to make this process more generic and my script, while it works, isn’t really production ready; that’s why I call it a demo script. But perhaps you’ll take inspiration and come up with some wonderful. If you do, I hope you’ll let me know and share with the PowerShell community.

Download Demo-HtmlBarChart.

Post to Twitter Post to Plurk Post to Yahoo Buzz Post to Delicious Post to Digg Post to Facebook Post to FriendFeed Post to Google Buzz Post to Ping.fm Post to Reddit Post to Slashdot Post to StumbleUpon Post to Technorati

Posted in PowerShell v2.0, Scripting, WMI | Tagged , , , | 3 Comments

Embrace and Extend the PowerShell ISE

I did a presentation today for the PowerShell Virtual Chapter of SQLPass. The recording will be posted later and I’ll update this when I have the link. But in the meantime, as promised, I wanted to make available my slide deck and demos. You’ll need to download the individual ISE Addons from the respective sites. Links are in the slides. You can use the script demos as guides for your own ISE extensions.

Download a PDF version of Embrace and Extend the PowerShell ISE.
Download ISEAddonDemoFiles.zip with my demo scripts.

Post to Twitter Post to Plurk Post to Yahoo Buzz Post to Delicious Post to Digg Post to Facebook Post to FriendFeed Post to Google Buzz Post to Ping.fm Post to Reddit Post to Slashdot Post to StumbleUpon Post to Technorati

Posted in PowerShell ISE | Tagged , , | 3 Comments

Valentines Day PowerShell Fun

In case you missed some of the fun on Twitter and Google Plus, here are the PowerShell valentines I sent today. These are intended to be run from the PowerShell console, not the ISE. Also, depending on your console font, you might get slightly different results. I use Lucida Console.

 

 

#1
write-host (([char]3 -as [string])*14) -ForegroundColor red

#2
$s="Be My Valentine"
[string]$hrt=[char]3

$s.split() | foreach -begin {$a="" }{$a+= "$_$hrt"} -end {write-host $a -ForegroundColor Magenta}

#alternative
$s.split() | foreach {Write-Host $_ -nonewline -foregroundcolor Magenta; Write-Host $hrt -nonewline -ForegroundColor Red} -end {"`n"}

#3
Write-Host "U make my $([char]3) $([char]14)" -foregroundcolor magenta -backgroundcolor yellow

#variation from Josh Atwell
Write-Host "Wild thing!" -ForegroundColor Yellow -BackgroundColor Magenta
Start-Sleep -Seconds 1
Write-Host "U make my $([char]3) $([char]14)" -ForegroundColor magenta -BackgroundColor yellow

#4
write-host "$([char]12)$([char]3)$([char]11)=$([char]2)" -foregroundcolor red -backgroundcolor white

Download MoreValentines.ps1 But I recommend you accompany this with at least a bouquet of nice flowers.

Post to Twitter Post to Plurk Post to Yahoo Buzz Post to Delicious Post to Digg Post to Facebook Post to FriendFeed Post to Google Buzz Post to Ping.fm Post to Reddit Post to Slashdot Post to StumbleUpon Post to Technorati

Posted in PowerShell | Tagged , | Leave a comment

Morning Report Revised

Last month I posted a PowerShell script I called The Morning Report. I received some very nice feedback. One comment was about making it easier to use the script in a pipelined expression. For example, get a list of computers from a text file and create a single HTML report. That sounds reasonable to me so I decided to revisit the script and add a few tweaks.

The latest version can still be used as I originally described. But now the computername parameter can be piped in to the script.

PS C:\> $report=get-content computers.txt | c:\scripts\morningreport.ps1

The report will still write a collection of custom report objects to the pipeline. But now I can do this:

PS C:\> get-content computers.txt | c:\scripts\morningreport.ps1 -text | out-file c:\work\morning-report.txt

This will create a single text file for all computers in the list. If you prefer a separate file per computer, use a ForEach loop.

PS C:\> get-content computers.txt | foreach {
>> $comp=$_
>> c:\scripts\morningreport.ps1  -Comp $comp -text |
>> out-file "c:\work\$comp-morning-report.txt"
>> }
>>

Similarly, I can now create a single HTML file.

PS C:\> get-content computers.txt | c:\scripts\morningreport.ps1 -html -hours 36 | out-file c:\work\morning-report.htm

I had to revise the HTML related code a bit to accommodate multiple computers in the same file. I modified the navigation links to the computername and inserted a list of computers at the beginning of the file. Clicking on a computername will take you to the corresponding summary. I probably wouldn’t try this with hundreds of computers, but for most small to mid-size groups I think this will work just fine.

The last change I made, which was as much for me as anyone, was to add a -Quick parameter. Querying event logs is time consuming so if you are in a hurry you can skip the event log query by using -Quick. You’ll still get an event log section in the output, but it will be empty.

Download the revised version of MorningReport.ps1 and let me know what you think.

Post to Twitter Post to Plurk Post to Yahoo Buzz Post to Delicious Post to Digg Post to Facebook Post to FriendFeed Post to Google Buzz Post to Ping.fm Post to Reddit Post to Slashdot Post to StumbleUpon Post to Technorati

Posted in Scripting, Windows Server, WMI | Tagged , , , , | 21 Comments