65.9K
CodeProject 正在变化。 阅读更多。
Home

从 ref ushort 获取字符串

emptyStarIconemptyStarIconemptyStarIconemptyStarIconemptyStarIcon

0/5 (0投票)

2007年8月17日

2分钟阅读

viewsIcon

18627

处理错误声明为 ref ushort 的字符串参数

引言

MSHTML 的 Microsoft PIA 包含许多方法签名,错误地将字符串参数声明为 ref ushort,导致它们无法使用。

本文解释了如何获取和设置错误声明为 ref ushort 的字符串。

背景

PIA(主互操作程序集)是供应商对某些 COM 对象接口的官方呈现。它已签名等等,因此您无法更改它。当 PIA 包含参数或编组提示的错误声明时,使用错误声明的方法几乎不可能。

您无法通过类型转换来规避这个问题。相关字符串声明为 POLECHAR,它是指向以空字符结尾的 Unicode 字符数组的第一个元素的指针。Unicode 字符宽度为 16 位且无符号,您需要指向它的指针,因此为 ref ushort

可以使用 tlbimp.exe 导入接口,然后更正它们。您所要做的就是将 "ref ushort" 替换为 "string"。但事情从来都不是那么简单。Webbrowser 控件使用 Microsoft PIA,并且 C# 强类型将您的声明和 PIA 等效项视为完全不同的东西。您可以显式类型转换,但您必须类型转换所有内容。这可行,但代码难以阅读且难以维护(我尝试过)。

因此,tblimp.exe 并没有完全出错,但无法直接将 ref ushort 类型转换为 string,我们无法更改互操作程序集,也无法替换它。

现在一切都丢失了……或者不是。Marshal 类登场。

我们像这样获取字符串

//create a managed string and copy the content of the OLECHAR 
//string pointed at by lpwszBlah into this string
string blah = Marshal.PtrToStringUni((IntPtr)lpwszBlah);

并且反过来(如果我们更改它)…

//lpwszBlah is a pointer, so we return a value by writing it to 
//global memory and putting a pointer to the new value into lpwszBlah 
//but first we free the old buffer
Marshal.FreeHGlobal(lpwszBlah);
lpwszBlah = Marshal.StringToHGlobalUni(blah);

关注点

大多数字符串编组方法都有 Unicode、ANSI 和 Auto 版本。Auto 根据底层平台选择 ANSI 或 Unicode 行为。在某些情况下,例如处理 COM,字符串类型与平台无关,这些调用的 Auto 版本将在旧平台上失败。例如,MSHTML 在所有平台上使用 POLECHAR,而 Marshal.PtrToStringAuto((IntPtr)lpwszBlah) 会在 Windows 9x 下将数据错误地解析为 ANSI 字符串。

Marshal 类本身就是一个有趣的焦点。您认为 Microsoft 如何执行所有神奇的转换?当然,您可以使用属性提示该过程,但迟早橡胶会与道路接触,通常 Marshal 会参与其中。Microsoft 非常周到地使这个非常方便的类可以直接访问,并且甚至偏离传统进行了文档记录。

© . All rights reserved.