我正在使用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 具有非英文字符,则在编码后,它会在 Windows 资源管理器搜索框中错误地显示(HttpUtility.UrlEncode())。例如,如果 rawQuery 是中文的,如"微软",它会在 Windows 资源管理器中搜索 å3/4®è1/2 ̄。这很糟糕。
但是,如果未对 rawQuery 进行编码,则无法在 Windows 资源管理器搜索框中显示特殊字符,如 &、% 等。
所以我不确定如何确定字符是否应该编码。我在搜索协议规范中没有找到任何有关此的文档。
有谁知道应该对哪些字符进行编码?
似乎确实没有关于在搜索查询中应该对什么进行 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 = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ","
现在,在这种特殊情况下,并非所有这些字符都需要编码,并且它们中的大多数都可以不编码地工作,但是如果您想安全起见 - 您可以将它们全部编码,或者通过反复试验来弄清楚(像"&","%","/"这样的字符显然无论如何都必须编码)。