The Microsoft PIA for MSHTML is riddled with method signatures that incorrectly declare string parameters as ref ushort, making them unusable.
This article explains how to get and set strings incorrectly declared as
A PIA (primary interop assembly) is the vendor's official rendering of the interfaces of some COM object(s). It's signed and so forth, so you can't alter it. When a PIA contains incorrect declarations of parameters or marshalling hints, it can be nigh impossible to use the incorrectly declared methods.
You can't dodge the problem with typecasting. The strings in question are declared as
POLECHAR, which is a pointer to the first element of a null terminated array of unicode characters. A unicode character is 16 bits wide and unsigned, and you need a pointer to it, hence
You could use
tlbimp.exe to import the interfaces and then correct them. All you have to do is replace "ref ushort" with "string". But nothing is ever that easy. The webbrowser control uses the Microsoft PIA and C# strong typing treats your declarations and the PIA equivalents as totally different. You can explicitly typecast, but you'll have to typecast everything. This works, but the code is illegible and unmaintainable (I tried).
tblimp.exe hasn't exactly got it wrong but there's no way to directly typecast a
ref ushort to a
string, and we can't alter the interop assembly, and we can't replace it.
All is now lost... or not. Enter the
We get the string like this:
string blah = Marshal.PtrToStringUni((IntPtr)lpwszBlah);
And going the other way (if we change it)...
lpwszBlah = Marshal.StringToHGlobalUni(blah);
Points of Interest
There are unicode, ANSI and Auto versions of most of the string marshalling methods. Auto selects ANSI or unicode behaviour depending on the underlying platform. In some cases, such as dealing with COM, the string type is platform invariant and the auto versions of these calls will fail on legacy platforms. For exampe, MSHTML uses POLECHAR on all platforms, and Marshal.PtrToStringAuto((IntPtr)lpwszBlah) would incorrectly parse the data as an ANSI string under Windows 9x.
The Marshal class is a point of interest all on its own. How do you think Microsoft does all that wonderful magic conversion? Sure, you hint the process with attributes, but sooner or later the rubber hits the road, and generally Marshal is involved. Microsoft has very thoughtfully made this incredibly handy class directly accessible, and in a departure from tradition even documented it.
On a personal level (this is a bio, after all) I love gourmet coffee and my wine collection is pretty good. My passion is alpine skiing. On a more technical level, I've been a Delphi/MSSQL hack for donkey's years. VB is a distant memory. It resurfaced as VB.NET but I managed not to get any on me. Java was nice. C# is nicer. Pet peeve: kids today don't appear to know what an RFC is. Or how to spell. My one consolation is that no matter what they get away with at school and on message boards, with a compiler they have to stop their bullshit and spell properly.