Sunday, January 18, 2015

This One Weird Trick the Visual Studio Team Doesn't Want You to Know!

I find it fascinating that most Windows boxes (these days, I can almost say all of them) have CLR compilers sitting around on their hard drives.  This would make it possible for people to experiment with C# and VB.NET without downloading squat...  But Microsoft forgot to do one thing: set up some file associations.  So this is a write-up on how to set them up in a quick and dirty fashion on any computer so that you can experiment with C# and VB.NET without having to download Visual Studio.

I don't like Visual Studio anyway, probably because I don't work on enterprise stuff.  I shamelessly admit that my codebase is a collection of cheap hacks, and my goal is to be able to crack open an editor, vomit out fifty or a thousand lines of code, execute my tests, and get on with my day.  I also get a smug sense of satisfaction and independence from eschewing an IDE, kind of like choosing to drive a manual transmission car.  (Why don't I use Linux, then?  Quiet, you.  It's because of software requirements.)

So, with no further ado, I present:

Visual Stu-DIY-o

For the impatient, here is the quick and dirty TL;DR:

assoc .cs=CSharpSourceFile
ftype CSharpSourceFile=%WINDIR%\Microsoft.NET\Framework\v4.0.30319\csc.exe %1
reg add hkcr\CSharpSourceFile\Shell\edit\command /ve /d "%WINDIR%\System32\notepad.exe %1"

But your .NET compiler might not be located there, or your code warnings and errors may zip by and disappear, or your executable may not get built, or you may have wanted to program VB.NET, et cetera.  If you care about such things, then go through the exercise of locating your compiler, creating a friendly compiler script, and associating that with your source files.  Read on for more.

Find your .NET compiler of choice

You're really just confirming what version you have.  You're doing this because you want to be sure the files exist before you copy and paste the script below.  Fortunately, this is easy, because it's in your path:

  1. Hit Win+R (to get the run dialog)
  2. Type Microsoft.NET
  3. Leap of faith: press Enter
  4. Browse to the Framework\v4.0.30319 directory
  5. Note the absolute path to csc.exe (hint: hit ALT+D, hit End, finish off that directory name with a backslash, and start typing csc, and it will let you auto-complete the path in the address bar; copy this address for later).

A little note: I use the Framework (and not Framework64) directory because I want my MSIL to run in 32- and 64-bit environments.  For my normal projects, I use .NET version 4.0, and for software that must be deployed to mixed and potentially un-maintained platforms (if I told you why, I'd have to kill you), I target .NET 2.0.  Lastly, I use C#, but you don't have to.  At this point, if you want to locate vbc.exe instead (That's the VB.NET Compiler), go ahead and replace csc with vbc.  I won't judge you.  Just remember to actually replace what I put in the script below with the path to vbc.

At this point, we could set the file association directly with the compiler, as in the "TL;DR" section above, but if you double-click your .cs (or .vb) files, and your source code has warnings or errors, a mysterious black box will appear and disappear before you have a chance to review and fix them.  That's why you're going to bother with the next step:

Write a quickie script

Choose a place where this script will live.  Make a "util" or "bin" or "scripts" directory somewhere in your user profile if you don't already have one.  Open Notepad, copy and paste what is below (replace the path to csc if you are targeting a different .NET version, architecture, compiler, etc.), and save it as something.  I chose buildcs4.cmd.  In the Save As dialog, under "Save as type", don't forget to select "All Files (*.*)" so that it does not "helpfully" append the .TXT file extension for you, thus neutering your command script.  Here's my version:

@ECHO OFF
%WINDIR%\Microsoft.NET\Framework\v4.0.30319\csc.exe %*
PAUSE

The PAUSE command is there so you can see the warnings before the script closes.  You can't use an IF ERRORLEVEL command to pause for warnings, because the compiler only returns 1 or greater if there are errors, not if there are warnings, so that is why I include an unconditional PAUSE.  %* tells the command interpreter to pass along all the arguments from the command line.  This is how the filename you double-click will be passed to the C# compiler (or VB.NET compiler, if that's your predilection).

Finally, make the file association

Open an administrative command prompt and invoke these three incantations:

assoc .cs=CSharpSourceFile
ftype CSharpSourceFile=%USERPROFILE%\path\to\buildcs4.cmd %1
reg add hkcr\CSharpSourceFile\Shell\edit\command /ve /d "%WINDIR%\System32\notepad.exe %1"

These define a filetype, set a file association, and add an "Edit" context menu command, respectively.  For more background on all that, type ASSOC /?FTYPE /?, and REG /? on the command-line.

Taking it for a Spin

If you want a test, here's a nice C# sample you can paste into notepad.  I think the traditional hello-world example is pretty boring, so here's something to spice up someone's life:

using System;
using System.Windows.Forms;

class mbox
{
    static public void Main()
    {
        MessageBox.Show(
            "Delete C:\\ - are you sure?",
            "Confirmation",
            MessageBoxButtons.OK,
            MessageBoxIcon.Warning
           );
    }
}

Now save that as hello.cs, and double-click it to compile.  Run the resulting hello.exe to see the result.



Right-click hello.cs and choose Edit when you want to mess about some more.  Aaaaaand, we're done.

No comments:

Post a Comment