4

我正在使用 c#/.net 开发一个 windows 桌面应用程序,并希望添加一个功能来打开 windows 资源管理器并从应用程序中搜索计算机中的查询。

我打算使用 Windows 搜索协议来实现它。下面是我的代码片段。rawQuery 从我的应用程序传递到 Windows 资源管理器搜索框。

var query = "&query=" + HttpUtility.UrlEncode(rawQuery);
var location = string.Empty;
foreach (var drive in DriveInfo.GetDrives().Where(d => d.IsReady && d.DriveType.Equals(DriveType.Fixed)))
{
    location += "&crumb=location:" + HttpUtility.UrlEncode(drive.Name);
}
var searchQuery = "search:displayname=Search computer" + query + location;
Process.Start(searchQuery);

上面的代码有问题。如果 rawQuery 包含非英文字符,则在编码后(HttpUtility.UrlEncode())在 Windows 资源管理器搜索框中显示不正确。例如,如果 rawQuery 是中文的,如“微软”,它会在 Windows 资源管理器中搜索 微软。这不好。

但是,如果 rawQuery 未编码,则无法在 Windows 资源管理器搜索框中显示特殊字符,如 &、% 等。

所以我不确定如何确定字符是否应该被编码。我在search protocol spec中没有找到任何相关文档。

有人知道应该编码哪些字符吗?

4

1 回答 1

1

似乎确实没有关于在搜索查询中究竟应该对什么进行 url 编码的文档,但我们可以做出有根据的猜测。

首先,如何HttpUtility.UrlEncode编码 unicode 字符?根据RFC 3986,此类字符应首先表示为 UTF-8 字节,然后这些字节应进行百分号编码。就是HttpUtility.UrlEncode这样。对于您的字符串:

var encoded = HttpUtility.UrlEncode(rawQuery); // = %e5%be%ae%e8%bd%af

2 个字符用 6 个字节表示,每个字符 3 个字节。它被解码为微软- 6 个字符。所以很明显,搜索查询解码器不期望 UTF-8 字符编码。它期望哪种编码?你可以通过一些小实验找到它——它是ISO-8859-1编码。您可以使用以下代码验证您的特定情况:

var rawQuery = "微软";
var encoded = HttpUtility.UrlEncode(rawQuery);
var iso = Encoding.GetEncoding("iso-8859-1");
var decoded = HttpUtility.UrlDecode(encoded, iso); // outputs "微软"

因此我们可以得出结论,对 ISO-8859-1 之外的任何内容进行编码是没有意义的,并且会产生无效的结果,因为这些字符无法在这种编码中表示(它只是 8 位的)。

应该在该集合中编码什么?ASCII 以上的任何内容(因此字符 128-256)都可以在不编码的情况下传递。这当然违反了 RFC,但我们已经知道搜索协议无论如何都不会遵循它,因为它允许 UTF-8 字符不编码。如果您想完全安全,您可以将像 ¢(ISO-8859-1 中的 162)这样的字符编码为 %A2,它可以工作,但没有它也可以工作。

现在我们需要对 ASCII 字符进行编码,这些字符在 url 的不同部分保留用于特殊用途,或者根本不允许(未转义),或者被视为“使用未转义时可能会导致问题”。RFC 说这样的字符是:

control     = <US-ASCII coded characters 00-1F and 7F hexadecimal>
space       = <US-ASCII coded character 20 hexadecimal>
delims      = "<" | ">" | "#" | "%" | <">
unwise      = "{" | "}" | "|" | "\" | "^" | "[" | "]" | "`"
reserved    = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ","

现在,在这种特殊情况下,并非所有这些字符都需要编码,并且它们中的大多数都可以在未编码的情况下工作,但如果你想安全起见 - 你可以将它们全部编码,或者通过试验来解决错误(像“&”、“%”、“/”这样的字符显然无论如何都必须编码)。

于 2017-04-10T08:45:12.290 回答