Quick One-Liner – Search in Files

Today’s one liner is all about how to search file contents in Powershell, recursively.  Bring on the code!

Get-ChildItem -recurse -filter *.cs | Select-String -pattern “SqlConnection” | group path | sort count | select name > sqlconnection.txt

First, let’s just get all C# source files:  Get-ChildItem -recurse -filter *.cs

Second, let’s select all lines with our search string: Select-String -pattern “SqlConnection”

Third, let’s group all the matchinfo objects returned by path: group path

Fourth, let’s sort the grouping objects by count ascending:  sort count

Fifth, let’s select only the name (full file path): select name

Finally, let’s pipe it into a file:  > sqlconnection.txt

Yay!  Easy and simple.  I’m going to turn this into a function that I can have at the ready.


Git Tip: Deleting Old Local Branches With PowerShell

So I was reading Git Tip: Deleting Old Local Branches, but the code was for Bash/Linux. My first instinct in all of these cases is to translate it into PowerShell.  I am shamelessly stealing the format of the original post as I liked the way he laid it out.

0) Prune Remote Branches

>git remote prune origin

Read more about git remote prune here

Deletes all stale remote-tracking branches under . These stale branches have already been removed from the remote repository referenced by , but are still locally available in “remotes/”.

1) List local git branches

git branch -vv will list all local branches along with some additional information such as their related upstream/remote branch and latest commit message

> git branch -vv
feature/some-local-only-feature cba8191 Some commit message
feature/some-old-feature cba2191 [origin/feature/some-old-feature: gone] Some commit message about some old feature
feature/some-active-feature wba2191 [origin/feature/some-active-feature: ahead 40, behind 10] Some active feature branch

2) Filter git branches down to only those with deleted upstream/remote counterparts

Next, we pipe the output from git branch -vv into grep ‘origin/.*: gone]’. This filters our list down to only lines that match the regex origin/.*: gone] leaving us with

> git branch -vv | where {$_ -match '\[origin/.*: gone\]'}
feature/some-old-feature cba2191 [origin/feature/some-old-feature: gone] Some commit message about some old feature
Read more about using regular expressions with PowerShell here.

3) Pluck out branch names from output

Piping that into split()[0] cleans up our output so we end up with a branch name per line.

> git branch -vv | where {$_ -match '\[origin/.*: gone\]'} | foreach {$_.split(" ", [StringSplitOptions]'RemoveEmptyEntries')[0]}'
feature/some-old-feature cba2191 [origin/feature/some-old-feature: gone] Some commit message about some old feature
This is because split translates the string to an array (items being separated by space(s)) and [0] is the first item, which is the branch name. We also use the RemoveEmptyEntries option so that any leading/trailing spaces are removed.  Example:

> git branch -vv | where {$_ -match '\[origin/.*: gone\]'} | foreach {$_.split(" ", [StringSplitOptions]'RemoveEmptyEntries')}
[0]: feature/some-old-feature
[1]: cba2191
[2]: [origin/feature/some-old-feature:
[3]: gone]
[4]: First
[5]: words
[6]: in_commit_message…

4) Delete the branches!

Next, we pipe our filtered down, cleaned up git branches list into git branch -d (short for –delete) and say our final goodbyes.

>git branch -vv | where {$_ -match '\[origin/.*: gone\]'} | foreach {git branch -d ($_.split(" ", [StringSplitOptions]'RemoveEmptyEntries')[0])}


You should always run step 0 and step 3 to validate the branches you are going to be deleting before running step 4.  Don’t say you weren’t warned.

This does not clean up any local branches that were never pushed to the remote server.  That’s a script for another day.

Visual Studio 2015 TFS and Powershell

I found a really great article about using the TFS Client dll’s here.  However, that only worked for VS2013.  I had to fix it for VS2015.

For some interesting reason, they are no longer GACing the assemblies, nor are they in a default location.  Now they are sym-linked to the existing version.

Here is my example PowerShell code:

$vs2015Path = “C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\CommonExtensions\Microsoft\TeamFoundation\Team Explorer”
Add-Type -Path “$vs2015Path\Microsoft.TeamFoundation.Client.dll”
Add-Type -Path “$vs2015Path\Microsoft.TeamFoundation.Common.dll”
Add-Type -Path “$vs2015Path\Microsoft.TeamFoundation.Build.Client.dll” 
Add-Type -Path “$vs2015Path\Microsoft.TeamFoundation.Build.Common.dll”
Add-Type -Path “$vs2015Path\Microsoft.TeamFoundation.WorkItemTracking.Client.dll”
Add-Type -Path “$vs2015Path\Microsoft.TeamFoundation.VersionControl.Client.dll”
Add-Type -Path “$vs2015Path\Microsoft.TeamFoundation.ProjectManagement.dll”

Computer Owner In PowerShell

I frequently need to figure out who the owner of a computer object is in Active Directory.

Enter PowerShell to the rescue!


Easy as pie.  Here is the full code for you to use.

$oADObject = Get-ADComputer <ComputerName> -Properties *
$oAceObj   = Get-Acl -Path (“ActiveDirectory:://RootDSE/” + $oADObject.DistinguishedName);

Gist Link: https://gist.github.com/dalehhirt/3f03b9ee27a245933e1a

SCOM, Data Warehouse Moves, and Get-SCOMDataWareHouseSetting

My operations team runs System Center Operations Manager 2012 R2 internally.

I host the OperationsManager database on a SQL Server 2012 Availability Group, and for the most part, it works well.  However, for space reasons, we needed to move the Data Warehouse database to its own server backed by SAN storage.

After following this guide (https://technet.microsoft.com/en-us/library/hh268492.aspx), the database was successfully moved, and the data is flowing correctly.  In addition, all reporting is working as expected.  It was moved from scomsql (SQL 2012 Availability Group) to scomsql3 (standalone instance).

Everything worked out except for the Get-SCOMDataWareHouseSetting PowerShell cmdlet.  It would return the name of the old server.


To find the current value, I ran the following:


And now it returns the correct value.

Update: due to the vagaries of WordPress, I’m linking to the SQL script here.