Monday, December 29, 2008

Project Euler and PowerShell - Problem 7

By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13, we can see that the 6^(th) prime is 13.

What is the 10001^(st) prime number?

function isPrime
param ($number)
$isPrime = $true
if($number -lt 2) { $isPrime = $False}
if($number -gt 2 -and $number%2 -eq 0) {$isPrime = $False}
for($i=3;$i -le [math]::Sqrt($number);$i+=2)
if($number % $i -eq 0) { $isPrime = $False}

$i = $j = 0
do {
if(isPrime $i){$j++;$i}
until ($j -eq 10001)

Project Euler and PowerShell - Problem 6

This was an easy one!
The sum of the squares of the first ten natural numbers is,

1^(2) + 2^(2) + ... + 10^(2) = 385

The square of the sum of the first ten natural numbers is,

(1 + 2 + ... + 10)^(2) = 55^(2) = 3025

Hence the difference between the sum of the squares of the first ten natural numbers and the square of the sum is 3025 − 385 = 2640.

Find the difference between the sum of the squares of the first one hundred natural numbers and the square of the sum.

$sumSquares = $squareSums = $difference = 0
for ($i=1;$i -le 100;$i++)
$sumSquares += [Math]::Pow($i,2)
$squareSums += $i
$difference = [math]::Pow($squareSums,2) - $sumSquares

Project Euler and PowerShell - Problem 5

Moving on...

Problem 5: 2520 is the smallest number that can be divided by each of the numbers from 1 to 10 without any remainder. What is the smallest number that is divisible with no remainder evenly divisible by all of the numbers from 1 to 20?
function modFunction ($mod)
$number = 1
$start = $mod
do {
if($number%$mod -eq 0)
until ($mod -eq 1)

modFunction 20
While short, this is clearly a brute force approach. Anyone have a more efficient algorithm?

Project Euler and PowerShell - Problem 4

Problem 4: A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers is 9009 = 91X99. Find the largest palindrome made from the product of two 3-digit numbers.

function Reverse-Integer
for ($i = $str.ToString().Length - 1; $i -ge 0; $i--)
$c = $c + ($str.ToString().Substring($i,1))

$big = 0
for($x=100;$x -le 999;$x++)
for($y=100;$y -le 999;$y++)
$xy = $x*$y
$yx = Reverse-Integer $xy
if ($yx -eq $xy)
if ($xy -gt $big) {$big=$xy}

This one takes a long time to run. If anyone has any ideas on how to refactor this, please share!

Project Euler and PowerShell - Problem 3

Problem 3 -The prime factors of 13195 are 5, 7, 13 and 29. What is the largest prime factor of the number 600851475143?
function isPrime
param ($number)
$isPrime = $true
if($number -lt 2) { $isPrime = $False}
if($number -gt 2 -and $number%2 -eq 0) {$isPrime = $False}
for($i=3;$i -le [math]::Sqrt($number);$i+=2)
if($number % $i -eq 0) { $isPrime = $False}

$sqrValue =[Math]::Sqrt($value)

for($i=3;$i -le $sqrValue; $i+=2)
if($value%$i -eq 0 -and (isPrime $i))
$maxPrime = $i


Project Euler and PowerShell - Problem 2

This is a continuation of my efforts to use PowerShell to solve some of the problems at Project Euler.

Problem 2: Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be:

1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...

Find the sum of all the even-valued terms in the sequence which do not exceed four million.

function Get-SumFib ($n)
$current = $previous = 1
while ($current -lt $n)
if($current%2 -eq 0)
$sum= $sum + $current

$current,$previous = ($current + $previous),$current}
Get-Fib 4000000

Project Euler and PowerShell - Problem 1

Was looking at Pete on Software the other day and saw a reference to Project Euler. What a cool site! Basically, the intent of this site is to use computational/programming skills to solve increasing complex mathematical problems. This seemed like an interesting way to test my PowerShell skills. The next few blog posts will be my attempts at solving a few of these.

- Spoiler Alert -

If you have any interest in solving any of these problems at Project Euler, quit reading this post and immediately pull up your programming editor of choice and have at it.

Problem 1: If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23. Find the sum of all the multiples of 3 or 5 below 1000.

$result = 0
for($i = 0; $i -lt 1000;$i++)
if ($i % 3 -eq 0 -or $i % 5 -eq 0)
$result += $i;

Saturday, December 20, 2008

PowerShell at HIMSS

I found out on Friday (December 19th, 2008) that my proposal to speak at the Healthcare Information and Management Systems Society (HIMSS) - Microsoft Health Users Group (MSHUG) was accepted! This is two years in a row that I have had the opportunity to speak at this conference. Last year, a colleague of mine (Andrew Klare) and I presented on the implementation of Microsoft Speech with the Ohio State University Medical Center's Patient Transportation application.

This year, the presentation will be titled, “Managing your Healthcare environment with PowerShell”. I am looking forward to evangelizing PowerShell with this group! Given the time constraint (approx. 50 minutes), I will more then likely show examples of various monitoring and scheduled jobs that we currently use. I will also try to demonstrate how the use of PowerShell has impacted productivity and budgets.

Any suggestions from the PowerShell community would be appreciated!

Friday, December 19, 2008

PowerShell Twitterers

Steven Murawski has collected and posted a list of PowerShell related Twitterers. If you are a fan of PowerShell and use Twitter, these are some of the folks that you should follow.

What is Twitter you ask? Good question! A concise definition would be - It is free social networking service. This however doesn't quite do it justice. Check out a few of the following posts for a better idea of how people are using it.

Better yet, go to Twitter and set up your free account.


Wednesday, December 17, 2008

BlackBerry Disaster Recover Information

Was asked yesterday if I could write something that would periodically generate a CSV file of our BlackBerry users and their pin numbers. This "report" would be used for communication purposes in a Disaster situation. I looked on the BlackBerry server for a few minutes hunting for a way to do it from the server. No such luck. I then remembered that all the data resides in SQL Server diligently waiting to be queried. Following is a small script that I have scheduled to run once a week:

# Parse the DN to get the SAMAccountName
$SQLQuery = "SELECT DisplayName,PIN,CreationTime,MailboxSMTPAddr,
Right(MailboxDN,(LEN(MailboxDN)-CHARINDEX('s/cn=', MailboxDN)-4)) AS SamAccountName
FROM UserConfig
ORDER BY DisplayName

#Set up connection
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "Server = YourServer; Database = YourDB; User ID=YourID; Password=YourPWD; Integrated Security = False"

# Setup SQL Command
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.CommandText = $SQLQuery
$SqlCmd.Connection = $SqlConnection

# Create the table and export!
$SqlVMDataReader = $SqlCmd.ExecuteReader()
$SqlVMDataTable = New-Object System.Data.DataTable
$SqlVMDataTable Export-Csv 'L:\DRDocs\BBPins.csv' -noTypeInformation

# Cleanup


Monday, December 15, 2008

PrimalForms Example (Virtual Center Log)

Recently saw a post on Twitter from alanrenouf. He was asking if there was a log file that could be parsed to search for who deleted a VM. I know that this data was kept in the Virtual Center Database, specifically in the VPX_EVENT table. I mentioned this to Alan and he quickly wrote a PowerShell script to find the data and blogged it.
Concurrently, I was investigating PrimalForms (PowerShell UI builder - FREE). Once I saw Alan's post, I knew it would be a good example to try PrimalForms with.

The UI was simple to create with PrimalForms, here is a screenshot of the UI.

The dropdowns are filled on the form load with the following:
- Distinct Virtual Machine
- Distinct User
- Distinct Event (in Alan's case vim.event.VmRemovedEvent)
- Search Start Date
- Search End Date

Selecting the above variables generates the SQL statement to the VPX_EVENT table. The results are then passed to the datagrid.

Pretty cool!

As soon as I figure out how to attach a text file to Blogger, I will do so. In the short-term, if you are interested in the script(s), send me a note at


Thursday, November 6, 2008

Creating Printer Install Batch Files

Was given the task to write a PowerShell script that would do the following:

  • Given a supplied list of host name, find the hostnames that have a specific named printer. In this case "osu_mc" will be in the Name property.
  • If a printer is found, create a batch file that is titled from the supplied host name.
  • The batch file should contain these 2 lines for every printer
    "rundll32 printui.dll,PrintUIEntry /in /q /n" and
    the printer name:
    (i.e. file:////OSU/NDPS_HP4350.OSU.HOSP.CAMPUS.OSU)

Here is the script that meets the need!

Function Get-PrinterName ([string]$HostName) {
Begin {}
Process {
-Host "HostName: "$_
= "C:\PrinterBatch\" + $_ + ".bat"
$file = New-Item -type file $FileName

= Get-WmiObject `
-Class Win32_Printer`
-ComputerName $_ `
-ErrorAction SilentlyContinue

ForEach ($Printer
in $Printers){ if ($Printer.Name -match 'osu_mc'){
-Content -Path $FileName `
-value "rundll32 printui.dll,PrintUIEntry /in /q /n"
-Content -Path $FileName `
-value $Printer.Name

-Content 'C:\HostNames.txt' Get-PrinterName


Wednesday, October 29, 2008

Logon Restrictions

Was approached yesterday with the following request.
- Find all users that have a logon restriction
- Return Last, First name and the users login ID
- Indicate if they belong to any group like "Citrix.PatientLink.*"

Quest AD CMDLETS to the rescue (again).

First let's find all the users with a logon restriction and toss them into a CSV file.
GET-QADUser -SizeLimit 0 -IncludeAllProperties `
WHERE {$_.logonHours -ne $null} `
SELECT logonname, logonHours `
EXPORT-CSV -Path 'C:\logonRestrictions.csv' -NoTypeInformation

We have to use the parameter -IncludeAllProperties to expand the property logonHours.

Next we will use this list to grab the users last, first name, department, logonName and indicate if they belong to any group matching "Citrix.PatientLink.*".

function Get-LogonRestrictions {
foreach($Users in $AllUsers) {
$MemberOF = $Null
$User = Get-QADUser $Users.LogonName `
Select LastName, FirstName, Department, LogonName, MemberOf
$Groups = (Get-QADUser $Users.LogonName).MemberOf
foreach ($Group in $Groups){
if($Group -match 'Citrix.Patient') {
$MemberOF = (get-qadgroup $Group).Name
$obj = New-Object psObject
$obj Add-Member NoteProperty LastName $User.LastName
$obj Add-Member NoteProperty FirstName $User.FirstName
$obj Add-Member NoteProperty Department $User.Department
$obj Add-Member NoteProperty LogonName $User.LogonName
$obj Add-Member NoteProperty MemberOF $MemberOF
-Output $obj

$AllUsers = Import-Csv -Path 'C:\logonRestrictions.csv'
$AllUsers Get-LogonRestrictions Export-Csv `
-Path 'C:\logonRestrictionsDetail.csv'

And we are done!

Wednesday, October 15, 2008

PowerScripting Podcast

If you have any interest at all in PowerShell, you have to check out the PowerScripting Podcast at Last weeks episode (#45) was a lot of fun, special guests included:
  • Jeffery Snover
  • Don Jones
  • Alex Reidel
  • Kirk Munro
If possible check out the ustream at You will get to see Hal & Jonathan in their element! (and view a half finished basement).

Do it!

Thursday, September 25, 2008

Calling Web Services through PowerShell

I do believe that in V2, this will be something that can be done natively within PowerShell. In the meantime, there are a few well documented ways to do this, check out Lee Holmes' example.

I have approached this from a slightly different angle. If you have access to Visual Studio, try something like this:

  1. Create a console app
  2. Set a web reference to your predefined web service
  3. Create your method
  4. Compile
  5. Move the exe to the appropriate location and call as needed from PowerShell

A specific example: I have a paging web service that I can call from my automated monitoring PowerShell scripts when certain conditions are met.

If ($cnt -gt 500) { D:\Script:\Paging.exe "9773" "Import Count: $cnt" }

Works like a charm!

Getting Screen Resolution with WMI and PowerShell

Getting the screen resolution with PowerShell is quite simple:

param( [string]$strComputer = "." )
= Get-WmiObject `
-class "Win32_DisplayConfiguration" `
-computername $strComputer

foreach ($display in $displays) {
= New-Object psObject
Add-Member NoteProperty DeviceName $display.DeviceName
Add-Member NoteProperty PelsWidth $display.PelsWidth
Add-Member NoteProperty PelsHeight $display.PelsHeight
Add-Member NoteProperty BitsPerPel $display.BitsPerPel
Add-Member NoteProperty DisplayFrequency $display.DisplayFrequency
-Output $obj

Setting the resolution is not so simple. There are a few ways to do this, none of them completely native to PowerShell. You can pass parameters to a compiled executable like this one listed on CodeProject or Qres (Thanks Hal for the links). If warranted, and ambition wasn't an issue, you could write inline C#. Check out Lee Holmes' Invoke-Inline for a wrapper for this.


Thursday, September 4, 2008

Off Topic - Google Chrome's About pages

Many tech (and probably non-tech) folks have been testing Google Chrome.  While my experience has been favorable, minus a couple vendor based black box apps, I am most impressed with the "hidden" about pages.  Check out the following post  Some great stuff here!  I like the fact that about:memory shows the utilization of other browsers.

In addition to the cool "about:" pages, here is a link to the Google Chrome list of shortcuts:


Wednesday, September 3, 2008

Print Queue Analysis - Revisited

A few weeks ago, I mentioned that I was asked to assist with the monitoring of a print queue. I have now included that PowerGadget chart. Enjoy!

function Get-PrintQueue {
= Get-WmiObject `
-Class Win32_PerfFormattedData_Spooler_PrintQueue `
-ComputerName 'PrintServer'`
-Filter 'Name <> "_Total"'

foreach ($Printer in $Printers) {
if($Printer.Jobs -gt 1) {
= New-Object psObject
| Add-Member NoteProperty Printer $Printer.Name
| Add-Member NoteProperty JobCount $Printer.Jobs
-Output $obj}
= Get-Date -Format g
-PrintQueue | Out-Chart `
-Title "PrintServer printer queues as of $dt" `
-Size 800,400 `
-gallery bar `
-LegendBox_Visible false `
-View3D_Enabled true `
-AllSeries_BarShape Cylinder `
-AllSeries_PointLabels_Visible true `
-AllSeries_Color Yellow `
-Output "\\WebServer\e$\Inetpub\Extranet\Departments\InfoSys\ClinApps\HIS-Print.png"

Resulting chart:


Monitor Citrix Licenses

Was tasked with monitoring Citrix Licenses. We needed a way to gauge when demand was the highest and overall utilization. Following is a PowerShell script that runs every 15 minutes and stores the result in a SQL Express DB. Will be using PowerGadgets at a later point to present a graphical representation of the data.

First the function to grab the Citrix info:

Function Get-CitrixLicenses {
= Get-WmiObject `
-class 'Citrix_GT_License_Pool' `
-Namespace "ROOT\CitrixLicensing" `
-ComputerName $_ Select __Server, Count, InUseCount
= Get-Date -Format g
foreach ($License in $Licenses) {
= New-Object psObject
Add-Member NoteProperty Server $License.__Server
Add-Member NoteProperty Total $License.Count
Add-Member NoteProperty InUse $License.InUseCount
Add-Member NoteProperty Date $dt
-Output $obj }

Second the DB insert function:

function Write-CitrixLicense {

# Open the DB Connection
= New-Object System.Data.OleDb.OleDbConnection
= "Your connection string"
= $connstr

# create DB command
= New-Object system.Data.OleDb.OleDbCommand
= $conn }

# create the INSERT statement
using object properties
= Get-Date -form g
= "INSERT INTO tblCitrixLicense (Server,Count,InUse,
SubmitDate) VALUES ("
+= "'" + $_.Server + "',"
+= "'" + $_.Total + "',"
+= "'" + $_.InUse + "',"
+= "'" + $now + "')"
= $sql
Out-Null }

END {$conn.close()}

Finally the call....

'Server1','Server2' %{Get-CitrixLicenses} Write-CitrixLicense

Wednesday, August 20, 2008

Print Queue Analysis

Wes - Can you tell us what printers on a particular print server have more then 10 jobs? Why yes, I can. And here is how you can do it.

$Printers = Get-WmiObject `
-Class Win32_PerfFormattedData_Spooler_PrintQueue `
-ComputerName 'hisprint-p01'`
-Filter 'Name <> "_Total"'
foreach ($Printer in $Printers) {
if($Printer.Jobs -ge 10){
Write-Host $Printer.Name $Printer.Jobs

RHS780 75
OSUHE235 15
MMCT475B 32
DNW375 74

Admittedly, this is could be much more generic. Also, a nice visual representation could be made via PowerGadgets. These are left to the reader as an exercise....

Friday, August 8, 2008

Getting Available Memory On Remote Servers

I am often asked to give total and available memory across our enterprise to our Disaster Recovery guys. Here is a simple script that achieves that goal:

$Servers = Get-Content 'c:\ProductionScripts\Servers.txt'
-Host "Server,Total,Free"
foreach ( $server in $Servers )
= Get-WmiObject `
-Class Win32_LogicalDisk `
-ComputerName $server `
-Filter "DriveType=3" `
-ErrorAction SilentlyContinue
= 0
= 0
foreach($drive in $drives)
double]$size += $drive.size
double]$available += $drive.freespace

= "{0},{1},{2}" -f $server,[MATH]::Round($size/1MB),[MATH]::Round($available/1MB)
-Host $str

Wednesday, August 6, 2008

External (outbound/inbound) eMail Verification

Given that MOM can only verify internal email, I was asked if there was a way to verify delivery of external bound email and receipt of external email. Following is a high-level description of a low-tech solution (using 2 scheduled PowerShell scripts).

  1. Scheduled PowerShell script that runs every 15 minutes that sends a specifically formatted email to gMail and GMX (a great Webmail!). The PowerShell script uses Send-SMTP from PSCX.
    Send-SmtpMail `
    -SmtpHost '' `
    -To '' `
    -From '' `
    -Subject 'Cryptic text here' `
    -AttachmentPath 'D:\File.txt'

  2. gMail and GMX have advanced filtering capabilities. In this case, both look for the specifically formatted email. Once received, it sends back to our domain and is deleted.

  3. Email traverses through spam filter and then to final destination.

  4. Using custom Outlook rule/script, we look for the above email. When received, it places the email attachment into a file share and deletes the email. This is the weakest step in that it assumes 24/7 on an email client. I will be looking into a better way to do this step.

  5. The second PowerShell script looks for the LastWriteTime of the file that was stripped from the email and placed into the fileshare. If the interval is greater then 15 minutes, an event log entry is made.

    $c = New-TimeSpan ((Get-Item c:\ProductionScripts\eMailVerification\InBoundAttachment.txt).LastWriteTime) $(Get-Date)
    int]$d = $c.TotalMinutes
    if ($d -gt 10)
    = New-Object -Type System.Diagnostics.EventLog -ArgumentList Application
    = "eMailVerification"
    "External eMail is taking $d minutes")

  6. MOM then picks up the event and responds accordingly.

There are many different ways we can take this. I am considering parsing the email headers to grab the time-stamps. With these, I can potentially use PowerGadgets to create some dashboards.

Monday, July 21, 2008

A generic error occurred in GDI+.

OK - sometimes I am a little slow.
One of the reasons I decided to maintain a blog was to help myself remember those peculiar idiosyncrasies when scripting. Well shame on me....

My script was working fine until I added the most important piece (from a customer perspective) - the pretty chart. I am a big fan of PowerGadgets and try to utilize them wherever possible. Well, when I added Out-Chart with an output parameter, I received the ambiguous error, "A generic error occurred in GDI+".

So naturally, I pulled up Google and started searching. I vaguely recalled seeing this before but couldn't quite put my finger on it. Then I saw it. ....Permissions....

Yes! Now I remember. If the UNC path I am trying to save my chart to is wrong or permissions are not configure properly, I get the error.

Lesson Learned:

  1. Verify your UNC path before throwing it into your script.
  2. Use your blog!

Monday, July 14, 2008

Resolved! Conflict between PrimalScript and PSCX

On a couple workstations we noticed a conflict between PrimalScript Enterprise and the Powershell Community Extensions (PSCX). PrimalScript would throw an error and terminate when opening a file with a .ps1 extension.


I posted a follow-up on the Codeplex discussion board. Oisin quickly responded with a fix.

Hey guys,
Look for the line in your Pscx installed $profile that says:
Start-TabExpansion and comment it out with a #. This will workaround the problem.
- Oisin

Bingo! Now I can continue using PSCX (if you are not, you need to take a look) with PrimalScript. Thanks Oisin!

Thursday, July 3, 2008

Unable to use SourceSafe LAN service, performance of SourceSafe operations will not be optimal

When trying to utilize Microsoft Visual SourceSafe 2005 (VSS) with Sapian's PrimalScript Enterprise, I was getting the following warning, "Unable to use SourceSafe LAN service, performance of SourceSafe operations will not be optimal". Well we can't have that! To remedy this, you need to enable the LAN service on the VSS server.
  1. On your VSS server - Go to Microsoft Visual SourceSafe Administration
  2. Click on the Server menu item
  3. Click configure
  4. In the Server Configuration dialog box, select LAN
  5. Check the Enable LAN service for this computer.

Saturday, June 28, 2008

Previous Post mentioned in PowerScripting Podcast - Episode 30

The fine folks that bring us the PowerScripting Podcast (a must listen!), have included a previous post (DNS/WINS IP changes) in their 30th episode. I am honored!

Thursday, June 26, 2008

ASPNet_WP.exe analysis on multiple servers via PowerGadgets

Was recently asked if I could help our development team analyze the ASPNet_WP process on 3 web servers. These 3 servers are load balanced and deliver the same content (FRS). There has been some spikes in the process and they wanted to be able to see this graphically. PowerGadgets to the rescue!

Steps are:
- Grabs an encrypted password (see previous post) as I am going across domains.
- Get WorkingSizeSet of the ASPNet_WP on the servers via WMI
- Store the WorkingSizeSet in a csv file (DB soon!)
- Grab the CSV file an pipe it to Out-Chart (PowerGadgets)
- Create a bat file that calls PowerShell with the appropriate ps1 file
(powershell.exe -nologo -command "& {c:\productionscripts\get-aspnet_wp1.ps1})
- Schedule the bat file
Please forgive the lack of pipes in this post. I am struggling to find a blog that handles code nicely.

# Script Name: Get-ASPNet_WP.ps1
# Description: PowerShell Script for ASPNet_WP
# analysis on intapp-p2, webster-vp01
# and webster-vp02
# Created By: Wes Stahler
# Date Created: 6/25/2008
# Change Log:
# 6/26/2008 Added PowerGadget chart for
# inclusion on admin web page

# Get password from encrypted file
# Once these servers are moved into the correct domain
# we won't have to worry about the creds....
$password = Get-Content c:\cred.txt ConvertTo-SecureString

# Create credentials
$creds = New-Object -typename System.Management.Automation.PSCredential `
-argumentlist "nt3osumc\stah06",$password

# Get WorkingSetSize for the 3 NT3OSUMC servers
$intapp_p2 = Get-WmiObject -Class Win32_Process `
-ComputerName intapp-p2 -Credential $creds `
Where-Object {$_.ProcessName -eq "aspnet_wp.exe"} `
Sort-Object WorkingSetSize -Descending `
Select-Object -First 1

$webster_vp01= Get-WmiObject -Class Win32_Process `
-ComputerName webster-vp01 -Credential $creds `
Where-Object {$_.ProcessName -eq "aspnet_wp.exe"} `
Sort-Object WorkingSetSize -Descending `
Select-Object -First 1

$webster_vp02= Get-WmiObject -Class Win32_Process `
-ComputerName webster-vp02 -Credential $creds `
Where-Object {$_.ProcessName -eq "aspnet_wp.exe"} `
Sort-Object WorkingSetSize -Descending `
Select-Object -First 1

# Being lazy....
$intappp2 = [math]::Round($intapp_p2.workingsetsize/1024/1024,0)
$webstervp01 = [math]::Round($webster_vp01.workingsetsize/1024/1024,0)
$webstervp02 = [math]::Round($webster_vp02.workingsetsize/1024/1024,0)
$dt = Get-Date -Format T

# Format string for to append to the historical file
# Will add to a DB later
$str = "{0},{1},{2},{3}" -f $dt,$intappp2,$webstervp01,$webstervp02

# Append to file
Add-Content -Path "c:\ProductionScripts\ASPNet_WP.csv" -Value $str

# Grab the data (last 7 hours worth) and chart!
$b = Import-Csv "c:\ProductionScripts\ASPNet_WP.csv" select -last 28
$b Out-Chart -Values Intapp-p2, webster-vp01, Webster-vp02 `
-Label Time `
-Title "ASPNet_WP.exe as of $dt" `
-gallery Lines `
-AxisY_Max 1000 `
-Size 800,533 `
-Series_1_AxisY AxesY_0 `
-Series_2_AxisY AxesY_0 `
-Output "file://intapp-p2/e$/Inetpub/Extranet/ProjectManager/Exception/ASPNet_WP.png"

Monday, June 23, 2008

Was recently asked to retrieve hard drive (type=3) information from a supplied list of servers for backup planning.

Following is a script used to gather this information.
Now if I could only find a way to get the file count.....

function Get-DriveInventory
#get drives from WMI
$drives = gwmi win32_logicaldisk -comp $_ -filter "drivetype=3"
#construct output objects
foreach ($drive in $drives)
$obj = New-Object psobject
$obj Add-Member NoteProperty ComputerName $_
$obj Add-Member NoteProperty DriveLetter $drive.deviceid
$obj Add-Member NoteProperty VolumeName $drive.VolumeName
$free = $drive.freespace/1MB -as [int]
$obj Add-Member NoteProperty AvailableSpace $free
$total = $drive.size/1MB -as [int]
$obj Add-Member NoteProperty TotalSpace $total
Write-Output $obj

function Get-FileName
$computer = Read-Host "Filename of computer names?"
return $computer
# get the filename
$f = Get-FileName
Get-Content $f Get-DriveInventory Export-Csv "C:\Users\Public\Documents\DriveInventory.csv"

Friday, June 20, 2008

Vista SP1 and PowerShell Commands for Active Directory by Quest Software

I recently made the move on one of my workstations to Vista with no real issues. Everything PowerShell related worked fine. I later decided to go ahead and install Vista SP1. After installation, things seemed to work fine until I tried to use the AD tools from Quest. The ActiveRoles management shell would not even load. After a bit of fruitless research, I uninstalled PowerShell and associated addins and reinstalled. This fixed the issue. Not sure what SP1 did, but a reinstall was the only thing that got me back up and running AD commands.

Wednesday, June 18, 2008

Change DNS/WINS IP on Multiple Servers

I was recently asked if I could change the DNS & WINS IP address on multiple servers via script. PowerShell to the rescue! After a brief search, I found a great post. Following is my implementation.

function Set-DNSWINS {
#Get NICS via WMI
$NICs = Get-WmiObject '
-Class Win32_NetworkAdapterConfiguration '
-ComputerName $_ '
-Filter "IPEnabled=TRUE"

foreach($NIC in $NICs) {
$DNSServers = "",""
$NIC.SetWINSServer("12.345.67.890", "12.345.67.891")

function Get-FileName {
$computer = Read-Host "Filename of computer names?"
return $computer

$f = Get-FileName
Get-Content $f foreach {Set-DNSWINS}

Gotta love PowerShell!

TechEd 2008

Spent most of last week in sunny Orlando attending TechEd 2008. It was a great conference for those interested in PowerShell. There were plenty of scripting sessions to attend. Even more importantly, I had the pleasure of meeting some of the people responsible for generating the excitement around PowerShell. Specifically, Jeffery Snover (Microsoft) and Hal Rottenberg (the man responsible for filling my iPod) - check out

Lots of swag was distributed, including PowerGadgets, you gotta take a look at this cool product!