Monday, October 30, 2006

I Hate ClearCase - Part I

ClearCase isn't my favourite source control system.  I find the UI clunky and for the most part, it's way over engineered.

I've just tried deleting a file and I'm getting an error message that says:

Trigger "NO_RMNAME" has refused to let rmname proceed. 
Unable to remove "[file]".

WHAT DOES THIS MEAN AND HOW DO I DELETE A FILE?!

My 20+ years of working with software - coupled with my powers of deduction, have led me to "guess" that this means I don't have the permission to delete a file! (I could be wrong;  I'm waiting for the in-house ClearCase administrator to advise!)

I'm going to stop using the advanced features of this software and continue with the basics...

Tuesday, October 24, 2006

Cassini and assembly loading problems

Cassini is the Visual Studio development web server. Generally, Cassini is great;  you give it a port number and a path and off it goes - hosting ASP.NET pages in a similar fashion to ISS but much quicker.  Plus, it's unloaded when you stop debugging.

One issue I came across today was with Cassini and the loading of assemblies.  During development of .NET applications, I like to use project references rather than binary references (whether those references are in our out of the GAC).

The problem lies with the fact that Cassini occasinally switches app domains, forcing objects to be serialised across.  This serialisation was failing as one of our serialisable objects were in an assembly that wasn't in the GAC and wasn't available anywhere for the Cassini process to load.  The exact error was:

Type is not resolved for member 'Company.Product.Type,Company.Product.dll, Version=1.0.0.0, Culture=neutral, PublicKeyToken=blah'

Investigation led to the suggestion to use DEVPATH.  Basically, this means adding the following entry to the ‘runtime’ section of the machine.config file:

<developmentMode developerInstallation="true"/>

… and setting the DEVPATH environment variable to the directory where your private copies of assemblies are located.  This is supposed to load a matching assembly regardless of version.  Unfortunately, this didn’t work and for whatever reason, a ComException was being thrown very early on when Cassini started.

Although this didn't work, there was a link in the page to another MSDN article describing a way to redirect assembly loading. This again used the runtime section of the machine.config file, but this time using:

<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="Company.Product" publicKeyToken="blah" culture="neutral" /> <codeBase version="1.0.0.0" href="file://C:/Blah/Company.Product.dll"/> </dependentAssembly> </assemblyBinding>

This worked great and saved me having to use IIS or copying my assemblies all over the place so Cassini can load them.

I hope this post proves useful to anyone having a similar problem.  It will probably prove useful to me when I come across the problem again in the far future having forgotten how I got around it the first time!

Monday, October 23, 2006

What to expose in a framework

Scott Hanselman  blogged recently on reasons to make a class public in a framework.  One reason was that a developer may want the functionality offered by a particular class, either to be used as-is or to be extended.

Normally, frameworks are quite specific in what they do and what they provide.  If a whole 'chunk' (class) is required to be made public, then it may be the case that this functionality isn't in the realm of what the Framework was designed to offer. For example, should a class that lists the zipped files in a directory be exposed from a compression framework?  Or, should a regular expression helper class be exposed from a logging/tracing framework?

Opening up large chunks of code because someone wants the functionality can dilute the Framework and make the API harder to understand because it offers so much functionality. With this in mind, if the framework you've given them doesn't do what they want, then maybe rethink ways of incorporating the functionality into the Framework rather than opening up a chunk of code.

You might be thinking that it'd be difficult incorporating all the functionality of a particular class into other parts of the framework;  classes, whether internal or exposed, should be succint (following the Single Responsibility Principle) - so there shouldn't be too much to move around to give them the features they require.

When we start talking about frameworks and OO concepts such as SRP, it brings to mind a very valid point raised in the excellent Framework Design Guidelines book - something along the lines that OO should play a part in the implementation of a framework but not in the API of the framework (I think the example of Streams/TextReaders was used as a very good example).  The .NET Framework now seems to have more and more utility classes that help to flatten the heirarchy and (in my opinion) increase usability/memorability.

Some examples would be a good way of testing our arguments.  Perhaps examples based on the .NET Framework wouldn't be the best to use as this is a lot more generic than say, frameworks for logging/tracing or compression.

Sunday, October 22, 2006

Retrieve your Windows OS Product Keys

Today I needed to get the Windows XP Product Key but didn't have the neccessary information to hand. I did a search and found the MagicJellyBean utility.


This worked but I was curious how it worked. I read around a little bit and discovered a snippet of C# code from Willem's blog.


I then modified it a bit and created my own C# WinForm application.



The application lists the most common product keys (Windows XP and Office) and has a button to search for more keys that look like product ID's. It searches all keys in HKEY_LOCAL_MACHINE.


Here's the source code and here's the binary. Note, the application depends on the .NET Framework 2.0. Also, save the binary before running it otherwise it'll run with restricted permissions and won't be able to probe the registry.

Saturday, October 21, 2006

Visual Studio Orphaned Project Items Finder

The name is a bit of a mouthful, but sums up what it's all about.  It finds orphaned items in a Visual Studio project.  Inspired by Clean Source Plus, this utility is a stand-alone application and also a right-click Explorer menu item.

Recently I came across several dozen projects that had been worked on by dozens of people for several years.  Inevitably, there were files present in the source tree that were not part of the project.

This is a tool to find those files.  Please feel free to download it from CodePlex.  There is an installer file and the source code is also available. If you'd like to contribute to the project, please let me know.

To use it is very simple.  Download it and run it, or right click a Visual Studio project in Explorer and 'Find Orphaned Items...'.

Warning!

I've tested this project on Visual Studio 2003 and 2005 projects.  I haven't tested this on Web Projects or Web Application Projects (in Visual Studio 2005).  I would recommend verifying what the application thinks are orhpaned items.  If it continually gets it right, you can trust it more and check it less.  If it continually gets it wrong, then please let me know!

Friday, October 20, 2006

Problems with Forms Authentication and ASP.NET Themes

It's sometimes the strangest (and seemingly irrelevant) combinations of technology that give you the most problems. For a good few hours I've been wondering why my web site, which uses Forms Authentication and Themes, was not displaying any formatting or images.

It turns out that the URLs specified in the authentication section in web.config are used for ALL resources. So, in my case, the page was trying to load a .css file but ASP.NET was redirecting the request to default.aspx, which of course, is not a style-sheet and has a different MIME type. Here's the section of my web.config file:

<authentication mode="Forms">
      <forms  loginUrl="Default.aspx"
        defaultUrl="Default.aspx"
        protection="All"
        timeout="30"
        path="/"
        requireSSL="false"
        slidingExpiration="true"
        cookieless="UseDeviceProfile"
        domain=""
        enableCrossAppRedirects="false"/>
    </authentication>

To fix this, I allow unauthenticated access to the resources, which was straight-forward. I added the following to the web.config file:

 <location path="App_Themes">
    <system.web>
      <authorization>
        <allow users="*"/>
      </authorization>
    </system.web>
  </location>

The tricky part in finding this was that the page's HTML looked fine, there were no errors, and saving the resulting HTML to a file and viewing it produced the right results.

Firefox's JavaScript Console proved incredibly helpful in finding the problem:

 
Once I saw this, it all fell into place!

Thursday, October 19, 2006

BackgroundWorker - automating this handy class

BackgroundWorker objects are an addition to .NET 2.0 to simplify asynchronous programming and are very useful in (but not restricted to) Windows Forms.

The basic idea is:

  • Create a BackgroundWorker object
  • Set-up various events on it, like DoWork, RunWorkerCompleted, and ProgressChanged
  • Set-up various properties, like WorkerReportsProgress and WorkerSupportCancellation
  • Call RunWorkerAysnc

...then, in your form you get notified of progress and can cancel the operation at any time.

I've created a ReSharper Live Template that will help you create and set-up the BackgroundWorker object. You can download it here. For instructions on importing the Live Template into ReSharper, see my previous post here.

Wednesday, October 18, 2006

Visual Studio Build Tip

By default, Visual Studio will build all of the projects in your solution regardless of any errors.

The problem with this is that if the first project it builds contains an error, the resulting binary will not get generated. If any other projects depend on this (which is normally the case, as it was the first to be built) then they'll fail too, and so on to the end of the project heirarchy.

Pointless; you'll spend ages sitting around in a locked IDE unable to edit the error until the build finishes.

You might as well stop at the first error. You could of press Ctrl+Break (several times) and hope that VS will eventually stop. But, there's a better way: get Visual Studio to stop automatically after an error.

  1. Go to Tools/Macros/Macro Explorer
  2. Expand MyMacros
  3. Double click Module1
  4. This will bring up the macro in a new window. In that window, double click the EnvironmentEvents entry.
  5. From the drop-down (currently 'General', select 'Build Events')
  6. Select 'OnBuildProjConfigDone' and paste this in:
If Success = False Then 'The build failed...cancel any further builds.
DTE.ExecuteCommand("Build.Cancel")
End If

The whole method should look like this:

Private Sub BuildEvents_OnBuildProjConfigDone( _  
ByVal Project As String, _ 
ByVal ProjectConfig As String, _ 
ByVal Platform As String, _ 
ByVal SolutionConfig As String, _ 
ByVal Success As Boolean) Handles BuildEvents.OnBuildProjConfigDone   
    If Success = False Then 'The build failed...cancel any further builds.     
        DTE.ExecuteCommand("Build.Cancel")   
    End If 
End Sub

Wednesday, October 04, 2006

ReSharper Live Templates for validating parameters of public C# methods.

ReSharper Live Templates are smart shortcuts you can type and have filled in automatically. For instance, typing 'foreach' and pressing tab produces:

      foreach ( object o in something )
      {
      }

I've created 3 Live Templates for validating arguments in public methods (C#). Here's a short video demonstration. I've blogged about these before for ReSharper 1.5 and said that there's no way to export/import the templates. But in ReSharper 2.0, there is! You can get them here. Go to ReSharper/Options/Templates/LiveTemplates and click the 'Import templates from file' button.