Thursday, January 18, 2007

I probably should have just submitted this one to Overheard at the Office, but I'd rather post it here.

"It's not that I'm lazy, it's just that I want to be thorough."

This was from one of my coworkers who was speaking to a user upstairs.

I found it hilarious.

posted on Thursday, January 18, 2007 1:20:52 PM (Central Standard Time, UTC-06:00)  #    Comments [0]
 Tuesday, January 16, 2007

I recently moved my RSS reading habits over to Google Reader, primarily because I read feeds at work and home both and I'd rather not have to keep my feeds synchronized in both places. The new design is a million times better than the old design, too.

Anyway, a feature that Google Reader provides is a location to view "Shared" items. I've started sharing items that I find interesting from my daily feed reading. So far, it is mainly some cool Engadget posts and some deals, but if anyone is interested, you can view my Google Reader Shared items here.

So now, you can see my blogroll (at the right side of the screen), my bookmarks (thank you del.icio.us!), and feed items I find interesting.

Just wait untill I post a public calendar! Hah!

posted on Tuesday, January 16, 2007 1:03:08 PM (Central Standard Time, UTC-06:00)  #    Comments [0]

We're in the process of migrating to .NET 2.0 at work and one of the the things we've encountered is a problem with remoting between .NET 1.1 and 2.0 frameworks.

This is our scenario in a nutshell.

An application is upgraded to 2.0 but is still referencing a 1.1 component. This works fine until the 1.1 component remotes to a 1.1 server. The client is running under the 2.0 framework while the server is running under the 1.1 framework. We can't upgrade the server because there are still other 1.1 clients out there as well.

What's funny about this is that it will work sometimes. Interoperability between 1.1 and 2.0 is actually fairly solid... unless you're serializing a DateTime across the wire. If you're sending a DateTime between the two frameworks, you'll see this error:

Exception: System.ArgumentOutOfRangeException
Message: Ticks must be between DateTime.MinValue.Ticks and DateTime.MaxValue.Ticks.
Parameter name: ticks

If you were to change the server side over to run under .NET 2.0, you won't see the problem anymore. On the plus side, Microsoft has released a hotfix to address this issue (and even more information here) that specifically patches the 1.1 framework. The problem is that you've got to contact Microsoft to get the hotfix.

I'm hoping that by posting this, I will let others know about it and maybe even to get Microsoft to release it for download.

Then again, maybe no one else has to deal with this issue :-)

posted on Tuesday, January 16, 2007 12:38:32 PM (Central Standard Time, UTC-06:00)  #    Comments [0]
 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]

This Christmas, my wife got me one of those awesome Logitech Harmony remotes (the Harmony 880 for those who are curious, and at a great price, too). I spent the better part of last night attempting to get it set up.

The out-of-box experience is great. The remote looks and feels excellent and the docking station for it is really cool. Of course, you should charge it prior to use. I got the thing charged and then began the installation process... on my Windows Vista box. Like so many things, it doesn't officially support Vista yet. What this means practically is that it doesn't yet support things like Aero Glass (I think because of WDDM support). It kicks the whole thing down to Aero Basic while the program runs. I also had some fun with Logitech's website because of some errors their server was having related to creating some COM objects.

At this point, it doesn't look all that good. Well, to be honest, I was feeling a little upset about the whole thing, but I WAS using the remote on an unsupported OS still and everybody has server issues once in a while. I was willing to give them the benefit of the doubt so I tried their website a few hours later. The thing worked great - even with the new security settings that Internet Explorer has. The website works by downloading a special file that the Harmony Remote Client opens so that all the settings are customized on their website and then loaded to the remote. I had a few extra security dialogs, but the thing still worked great.

Once I had the remote customized to my liking, I went into the living room to try it out.

POWER!

...

POWER!

...

POWER! POWER! TURN ON! TURN ON!

What is going on?!?

My TV came on, my receiver came on, but my satellite receiver just sat there.

For those who may have read the title of this blog post, you may have already figured out what my problem was. My satellite receiver's remote uses UHF instead of IR. My Harmony remote only uses IR (AFAIK). In other words, my remote cannot talk to my satellite receiver.

*sigh*

I am happy to report that I'm planning on investigating digital cable again anyway, because my satellite company likes new sign-ups better than existing customers. They'll give you an HD receiver without any questions if you're a new customer, but if you want to upgrade your receiver later, they want to charge you $800+ for a new receiver. Yeahhh, I think I'd rather go another route, thank you.

Hopefully, the digital cable box uses an IR signal instead of a UHF signal.

For those who may be scared away from the Harmony remotes, don't be. The thing works great with everything else. I entered in the model numbers for my receiver, TV, XBox 360, and PlayStation 2 and it talks with all of them without any problems. I'd been lazy and not using my receiver for sound before because I had to get out 2+ remotes everytime, but now, I'll be enjoying some surround sound when I play games on my 360 now.

posted on Thursday, December 28, 2006 7:21:19 AM (Central Standard Time, UTC-06:00)  #    Comments [0]
 Thursday, December 14, 2006

Ahhh, JavaScript error messages.

<sarcasm>
They are the epitome of the user friendly error message. Developers love them, because they always tell you exactly where the problem is. Absolute error message perfection.
</sarcasm>

Below is an example of one of these messages that a friend sent:

Nice, eh?

You can tell EXACTLY what the problem is. That... thing... is null or not an object! And we've even got a line number, too!

NOTE: The above message was generated by a script I wrote a while back that is kicked off by the window.onerror event that fires when JavaScript exceptions are thrown. It posts to an application which then emails the developers in question.

posted on Thursday, December 14, 2006 11:05:47 AM (Central Standard Time, UTC-06:00)  #    Comments [0]
 Monday, December 11, 2006

I'll tell you what it looks like.

It looks like -1.#IND.

That's what it looks like. At least if the code is using the Double.NaN constant. I sure didn't know that before I saw it and, I can tell you, it sure freaked me out when I saw that in the immediate window in Visual Studio. I was working on speeding up another dev's code here and apparently they were using NaN to signify the difference between 0 and "not yet initialized." It works pretty well for them in that case, but as I said, if you're not expecting that, it very well may throw you off.

And PowerShell is smart enough to just say NaN instead of this -1.#IND stuff.

Along the same lines, -1.#INF is apparently how Infinity is represented.

(IND would be indefinite whereas INF is infinite... makes sense I guess.)

posted on Monday, December 11, 2006 2:34:15 PM (Central Standard Time, UTC-06:00)  #    Comments [0]
 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]
 Tuesday, November 07, 2006

The web has been busy with news about .NET 3.0 going RTM, along with Office 2007, Vista, etc. But some other news that hasn't received quite as much publicity is news regarding Sysinternals at Microsoft. There were a couple of posts today that I thought were very interesting.

The first post is about the move from the original Sysinternals site over to Microsoft. I think the best part of the announcement is the focus on letting the "community demand help drive [their] priorities." A few of the comments have been negative regarding the decision to not post the source code to the tools, but that is the only negative thing that I can see in the post. Besides, if people want the source enough, maybe Microsoft will put it back out again. They listened when people complained about the Vista EULA didn't they?

The second post is even better news. In addition to some new releases of some great tools from Sysinternals (mostly to support Vista), a new tool has been released called Process Monitor! Process Monitor takes all of the functionality provided by RegMon and FileMon and combines them with even more information such as information about threads! If you're worried that it will put too much into one place because it was nice to focus only on registry or file access, don't because with the click of a button, you can tell it to only display registry changes, file changes, or thread changes. If you want to get straight to the main Process Monitor page, it is here.

Here's a screenshot of Process Monitor in action:

Unrelated to this post, but I used the Snipping Tool in Vista to get this screenshot. It works pretty well.

posted on Tuesday, November 07, 2006 6:58:17 PM (Central Standard Time, UTC-06:00)  #    Comments [0]