Skip to main content


Showing posts from 2012


This is one of my most favorite PS hacks. It allows you to add a type alias, similar to [PSObject], [ADSI], or [WMI].
param(      [Parameter(Mandatory = $true, ValueFromPipeline = $true)]      [ValidateNotNull()]      [Type] $Type,      [Parameter(ValueFromPipelineByPropertyName = $true)]      [ValidateNotNullOrEmpty()]      [string] $Name = $Type.Name  )  BEGIN {  $ErrorActionPreference = 'Stop'$PSTypeAccelerators = [Type]::GetType("System.Management.Automation.TypeAccelerators, $([PSObject].Assembly.FullName)")  }  PROCESS {  if ($PSTypeAccelerators::Add) {  $PSTypeAccelerators::Add($Name, $Type)      } elseif ($PSTypeAccelerators::AddReplace) {  $PSTypeAccelerators::AddReplace($Name, $Type)      }  }   You can add a single alias:
Add-PSTypeAccelerator System.Management.Automation.PSCredential   Or an entire namespace or assembly (by removing the namespace filter):
[System.Reflection.Assembly]::LoadWithPartialName('System.Messaging').GetTypes() |? { $_.N…

Failover Cluster Node Maintenance Automation

I have been using the Exchange 2010 scripts to start/stop DAG member maintenance as well as redistribution of databases to preferred owners after maintenance is complete.

I was doing some work on several failover cluster nodes, and thought, it'd be nice to have the same functionality. The ability to pause a node, move all the cluster resources off it, stop the maintenance, and then to redistribution the cluster groups to the preferred nodes.

So, I present the below three scripts to perform these tasks on Windows Server 2008 R2 failover clusters.

param([string] $Node = $ENV:COMPUTERNAME, [string] $Cluster = '.')  Import-Module FailoverClusters  Suspend-ClusterNode -Name $Node -Cluster $ClusterGet-ClusterNode -Name $Node -Cluster $Cluster | Get-ClusterGroup -Cluster $Cluster | Move-ClusterGroup -Cluster $Cluster [Stop-ClusterNodeMaintenance.ps1]
param([string] $Node = $ENV:COMPUTERNAME, [string] $Cluster = '.')  Import-Module Failover…

Synchronize Windows Features and Roles

I didn't see anything specific to this with a quick Google, so I thought I'd post this. Perhaps, it will help other administrators replicate/copy Windows features and roles to multiple servers from a source server. In my particular case I needed to copy the features and roles from a test environment server to a certification server.

This will add new features and roles as well as remove any not in use from the source to the localhost.

param([string] $Source)  Import-Module ServerManager  $features = Invoke-Command -Computer $Source -Script {      Import-Module ServerManager      Get-WindowsFeature  }  $features |? { $_.Installed -and $_.SubFeatures.Count -eq 0} | Add-WindowsFeature  $features |? { !$_.Installed } | Remove-WindowsFeature  
Note: The Remove-WindowsFeature may fail if a reboot is required after the Add-WindowsFeature completes. Just run the command again after the server is rebooted.

Note: The script had to select only features that have no subfeatures to install,…

PowerShell 3.0 Workflows

As a system administrator, this has me really excited about automation and the next generation of Microsoft System Center products.

As a developer, this has me excited for hot-plug-and-go workflows within my app by hosting a PowerShell host... I've long wanted to use workflows within an app but was hesitant because it required coding knowledge to build new ones. This may be my way out of that problem so that admins can write their own workflows within the app but in PowerShell ...

Generate Random SecureString Key

Ever need to encrypt a SecureString that can be used across multiple servers? I suggest storing this BASE64 value in a secure location only accessible by the account(s) that need to decrypt the SecureString.
$secret = 'secret1234'$key    = [Convert]::ToBase64String((1..32 |% { [byte](Get-Random -Minimum 0 -Maximum 255) }))  $encryptedSecret = ConvertTo-SecureString -AsPlainText -Force -String $secret | ConvertFrom-SecureString -Key ([Convert]::FromBase64String($key))  $encryptedSecret | Select-Object @{Name='Key';Expression={$key}},@{Name='EncryptedSecret';Expression={$encryptedSecret}} | fl  $ss = ConvertTo-SecureString -Key ([Convert]::FromBase64String($key)) -String $encryptedSecret(New-Object System.Management.Automation.PSCredential 'SECURESTRING',$ss).GetNetworkCredential().Password

FIM Run History Statistics

Probably not optimal but I didn't find any problem running this on a server with over 500 runs in the history
Note: Remember to clear your run history every so often!

param(      [string]   $ComputerName = '.',      [string[]] $MaName       = $null,      [string[]] $RunProfile   = $null)  process {  Get-WmiObject -Class 'MIIS_RunHistory' -Namespace 'root\MicrosoftIdentityIntegrationServer' -Filter 'RunStatus != "in-progress"' `          |? { ([int]$MaName.Count -eq 0 -or $MaName -contains $_.MaName) -and ([int]$RunProfile.Count -eq 0 -or $RunProfile -contains $_.RunProfile) } `          | Select-Object -Property MaName,RunProfile,@{Name='RunTime';Expression={[DateTime]::Parse($_.RunEndTime).Subtract([DateTime]$_.RunStartTime).Ticks}} `          | Group-Object -Property MaName,RunProfile `          | Sort-Object -Property Name `          | Select-Object -Property *,@{Name='RunTimeStatistics';E…

Export SQL Reporting Services Execution Log to CSV

We recently needed to export the SQL Server Reporting Services execution log so we can audit usage of our reporting services environment.

I just love how PowerShell makes this easy to do.

param(      [string]   $ConnectionString = 'Server=(local);Database=ReportServer;Integrated Security=SSPI;',      [string]   $CommandText      = 'SELECT * FROM dbo.ExecutionLog3 WHERE TimeStart BETWEEN ''{0:MM/dd/yyyy} 12:00:00 AM'' AND ''{0:MM/dd/yyyy} 11:59:59 PM''',      [string]   $Path             = "$($ENV:WINDIR)\system32\LogFiles\SQL",      [string]   $FileName         = 'ReportServer-ExecutionLog3-{0:yyyyMMdd}.csv',      [DateTime] $Date             = [DateTime]::Now.Subtract([TimeSpan]::FromDays(1))  )  begin {  $ErrorActionPreference = 'Stop'$connection = New-Object System.Data.SqlClient.SqlConnection $ConnectionString$connection.Open()  }  process {  $adapter = New-Object System.Data.S…