01 May 2012
Run MbUnit v2 tests under .NET 4
We still use MbUnit v2 for some of our assemblies, primarily because the items mentioned in the migration guide still haven't been implemented in MbUnit v3, and we haven't taken the time to port the tests to NUnit.
I wanted to compile our code for .NET 4 and still run all the existing tests against it.
The test runner (MbUnit.Cons.exe) is a .NET 1.1 app, so by default it will
fail to load a .NET 4 test assembly. You can use the <supportedRuntime> configuration element
to force the program to run under .NET 4,
but it still fails to load the test assembly.
The message printed at the console isn't helpful, but if you debug the test runner, the following exception occurs:
NotSupportedException: This method implicitly uses CAS
policy, which has been obsoleted by the .NET Framework.
In order to enable CAS policy for compatibility reasons,
please use the NetFx40_LegacySecurityPolicy configuration
switch.
Please see http://go.microsoft.com/fwlink/?LinkID=155570
for more information.
This occurs because MbUnit uses the obsolete Assembly.Load(string, Evidence)
method. To fix this, add the NetFx40_LegacySecurityPolicy configuration
element, as instructed by the exception message.
Ultimately, your MbUnit.Cons.exe.config file should look as follows:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<runtime>
<!-- Don't kill application on first uncaught exception. -->
<legacyUnhandledExceptionPolicy enabled="1" />
<!-- Use legacy CAS policy so MbUnit's assembly loading succeeds. -->
<NetFx40_LegacySecurityPolicy enabled="true"/>
</runtime>
<!-- Force use of .NET 4. -->
<startup>
<supportedRuntime version="v4.0" />
</startup>
</configuration>
With this new configuration, MbUnit can successfully run under .NET 4 and load .NET 4 assemblies. However, it still runs as a 32-bit process, so "Any CPU" test assemblies will get loaded as 32-bit. To make it run as 64-bit, you can use the CorFlags utility. As per the StackOverflow wiki, an "Any CPU" application should be a PE32 executable with the 32BIT flag cleared.
To change MbUnit to an "Any CPU" executable (so it runs as 64-bit on an x64 system), run:
CorFlags /UpgradeCLRHeader /32BIT- MbUnit.Cons.exe
Posted by Bradley Grainger at 07:30 AM
23 February 2012
Persistent Hash Codes
What does "hello".GetHashCode() return?
The answer is: it depends.
Under the Microsoft .NET 4 CLR, that method returns 0xFFF561E1 in a 32-bit application,
but 0xEC7BF82A in a 64-bit build. Other runtimes, such as Mono and the Compact Framework,
might return other values.
As per the documentation, “The behavior of GetHashCode is dependent on its implementation, which might change from one version of the common language runtime to another. … The value returned by GetHashCode is platform-dependent. It differs on the 32-bit and 64-bit versions of the .NET Framework.”
In certain scenarios (e.g., saving a hash code to a file, or creating a hash code on a 32-bit client and using it on a 64-bit server), it's useful to have an algorithm that will always generate the same hash code for the same input.
Based on Paul Hsieh‘s SuperFastHash,
Bob Jenkin‘s hash function, and
Thomas Wang‘s Integer Hash Function,
we developed HashCodeUtility.GetPersistentHashCode. (The C# methods are basically a straightforward
port of the corresponding C functions.)
These methods perform a thorough mixing of their input (so the return value works well as a key in a hashtable), have good performance, and will always return the same result no matter what version of the CLR they're running on.
The source is available on GitHub: HashCodeUtility.cs, HashCodeUtilityTests.cs.
For information about the CombineHashCodes method in those files, see my earlier post,
Creating hash codes.
Posted by Bradley Grainger at 06:32 AM
18 February 2012
Ascii85 implementation in C#
Ascii85 is an encoding scheme that converts 4 bytes into 5 ASCII characters (in the range ! through u). As a result, it only has 25% encoding overhead compared to the 33% of Base64.
I recently needed to smuggle some binary data through HTTP headers without exceeding the message length limit; Ascii85 seemed like the best choice.
There were a couple of implementations available on the bathroom wall of code, but they had various problems that precluded their use:
- No tests
- Few comments
- Unknown license
- Violated .NET Framework Design Guidelines
- NIH
So I wrote my own. The code is available on GitHub: Ascii85.cs, Ascii85Tests.cs
As with the other code on this blog, it's released under a MIT-style license.
Posted by Bradley Grainger at 11:25 AM
04 January 2012
WebException: "The message length limit was exceeded"
An uncommon WebException thrown by HttpWebRequest.GetResponse() has the message
"The underlying connection was closed: The message length limit was exceeded."
By default, HttpWebResponse only allows 64KB of HTTP headers; any more and
it will throw this exception.
To resolve the issue, set the MaximumResponseHeadersLength
property on the request to a larger value, or to -1 for no limit. (Note that the value is
expressed in kilobytes, so the default value 64 allows 65,536 bytes of headers.)
Posted by Bradley Grainger at 01:04 PM
02 January 2012
Avoid System.Windows.Rect.ToString()
System.Windows.Rect.ToString() is documented as returning a string in “the following form: "X,Y,Width,Height"”.
It seems like this method is the complement to the Parse method, which accepts the “string representation of the rectangle, in the form "x, y, width, height"”.
Unfortunately, while Parse is culture-invariant (as documented), ToString follows the .NET convention
of returning locale-sensitive results; you need to call the ToString(IFormatProvider) overload
to produce a string in the "x,y,width,height" format (that can be accepted by Parse).
Rect rect = new Rect(1.5, 2, 3.5, 4);
string s;
s = rect.ToString(); // "1.5,2,3.5,4"
Rect.Parse(s); // success
Thread.CurrentThread.CurrentCulture = new CultureInfo("de"); // or "es", "fr", etc.
s = rect.ToString(); // "1,5;2;3,5;4"
Rect.Parse(s); // throws FormatException
s = rect.ToString(CultureInfo.InvariantCulture);
Rect.Parse(s); // success
I filed a bug report, even though this is arguably an error in the documentation, not in the .NET Framework itself.
Posted by Bradley Grainger at 12:03 PM
30 December 2011
Printing from .NET 3.5 in Windows 7
Our users discovered a curious bug that appears to be caused by:
- Printing an XpsDocument
- that uses a font embedded in the application's resources
- from a .NET 3.5 application
- running on Windows 7
The printed output looks like the following image; various glyphs are substituted with larger sans-serif versions of themselves, causing a ransom-note-like appearance.

We found that changing any one of the conditions above fixes the problem, but unfortunately we need to print XPS using an embedded font, we're still using .NET 3.5, and we have to run on Windows 7.
Strangely enough, printing to the XPS Document Writer print driver, and then printing that document with the XPS Viewer built into Windows 7 doesn't reproduce the problem; it only happens when our app prints directly to an actual printer.
Workaround
I noticed that the XPS Viewer is a native application; this led me to discover the Windows 7 XPS Print API. In conjunction with the (also new in Windows 7) XPS Document API, this lets you print XPS documents from native code.
We were able to solve the problem by automating the workaround described above: our code writes its output to an XpsDocumentWriter backed by a temporary file (instead of a PrintQueue); we then use the native APIs to print the temporary XPS file to the currently-selected printer.
The first part is to define the native methods and COM interfaces we will need.
(And, as noted in this StackOverflow question,
the IXpsPrintJobStream interface is either declared or implemented incorrectly, so we
have to call the Close method as if it existed on ISequentialStream.)
With those declared, the printing code can be written. This method (which should be called on a
background thread), prints a XPS file to a specific printer, returning true if printing
succeeded. (If it fails, the application should fall back to the .NET printing APIs.)
All the code below is also available in a gist.
internal static class NativeMethods
{
[DllImport("XpsPrint.dll", ExactSpelling = true, CharSet = CharSet.Unicode)]
public static extern int StartXpsPrintJob(string printerName, string jobName, string outputFileName, IntPtr progressEvent,
SafeWaitHandle completionEvent, [MarshalAs(UnmanagedType.LPArray)] byte[] printablePagesOn, int printablePagesOnCount,
out IXpsPrintJob xpsPrintJob, out IXpsPrintJobStream documentStream, out IXpsPrintJobStream printTicketStream);
}
[ComImport, Guid("E974D26D-3D9B-4D47-88CC-3872F2DC3585"), ClassInterface(ClassInterfaceType.None)]
internal class XpsOMObjectFactory
{
}
[ComImport, Guid("F9B2A685-A50D-4FC2-B764-B56E093EA0CA"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IXpsOMObjectFactory
{
void CreatePackage();
[return: MarshalAs(UnmanagedType.Interface)]
IXpsOMPackage CreatePackageFromFile([MarshalAs(UnmanagedType.LPWStr)] string filename, bool reuseObjects);
void CreatePackageFromStream();
void CreateStoryFragmentsResource();
void CreateDocumentStructureResource();
void CreateSignatureBlockResource();
void CreateRemoteDictionaryResource();
void CreateRemoteDictionaryResourceFromStream();
void CreatePartResources();
void CreateDocumentSequence();
void CreateDocument();
void CreatePageReference();
void CreatePage();
void CreatePageFromStream();
void CreateCanvas();
void CreateGlyphs();
void CreatePath();
void CreateGeometry();
void CreateGeometryFigure();
void CreateMatrixTransform();
void CreateSolidColorBrush();
void CreateColorProfileResource();
void CreateImageBrush();
void CreateVisualBrush();
void CreateImageResource();
void CreatePrintTicketResource();
void CreateFontResource();
void CreateGradientStop();
void CreateLinearGradientBrush();
void CreateRadialGradientBrush();
void CreateCoreProperties();
void CreateDictionary();
void CreatePartUriCollection();
void CreatePackageWriterOnFile();
void CreatePackageWriterOnStream();
void CreatePartUri();
void CreateReadOnlyStreamOnFile();
}
[ComImport, Guid("18C3DF65-81E1-4674-91DC-FC452F5A416F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IXpsOMPackage
{
void GetDocumentSequence();
void SetDocumentSequence();
void GetCoreProperties();
void SetCoreProperties();
void GetDiscardControlPartName();
void SetDiscardControlPartName();
void GetThumbnailResource();
void SetThumbnailResource();
void WriteToFile();
void WriteToStream(IXpsPrintJobStream stream, bool optimizeMarkupSize);
};
// NOTE: It appears that the IID for IXpsPrintJobStream specified in XpsPrint.h --
// MIDL_INTERFACE("7a77dc5f-45d6-4dff-9307-d8cb846347ca") -- is not correct, or the object
// doesn't implement QueryInterface correctly. However, we can QI for ISequentialStream and
// successfully (at least in Windows 7 SP1 x86) call the Close method as if it existed on that
// interface.
// That is, we obtain the ISequentialStream interface, but work with it as the IXpsPrintJobStream interface.
// Thanks to http://stackoverflow.com/questions/6123507/xps-printing-from-windows-service for this tip.
[ComImport, Guid("0C733A30-2A1C-11CE-ADE5-00AA0044773D"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IXpsPrintJobStream
{
// ISequentialStream methods
void Read([MarshalAs(UnmanagedType.LPArray)] byte[] pv, uint cb, out uint pcbRead);
void Write([MarshalAs(UnmanagedType.LPArray)] byte[] pv, uint cb, out uint pcbWritten);
// IXpsPrintJobStream methods
void Close();
}
[ComImport, Guid("5AB89B06-8194-425F-AB3B-D7A96E350161"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IXpsPrintJob
{
void Cancel();
IntPtr GetJobStatus();
};
/// <summary>
/// Prints the specified XPS document to a printer using the native XPS Print API.
/// </summary>
/// <param name="xpsFilePath">The path to the XPS document.</param>
/// <param name="printerName">The printer name.</param>
/// <param name="printTicket">A PrintTicket with settings for this print job.</param>
/// <returns><c>true</c> if the document was successfully printed; otherwise, <c>false</c>.</returns>
/// <remarks>This method should be called from a background thread.</remarks>
public bool Print(string xpsFilePath, string printerName, PrintTicket printTicket)
{
// try to create the XPS Object Model factory (only available on Windows 7 and Vista with the Platform Update)
IXpsOMObjectFactory xpsFactory = null;
try
{
xpsFactory = (IXpsOMObjectFactory)new XpsOMObjectFactory();
}
catch (COMException)
{
// OS doesn't support the XPS Document API
return false;
}
bool success = false;
IXpsOMPackage package = null;
try
{
// load the saved document as a native XpsOMPackage
package = xpsFactory.CreatePackageFromFile(xpsFilePath, false);
using (ManualResetEvent handle = new ManualResetEvent(false))
{
// attempt to start the print job
IXpsPrintJob printJob;
IXpsPrintJobStream docStream, ticketStream;
int hresult = NativeMethods.StartXpsPrintJob(printerName, jobTitle, null, IntPtr.Zero, handle.SafeWaitHandle,
null, 0, out printJob, out docStream, out ticketStream);
// check for success (NOTE: checking HRESULT value directly instead of calling Marshal.ThrowExceptionForHR
// to avoid proliferation of 'catch' blocks)
if (hresult >= 0)
{
// write the current printer settings to the print ticket stream
byte[] ticketData = printTicket.GetXmlStream().ToArray();
uint bytesWritten;
ticketStream.Write(ticketData, (uint)ticketData.Length, out bytesWritten);
ticketStream.Close();
// write the XPS package to the document stream
package.WriteToStream(docStream, false);
docStream.Close();
// wait for printing to finish
handle.WaitOne();
success = true;
}
}
}
catch (COMException)
{
// printing failed
}
catch (DllNotFoundException)
{
// OS doesn't support XPS Print API
}
catch (EntryPointNotFoundException)
{
// OS doesn't support XPS Print API
}
// force the XPS package to be released, so that the temporary file can be deleted
if (package != null)
Marshal.FinalReleaseComObject(package);
return success;
}
Posted by Bradley Grainger at 04:01 PM
09 June 2011
Git Bash in Console2
I started using Console2 after reading Scott Hanselman’s recommendation. Not only can it display a regular command prompt and PowerShell in tabs (as he describes), any console process can be added. msysgit users can add Git Bash to by opening the Settings dialog and adding a tab with the following properties:
- Title: Git Bash
- Icon: C:\Program Files (x86)\Git\etc\git.ico
- Shell: C:\Windows\SysWOW64\cmd.exe /c ""C:\Program Files (x86)\Git\bin\sh.exe" --login -i"
- Startup dir: C:\YourCode
Posted by Bradley Grainger at 10:26 AM
13 April 2011
Generating a deterministic GUID
Although a new GUID is typically created in order to provide a unique ID, there are occasions when it’s useful for two different systems to generate the same GUID independently. RFC 4122 provides an algorithm for deterministic creation of a GUID based on a namespace ID (itself a GUID) and a name within that namespace. These name- based GUIDs will never collide with GUIDs from other sources (e.g., Guid.NewGuid), and have a very (very) small chance of colliding with other name-based GUIDs. As per section 4.3:
- The UUIDs generated at different times from the same name in the same namespace MUST be equal.
- The UUIDs generated from two different names in the same namespace should be different (with very high probability).
- The UUIDs generated from the same name in two different namespaces should be different with (very high probability).
- If two UUIDs that were generated from names are equal, then they were generated from the same name in the same namespace (with very high probability).
Because the .NET Framework doesn’t provide a way to create these GUIDs, it’s tempting to create a custom solution (e.g., using a MD5 hash as a GUID, because it has the same number of bytes), but because that doesn’t follow the rules of GUID creation, it’s not guaranteed to be unique with respect to other GUIDs.
The algorithm for generating these GUIDs is fairly straightforward; the most complicated part may be converting the GUID to network byte order as specified in the RFC. (It’s complicated enough that the RFC authors got it wrong; the example given in Appendix B is incorrect.)
There are libraries to do this for Python and C++; I didn’t find one for .NET, so I wrote GuidUtility.Create which implements the RFC 4122 rules. Using it is simple (once you’ve decided on the namespace ID to use):
Guid guid = GuidUtility.Create(GuidUtility.DnsNamespace, "code.logos.com");
Posted by Bradley Grainger at 06:31 PM
29 December 2010
Binary Patching with bsdiff in C#
bsdiff and bspatch are tools for building and applying patches to binary files. If the files are reasonably similar (e.g., built from the same source code), a patch that can transform v1 of a file into v2 is often significantly smaller than downloading the entire v2 file. According to Naïve Differences of Executable Code (the paper that introduced the algorithm), compression ratios of 10x or more are typically achieved.
The reference implementation is written in C and uses bzip2 to compress chunks in the patch file. I ported the algorithm to C# and used #ziplib for bzip2 support.
The primary file is BinaryPatchUtility.cs; the entire project (with bsdiff and bspatch front ends) is available at github. (Note that if you just want to run bsdiff from the command prompt, a Windows port is already available. This project is designed for reuse within another program, under the same license as the original bsdiff code.)
Posted by Bradley Grainger at 04:00 PM
16 December 2010
DirectoryInfo.GetFiles improved in .NET 4
A nice improvement in .NET 4 is that the following code runs significantly faster than it did under .NET 3.5:
new DirectoryInfo(folderPath)
.GetFiles()
.Select<FileInfo, long>(fi => fi.Length)
.ToList();
In .NET 3.5, the Length property (as well as most of the other properties on
FileInfo) is fetched lazily; accessing the property hits the filesystem
again for each file returned by GetFiles, incurring a substantial speed
penalty. In .NET 4, GetFiles uses the information already returned by the OS when
enumerating the contents of the directory to pre-populate the values of the
FileInfo properties, avoiding subsequent filesystem accesses.
For a folder containing several thousand files, the .NET 4 implementation can be from three times (on a local drive) to 50 times (on a network path) faster.
For more information on this and other changes, see Justin Van Patten's MSDN magazine article, What's New in the Base Class Libraries in .NET Framework 4.
Posted by Bradley Grainger at 08:30 PM