How to Save XAML as an Image

Here’s a quick note to self that you may enjoy. I suck at art. Didn’t use to always, but it requires too much brain power. But I’m not bad at getting WPF to draw what I want. I had a logo in mind for this site and used WPF to generate it after unsuccessfully getting Paint.NET to do the same.

I recently needed to use this code again, but forgot how I solved it. So, rather than hunt it down on Google again, I came home and loaded up ye olde Windows Live Writer to write this post.

To save the XAML you want as an image, put the elements you want to save into a canvas element called canvas. Then run the following code.

private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
{
   Rect rect = new Rect(canvas.RenderSize);
   RenderTargetBitmap rtb = new RenderTargetBitmap((int)rect.Right,
     (int)rect.Bottom, 96d, 96d, System.Windows.Media.PixelFormats.Default);
   rtb.Render(canvas);
   //endcode as PNG
   BitmapEncoder pngEncoder = new PngBitmapEncoder();
   pngEncoder.Frames.Add(BitmapFrame.Create(rtb));

   //save to memory stream
   System.IO.MemoryStream ms = new System.IO.MemoryStream();

   pngEncoder.Save(ms);
   ms.Close();
   System.IO.File.WriteAllBytes("logo.png", ms.ToArray());
   Console.WriteLine("Done");
}

I hooked up a key binding to a command to execute this code, but you could use a button click too. It’ll save the elements in canvas to a file in the same folder as the executable, called logo.png, but you can change that if you want. You can also you a different encoder if you like. They’re in System.Windows.Media.Imaging.

Enjoy!

Setting Up A Symbol Server in Visual Studio 2005

Through a serendipitous series of links on the ol’ intarweb, I came upon this excellent post by the always excellent Jessica (aka JFo) on setting up a symbol server in Visual Studio 2003. A symbol server allows you to debug code to which you don’t own the source. I knew you could do this, but never had the need to do it at work (I’m a library author at work). But recently, I’ve been writing my own controls and I find some things are happening that I’m not expecting, so I figured I’d set this up in Visual Studio 2005. If you follow Jessica’s instructions you’ll quickly become confused, like I did: they moved the spot where you configure this.

In Visual Studio 2005, click Tools -> Options. Expand the Debugging node and select the Symbols sub-node. Click the folder icon. Type in the location of the symbols. In my case I want Microsoft’s public symbols; you can find them here: http://msdl.microsoft.com/download/symbols. Type the above as the new entry. For Microsoft’s public symbols, you’ll have to enter a folder location to cache them. You should have something like the following:

Setting up a symbol server in Visual Studio 2005

Once you click OK, you’ll have to agree to a EULA. I used Jessica’s test  from the post above to see if it was working. It wasn’t. The symbols weren’t being loaded by the IDE automatically. Maybe I did it wrong? Went back tried again; checked my settings. Nothing. Hmmm. When in doubt right-click: I found the answer on something I clicked on, I can’t remember what it was.

But I do remember the answer: there’s a setting on the General sub-node of the Debugging node of the Options dialog called Just My Code that is selected by default. That’s why the symbols weren’t loaded. De-select that setting; run Jessica’s sample app and you get the breakpoint. Yay! You’ll also note that the red dot has a + sign in it when the breakpoint is hit, unlike a break point in your code.

Technorati tags:  

Now playing: Three Days Grace – Animal I Have Become

Hey, Where did my Visual Studio Add-In Go? I know I Installed it.

I recently installed the 2005 version of the excellent CopySourceAsHtml Visual Studio Add-in. Then I started up an instance of the IDE, opened a project and …couldn’t find the right click option to copy as HTML. So then I went to Tools -> Add-In Manager and it’s blank! WTF? This is weird. I know I just installed it.

I try repairing the installation, nothing; then I try reinstalling, nope.

Quick! To the web!

It appears Visual Studio has a set list of folders from which it will load add-ins. If your add-in’s path is not on the list, then VS won’t load it. It’s easy to override, as Eric S says in the comments of this post:  

in VS.NET 2005:
1. Go to Tools > Options
2. Under Environment, select “Add-in/Macros Security”
3. Click the “Add…” button
4. Browse to the installation folder (C:\Program Files\J.T. Leigh & Associates\CopySourceAsHtml2005)
5. Click the necessary “OK” buttons
6. Restart VS.NET 2005.

Now I can see the option in the right-click menu.

Now you know.

Technorati Tags: , ,

Writing Your Own UriParser Part 2: Implementing GetComponents

In my last article on UriParser, I explained how to register your custom parser as well as outline the pitfalls you may encounter along the way. The documentation is sparse when it comes to UriParser and its descendents. This time I’ll start writing my own custom parser and explain the details of UriParser.GetComponents(), a virtual method that you will have to override for your custom parser.

Before I get into UriParser, it helps to know the terms for the parts of a URI, because there is some overlap with the terms and the Uri class uses them. Without looking up the RFC that defines URIs, they have the following format:

[scheme]://[userinfo]:[password]@[host|authority]:[port]/[path]?[query]#[fragment]

Something like that anyway; I’m probably missing something, but this will be good enough for the article. For http, the userinfo and password aren’t typically used; for email addresses, there is no path.

For my examples, Ill again use the SIP URI scheme as my example URI scheme. It is described thus (in RFC 3261, Section 19.1.1):

The “sip:” and “sips:” schemes follow the guidelines in RFC 2396 [5]. They use a form similar to the mailto URL, allowing the specification of SIP request-header fields and the SIP message-body.

Essentially, it looks a like mailto URI except the scheme is sip. For example: sip:jason@example.com is a valid SIP URI.

Creating a Custom UriParser

To create a custom parser, the documentation recommends inheriting from one of the well known URI scheme parsers: FtpStyleUriParser, HttpStyleUriParser, FileStyleUriParser, GopherStyleUriParser, or LdapStyleUriParser. However, if your scheme is mailto-like, then you have to inherit from either the base UriParser, or GenericUriParser, because there is no MailtoStyleUriParser. So for this article, I’ll inherit from GenericUriParser. However, suppose I was doing this for Subversion URLs or feed URIs, I’d inherit from HttpStyleUriParser.

My custom SIP URI parser class will have the following declaration:

public class SipUriParser : GenericUriParser{}

GenericUriParser has one public constructor that takes GenericUriParserOptions flags to configure the parser. These parser options map to an internal enum, UriSyntaxFlags, that were used in V1.x. One thing I should warn you about is that trying to follow whats going on with these classes will drive you insane. The reason it took so long for part 2 of my UriParser class? I was stuck in the corner of my bedroom, dried tears on my face, with my head and eyes making sharp, jerky movements left and right. I was still haunted by all the back and forth tracing one must do to figure out the relationship between UriParser and Uri. I think there’s a technical term for this kind of code. I realize re-writing working code is something that you shouldn’t do, but if you’re a giant software company with the best and brightest, as they claim, and you have five years to redesign a set of classes, then I think it’s fair to expect that you follow your own freakin’ pattern.

All the code for parsing the Uri class is still in the Uri class, as it was in V1.x. If you Reflector into the UriParser code, you’ll see that the base class has private const values for all XxxStyleUriParser sub-classes. It handles all the schemes that the framework handles by default: http, ftp, etc. by calling all the internal methods on the Uri class. This is code you don’t want associating with your code. It’s the type of code that smokes in the bathroom and wears leather jackets in those high-school movies about the 50s. Sure, it may seem cool to work with code so dangerous, but I have no idea what I was talking about. Hey, Golden Girls is on!

Where was I?

You can find the definition for GenericUriParserOptions online at MSDN. Since SIP URIs look like mailto URIs, I want the following GenericUriParserOptions: NoFragment, GenericAuthority and Default (For the example, it could be anything; make sure you study the rules for any URI scheme you have to implement). So, my SipUriParser consists of the following, right now:

using Options = System.GenericUriParserOptions;

 

public class SipUriParser : GenericUriParser

{

    public SipUriParser()

        : base(Options.NoFragment|Options.GenericAuthority|Options.Default)

    {

    }

}

If I were to register my parser as it is now and create a Uri instance that contained a SIP URI, like in the code below, then it would fail on the constructor: it throws a UriFormatException:

    class Program

    {

        static void Main(string[] args)

        {

            UriParser.Register(new SipUriParser(), “sip”, 5060);

            Uri u = new Uri(“sip:jason@jasonkemp.ca”); //fails here

            PrintUri(u);

            Console.ReadLine();

        }

    }

That’s because my parser is using the base method for InitializeAndValidate(). Everytime a Uri is created, it calls into the InitializeAndValidate method of the parser. The default method ends up in one of those labyrinthine calls through Uri which results in throwing a UriFormatException. The InitializeAndValidate method is the first chance to see if the string passed in the Uri constructor is a valid URI for that scheme. This is scheme-specific and since the myriad details of valid SIP URIs isn’t important to this article, I’ll just pretend all values passed are valid. I’ll add the following method to my parser:

    protected override void InitializeAndValidate(Uri uri,

        out UriFormatException parsingError)

    {

        Console.WriteLine(“In InitializeAndValidate()”);

        parsingError = null;

    }

Note that I don’t call the base method. Calling the base methods for any of the virtual methods is not only not recommended, its downright forbidden: you’ll get an InvalidOperationException if you call the base with a message saying, don’t do that! They probably should have made them abstract.

To access the string that was passed to the Uri constructor in the InitializeAndValidate() method, you should access it through the uri.OriginalString property. Any other property will cause GetComponents() to be called.

Overriding GetComponents()

In V1.1 of the framework, entering a valid URI string as an argument to the Uri constructor that Uri did not know how to parse would result in null values for any Uri property called. Microsoft’s 2.0-solution to that problem was the UriParser. The UriParser.GetComponents() method is where all the magic happens.

Suppose I created the following Uri instance with my parser registered:

Uri u = new Uri(“sip:jason@jasonkemp.ca”);

If I wanted to know the user info portion of the URI, I’d call u.UserInfo. This would, in turn, call SipUriParser.GetComponents() with the Uri instance, a UriComponents enum value and a UriFormat enum value as arguments. With those three things, the parser is responsible for returning the requested component of the URI. In my example, the UriComponents.UserInfo enum value would be passed. The UriFormat enum is used for character escaping.

The UriComponents enum is marked with the FlagsAttribute; thus, the values can be OR’ed together. In fact, there are some that youll never see in isolation; and some youll see often, sometimes isolated, sometimes not. Just for you, dear reader, I’ve compiled a table of what property on Uri causes a call to UriParser.GetComponent with what UriComponents enum values. The | character denotes that they are OR’ed together.

Uri Property

UriComponents passed to GetComponents

AbsoluteUri

AbsoluteUri

AbsolutePath

Path | KeepDelimiter

Authority

Host | Port

DnsSafeHost

Two Calls: 1. Host 2. StrongPort

Fragment

Fragment | KeepDelimiter

Host

Host

PathAndQuery

PathAndQuery

Port

Two Calls 1. Host 2. StrongPort

Query

Query | KeepDelimiter

UserInfo

UserInfo

But that’s not all: there is also a public Uri.GetComponents() method. This allows you to grab practically any combination of UriComponents enum values OR’ed together. Great design! Sure, the documentation says that invalid combinations will cause an exception to be thrown, but they don’t tell you which ones. Here at jasonkemp.ca, we go the extra mile for our 4 readers. Looking through Reflector, again, it shows that anything OR’ed with UriComponents.SerializationInfoString will throw an ArgumentOutOfRangeException before it reaches your parser; everything else is the responsibility of your parser to validate. So, even though asking for Scheme and Query at the same time is invalid for …oh… every URI scheme ever, you’ll have to put that argument checking into your parser, for every parser you write. Thanks for the reuse, Microsoft.

The idea and design of the UriParser/Uri relationship is basically a good one; its too bad the implementation is so butt ugly that I’d rather watch Golden Girls rather than write about it. The GetComponents method is the key to your custom parser. This article has uncovered some of the landmines you may encounter, hopefully before you got started on implementing your own URI parser.

Loading Visual Studio 2005\.NET 2.0 SDK Tools (vsvars32.bat) in Monad (MSH)

Scott Hanselman’s recent zeal for MSH has motivated me to take another look at Monad.

I saw the original Jeffrey Snover Channel 9 video and downloaded the beta then; he just about drop kicks you with his enthusiasm, so I had to try it. My first two co-op terms (internships is another term) were spent as a system administrator, so there will always be a soft spot for a powerful command line\scripting platform in my heart. So I took a look, played around, saw that it was WAY too much to learn, and quickly dropped it. Now that Scott has extolled the virtues of Monad in recordable audio format, I figured I’d give it another try.

Scott’s right when he says it’s rough to start with; there definitely is a learning curve and I don’t think I’m out of the dark yet. But I’ve decided to take the first steps by customizing the bejeezus out of it. The first thing I wanted to do was start every instance with the VS/.NET SDK tools set up. I’m not a huge command line guy in my day-to-day work, but I tend to use the .NET SDK tools when I do. So it would be more convenient to load them every time I run MSH.

You, of course, know the “Visual Studio Command Prompt” menu option in the Visual Studio Tools start menu group is merely a call to cmd.exe with a batch file loaded. Well, I figured my first task would be to rewrite that as a msh script (although not strictly necessary – at least, I think – I figured it was a good place to start scripting), then set it be called whenever I start an instance of msh.exe.

So that’s what I did.

See ya.

Why aren’t you leaving?

Oh alright.

The first part, writing the script, was pretty easy. I opened TextPad with a new document and opened the vsvars32.bat file (located in “%PROGRAMFILES%\Microsoft Visual Studio 8\Common7\Tools”) side by side and started converting.

The file in its entirety is provided below. Download it here. It’s not a very complex script and certainly doesn’t take advantage of the power of the msh script engine, but I still took away a lot from doing this script. First, I forgot what a pain in the ass it is to debug scripts if you’re just learning the syntax. I’m sure once I get going, I’ll be more productive with this, but typos really killed me.

I really like setting variables in msh. You’ll note the syntax for setting variables in different scopes makes it very clear to read. For example, $env:Path is the %PATH% environment variable; $script:tools sets the tools variable for the whole script. One gotcha that I’m not used to is that functions have to be declared before they’re used. I know that dates me as a young’un, but whatever, so I’m not old enough to use C so much. JScript and VBScript don’t have that restriction, and that’s where I’ve done most of my scripting. Another thing I like is variable expansion. If you embed the variable name in a string, msh will expand it for you. That’s very handy for writing file paths as you’ll note below. I put in a few different ways of doing it, just because.

The second part of the problem is to load this for every msh.exe instance. I could do what MS does for the Windows SDK and a have a shortcut that calls msh.exe with some command line arguments, notably the script, but that would mean I have to open every instance from the same shortcut; that’s inconvenient, especially if you’re used to, like I am, opening it up from the Run dialog. The best way to do this for my needs (yours may differ) was to set it up in my profile.msh file located at “My Documents\msh\profile.msh”. This is a place for users to set their own preferences for the shell. I found this post about calling multiple msh scripts from profile.msh but it didn’t quite work for me. I set a variable to the full path of the vsvars32.msh file location and then called . $vsvars, which loads the script for me. I think that’s a unix shell command – the ‘.’ – but it’s been so long since I’ve used unix, so I don’t know. Run gacutil or xsd and watch in churn out the usage message. Sweet, huh?

# vsvars32.msh
# This is a re-write of the vsvars32.bat file that is
# installed by Visual Studio 2005. I did this to learn
# msh script. Your mileage may vary. This is not supported.

$script:VsInstall = "${env:ProgramFiles}\Microsoft Visual Studio 8"
$script:tools = "$script:VsInstall\Common7\Tools"
$script:vc = "$script:VsInstall\VC"

$env:VSINSTALLDIR = $script:VsInstall
$env:VCINSTALLDIR = $script:vc
$env:FrameworkDir = "${env:windir}\Microsoft.NET\Framework"
$env:FrameworkVersion = "v2.0.50727"
$env:FrameworkSDKDir = $script:VsInstall + "\SDK\v2.0"

write-host "Setting environment for using Microsoft Visual Studio 2005 x86 tools."

$env:DevEnvDir = $script:VsInstall + "\Common7\IDE"
$script:FxDir = $env:FrameworkDir + "\" + $env:FrameworkVersion

# ------------------------------------------------------------------
# Prepend a directory to a semi-colon delimited list of directories
# I stole this function from the SetEnv.msh script provided by the Windows SDK
# ------------------------------------------------------------------
function PrependToVar
{
param ([string]$list, [string]$newdir)
	return "$newDir;$list"
}

$Path = PrependToVar $env:Path $env:DevEnvDir
$Path = PrependToVar $Path "$script:vc\bin"
$Path = PrependToVar $Path $script:tools
$Path = PrependToVar $Path "$script:tools\bin"
$Path = PrependToVar $Path "$script:vc\PlatformSDK\bin"
$Path = PrependToVar $Path "$env:FrameworkSDKDir\bin"
$Path = PrependToVar $Path $script:FxDir
$Path = PrependToVar $Path "$script:vc\VCPackages"

$Include = PrependToVar $Include "$script:vc\atlmfc\include"
$Include = PrependToVar $Include "$script:vc\INCLUDE"
$Include = PrependToVar $Include "$script:vc\PlatformSDK\INCLUDE"
$Include = PrependToVar $Include "$script:FrameworkSDKDir\INCLUDE"

$Lib = PrependToVar $Lib "$script:vc\atlmfc\lib"
$Lib = PrependToVar $Lib "$script:vc\lib"
$Lib = PrependToVar $Lib "$script:vc\platformsdk\lib"
$Lib = PrependToVar $Lib "$script:FrameworkSDKDir\lib"

$env:Path = $script:Path
$env:Include = $script:Include
$env:Lib = $script:Lib
$env:LibPath = "$script:FxDir;$script:vc\atlmfc\lib"