# Friday, February 05, 2010

I’m sure I’m the only person in the world who ever wants to know what the command line arguments for running processes is, but in the remote chance that someone else out there might need this some day, here you go.

We’ve got a few programs at work that do a lot of interprocess communication (IPC). They initialize the IPC communication in a variety of different ways, but one way is by command line arguments that were passed to them. From a debugging standpoint, it is very useful to be able to determine what the command line arguments were that were passed to the process.

The easiest way to get this information is with Process Explorer. You can either right click the process and select its properties, or you can add a custom column with the command line. What you’ll get is something like this:

image

You can see that I passed “haha.txt” into GVim.

Sometimes, though, I want that information faster. Why not from Powershell? The System.Diagnostics.Process object doesn’t provide any means (that I’m aware of) to retrieve the command line arguments from an already running process. Yes, there is the StartInfo.Arguments property, but it is only there for letting you pass arguments to a process that you’re going to start. It doesn’t populate that information from a running process.

You can get it from WMI, though, using a command like this:

Get-WmiObject win32_process -Filter "name like '%vim.exe'"

You can grab the command line from it by doing this:

Get-WmiObject win32_process -Filter "name like '%vim.exe'" | select commandline

So yeah, that works. It sure isn’t quite as easy as typing this, though:

ps *vim | select commandline

Sure wish I could do that. Sure glad that I can! Powershell has the ability for you to tack on your properties. It isn’t quite monkey patching like in Ruby, but it’s close. Here’s how to do it.

You’ll first need a ps1xml file to contain this information. I put mine in ~/Documents/WindowsPowerShell/TypeData/System.Diagnostics.Process.ps1xml. It will look like this:

<?xml version="1.0"?>
<Types>
    <Type> 
        <Name>System.Diagnostics.Process</Name> 
        <Members> 
            <ScriptProperty> 
                <Name>CommandLine</Name> 
                <GetScriptBlock> 
                    $id = $this.Id
                    $result = Get-WmiObject win32_process -Filter "ProcessId = $id"
                    $result.CommandLine
                </GetScriptBlock> 
            </ScriptProperty> 
        </Members> 
    </Type>
</Types>

What this does is tell Powershell that, for every System.Diagnostics.Process instance it sees, add a new ScriptProperty to it with the name CommandLine. The GetScriptBlock section defines how to actually retrieve the value for the new property. In there, you just put Powershell code. So, I’m doing almost the same WMI query as before except that I’m searching by ID instead. It’s faster that way.

To inform Powershell about this, just run this:

Update-TypeData ~/Documents/WindowsPowerShell/TypeData/System.Diagnostics.Process.ps1xml

You’ll probably want to put that in your profile so that it runs every time you start Powershell. Here’s a screenshot of it in action:

image

posted on Friday, February 05, 2010 1:17:28 PM (Central Standard Time, UTC-06:00)  #    Comments [0]
# Sunday, July 12, 2009

If you seriously still haven’t heard or used PowerShell yet, come to my Little Rock DNUG presentation on the topic on Monday, July 13. Or, if you’re busy Monday night because you’re going to hear Keith Elder speak on Velocity to the Fort Smith DNUG, then come Tuesday night to hear me give my PowerShell presentation to the Conway DNUG instead!

I’ve never given a talk two days in a row, so this will be a new experience for me. If you’re interested in the content, I’m trying to keep my presentation notes and related files up on one of my github projects. I’m finding that the whole distributed source control works well for me for accessing and working on my presentation from all different areas and computers.

If you’re at the meeting, stop by and say hi!

posted on Sunday, July 12, 2009 2:28:28 PM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# 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 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]
# 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]
# 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]
# Wednesday, December 31, 2008

Last week, the PowerShell team released PowerShell v2 CTP3. And, of course, there was much rejoicing. I’ve got quite a bit I’d like to blog about regarding PowerShell, but I couldn’t wait to share one feature I love.

PowerShell ISE Themes.

Okay, so, it doesn’t actually ship with themes. But you can create them. Let me provide some background. The “ISE” in PowerShell ISE stands for Integrated Scripting Environment and is based on the upcoming WPF editor that will ship with Visual Studio 2010. Here is a screenshot of it.

image

As you can see, there are three panes included: one that allows you to edit PS1 scripts (with syntax highlighting and tab completion included), one that displays the output of your commands (whether from the script editor or the command pane), and one that allows you to type in commands (the equivalent of the prompt you get in the console host).

I’ll admit, when I heard about the graphical host, I thought it was nice but I really didn’t think I’d use it much. I use gVim to edit my scripts and have the console up all day. Why did I need another editor? I didn’t get really excited until I saw all of the customizations that you can do with it.

The $psISE variable offers up a wealth of options. I’m particularly fond of the Options property off of $psISE. I’ll let the screenshot describe why:

image

Looks different, eh? Below is the code to get it to work:

# PowerShell ISE version of the VIM blackboard theme at 
# http://www.vim.org/scripts/script.php?script_id=2280

# fonts
$psISE.Options.FontName = 'DejaVu Sans Mono'
$psISE.Options.FontSize = 16

# output pane
$psISE.Options.OutputPaneBackground = '#FF000000'
$psISE.Options.OutputPaneTextBackground = '#FF000000'
$psISE.Options.OutputPaneForeground = '#FFFFFFFF'

# command pane
$psISE.Options.CommandPaneBackground = '#FF000000'

# script pane
$psISE.Options.ScriptPaneBackground = '#FF000000'

# tokens
$psISE.Options.TokenColors['Command'] = '#FFFFFF60'
$psISE.Options.TokenColors['Unknown'] = '#FFFFFFFF'
$psISE.Options.TokenColors['Member'] = '#FFFFFFFF'
$psISE.Options.TokenColors['Position'] = '#FFFFFFFF'
$psISE.Options.TokenColors['GroupEnd'] = '#FFFFFFFF'
$psISE.Options.TokenColors['GroupStart'] = '#FFFFFFFF'
$psISE.Options.TokenColors['LineContinuation'] = '#FFFFFFFF'
$psISE.Options.TokenColors['NewLine'] = '#FFFFFFFF'
$psISE.Options.TokenColors['StatementSeparator'] = '#FFFFFFFF'
$psISE.Options.TokenColors['Comment'] = '#FFAEAEAE'
$psISE.Options.TokenColors['String'] = '#FF00D42D'
$psISE.Options.TokenColors['Keyword'] = '#FFFFDE00'
$psISE.Options.TokenColors['Attribute'] = '#FF84A7C1'
$psISE.Options.TokenColors['Type'] = '#FF84A7C1'
$psISE.Options.TokenColors['Variable'] = '#FF00D42D'
$psISE.Options.TokenColors['CommandParameter'] = '#FFFFDE00'
$psISE.Options.TokenColors['CommandArgument'] = '#FFFFFFFF'
$psISE.Options.TokenColors['Number'] = '#FF98FE1E'

To use it, I just dot the script into my PowerShell ISE profile (see the $profile variable while in PowerShell ISE) like so (where ./Themes/blackboard.ps1 is the path to the blackboard theme):

. ./Themes/blackboard.ps1

The script is a conversion I did of the vim blackboard theme which itself is a clone of the blackboard theme from TextMate. I’m sure it could use some tweaking, but it works for me for now.

One thing I’m missing so far is how to change the color of the text caret. Because I have a black background, I can’t see where I’ve got focus in the editor! Hopefully the PowerShell team will add an additional property to the Options to change the caret color or, even better, hopefully I’ve just missed the setting :-)

Let me know what you think! I’ve got even more PowerShell profile posts I’m working on so stay tuned.

UPDATE: Based on Joel’s comment, I’ve posted a bug on the Microsoft Connect site for PowerShell. Go vote for it at https://connect.microsoft.com/feedback/ViewFeedback.aspx?FeedbackID=390304&SiteID=99. Note that you can only access the site if you’ve signed up on Microsoft Connect and added PowerShell as a project.

posted on Wednesday, December 31, 2008 9:17:11 AM (Central Standard Time, UTC-06:00)  #    Comments [5]
# Saturday, October 11, 2008

I was working with a lot of images for a website today and I needed to quickly create thumbnails for each one. I did a quick Google search on PowerShell and creating thumbnails, but I gave up after about a minute… yeah, I probably got impatient, but oh well.

Anyway, here it is:

get-childitem *.jpg | foreach {
    $full = [System.Drawing.Image]::FromFile("$(resolve-path $_)");
    $thumb = $full.GetThumbnailImage(72, 72, $null, [intptr]::Zero);
    $thumb.Save("$(resolve-path $_).thumb.jpg" );
    $full.Dispose();
    $thumb.Dispose();
}

Obviously, you likely wouldn’t hardcode the height and width for the thumbnail, but would probably base it off of the original image (i.e. varying it off of whether the image was wide or tall). But, I didn’t need to. That’s up to you to figure out :-)

posted on Saturday, October 11, 2008 5:21:14 PM (Central Daylight Time, UTC-05:00)  #    Comments [4]
# Tuesday, September 30, 2008

I promised the slides, notes and links from my Memphis .NET User Group talk, so here they are… and wow, they haven’t really changed much from when I gave the PowerShell talk to the FSDNUG group. So, I’ll just link to the zip of the presentation from that talk.

The primary slide that I added to my presentation was entirely related to a StackOverflow question entitled, “how do you use PowerShell.”

I felt that the talk went fairly well, but I did have to rush towards the end because I added an overview of some real scripts that I use, but I didn’t remove enough of my prior content… thus, the rush. :-)  No big deal, though. I did get the feeling that there were a few people who didn’t really feel that PowerShell applied to them, but hey, that’s fine. At least there weren’t any tomatoes!

I’ll be presenting one more time (as far as I know) this year at Harding University. I’m looking forward to it, too. I’ll be presenting for the Computing Seminar on October 9. The last time I spoke before Seminar was in 2003 when I talked about “Smart Client Software.” That was when it was for college credit! I’m planning on changing the talk up a little to direct it more towards CS students instead of professional developers. I imagine it will be a slightly different audience than the typical .NET User Group, too. We’ll see.

Back on the MNUG talk, thanks to Randy for driving and thanks to Colin for inviting me to speak. It was fun!

posted on Tuesday, September 30, 2008 8:13:41 AM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Wednesday, September 24, 2008

Colin is risking it I say. How is he risking it you might ask? By asking me to speak to the Memphis .NET User Group!

I think he’s crazy, but whatever.

Randy Walker and I will be traveling to Memphis, TN tomorrow night where I’ll be presenting on PowerShell. Randy is coming out to meet with the founding members of the Northeast Arkansas .NET User Group, which is very cool. Regarding my presentation, it will likely be a similar presentation to what I gave to the FSDNUG group, but I’m hoping to have more script examples. I think I gave the Fort Smith group a good picture of PowerShell, but I don’t think I showed them nearly as many practical uses of PowerShell as I would have liked. I’ve got a folder of scripts now, some that I’ve written for myself and a few that we’re using at work, that I’ll be showing and walking through during the presentation.

If you’re in the area, come on out!

posted on Wednesday, September 24, 2008 1:42:45 PM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Wednesday, May 07, 2008

A coworker swung by a few days ago to ask some questions about using Reflection. I learn really well by example so I decided to use Powershell to show using Reflection. Below is the session I used and later emailed to him. You can see a few spots at the bottom of the example where I was unsure of the syntax on passing an empty parameter array, but I figured it out.

This is a good example of why I like Powershell :-)

  1 [1] » "haha".gettype()
  2
  3 IsPublic IsSerial Name                                     BaseType
  4 -------- -------- ----                                     --------
  5 True     True     String                                   System.Object
  6
  7
  8 [2] » $temp = "haha".gettype()
  9 [3] » $temp.GetProperties()
10
11
12 MemberType    : Property
13 Name          : Chars
14 DeclaringType : System.String
15 ReflectedType : System.String
16 MetadataToken : 385875994
17 Module        : CommonLanguageRuntimeLibrary
18 PropertyType  : System.Char
19 Attributes    : None
20 CanRead       : True
21 CanWrite      : False
22 IsSpecialName : False
23
24 MemberType    : Property
25 Name          : Length
26 DeclaringType : System.String
27 ReflectedType : System.String
28 MetadataToken : 385875995
29 Module        : CommonLanguageRuntimeLibrary
30 PropertyType  : System.Int32
31 Attributes    : None
32 CanRead       : True
33 CanWrite      : False
34 IsSpecialName : False
35
36
37
38 [4] » $temp.GetProperties()[0]
39
40
41 MemberType    : Property
42 Name          : Chars
43 DeclaringType : System.String
44 ReflectedType : System.String
45 MetadataToken : 385875994
46 Module        : CommonLanguageRuntimeLibrary
47 PropertyType  : System.Char
48 Attributes    : None
49 CanRead       : True
50 CanWrite      : False
51 IsSpecialName : False
52
53
54
55 [5] » $temp.GetProperties()[0].name
56 Chars
57 [6] » $temp.GetProperties()[1].name
58 Length
59 [7] » $temp.GetProperties()[1].GetGetMethod()
60
61
62 Name                       : get_Length
63 DeclaringType              : System.String
64 ReflectedType              : System.String
65 MemberType                 : Method
66 MetadataToken              : 100663629
67 Module                     : CommonLanguageRuntimeLibrary
68 MethodHandle               : System.RuntimeMethodHandle
69 Attributes                 : PrivateScope, Public, HideBySig, SpecialName
70 CallingConvention          : Standard, HasThis
71 ReturnType                 : System.Int32
72 ReturnTypeCustomAttributes : Int32
73 ReturnParameter            : Int32
74 IsGenericMethod            : False
75 IsGenericMethodDefinition  : False
76 ContainsGenericParameters  : False
77 IsPublic                   : True
78 IsPrivate                  : False
79 IsFamily                   : False
80 IsAssembly                 : False
81 IsFamilyAndAssembly        : False
82 IsFamilyOrAssembly         : False
83 IsStatic                   : False
84 IsFinal                    : False
85 IsVirtual                  : False
86 IsHideBySig                : True
87 IsAbstract                 : False
88 IsSpecialName              : True
89 IsConstructor              : False
90
91
92
93 [8] » $temp.GetProperties()[1].GetGetMethod().Invoke
94
95
96 MemberType          : Method
97 OverloadDefinitions : {System.Object Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo cu
98                       lture), System.Object Invoke(Object obj, Object[] parameters)}
99 TypeNameOfValue     : System.Management.Automation.PSMethod
100 Value               : System.Object Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo cul
101                       ture), System.Object Invoke(Object obj, Object[] parameters)
102 Name                : Invoke
103 IsInstance          : True
104
105
106
107 [9] » $temp.GetProperties()[1].GetGetMethod().Invoke("hello world", [])
108 Unable to find type []: make sure that the assembly containing this type is loaded.
109 At line:1 char:65
110 + $temp.GetProperties()[1].GetGetMethod().Invoke("hello world", []) <<<<
111 [10] » $temp.GetProperties()[1].GetGetMethod().Invoke("hello world")
112 Cannot find an overload for "Invoke" and the argument count: "1".
113 At line:1 char:47
114 + $temp.GetProperties()[1].GetGetMethod().Invoke( <<<< "hello world")
115 [11] » $temp.GetProperties()[1].GetGetMethod().Invoke("hello world", {})
116 Exception calling "Invoke" with "2" argument(s): "Parameter count mismatch."
117 At line:1 char:47
118 + $temp.GetProperties()[1].GetGetMethod().Invoke( <<<< "hello world", {})
119 [12] » $temp.GetProperties()[1].GetGetMethod().Invoke("hello world", $Null)
120 11
121 [13] »
122

Note - I used the :toHTML command from Vim along with Peter Provost's Powershell syntax file to get the color. Powershell doesn't support color at the console like this yet without explicitly passing color arguments to Write-Host.

posted on Wednesday, May 07, 2008 8:51:00 AM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Thursday, April 24, 2008

Here is a simple script I wrote which was inspired by this post on terminal color highlighting and by ColorDiff that does essentially the same thing.

# Out-ColorDiff.ps1
Process {
    if ($_) {
        foreach ($line in $_) {
            if ($line -match '^[<|-]') {
                Write-Host -ForegroundColor red $line
            }
            elseif ($line -match '^[>|+]') {
                Write-Host -ForegroundColor green $line
            }
            else {
                Write-Host $line
            }
        }
    }
}

Here is a screenshot of sample output from the script:

image

You can use it by piping the diff output to the script, like 'svn diff somefile | out-colordiff' or if you're stuck using something like MKS, you can use 'si diff somefile | out-colordiff'.

Possible (and easy) additions would be to add direct parsing of a file instead of taking an argument off of the pipeline. This is all I need currently, but if you wish to add more features, feel free to leave them in the comments.

posted on Thursday, April 24, 2008 10:55:44 AM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Tuesday, November 06, 2007

image

I didn't expect to see this in the next version of PowerShell - very cool. It definitely still needs some work, but I like the start. The syntax highlighting for opened script files is nice. I'd like to see some intellisense in there, but it isn't a big deal. If intellisense would slow it down much, I think I'd rather not have it anyway. I think the biggest issues I've got with it so far is the lack of options to customize fonts and colors as well as tab expansion.

I've haven't had a chance to play with anything else, but it seems nice so far.

posted on Tuesday, November 06, 2007 8:40:44 AM (Central Standard Time, UTC-06:00)  #    Comments [0]
# Friday, November 02, 2007

I'm finding myself wondering if I'm a beta junkie or a CTP junkie.

Why?

Because Jeffrey Snover announced that there will be a CTP release of PowerShell 2.0 next week. I'm not waiting for the beta either - I'm downloading the CTP bits as soon as the post announcing its release gets to Google Reader. Maybe I should change my "beta junkie" title to "pre-release junkie" or "I just like to install things junkie."*

PowerShell 1.0 single handedly turned me into a console user. I do 90+% of my file operations from PowerShell instead of Windows Explorer. I also do a large portion of my pseudo coding at the command prompt to see whether a basic algorithm will work the way I expect it to. I'm very excited to see what the team has come up with.

Update (per post from Jeffrey Snover):

The PowerShell V2 CTP is not for everyone. You should read this PowerShell Team blog entry ( http://blogs.msdn.com/powershell/archive/2007/11/02/ctp-watch-this-space.aspx ) to find out what it is and what it isn't and then make an informed decision before installing the CTP.

I may be an "I just like to install things junkie" but that doesn't mean that you should be to. Be responsible with pre-release software. If you've got production code that relies on PowerShell behavior, etc. you should consider holding off on installing it on your development machine.

 

* With all these installs I do, I actually do see UAC prompts a lot. And no, I haven't turned off the prompt.

posted on Friday, November 02, 2007 11:26:11 AM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Thursday, June 28, 2007

I was browsing around a few days ago and came across a link to a blog post on the SAPIEN website about searching live.com from PowerShell. Sounds cool, I think, so I download it to try it out only to be thwarted by the proxy at work.

There are a lot of scripts out there that use the System.Net.WebClient and the vast majority don't take proxies into account. To get around this issue, here's a simple script that I wrote to help out:

function Get-ProxyWebClient {
    $webclient = New-Object System.Net.WebClient
    $proxy = New-Object System.Net.WebProxy($global:ProxyUrl, $global:ProxyPort)
    $proxy.Credentials = (Get-Credential).GetNetworkCredential()
    $webclient.Proxy = $proxy
    return $webclient
}

This script makes the assumption that you've already predefined the $global.ProxyUrl and $global.ProxyPort variables in your profile. It is also nice for me because it prompts me for my credentials instead of having them hard-coded in the script or in my profile.

Now I can also check the weather from PowerShell using the Show-Weather script that the guys at SAPIEN provided in their über-prompt post.

posted on Thursday, June 28, 2007 12:39:11 PM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Thursday, June 21, 2007

/n software has a promotion going right now where you can get a free Powershell sticker from them. I haven't been so excited about stickers since elementary school!

Now to figure out where  to put it...

posted on Thursday, June 21, 2007 8:03:26 AM (Central Daylight Time, UTC-05:00)  #    Comments [2]
# Wednesday, January 10, 2007

A recent post by Lee Holmes on breaking your writer's (blogger's?) block is prompting this post. I recently finished reading Steve McConnell's book, Code Complete*, over the Christmas holidays and the book was amazing. As I read it, I began taking lists of things I wanted to post on that were excellent advice... and ran into a block because there was just so much I wanted to say about. I still plan on writing more detailed posts on the issue but, as Lee suggests, I need to just get out here and post more.

So anyway.

Recently, I posted an entry on calculating file hashes with PowerShell and promptly had to put an update because the PowerShell Community Extensions (PsCx) had provided a better file hash function. The good thing about PsCx is that it really provides a good example of PowerShell code and has a lot of cmdlets that drive home automating PowerShell for your needs.

One of my favorite functions is incredibly simple but it highlights how you can save just a few keystrokes for more productivity. The Edit-File function uses a predefined variable that points to an EXE path and runs the EXE with the specified parameter. There is also an alias for it (e) so you can type something like "e somefile.txt" and it will open. I like this method a little better than actually renaming notepad.exe to n.exe (*cough* Scott Hanselman *cough* :-) ). It actually prompted me to create multiple, similar functions so that I can open files in different editors (I use Ultra-Edit, Notepad2, Notepad++, or who knows what else) without having to respecify the editor variable. Now I type "u somefile.txt" to open a file in Ultra-Edit.

This also prompted me to set up the winmerge function below:

function winmerge ([string]$path1, [string]$path2) {

    $winmergePath = "c:\program files\winmerge\winmerge.exe"
    . $winmergePath $path1 $path2
}

It allows me to quickly see the comparisons between two different files without having to preselect them with the mouse. It is simple, but quite convenient. And I also don't have to go adding all sorts of random directories to my PATH just so I can get to them more quickly.

So there you go: my PowerShell automation.

I also promised some unrelated updates. On Monday, January 8, I had LASIK surgery on both of my eyes to correct my extreme nearsightedness. The whole operation took 15 minutes and the only discomfort I had was a headache and some stinging eyes on the day of the operation. Since that time, my left eye can already see with 20/15 vision. My right eye is still a little fuzzy, but that is supposed to clear up in another day or so - it took the laser twice as long to correct my right eye as it did my left eye!

If anyone is interested in more details on my experiences with LASIK, I'd be happy to provide a follow-up post on it.

* - Jeff Atwood really should get some sort of referral rewards for recommending Code Complete... I mean seriously...

posted on Wednesday, January 10, 2007 9:38:44 PM (Central Standard Time, UTC-06:00)  #    Comments [0]
# Thursday, December 28, 2006

UPDATE NUMBER 2:

Kevin commented about a flaw in my script wherein it would keep files open until the PowerShell process was closed - a scenario I should've tested but, in all of the excitement (ha), I missed. You won't believe what the problem was, either. I forgot parentheses on my $inStream.Close() method (it looked like $inStream.Close instead of $inStream.Close() ). The reason the trap { } script block didn't catch it is because the statement was still valid... it would just display the MethodInfo like below:

MemberType          : Method
OverloadDefinitions : {System.Void Close()}
TypeNameOfValue     : System.Management.Automation.PSMethod
Value               : System.Void Close()
Name                : Close
IsInstance          : True

The [void] statement before it prevented the output from displaying, hence me not catching the bug. The script has now been fixed (hopefully). Thanks for the catch Kevin!

UPDATE:

Ignore my script. Go download the PowerShell Community Extensions instead. It has a great Get-Hash script that does everything that my script does and more. I wish I had downloaded it sooner :-)

 

Jeffrey Snover posted a suggestion on the PowerShell blog recently to post automation scripts people have written in PowerShell that they use. Well, here is a script I wrote that I also submitted for the PowerShell Scripting Contest a few weeks back. The script is quite basic and is based on other code I found, but I added a little bit to it to handle some of my own needs. It calculates file hashes based on a specified hash algorithm (i.e. SHA1, MD5, etc). I like to use it to determine if a large file I've downloaded (like an ISO from MSDN) is a good file or if it was corrupted during the download.

Here is Calc-Hash.ps1:

param (
	[string] $inFile = $(throw "Usage: Calc-Hash.ps1 file.txt [sha1|md5] "),
	[string] $hashType = "sha1"
)

function Main
{
	if ($hashType -eq "")
	{
		throw "Usage: Calc-Hash.ps1 file.txt [sha1|md5] "
	}
	
	if ($hashType -eq "sha1")
	{
		$provider = New-Object System.Security.Cryptography.SHA1CryptoServiceProvider
	}
	elseif ($hashType -eq "md5")
	{
		$provider = New-Object System.Security.Cryptography.MD5CryptoServiceProvider
	}
	else
	{
		throw "Unsupported hash type $hashType"
	}
		
	$inFileInfo = New-Object System.IO.FileInfo($inFile)
	if (-not $inFileInfo.Exists)
	{
		# If the file can't be found, try looking for it in the current directory.
		$inFileInfo = New-Object System.IO.FileInfo("$pwd\$inFile")
		if (-not $inFileInfo.Exists)
		{
			throw "Can't find $inFileInfo"
		}
	}

	$inStream = $inFileInfo.OpenRead()
	$hashBytes = $provider.ComputeHash($inStream)
	[void] $inStream.Close()
	
	trap
	{
		if ($inStream -ne $null)
		{
			[void] $inStream.Close()
		}
		break
	}
	
	foreach ($byte in $hashBytes)
	{
		Write-Host -NoNewLine $byte.ToString("X2")
	}
	
	Write-Host
}

. Main
posted on Thursday, December 28, 2006 7:55:57 AM (Central Standard Time, UTC-06:00)  #    Comments [4]
# Wednesday, November 29, 2006

A few weeks ago I posted a way to use PowerShell to find in files. This is just an extension of that post to show how you might open the results of your find in a program.

Try this out:

dir -include *.vb -recurse | select-string "text to search for" | % { notepad $_.Path }

If you've got a lot of Visual Basic files that contain "text to search for", you may end up with a lot of instances of notepad open. At work, I use UltraEdit, so I typically would open my files using uedit32 so that all of the results get opened in tabs. You could do the same with Notepad++ or any other program.

I haven't really used PowerShell for much production work, but it has already made me for more productive than I used to be.

While I'm at it, I'll share another nice one-liner that Kerry shared with me to ngen all assemblies in a directory:

dir *.dll | % { C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\ngen.exe $_.fullname}

posted on Wednesday, November 29, 2006 1:21:49 PM (Central Standard Time, UTC-06:00)  #    Comments [0]
# Monday, November 06, 2006

I haven't posted anything on PowerShell in a while so here's something that's useful.

Get-ChildItem -Recurse -Include *.* | Select-String "text to search for"

Or, if you like things a little more abbreviated, try this:

dir -r -i *.* | Select-String "text to search for"

Select-String is a cmdlet that will search files or strings, sort of like grep in Unix or findstr in cmd.exe. If you use the Get-ChildItem cmdlet, you can specify the -Recurse switch to retrieve subdirectories and the -Include switch will only include the file types that you specify. Then you can pipe it over to Select-String.

Pretty nifty if you're wanting to do some quick file searches.

Check out this PowerShell in Action book excerpt. It gives a good overview on file manipulation from PowerShell and also introduced me to using the Get-ChildItem command and piping the output to Select-String.

Before I began using PowerShell, I had been using a small cmd file called ff.cmd that used the following:

findstr /p /s /i /c:%1 %2

Then I could type things like:

ff "text to search for" .\*.*

But PowerShell is so much cooler now :-)

posted on Monday, November 06, 2006 1:12:11 PM (Central Standard Time, UTC-06:00)  #    Comments [0]
# Thursday, September 07, 2006

Having trouble changing your PowerShell Script Execution Policy in Vista because of access problems? This whole limited user thing will take some time to get used to, but it certainly is a good idea for security. What I did to fix this problem was I ran the command prompt as an admin. If you go under your start menu and accessories, you'll see a link to the command prompt. If you right click on it, you'll see an option to run as administrator. Here's a screenshot:

Once you do that, you'll be able to start up Powershell and then you'll have authority to change the execution policy. I've typically been setting mine to RemoteSigned (Set-ExecutionPolicy RemoteSigned).

Unrelated to Powershell, but wow will I need more memory if I want to run Vista! I barely have any programs open and my pagefile is getting hit like crazy! I'm probably averaging a gig of memory usage... with only one program open!

posted on Thursday, September 07, 2006 9:09:55 PM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Wednesday, July 26, 2006

Recently, I've been experimenting with different console colors in PowerShell, primarily because the light gray on black is sort of boring (lame excuse, I know). I've been using Console and I had set the foreground color to green in the options. The only problem with doing this is that programs that output other colors, such as the error messages from MSBuild, are not displayed. I like seeing the color difference because the red text really jumps out at me and says that I have an error.

This got me curious about whether or not I could set a different color in PowerShell, instead of in Console. I stumbled across this TechNet article from way back when PowerShell was still MSH. Basically, you use the -foregroundcolor or -backgroundcolor switch against Write-Host to alter the color of the text you're outputting. That's certainly userful information if you're writing cmdlets, but I wanted to change the default color for the entire session.

If you've worked with .NET console applications, you may have seen System.Console.ForegroundColor. Well, this is available from PowerShell as well! .NET shell integration is great! So now, my PowerShell profile has a brand new line in it:

[System.Console]::ForegroundColor = [System.ConsoleColor]::Green

By doing this, whenever an application, cmdlet, function or whatever changes the default output color, like MSBuild does, you'll be able to see it. As a side note, I really like the PowerShell profile idea. Though options dialogs tend to be more user friendly, the PowerShell profile (try 'notepad $profile') is far more powerful and customizable.

posted on Wednesday, July 26, 2006 1:00:28 PM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Thursday, July 13, 2006

Yesterday, I downloaded the Developer Productivity Tools video from the Wrox website that Scott Hanselman did for one of his presentations with a user group. He had a lot of great resources in the video but the command prompt tips he had were new to me. I've done some work with the console, but I've only recently been using it more, particularly with PowerShell coming along.

Scott's tip about customizing your prompt (from c:\dir\> to whatever) was really cool (also posted here). I knew that the prompt could be customized, but at the time I saw someone do it, I didn't have a good grasp of environment variables so it didn't really make sense what was going on, but Scott's video and his post have helped out a lot. They also prompted me to want to do the same with my PowerShell prompt!

The PROMPT environment variable trick doesn't work for the PowerShell prompt, but after a little digging around with Google, I discovered this post from Lee Holmes about the prompt function. If you have a function named prompt declared, PowerShell will use the value returned by that function to alter the display of your prompt. Here's my prompt function, which I have saved in PowerShell profile so that it will load every time (mine is located here C:\Documents and Settings\David\My Documents\PSConfiguration\Microsoft.PowerShell_profile.ps1)

# Initialize custom prompt
function prompt
{
   "PS " + (get-location).Path + [System.Environment]::NewLine + ">".PadLeft((get-location -stack).Count + 1, "+")
}

The only thing I haven't figured out yet is how to get a visual indication of how far in the stack you are (by using pushd and popd). Once I figure that out, I'll have a PowerShell prompt customized just like my cmd prompt!

UPDATE: I did some more research and discovered get-location -stack which will return everything on the pushd/popd stack. I've updated my prompt function accordingly. Now it matches my cmd prompt in every way!

posted on Thursday, July 13, 2006 1:00:39 PM (Central Daylight Time, UTC-05:00)  #    Comments [0]