Wednesday, December 15, 2010

MSBuild goodies

1. Inline tasks: no more creating and managing a separate assembly just to execute a piece of non-trivial code during build process.
2. Property functions: if the piece of code is merely a couple of method calls, it can go anywhere $() can go with the $([Class]::Method()) syntax. There are all kinds of limitations and the list of officially whitelisted methods is rather short — e.g. it does not include AssemblyName.GetAssemblyName — but whitelist checks can be disabled by setting the environment variable MSBUILDENABLEALLPROPERTYFUNCTIONS to 1.

Wednesday, November 10, 2010

Bootstrapper package for Windows Imaging Component

Developers who target .NET 4 and choose to create a proper bootstrapper for their installer have been bit repeatedly by installation failures on Windows XP SP2 and Windows Server 2003. .NET 4 fails to install on these admittedly outdated, but still widespread OSes because it depends on the Windows Imaging Component, which appears in XP SP3, Vista, 7 and 2008 Server and is installed with .NET 3.5 SP1. These OSes increasingly being the majority, Microsoft decided to leave WIC out of the .NET 4 installer in order to reduce the download size, a laudable intention. Since they actually documented this, there is no cause to complain; but why not also provide a bootstrapper package for WIC in the Windows SDK since it began to include packages for .NET 4? Developers usually direct the bootstrapper to download Microsoft files from the home site, so setup size would not increase appreciably.
Anyway. I created a WIC bootstrapper package and tested it on XP SP2, XP SP3 and 7. I also added a dependence on WIC to the .NET 4 packages. No warranty; use at own risk but comments welcome!

Thursday, June 24, 2010

How to use SSL3 instead of TLS in a particular HttpWebRequest

My application has to talk to different hosts over https, and the default setting of ServicePointManager.SecurityProtocol = TLS served me well. The other day, though, I had some NetWare hosts which (as System.Net trace log shows) don't answer the initial TLS handshake message but keep the underlying connection open until it times out, throwing a timeout exception. It seems that Netware's policy regarding unrecognized/invalid requests is not to respond or give any error messages, presumably to reduce attack surface. Very understandable, but this behaviour does not give .NET's built-in TLS-to-SSL3 fallback mechanism a chance to kick in.
I really didn't want to have to degrade the security protocol setting to SSL3 in the whole application for the sake of a few musty Netware hosts, but this ServicePointManager setting is global and there is no way to force a downgrade through HttpWebRequest. Luckily, 'global' has more than one meaning in the .NET world; ServicePointManager settings are actually per-appdomain. This enabled me to work around the problem by creating a separate appdomain set up to use only SSL3, making my data collection object MarshalByRefObject (WebClient and WebRequest are marshal-by-ref too, but better to reduce the number of cross-appdomain calls and avoid marshaling anything more complicated than a string) and creating it there. Worked perfectly combined with a timeout-based detection scheme.