Archive for the 'Technical How-To's' Category

Writing an SVN PreCommit Hook in .NET that integrates with Jira

What are Subversion hooks and why would you use them?

Hooks are extension points that allow you to add behavior at various stages of the commit process through an executable file.

The most useful one is the probably the pre-commit hook because it allows you to prevent a commit from occurring, thus providing a way to enforce whatever policies that can dream up to help your development process run more smoothly.

We use it to ensure that developers enter a valid Jira key into the commit notes, which is a crucial step in making our code review process as painless as possible.

How do pre-commit hooks work?

All you have to do is create a console application or script named pre-commit and copy it in the hooks directory of your repository. Subversion will automatically execute any application following this convention before each commit.

The repository path and transaction id associated with the commit will be passed in as the first two arguments, thus allowing you to look up relevant information about the revision before making the decision about whether or not to allow the commit to occur.

To prevent the commit from happening, all you have to do is exit with a ‘1′. You can even display an explanatory message to the user (at least in TortoiseSVN) by writing to Console.Error.
SVNHook_tortoiseSVN_Failure_Message

Using SharpSVN to Avoiding Command Line Parsing Hell

During my first attempt at implementing a hook, I programmatically spawned a process and executed svnlook.exe to extract the information I needed about the revision.

This worked fine for simple cases, but quickly began to require some serious Command Line Parsing-Fu in order to accomplish what I wanted. At that point my “There-has-to-be-an-easier-way” alarm went off in my head, so I began to search around for a pre-built API to simplify the task.

I soon found SharpSVN, a stable open source project that is used by AnkhSVN and SharpDevelop.

Aside from a few annoying testability issues that forced me to create wrapper classes in order to do unit testing, I had a good experience with the framework and would definitely recommend it over rolling your own.

Integrating with Jira

Jira exposes a large portion of their functionality through web services that you can access by simply turning the “Accept Remote API calls” option on in the General Configuration area of the administration page.

We use the key parsed from the comment to query the Jira web service and verify that the referenced issue is in an opened state and has a fix version that has not already been released.

Downloading the Code

I zipped up a sanitized version of our pre-commit hook that you can download and either use as a learning sample or modify for your own use.

Popularity: 2% [?]

Tips on Upgrading from VSS to Subversion

We’ve almost completed our first week on Subversion and all is well. Here are a few pieces of advice to those of you about to embark on a VSS to SVN migration of your own.

  1. Spend Time Getting Buy-In from all Developers BEFORE the Migration – Force feeding a new tool to your co-workers is a recipe for disaster. Developers who aren’t given any input or choice in the matter may be compliant at first but will likely turn passive-aggressive on you at the first sign of trouble. We did some lunch-and-learns and focused specifically on current source control related problems that would be solved by migrating to a new tool well before we did the actual migration. This made life much easier during the inevitable bumps that came up during the first few days after the migration.
  2. Be Aware of Tool Limitations When Migrating History – Unfortunately there don’t seem to be very many good options out there when it comes to migrating VSS history. After some failed attempts at using VSS2SVN and SVNImporter, I settled on using Eric Lane’s version of VSSMigrate. It accurately converted all the files in a 5GB VSS database, preserved history from the perspective of a single file, and stripped the VSS bindings from the project and solution files. The utility is also written in C# and the source code is provided so you can make tweaks as needed (I changed it to put the associated version label in the comment of the revision). Unfortunately, it doesn’t convert labels and more importantly it doesn’t preserve history from a holistic perspective since it loops through and commits the version history of one file at a time. If you really only care about doing diffs and not about reconstructing your apps as of a certain point in time, then I would recommend using this tool. Otherwise, keep looking.
  3. Do Several Practice Migrations – I set up a Virtual Machine that mirrored our source control server and not only went through the migration several times on a copy of the full VSS database, but also documented each step to make life easier during the actual migration, which took place over the weekend when I was less…focused.
  4. Don’t Forget About Dependencies – We had quite a few Nant, CruiseControl, and VisualBuild scripts that needed to be modified, which added quite a bit of time and effort to the migration process. A VM definitely came in handy when testing these changes as well.
  5. Run VSSAnalyze Before Migration – Corrupted VSS chains are common and will likely cause havoc with a migration tool unless you try to fix them prior to the migration. Even after running Analyze, the VSS equivalent of duct tape, there were still 2 files with corrupted version history that I had to remove from the VSS database prior to the migration and manually add to SVN after the migration.
  6. Use BeyondCompare to Verify Migration – Make sure that you do a full comparison of working directories from the new SVN repository and old VSS repository. Before performing the comparison, you’ll want to configure exclusions for the svn and vss specific files as well as the project and solution files if they have been stripped of bindings either by the migration tool or manually.
  7. Open Up and Compile All Solutions After Migration – I discovered a resource file that somehow got dropped during the migration because one of the solutions would no longer compile.
  8. Use SharpSVN to Extend and Script For SVN – I was surprised at how easy it was to create a pre-commit hook for SVN that would analyze commits and prevent the ones that didn’t contain a valid issue for our issue tracker (JIRA). This was partially because I used SharpSVN, an open source API, and was thus able to interact with the repository without having to parse command line return values from SvnLook.
  9. Practice Backups and Restores Before Migration – Resist the temptation to put this off until after the migration and make sure you fully test any scripts that you use, especially if you don’t use the recommended Python scripts that can be found on the official SVN site . I couldn’t convince the Powers-That-Be to let me install a Python interpreter on our server, so I went surfing for PowerShell scripts and the first one I tried for incremental backups only actually saved the latest revision instead of the latest range of revisions. I didn’t discover until doing some testing on a practice restore that I did.
  10. Plan the Migration over a Weekend – Most of the processes are very long running. The one that migrated our VSS history took almost 10 hours for a 5 GB database and we ran into some problems with our build scripts that took much of the day Sunday to debug.

Happy Migration!

Popularity: 27% [?]

Using YSlow and HammerHead to Enhance Web App Performance

I recently installed YSlow, a Firefox add-on integrated with the popular Firebug web development tool that does performance analysis based on the rules for high performance web sites developed by Yahoo.

I tried it on DosPecesCreations.com, the e-commerce site I recently built for my wife using Ruby on Rails, and was surprised to learn that the site received a failing grade according to the YSlow Report Card.

yslow_grade_before

It took me just over an hour of clicking on the explanations for failed failed categories and researching how to make some of the configuration changes in Apache to bring that grade up to a high B.

Bringing it up to an A would require me to use a Content Delivery Network like Akamai Technologies, which deploys content across multiple, geographically dispersed servers and dynamically chooses the fastest option in a given scenario based on proximity and available connections. However, since the customer base for the site is not international and we don’t have thousands of dollars a month to spend at the moment, I’ll just have to content myself with being a B student.

So what was the payoff for making these changes?

I wanted to have a somewhat objective way to measure the performance improvements, so I also downloaded HammerHead, another firebug add-on that provides average load times for pages with and without the cache being used.

Here are my baseline metrics.

yslow_2

Here are the results after I made the changes.

yslow_after_2

As you can see, I more than doubled the speed of the site with little effort and almost no coding changes. Here’s a quick summary of what I did:

  1. Reduced the size of the HTTP response
    • Enabled Gzip Compression -  This is done in Apache with an output filter, which I enabled by adding one line to the .htaccess in the root directory of the site.
    • Minified Javascript Files – This involved removing all the comments as well as unneeded white space characters (space, newline, and tab) from javascript files. Luckily there are tools such as JSMin that will do this for you. I ran the Ruby version of JSMin as a Rake task and was able to reduce my Prototype Javascript Library files by about 25%.
    • Removed Unused Javascript Reference – This sounds obvious, but by using the default option with the javascript_include_tag Rails helper tag I was referencing 6 Prototype files even though I was only using 2 of them. By removing the unused references, I was able to trim 65k from my pages.
  2. Reduced # of trips
    • Merged javascript files – The Rake task I used above also merged the remaining prototype files into one file so the client would have to make one less round trip to retrieve the files.
    • Enabled Caching – I configured Apache to use Far Future Expire tags for my static content (images, js, & css) and Cache-Control tags for my dynamic content (2 hour expiration). I followed the recommendation of disabling ETags as well even though this only appears to only interfere with caching on web farms and I’m currently on a single server.
  3. Maximized parallel download speed – I did this by moving all my scripts from the html header to the bottom of the page. Apparently javascript files can block parallel downloads so simply moving these from the header to the bottom of the page will increase the overall load time.

I used this resource while making all of the Apache configuration changes. If you’re using IIS, then you might want to try this post.

As someone who spends most of his time doing middle tier and database development, I was surprised to learn how much of a web application’s performance is affected by these front end concerns.

Luckily, all of these front-end recommendations were much easier to fix than almost any performance tuning efforts applied to the back end.

Popularity: 20% [?]

Thinking of Breaking Away from the Blogging Herd?

Blogging communities like GeeksWithBlogs offer the advantage of a pre-established readership, free hosting, and no hassles when it comes to setting up and maintaining your blog.

Unfortunately, you also give up a lot of control when you become part of a large blogging community and ultimately miss out on the basic joys of tinkering. For the more capitalist minded among you, you also forgo the possibility of ever monetizing your blog.

If you are currently considering migrating your blog to your own domain or getting ready to start your own blog and aren’t sure which direction to go, here are a few things I would recommend based on my recent experience.

  1. Consider Using WordPress – SubText is a fine blogging engine, but I have been won over by the enormous number of plugins and themes available for WordPress. That translates into a lot more functionality as well as a more professional look and feel of your blog. I initially assumed that it would require a lot more technical investment on my part because it runs on PHP and mySQL, but so far I have been able to make a large number of customizations without ever having to refer to a tutorial due to the similarity of PHP and classic ASP as well as the intuitive design and naming conventions used by WordPress.
  2. Choose a Readable Theme – With over 1500 free themes to choose from, it’s easy to get distracted by designs that are flashy but make it difficult to accomplish the primary purpose of a blog, which is to facilitate reading content. Make sure the text is the main focus of your page and that it is in a clear font. Simpler is usually better.
  3. Expect Issues with Importing Old Blog Posts – Even though SubText provides a nice xml export feature (BlogML), the import process into WordPress was still a little bumpy. I found a plugin to help with the process, but there were still some issues with formatting and category names after the import process.
  4. Don’t Underestimate the Damage Done by WYSIWYG Editors (i.e. FckEditor) - WordPress lets you change themes effortlessly, but if you have pre-existing posts that were created with a WYSIWYG editor, then the chances are good that the HTML in your old posts is so polluted with inline tags that the CSS stylesheets in your fancy new theme won’t work properly. I’m still in the process of manually cleaning up the HTML from my old posts and it is a mind-numbingly tedious process that I’ll probably give up on before I finish.
  5. Get Sophisticated with Subscriber Statistics – SubText offers some rudimentary statistics on readers, but I took the opportunity to switch to Feedburner and install plugins for google analytics and WordPress.com Stats. I have been impressed with the level of reporting detail they offer when it comes to analyzing site traffic.
  6. Widgetize your Blog – What’s the fun of tinkering if you can’t go crazy with the plugins? Some of my favorites so far are Popularity Contest, ShareThis, KG Archives, Twitter Tools, Yet Another Related Posts Plugin, and Subscribe To Comments.
  7. Expect a drop in Subscribers – This is one of the advantages that a blogging community offers, so you can definitely expect to lose a few readers during the transition. In the case of GeeksWithBlogs, it didn’t help that I was removed from the main feed as soon as I put my notice up and had no ability to set up 301 redirects.
  8. Learn about SEO (Search Engine Optimizations) - If you want to make up for your drop in readership, then you’ll probably want to roll up your sleeves and learn a little about the black art of search engine optimization while setting up your blog. If you use WordPress, start by using these plugins: All in One SEO Pack, Jerome’s Keywords, Head META Description, Enforce www. Preference, Google Sitemap Generator, and Google Analytics plugin. If you want to get really serious about it, I hear Max from codesqueeze is planning on offering a 2 day advanced course on SEO later this year in exotic Fargo, ND.
  9. Test in multiple browsers/readers – I had to abandon my first theme completely after I realized it looked absolutely horrible in Internet Explorer. Unfortunately, I had already wasted a lot of time trying to customize it. I also forgot to retest my comment section functionality after installing the second theme and thus didn’t find out that it was broken until several days after going live.
  10. Find a Good FTP Client – the web interfaces supplied by hosting companies will work in a pinch, but you’ll really want a good FTP program. I am totally hooked on SmartFTP, which I discovered after consulting Scott Hanselman’s tool list.

Setting up your own blog is definitely not for everybody. If all you want to do is focus on writing good content and not worry about anything else, then I would recommend sticking with the blogging community site.

However, if you want to learn about all the gooey goodness that goes into making a blogging engine purr, then I would highly recommend the experience of setting up a blog on your own domain. So far I’m glad I did it.

Popularity: 12% [?]

.NET Framework Debugging 1, Reflector 0

Reflector has and will continue to be one of the coolest, most useful development tools around. However, when it comes to demystifying .NET framework classes, there is a new game in town.

Here’s a glimpse into what a method in the System.URI .NET framework class looks like using Reflector.

Not bad…but here is what it looks from inside the Visual Studio debugger after configuring it to use the newly available Microsoft symbol server.

Besides actually allowing you to see the control flow in action, manipulate input values, and replay edge case scenarios, this new approach lets you see all of the original developer comments. The ones I’ve looked at so far have tended to add real value to the code reading experience rather than just pointing out the obvious.

Also, since it is derived from the actual source code files rather than a reverse-engineered approximation, the code can serve as a valuable learning tool by showing real-world examples of best practices rather than the 2-3 line fluff usually found in documentation.

Well, ok…the code fragments above are screaming for some “Extract Method” refactorings, but in general I’m guessing the Framework has some instructive examples of how to program given the vast amount of effort and review that goes into the framework classes.

If you haven’t given it a try yet, the setup process to get this working is fairly easy. It simply involves installing a Visual Studio 2008 QFE and changing a couple of debugging configuration options (see Shawn Burke’s post). Within minutes, I was able to F11 into WebClient.DownloadString(). For some reason this just magically worked the first time, but the next day I had to right click on System.dll in the modules window and select “Load Symbols” in order to get it to work.

Below you can see in the Modules window how it shows that the symbols are loaded for System.dll and you can see in the call stack window that I am inside a framework method. If you look in the directory on your local machine that you configure as the symbols location, you’ll also be able to see the downloaded PDB file after you do this step.

Reflector will still hold an esteemed place in my developer toolbox when I need to peek inside all non-framework dll’s or verify the contents of a deployed dll, but I doubt I will use it anymore to spelunk framework dll’s (at least the ones whose symbols have been released).

Update: Although the setup was seamless on my Vista box at home, I haven’t been able to get the QFE to install on my Windows XP laptop yet. I don’t know if this is a common problem or if my machine has some unusual quirk due to the hundreds of utilities I install on it.

Popularity: 10% [?]

Puzzling Issue Involving Reflection and MbUnit

I just sent the following email to the BCL (Base Class Library) Team Blog email address in hopes of getting some insight into a weird problem we’ve been having.

I was hoping you could give me some general guidance on how Type.GetProperties() determines the sequence of the PropertyInfo objects it returns.

I just ran across this remark on MSDN about the order that Type.GetProperties() returns PropertyInfo objects

The GetProperties method does not return properties in a particular order, such as alphabetical or declaration order. Your code must not depend on the order in which properties are returned, because that order varies.

We have parsing code that uses the 1.1 framework which is dependent on the order in which properties are returned. It fails intermittently when run as part of a suite of MbUnit tests. After seeing this msdn remark, I changed the code to remove the sequence dependency and the MbUnit intermittent failure problem disappeared. This led me to believe that properties were sometimes being returned in an order other than what we expected (the order they were declared in the code files).

Normally we are not allowed to make production changes this time of the year unless the issue is critical, so we are trying to determine the likelihood of this causing production issues. The problem is that we get contradictory results based on how we test this. If I wrap the method in a hundred thousand loop iteration, then I can’t reproduce the error in MbUnit. The properties always return in the order in which they are declared in the class file. However, if I run the whole suite of tests several times in succession, then I receive random errors that seem to derive from the sequence being returned in a different order.

Is there some internal algorithm that might trigger a different sequential order to be generated based on some unique condition that running the whole MbUnit suite of tests as opposed to running them in a large loop would cause (i.e. a certain number of threads or memory/cpu pressure)?

Any insight you could offer in this problem would be greatly appreciated.

Thank you,

Russell Ball

Does anyone else have any ideas?

** Update **

We no longer get these failures in MbUnit if we revert it to the 1.1 framework by changing the supported frameworks node in the config file as described here. I’m guessing they changed the algorithm in the 2.0 framework that is used to determine the sequence.

That still doesn’t explain why there is a difference between calling our code in a massive loop versus calling it as part of a suite of tests, but at least it puts our minds at ease with respect to the risk of intermittent failures occurring in our current production code.

Popularity: 6% [?]

Don’t Forget to Verigoogle

I knew that SQL Server 2005 had structured exception handling, but for some reason I assumed that you could only use it within CLR sprocs. Since I still haven’t actually heard of anyone using CLR sprocs for anything other than demos or sample projects (at least not without being pummeled by hoards of angry DBA’s), I mostly ignored this new feature until now.

Today I worked on a sproc that involved over a dozen DML statements (it was a utility sproc to handle security and setup steps for developers as part of our build process, so there is no need to chastise me about it being bad design to have so much logic in the database). The thought of copy-pasting dozens of tedious procedural error handling code snippets was so distasteful to me that I decided to do a quick verigoogle. Verigoogling is my freshly coined word for challenging one of my assumptions through google. I was delighted to discover that this new Try/Catch syntax is available to the masses to be used in plain vanilla sprocs. Instead of checking the @@error variable after each statement, we can now be lazy..er..I mean concise and consolidate all the error handling code into the catch block like we’re used to doing in good ole’ OOP code.

For those of you like me who haven’t been taking advantage of this new feature yet, here is some sample code that demonstrates the how easy it is to use. As for the rest of you, please restrain yourself for making fun of me and go verigoogle one of your own assumptions.

BEGIN TRY

      BEGIN TRANSACTION

          DELETE FROM table1

          DELETE FROM table2

      COMMIT

END TRY

BEGIN CATCH

    IF @@TRANCOUNT > 0
           ROLLBACK

     DECLARE @ErrMsg nvarchar(4000), @ErrSeverity int
     SELECT @ErrMsg = ERROR_MESSAGE(),
     @ErrSeverity = ERROR_SEVERITY()

     RAISERROR(@ErrMsg, @ErrSeverity, 1)

END CATCH

 

Popularity: 6% [?]

Confessions of an Aero Addict

When given a choice between style and substance in software, I usually opt for what I consider to be substantive qualities such as speed, functionality, usability, and cost. Since I never saw a sentence about Vista without the phrase ”eye candy”, I casually dismissed Microsoft’s long-awaited OS release as fluff when it first came out and was in no hurry to jump aboard the upgrade band-wagon.

Well despite my valiant effort at indifference, I am ashamed to admit that I have finally succumbed to the narcotic affects of the Aero and was compelled to upgrade both my work and home PCs to Vista last week. After less than a week, I now experience acute withdrawal symptoms every time I sign back onto an XP machine and am deprived of my glass translucency goodness. I could talk enthusiastically about some my favorite non-visual features in Vista, such as the pervasive search box (ctrl + esc) that I now use in lieu of Google Desktop to quickly find content and launch programs, but who am I kidding? My name is Russell Ball and I am an eye-candy junkie.

For those of you who are weak like me and are considering an upgrade in the near future, here are a few things to keep in mind.

At the Office

  • If you’re going to take advantage of an MSDN license and upgrade your OS well ahead of the crowd, make sure you’re nice to the IT Pro group. I got their blessing ahead of time by offering to give them a scouting report of any issues they will likely encounter when trying to upgrade the entire department. 
  • When encountering an application error in Vista, try restarting the app using the right-click ‘Run as Admin’ option. Several rather cryptic errors have miraculously disappeared after re-opening the app under elevated priviledges.
  • Go paperless. The IT Pros in my shop are understandably reluctant to risk upgrading drivers on the print server just for me, so I am currently remoting in to the dev box to print documents until I can get someone to punch a whole in the dev domain firewall and let me connect directly to the printer. 
  • Expect to have to spend a little time applying a new service packs and installing new versions of applications. PowerShell requires a new version and Visual Studio and SQL Management Studio both require service pack upgrades before they will properly work on Vista. 
  • Expect a few apps to not work. I had to turn off a visual affect in order to get the UltraMon title bar butttons to show up and shut down the Track-It agents on my machine to stop getting bombarded with error messages. Transcender won’t work at all, so I’m having to remote into the development server to take practice tests for my upcoming certification exam. Considering that I probably have a hundred apps installed on my machine, that’s really not that bad.

At Home

  • If you have a machine that is more than a few years, just let it go. I had a P4 that worked fine for remoting into the office and web browsing, but it was easier to just spend the $800 at my local computer store for a basic machine than fuss with tracking down incompatible parts as part of the upgrade process. After a quick $150 upgrade for a new video card that supported dual monitors, I found myself with a Windows Experience Score of 4.8 (not bad) and enough RAM, disk space, and processing cycles to power a small third world country. 
  • When your wife sees the bill for the new PC, cast an “Aero Translucent Glass” spell on her. If she isn’t fully distracted, try the alt-tab spinning windows trick. If that doesn’t work, then try defending yourself with one of the countless left-over non-Vista compliant parts that will soon litter the tech landscape.

See you at the Vista half-way house. 

Popularity: 5% [?]

Using Powershell with SQL Server

Anything that can be done with ADO.NET is possible in PowerShell through a call to Assembly::Load and the New-Object cmdLet, but that doesn’t mean that the resulting code will seem very shell-like or practical. Two approaches to database access that definitely do seem compelling to me, however, are the sample SQL Provider recently demoed by the PowerShell team and Dan Sullivan’s PowerSMO script, which is really just a thin wrapper around the SQL Management Objects found in the Microsoft.SqlServer.Management.Smo namespace. The SQL Provider allows traditional command line navigation through the database using dir and cd and the SMO objects provide access to nearly any administrative function in SQL Server.

In order to use the PowerShell team’s SQL Provider, you’ll need to download SQLProvider.dll, install it in the GAC, and call the Add-PSSnapin cmdLet. Then you can treat the database just like the filesystem and cd or dir your way around with statements such as the following:


PS>cd SQL:

SQL:>cd MySQLServerName

SQL:>dir

master
tempdb
model
msdb
pubs
Northwind

SQL:>cd Northwind

SQL:>dir

name
—-
Categories
CustomerCustomerDemo
CustomerDemographics
.. etc…

SQL:>cd Employees

SQL:>Dir -filter {where EmployeeId=8}

EmployeeID      : 8
LastName        : Callahan
…etc…

Unfortunately, this provider is only a partially implemented sample and I quickly lost interest when I figured out that I couldn’t easily or naturally pipe the results to the where, select, and sort cmdLets. I did some quick searching to see if someone else had taken the next step and fully implemented a sql provider but I didn’t come across anything. However, I’m sure it won’t be long before somebody creates a production-ready version. The PS team did include the code for their sample provider, so perhaps I’ll take a look at it myself to see how hard it is.

To run the PowerSMO examples found on Dan Sullivan’s blog, you simply need to run a powershell script or place it in your profile so that it is run automatically when you start the shell. The script preloads some required dll’s and provides a factory function for retrieving some of the key objects, so retrieving a server object feels more like a cmdLet experience.

$server = get-SMO_Server mySQLServerName

However, since he warns that his script is for instructional purposes only, you might also just want to load the server object directly: 

[System.Reflection.Assembly]::Load(”Microsoft.SqlServer.Smo,Culture=Neutral,Version=9.0.242.0,PublicKeyToken=89845dcd8080cc91″) | out-null

$server = new-object “Microsoft.SqlServer.Management.Smo.Server” myServer

Then you can grab a database object and do interesting things like finding which tables and indexes in your database are taking up the most space.

$pubs = $s.databases | ?{$_.name -eq “pubs”}

$pubs.tables | ?{$_.name -notlike “sys*”} | select name, dataspaceused,indexspaceused,@{name=”Total Space”;expression={$_.dataspaceused + $_.indexspaceused}} | sort dataspaceused -desc

…or finding out the firve widest tables in the database as potential candidates for normalization and save it to an html file.

 $pubs.tables | ?{$_.name -notlike “sys*”} |select name, @{name=”Columns”;expression={$_.columns.count}} -first 5 | sort columns -desc | convertto-html > C:\wideTables.html

Again, you can do almost any of these functions through some other way (system sproc, sql function, utility), but what is significant is the capabilities that powerShell gives you to be able to manipulate the resulting data once you have it (sort, group, filter, format, etc.).

Popularity: 7% [?]

Disk Space Management with Powershell

The more I work with powershell, the more I start seeing everything that lives on the computer as part of a giant database that I can query. When used in conjunction with the pipeline and get-member -type property to discover the available properties on an object, the where-object, sort-object, select-object, and group-object cmdlets can be strung together to answer some very sophisticated questions. We often seem to run out of space on our development sql servers, so one tedious question that I am often forced to answer manually or with a utility such as windirstat is which sql backups are taking the most space so we can delete unused ones and free up space. This question can be answered easily and quickly in one line from powershell and then exported to text, csv, or html so that it can be sent to anyone else that needs to assist in the decision making process. In fact, with an extra line of code you could easily load up the .NET SMTPClient class in system.net.mail and email the output without leaving the command line. Here is the powershell one-liner that I used to find the largest 10 backups on a development server and save the output to a text file:

Dir \\devsql\sqlbackups *.bak -rec | sort length -desc | select name,directory, @{name=”Size in GB”;Expression={[System.Math]::Round($_.length/1073741824,1)}},CreationTime -first 10 | ft -auto > C:\LargeBackups.txt

This produces output that looks something like this:

Name                                      Directory                   Size-GB   CreationTime 
—-                                           ———                          ——–       ———— 
LendingHistory.bak              \\devsql\sqlbackups\Dev03       7.5     0/27/2006
Lending0702.bak                 \\devsql\sqlbackups\Dev01       6.2     06/29/2007
LendingPostEOD0628.bak   \\devsql\sqlbackups\Dev01       6.2     06/29/2007
LendingSOD0628.bak          \\devsql\sqlbackups\Dev01      6.1      06/12/2007
LendingSOD0627.bak          \\devsql\sqlbackups\Dev01      6.1      06/29/2007
Lending.bak                        \\devsql\sqlbackups\Dev02      6.1      11/27/2006
Investments.bak                  \\devsql\sqlbackups\Dev02      6.1      05/23/2007
InvestmentsHistory.bak        \\devsql\sqlbackups\Dev02     6 1       1/27/2006
Warehouse.bak                   \\devsql\sqlbackups\Dev01     5.9        04/25/2007
Lending.bak                        \\devsql\sqlbackups\Dev01     5.9        10/27/2006

Popularity: 7% [?]

Next Page »