如何从桌面应用程序打开Windows资源管理器并进行搜索?

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资源管理器的搜索框中显示。
所以我不确定应该对哪些字符进行编码。我在搜索协议规范文档中没有找到相关文档。
请问有人知道应该对哪些字符进行编码吗?

1
你尝试过先将它编码为ASCII吗? - Daniel A. White
@Daniel.White 那行不通。你的命令行是ASCII,你可以WINKEY+R,尝试运行“search:computer&query=this&that”,你会看到他所说的问题。 - Stavm
1个回答

1

看起来确实没有关于搜索查询中应该进行url编码的具体文档,但我们可以做出合理的猜测。

首先,HttpUtility.UrlEncode 如何对 Unicode 字符进行编码?根据 RFC 3986,这些字符应该首先表示为 UTF-8 字节,然后这些字节应该被百分比编码。这正是 HttpUtility.UrlEncode 所做的。对于您的字符串:

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

两个字符用六个字节表示,每个字符占用三个字节。它被解码为微软 - 六个字符。因此,搜索查询解码器不支持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的规定,但我们已经知道搜索协议不遵循RFC,因为它允许使用UTF-8字符而无需编码。例如,您可以将类似于¢(ISO-8859-1中的162)的字符编码为%A2,如果您想完全保险,它也可以正常工作,但不进行编码也可以。

现在,我们需要对URL的不同部分中专门用于保留或不允许未转义的ASCII字符进行编码,或者将其视为“可能在使用未转义时导致问题”的字符。RFC指出这些字符包括:

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

现在,在这种特定情况下,并不需要对所有这些字符进行编码,大多数情况下它们可以不经过编码就能正常工作,但是如果您想保险起见,您可以对它们全部进行编码,或通过试验和错误来确定(像"&"、"%"、"/"这样的字符显然必须进行编码)。

你可以通过一些小实验找到这个 - 它是ISO-8859-1编码。 我不仅发现了iso-8859-1,还有Windows-1252、windows-1254、windows-1258、utf-7,会将“微软”解码为“微软”。 - zhhzhang
@zhhzhang 是的,但您可以通过尝试不同的字符串来排除其他编码。例如,在 windows-1252、windows-1254、windows-1258 中,字节代码为 0x80 的字符是欧元符号 ("€")。但是如果您从 "query=%80" 开始搜索,它将不显示该符号,而是显示空格(因为在 iso-8859-1 中,字符 0x80 是不可显示的控制字符)。 - Evk
谢谢!我计划使用iso-8859-1编码将字符编码在0到255之间,以保险起见,如下代码所示。我测试了65536个Unicode字符。它们都在Windows资源管理器搜索框中正确显示。foreach (var c in query.ToCharArray()) { if (Convert.ToInt32(c) < 256) { potocolQuery += HttpUtility.UrlEncode(c.ToString(), Encoding.GetEncoding("iso-8859-1")); } else { potocolQuery += c; } } - zhhzhang

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接