# Friday, June 12, 2009

Never heard of ack? Well, by ack’s admission, it is “better than grep.” That’s up to you to decide, but it does make searching code easier than grep.

As a means of illustration, here is a grep example of a recursive search for StringBuilder across multiple C# files that I used back in my post on “finding stuff quickly.”

The output is pretty nice, but the addition of the find command to limit the searching to only C# files isn’t the easiest to type quickly.

ack makes this a little… well, a lot easier.

image

Nice! Even EASIER to read than the grep matching. And it is easier to type.

Well, of course, I had to add this functionality to Find-String. (Guess what, it runs faster than grep and ack both! At least on Windows…)

image

Now, this makes… the third post I’ve had on a Find-String PowerShell script I think. At some point, you’re going to get tired of this if you haven’t already.

“Is this guy seriously going to post every time he changes the way Find-String works?”

No, no, I guess I shouldn’t.

But for my own benefit, I do want this in source control. And I’d like to make it easier to use and find this. I’ve been using a local SVN repository for my changes to my scripts, but they included all of my scripts. Well, I moved just the Find-String source over to GitHub yesterday. I even started from the initial version of Find-String and committed my change history over from SVN :-)

image

For up to date versions of Find-String, they’ll be out there. The URL is http://github.com/drmohundro/Find-String/tree/master. If you don’t want to install git to check the source out, there is a big download button on the project page. It will package up the current version of Find-String for you which you can then download and use to your heart’s content.

If you improve upon the script, send me pull requests or a patch and I’d be happy to make it better.

 

Warning, upcoming tangent regarding GitHub adding PowerShell syntax support…

My other hope with posting this is that maybe GitHub will add the PowerShell syntax support to GitHub. If you view the source for Find-String on the GitHub website, you won’t see any syntax highlighting.

image

But… they have syntax highlighting for lots of other file types, as is evidenced by the gists I’ve already shared.

image

I already asked for this on the GitHub support site, but it was inexplicably closed with “no more actions from GitHub… are required” and that it is apparently “resolved.” Maybe I shouldn’t worry and the feature just hasn’t gone live yet. In which case, I’m just blabbing on and on for no reason and creating a long tangent to the rest of my post. If not, well, maybe they’ll add support if I complain some more!

posted on Friday, June 12, 2009 7:58:18 AM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Tuesday, May 19, 2009

I’ve been attempting to learn NHibernate lately. One of the big draws for me was the ability to write unit tests that did hit a database, but an in-memory one. Ayende recently posted on how to use SQLite to get in-memory unit tests. His example assumed standard hbm mappings and configuration.

I was curious how hard it would be port his example over to Fluent NHibernate. Not surprisingly, it was quite easy actually!

Here’s the Blog entity I used, which is based on the usage I saw from Ayende’s post:

And here is the mapping:

As you can see, it is pretty straight forward so far. The next piece of code is the Fluent NHibernate implementation of Ayende’s InMemoryDatabaseTest.

There aren’t too many differences really. We’re using the same SchemaExport, but we do need to call ExposeConfiguration so that we can store off a reference to the Configuration to be used by the SchemaExport instance.

The final piece, the actual test itself, is identical to Ayende’s example, except that I’m using MbUnit instead of xUnit:

Nice and easy! I like it!

As you can also tell, I’m experimenting with using github’s gist feature. I’ve been using github to store off my dot files and other environment-related settings as well as my presentations, but the gist feature seems pretty nice.

posted on Tuesday, May 19, 2009 12:34:06 PM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Tuesday, May 12, 2009

I blogged a while back about finding in files with PowerShell and I wanted to share an update on that.

The original post highlighted using a combination of Get-ChildItem and Select-String to quickly find things. It works fine, but the output isn’t the easiest to read, because the found text isn’t highlighted in any way.

Get-ChildItem –include *.cs –recurse | Select-String searchText

image

I really like the color output that grep provides. Check out the results of grep on the same search.

find –name *.cs | xargs grep StringBuilder

image

That is so much easier to read that it isn’t even funny. The match jumps out at you because of the color difference.

I did some searching and found Wes Haggard’s Find-String script. It had the additional benefit that it also displayed the line number, but it didn’t display the relative path.

find-string.ps1 StringBuilder *.cs -recurse

image

Wes’ script still served my purposes, though, so I used it for a long time until I learned about grep’s Context Line Control arguments. They would let grep print out additional lines before or after the display search result so that you could see the context of your search result. Like so:

find –name *.cs | xargs grep StringBuilder –A 3

image

Unfortunately for me, PowerShell’s Select-String didn’t support context… at least until version 2.

With the addition of the Context parameter, I could now build a nice grep replacement in PowerShell. I broke my version out into two separate scripts: one to actually format the MatchInfo object and one to do the finding. As you might imagine, the formatting script is a little more interesting. You can get Out-ColorMatchInfo at http://poshcode.org/1095 and you can get my version of Find-String at http://poshcode.org/1096.

Here’s sample output:

find-string StringBuilder *.cs –context 0,3

image 

I went with only displaying the relative path to the file on one line and then displaying the results on the following lines. It makes reading context easier for me.

Let me know what you think.

posted on Tuesday, May 12, 2009 2:55:25 PM (Central Daylight Time, UTC-05:00)  #    Comments [3]
# Friday, April 24, 2009

If you’ll be in the northwest Arkansas area tomorrow (April 25), be sure to come out for the NWA Code Camp. There will be presentations on everything ranging from LINQ and Silverlight to iPhone development. I’ll be presenting my PowerShell talk one more time as well. If I can count at all, it looks like there will be 15 different speakers total.

I’m looking forward to it!

image 

Technorati Tags:
posted on Friday, April 24, 2009 7:28:37 AM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Monday, March 30, 2009

This is just a quick post to share a very simple PowerShell script I wrote to extract files from a compressed file (zip, 7z, whatever). When downloading utilities that don’t have installers, like Sysinternals tools, I typically extract them to a Utils directory that is in my PATH. Previously, I would always do this by right-clicking, choosing the 7-Zip context menu option and then extracting to to c:\Utils. Another common option would be to extract to a folder of the same name.

image

I had tried in the past to use the 7-Zip command line tool, but the arguments were not very intuitive or consistent with other command line tools (Windows, Unix, PowerShell or otherwise). So, I got fed up and wrote a script to do it for me. It just shells out to the 7-Zip command line app, but it saves me some time.

The script assumes that you’ve aliased ‘zip’ to the 7z.exe command line executable.

[1] » ls alias:zip

CommandType     Name                                                  Definition
-----------     ----                                                  ----------
Alias           zip                                                   7z

[2] » get-command 7z

CommandType     Name                                                  Definition
-----------     ----                                                  ----------
Application     7z.exe                                                C:\Utils\7z.exe

Here’s the script:

param (
    [string]$file,
    [string]$outputDir = ''
)

if (-not (Test-Path $file)) {
    $file = Resolve-Path $file
}

if ($outputDir -eq '') {
    $outputDir = [System.IO.Path]::GetFileNameWithoutExtension($file)
}

zip e "-o$outputDir" $file

Like I said, pretty basic. If you don’t specify an output directory, it uses the name of the file.

Other people have written scripts that do this, too, but I needed an excuse to publish something on my blog for March :-)

posted on Monday, March 30, 2009 9:55:29 PM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Wednesday, February 25, 2009

I couldn’t resist borrowing my title from Christopher Bennage’s post entitled “An Essential Tip for Working with XAML.” My “essential tip” is identical to what he has already shown for WPF (and Fabrice originally) – it just applies to Windows Forms instead of WPF :-)

I’ll mix it up some and show with pictures instead of text, though.

Step 1. Right click on a Form, UserControl, or Component and select “Open With…”

image

Step 2. Select “CSharp Editor” and click “Set as Default” - (note that this setting only applies to C# code, though you can perform the identical setup for VB.NET as well)

image

Step 3. Enjoy your delicious, hot meal of faster Visual Studio!

In case you missed it, the real benefit that you get from this setting is that double clicking a file in the Solution Explorer will now go directly to the code instead of defaulting to the designer view. If you want to get to the designer view, just right click and select “View Designer.”

Thanks again to Christopher and Fabrice who did the real work here!

posted on Wednesday, February 25, 2009 10:32:12 AM (Central Standard Time, UTC-06:00)  #    Comments [0]
# Monday, February 23, 2009

WiX Setup

I’ve been doing some work with MSIs lately, specifically using the WiX toolkit, so I thought I’d share a short primer on using WiX to build your own MSIs, and also to share some links and some tricks to avoid some pitfalls that I ran into.

First off, WiX stands for Windows Installer XML and, from what I understand, is the first Microsoft-supported open source project. Not only that, but it is the way that Microsoft builds their MSIs, too, so it is pretty significant.

To get started, I wouldn’t even bother with the release version of 2.0. The real fun is in version 3.0, which, even though it is in beta, is plenty stable (IMHO) and supports Visual Studio with a project template and intellisense support via schema files. It also makes the building step a lot easier.

image

My First WiX Project

Once you start your project, you’re presented with a WXS file pre-filled with a few initial options that looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
    <Product Id="de9157d6-2fbf-4c16-9d28-77f790788b28" Name="WixProject1" Language="1033" Version="1.0.0.0" Manufacturer="WixProject1" UpgradeCode="f5614cd8-aa70-4bc4-948b-208b34e16a6d">
        <Package InstallerVersion="200" Compressed="yes" />

        <Media Id="1" Cabinet="media1.cab" EmbedCab="yes" />

        <Directory Id="TARGETDIR" Name="SourceDir">
            <Directory Id="ProgramFilesFolder">
                <Directory Id="INSTALLLOCATION" Name="WixProject1">
                    <!-- TODO: Remove the comments around this Component element and the ComponentRef below in order to add resources to this installer. -->
                    <!-- <Component Id="ProductComponent" Guid="95758d74-281c-4eee-84ce-4fda6ad60557"> -->
                        <!-- TODO: Insert files, registry keys, and other resources here. -->
                    <!-- </Component> -->
                </Directory>
            </Directory>
        </Directory>

        <Feature Id="ProductFeature" Title="WixProject1" Level="1">
            <!-- TODO: Remove the comments around this ComponentRef element and the Component above in order to add resources to this installer. -->
            <!-- <ComponentRef Id="ProductComponent" /> -->
        </Feature>
    </Product>
</Wix>

It has most of the things that you’ll be interested in.

The Product element is likely the most important element as it defines the application that your MSI will install. You’ll notice that WiX is built around a lot of Guids. MSIs, or Windows Installer actually, is built around tables. Using the orca tool that ships with the Windows SDK, you can actually see these tables for any MSI. (FYI, you’ll find your Product Id Guid if you look under \\HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\ after installation.)

image

You Can Refactor WiX, Too

Before going further with your WiX file, I would strongly recommend refactoring some of the Guids and common strings out into variables like so:

<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
  <?define ProductName = "WixProject1"?>
  <?define ProductCode = "de9157d6-2fbf-4c16-9d28-77f790788b28"?>
  <?define UpgradeCode = "f5614cd8-aa70-4bc4-948b-208b34e16a6d"?>
  <?define ProductVersion = "1.0.0.0"?>
  
  <Product Id="$(var.ProductCode)"
           Name="$(var.ProductName)"
           Language="1033"
           Version="$(var.ProductVersion)"
           Manufacturer="WixProject1"
           UpgradeCode="$(var.UpgradeCode)">

Doing this can help you greatly later when you’re trying to figure out which Guid goes where or what the Guid is actually for. The rest of the process of building your WiX file involves mapping out your dependencies. The project template by default already creates Directory elements pointing to the ProgramFilesFolder constant (see http://msdn.microsoft.com/en-us/library/aa370905(VS.85).aspx#system_folder_properties for the other system folder constants). The Component tag resolves to what I think of as a separate installable component. Components go together to form a Feature (think Complete versus Custom installs) so you’ll refer to your Component (by Id) in the Feature element using a ComponentRef element. The template has this commented out, but it shows how this would work. I’ll defer to the WiX Tutorial for specific examples here.

To build your MSI, you just have to do a Visual Studio build because you followed my instructions and installed beta 3.0, which comes with Visual Studio integration! Behind the scenes, though, all the build does is call out to candle.exe passing in your WXS file which results in a wixobj file. Then it calls out to light.exe passing in the wixobj file which results in an MSI. (WiX is pronounced like “wicks” – that should help you get the candle and light jokes… WiX also includes tools like dark, torch, votive, smoke, melt… :-))

Upgrading!

Up to this point, I didn’t really run into any problems with building my MSI. The online resources were fairly good at getting me started. What I wanted was for my MSI to be able to remove existing versions of my software before installing its version. MSIs support three types of upgrades: small update, minor upgrade, and major upgrades. I’d recommend skipping directly to major upgrade. From what I’ve seen so far, the other two options require additional command line arguments to msiexec to actually perform the removal of a prior install of your product.

To get a major upgrade to work, the most important thing you’ll need is your UpgradeCode. This is an attribute off of your Product element tag. Always store that off, regardless of whether or not you plan on allowing upgrades. As soon as you decide you don’t need to upgrade, you’ll want to upgrade. If you don’t have an UpgradeCode, you can’t upgrade.

You’ll use your UpgradeCode in an Upgrade tag like so:

<Upgrade Id='$(var.UpgradeCode)'>
  <UpgradeVersion Minimum='$(var.ProductVersion)'
                  IncludeMinimum='no'
                  OnlyDetect='yes'
                  Property='NEWPRODUCTFOUND' />
  <UpgradeVersion Minimum='$(var.RTMProductVersion)'
                  IncludeMinimum='yes'
                  Maximum='$(var.ProductVersion)'
                  IncludeMaximum='no'
                  Property='UPGRADEFOUND' />
</Upgrade>

Notice how I’m using my predefined variables. Makes it easier, eh? I’ve also added an additional variable defined as RTMProductVersion. This is the version of my installed application that I am upgrading from. UpgradeVersion tags work like ranges. So, for the UPGRADEFOUND to match, the installed application has to match inclusive RTMProductVersion (inclusive because of IncludeMinimum=’yes’) up to exclusive ProductVersion, which is the new version we’re about to install.

Now, changing the version isn’t enough for a major upgrade to work. You also need to change your ProductCode. This is what I continued to miss and why I was getting so frustrated with WiX. Now that I know what it should do (and what to search for), I’m finding plenty of WiX articles on how to do major upgrades! The reasoning for this is because major upgrades only work between two completely different products (think of Visual Studio 2005 and Visual Studio 2008 as having two different ProductCodes). These two products can run side-by-side, hence the different Guids for their product code. These applications allow side-by-side execution so they’re not specifying the removal of the old software, but they certainly could. MSDN has a good article on everything that you’ll need to check before getting an MSI ready for a major upgrade.

Once you have a new version and a new product code, you’ll need to actually tell the MSI to remove the existing version. To do this, you’ll add a RemoveExistingProducts element to an InstallExecuteSequence. Like this:

<InstallExecuteSequence>
  <Custom Action='PreventDowngrading'
          After='FindRelatedProducts'>NEWPRODUCTFOUND</Custom>
  <RemoveExistingProducts After='InstallFinalize' />
</InstallExecuteSequence>

<InstallUISequence>
  <Custom Action='PreventDowngrading'
          After='FindRelatedProducts'>NEWPRODUCTFOUND</Custom>
</InstallUISequence>

<CustomAction Id='PreventDowngrading'
              Error='Newer version already installed' />

In my example, I’ve told RemoveExistingProducts to run after the ‘InstallFinalize’ action, but this is customizable and can have an impact on the efficiency of your installer.

Once I set my WiX project up like this, it worked like a charm.

There are two resources that are essential for getting up to speed with WiX that I’d like to share. One is the WiX Tutorial. I’m probably using about a 10th of the content posted there. Second is Alex Shevchuk’s “From MSI to WiX” articles, particularly his post on major upgrades, which was invaluable to me.

posted on Monday, February 23, 2009 1:38:15 PM (Central Standard Time, UTC-06:00)  #    Comments [1]
# Monday, January 26, 2009

If you’ve been writing .NET applications for a while, you’re likely aware that you’re not supposed to just throw Exception. Instead, if you’re dealing with a null argument, you should be throwing an ArgumentNullException instead. FxCop warns against cases like this.

My problem isn’t knowing to not throw Exception. My problem is finding the appropriate exception to throw.

Just about every time I need to throw an exception in code, I type something like throw new… then wait for intellisense, and then inevitably try to type something like *Exception. Which fails of course. Then I do a google search for common exception types and will come across a post like Brad Abram’s Common Exception Types. Which is somewhat useful, except that his list only contains Exception names including Exceptions like the InvalidProgramException, which has a description of “the exception that is thrown when a program contains invalid MSIL.” Most likely not what I need :-) Jeff Atwood has an older post about a console application he wrote to write out Exception types from assemblies, but once again, it doesn’t provide the description I needed to help make my decision, too.

So, I decided to solve this problem myself.

I liked Jeff’s approach because it was lightweight and could be piped to programs like findstr so that I could look for certain types of exceptions. I essentially wanted what he had, but I wanted summary information as well. I ended up solving the problem with PowerShell. First, check out the output:

[3] » Get-Exception Null | Format-List

Name    : System.ArgumentNullException
Summary : The exception that is thrown when a null reference (Nothing in Visual Basic) is passed to a method that does not
          accept it as a valid argument.

Name    : System.NullReferenceException
Summary : The exception that is thrown when there is an attempt to dereference a null object reference.

Name    : System.Management.Automation.PSArgumentNullException
Summary : No summary found.

Name    : System.Data.NoNullAllowedException
Summary : No summary found.

Name    : System.Data.SqlTypes.SqlNullValueException
Summary : No summary found.

As you can see, my script is called Get-Exception and it can handle searches. The results can be passed to the various formatting cmdlets like Format-List. You can also pipe the results to Select-String for further searching if you wish or just pipe it to a Where statement.

The script itself is fairly simple. The pulling of exception types is based entirely off of the following statement:

$exceptions = [System.AppDomain]::CurrentDomain.GetAssemblies() | foreach {   
    $_.GetTypes() | where { $_.FullName -match "System$filter.*Exception$" }  
}

To pull the summary documentation, I’m using the returned type’s Assembly.Location property and checking for an XML file with the same name at the same location. This usually equates to an XML file in C:\windows\microsoft.net\framework\v2.0.50727. Then I use an XPath expression against it.

I’ve posted the script out on the PowerShell Code Repository at http://poshcode.org/827 if you’re interested in downloading it and trying it out. There are a lot of other great scripts there as well.

posted on Monday, January 26, 2009 7:47:21 AM (Central Standard Time, UTC-06:00)  #    Comments [3]
# Monday, January 12, 2009

Tonight, the FSDNUG group participated in their first launch event ever – for SQL Server 2008! Woo!

The gist of it was that 4 of us took about 15 to 20 minutes to talk about different portions of SQL Server. It turned out to be more intro than deep dives, but I think the group got more out of the presentation this way.

My portion of the presentation was on SQL CLR.

I think my talk went alright, but my demo definitely didn’t work. I blamed the Windows 7 beta but it probably had more to do with my lack of knowledge. *shrug* If you’re interested in trying the example out for yourself, Bashar Kokash has a good post on it. The example worked fine on my machine without any problems the first time, but during the talk, the Visual Studio deployment apparently didn’t work. Oh well.

The other code examples that I had all are linked off of the MSDN overview of SQL CLR link from above, so knock yourself out. Keith Elder’s post on creating custom SQL CLR user-defined types is also a good start.

The final two links I used were this one from SQL Skills and this one… that provided most of my information :-) Thanks Google!

I enjoyed the chance to present again! If you have any feedback, feel free to let me know.

posted on Monday, January 12, 2009 10:09:06 PM (Central Standard Time, UTC-06:00)  #    Comments [0]
# Thursday, January 01, 2009

So, a year ago to the day, I posted my review of 2007 with a look towards 2008. To continue that age old tradition, I will now review 2008.

Learning

I started off the month by stating that I wanted to learn some new languages, primarily Python and Ruby. I’m sad to say that I haven’t made it past the 5th python challenge yet. I pretty much got distracted, which is a lame excuse. On the other hand, instead of learning languages, I’ve learned a ton about editing in VIM and even a little about Emacs (though I have to use viper or vimpulse to be at all productive in Emacs). I’m even using ViEmu in Visual Studio. The Vim key-bindings have become muscle memory now and I consider that a positive thing. I’m still going to try to learn other languages this year, but I’m going to need a project to work on before I can become proficient.

FSDNUG

This year, a very exciting thing for me was the formation of FSDNUG. Michael Paladino pretty much did all of the work, but he lets me call myself a co-leader. Raymond Lewallen opened up the FSDNUG meetings by speaking about Behavior Driven Development. I didn’t really grok BDD at that point, but I’m learning. I most definitely prefer the context/specification style of naming specs over traditional TDD test names.

Conferences

I was fortunate enough to attend both Tech Ed and DevLink this year. I even told people at DevLink that I’d be attending CodeMash, but I sadly won’t be able to make it after all. I have no doubts that it will be an amazing conference, though, and wish I could be there.

Presentations

I presented on PowerShell three times in 2008. Once to FSDNUG, once to MNUG and then once to Harding University CS students. My presentations pretty much took up all of September. It was a great experience and I’m looking forward to speaking to the Shreveport .NET User Group in March!

Posts

My post on “real world debugging witn WinDbg” post was featured on the Tech Ed bloggers site, which led to me being selected as a “featured Tech Ed blogger” for a day. I was also excited to have my PowerShell thumbnail script mentioned on the PowerScripting Podcast.

In closing…

All in all, a really great year. I noted in 2007, that it had been the year of the most growth for me as a developer. That was true… at least until 2008. My opinion right now is that there is no such thing as a good developer, only a better developer. This saying comes from a discussion I had with a coworker a few months back where we came to the conclusion that there isn’t such a thing as a good design or architecture, only a better design or architecture – all because we’ll inevitably have learned a better way to do things in the future.

I hope everyone has a great 2009!

posted on Thursday, January 01, 2009 2:13:41 PM (Central Standard Time, UTC-06:00)  #    Comments [1]