Powerscripting Podcast

Posted Leave a commentPosted in Compellent, PowerShell

I will be the guest for an interview on the Powerscripting Podcast, a Powershell podcast designed to help people learn Windows PowerShell.

I will be on to discuss the Compellent Command Set for Windows PowerShell, our free offering for customers who want the ability to manage their Compellent Storage Center via script, or automate administration processes, a lot of which I will talk about in the interview.

This is a live show and the hosts will take questions during the broadcast, So, tune in Thursday night (January 8) at 9 AM EST (8 PM CST)!

Finding Active IP Addresses and Resolved Hostnames with PowerShell

Posted 3 CommentsPosted in PowerShell

Ever wanted to know what IP addresses are being used on a particular subnet and what each IP address resolves to which hostname, if any?  This script accomplishes just that.

# Continue to run script when an error occurs
$ErrorActionPreference = "SilentlyContinue"
# Process through the loop of IP addresses 1-254
1..254 | foreach -Process `
    # We're combining the contents of different objects, so create our own
    $obj = New-Object PSObject;
    # Perform the Ping using WMI
    $ping = get-WmiObject -Class Win32_PingStatus -Filter ("Address='10.10.2." + $_ + "'");
    # Put the IP Address into our object
    $obj | Add-Member NoteProperty IPAddress($ping.Address);
    # Take the Ping Status Code that is returned (0 = pingable)
    $obj | Add-Member NoteProperty StatusCode($ping.StatusCode);
    # If we can ping the address, let's try to resolve the hostname
    if($ping.StatusCode -eq 0)
          # Record that the ping was successful
           $obj | Add-Member NoteProperty Status("Online");
        # Try to resolve the IP address to a hostname in DNS
        $dns = [System.Net.Dns]::GetHostByAddress($ping.Address);
           if($dns -ne $null)
            # Add the resolved hostname to our collection
             $obj | Add-Member NoteProperty ResolvedHostName($dns.HostName);
            # Couldn't resolve the IP address to a hostname
               $obj | Add-Member NoteProperty ResolvedHostName("");
        # Can't ping IP address, so mark host as offline
           $obj | Add-Member NoteProperty ResolvedHostName("");
           $obj | Add-Member NoteProperty Status("Offline");
    # Write the collection out
    Write-Output $obj;
    # Cleanup DNS object
    $dns = $null;

Discovering Stale Computer Accounts with PowerShell

Posted 1 CommentPosted in PowerShell

We all know that most test domains are the perfect breeding ground for non-standard practices.  This includes the lack of managing user accounts, computer accounts, DNS records and the like.

ADSI scripting has always been challenging, but I did do some of it back in my IT days when writing code in VBScript.  I wanted to try to tie in to a test domain to determine what computer accounts hadn’t had their password changed in the last 90 days.  By default, Windows machines will talk to the domain in which they have a computer account in and change their password every 30 days.  With that in mind, we can look for computer accounts who haven’t changed their computer account password in the last month.

We probably want to allow a little more than 30 days; perhaps computer accounts might be considered stale after 60 or 90 days.  That means that the computer hasn’t made network contact in the allotted amount of time.

Within PowerShell I tapped into the ADSI adapter and some of the .NET Framework objects that let me search Active Directory.  Really I was only interested in the computer name and the date of the last password change.  Both of those were easy to access.  Here is a copy of what my script looks like:

function Get-DomainComputerAccounts
    # Use Directory Services object to attach to the domain
    $searcher = new-object DirectoryServices.DirectorySearcher([ADSI]"")
    # Filter down to computer accounts
    $searcher.filter = "(&(objectClass=computer))"
    # Cache the results
    $searcher.CacheResults = $true
    $searcher.SearchScope = “Subtree”
    $searcher.PageSize = 1000
    # Find anything you can that matches the definition of being a computer object
    $accounts = $searcher.FindAll()
    # Check to make sure we found some accounts
    if($accounts.Count -gt 0)
        foreach($account in $accounts)
            # Property that contains the last password change in long integer format
            $pwdlastset = $account.Properties["pwdlastset"];
            # Convert the long integer to normal DateTime format
            $lastchange = [datetime]::FromFileTimeUTC($pwdlastset[0]);
            # Determine the timespan between the two dates
            $datediff = new-TimeSpan $lastchange $(Get-Date);
            # Create an output object for table formatting
            $obj = new-Object PSObject;
            # Add member properties with their name and value pair
            $obj | Add-Member NoteProperty ComputerName($account.Properties["name"][0]);
            $obj | Add-Member NoteProperty LastPasswordChange($lastchange);
            $obj | Add-Member NoteProperty DaysSinceChange($datediff.Days);
            # Write the output to the screen
            Write-Output $obj;
# Get computer accounts where a password change hasn't occurred in 60 days or more
# If nothing outputted, then there are no accounts that meet that criteria
Get-DomainComputerAccounts |Where-Object {$_.DaysSinceChange -gt 60}

This script could be modified to include functionality that would take the suspect computer accounts and disable them, then eventually delete them.

Storage Center Command Set Makes Automation a Snap!

Posted Leave a commentPosted in PowerShell, Storage

This week we announced the availability of the Storage Center Command Set for Windows PowerShell as a free download for Compellent customers.

PowerShell is the powerful, new scripting interface from Microsoft with support for Windows Server 2008 (including Hyper-V), Windows Server 2003, Windows XP, and Windows Vista.  We’ve integrated PowerShell automation with our Command Set scripting shell. From Command Set, IT pros can  automate administration tasks on the Windows platforms for their Compellent Storage Center.

We’ve integrated PowerShell automation with our Command Set scripting shell. From Command Set, IT pros can automate administration tasks on the Windows platforms for their Compellent Storage Center.

We’ve exposed over 60 cmdlets that you can use to manage different objects within Storage Center including the controllers, servers, volumes, and alerts in addition to features like Copy-Mirror-Migrate (CMM). With the installation of the Command Set, we also include a few samples scripts to get you started in your scripting endeavors.

What types of scenarios are the Storage Center Command Set useful for?

Exchange Volume Provisioning

With Exchange Server 2007, you can have up to 50 storage groups. In a scenario where you need to deploy 50 storage groups with one database each, you’ll probably deploy with an individual volume for each database and each storage group for the transaction logs totally 100 volumes.

Although the Storage Center web management tool is very easy to use, it can be time consuming to complete the process of creating the volume, mapping it to the server, and then assigning a drive letter or mountpoint server-side for the volume. With the Command Set, you can automate this process from start to finish and complete your provisioning process in minutes instead of hours or days.

To augment this process, you can leverage the Exchange 2007 cmdlets to create your storage groups and databases all in the same pass after the volumes are created.

Windows Failover Cluster Deployment

Taking the same principles from above, you can handle mapping the same volume on the Storage Center to multiple servers at the same time including multiple paths for scenarios that require Multipath I/O (MPIO). You can also leverage CLUSTER.EXE (part of MSCS) to automate the creation of your cluster and the individual cluster resources including details like dependencies.

Virtual Machine Deployment

Using a combination of the Storage Center Command Set and cmdlets that are available within Hyper-V, you can automate the process of provisioning storage as well as deploying virtual machines in literally minutes!

Use Replays for Backups

Instead of backing up each individual volume, how about using the replays for each volume as the source for a backup? Included with the Storage Center Command Set is sample script called “Push2Tape”. This script will take the name of the volume on the Storage Center, retrieve a list of available replays for that volume, and then create a view of the latest replay map that to a tape or media server as either a drive letter or mountpoint. With the replays mounted on the tape or media server, that server is then the sole point for all your backups. This process will take the overhead that is typically associated with running backups on a production server, and put that on the tape or media server.

The possibilities are endless. Login to Knowledge Center today and download your copy of the Storage Center Command Set for Windows PowerShell. You can also register to join our secure online group and share best practices with other Compellent PowerShell users.

Using Powershell To Generate Test Mailboxes

Posted 1 CommentPosted in Exchange, PowerShell

There are situations where you may want to generate a number of test mailboxes whether it be for a demo or another scenario.  With Exchange 2007, you can leverage Powershell cmdlets to complete this process for you in just seconds.

First, I start out with the a CSV file that contains a limited number of columns, basically the minimum needed to create an Active Directory user account and mailbox-enable it.  Since I have a passion for baseball, my test CSV file is a tribute to some of my favorite players in history.  This is what the sample users.csv file looks like:


Next, it only takes a couple lines of code for us to generate the accounts and mailboxes.  You can take this code and save it into a file named something like createmailboxes.ps1.  This is what the script should look like:

# Test Mailbox Creation Script

# Variables Used Globally
$database = “First Storage GroupMailbox Database”
$ou = “Users”
$upnsuffix = “@e2k7test.local”

import-csv users.csv | foreach {$pass = ConvertTo-SecureString $_.Password -AsPlainText -Force; New-Mailbox -Name ($_.FirstName+” “+$_.LastName) -Password $pass -UserPrincipalName ($_.UPN+$upnsuffix) -Database $database -OrganizationalUnit $ou -FirstName $_.FirstName -LastName $_.LastName -DisplayName ($_.FirstName+” “+$_.LastName)}

In my script I include some variables that I reuse for all of my users.  In this case, they are all going to be part of the same organizational unit (OU) in Active Directory and their mailboxes will all be part of the same mailbox database.  They are also part of the same domain so the suffix for their User Principal Name (UPN) will be the same.

Literally, the meat of the script is just one line of code thanks for the piping you can do in Powershell.

The import-csv cmdlet takes in a comma-separated text file and lets us read its contents like a data object.  Basically we’re taking the contents of the CSV file and passing it into the next segment of code which is the “For Each” block.

Since we want to create an account and mailbox for each line in the CSV file, we’ll do that line by line processing within the “For Each” block.  The first command within that block is where we’ll save the password as a variable.  Since the password can’t be passed into the cmdlet as plain text, we have to convert it to a secure string using the ConvertTo-SecureString cmdlet.  We pass in the plain text password and it returns a secure string that can be used.

Next we call the New-Mailbox cmdlet which will create the account and mailbox enable it.  We’ll pass in information like the name of the account, first name, last name, display name, UPN, mailbox database, OU, and password.  There are additional fields that you can include, but are not required.

We can access the different “fields” from the CSV by calling them with the $_.ColumnName format as you can see in the script sample. 

This clearly simplifies the process of bulk account creation and provisioning for Exchange.  We’ll work on continuing to evolve this into a more complex script that adds some additional functionality.