有没有一种方法可以执行progid谓词的命令,而不必在注册表中挖掘和执行字符串操作?
使用ShObjIdl.idl,我可以运行以下命令来获取默认浏览器的ProgId:
var reg = new ShellObjects.ApplicationAssociationRegistration();
string progID;
reg.QueryCurrentDefault("http", ShellObjects.ASSOCIATIONTYPE.AT_URLPROTOCOL, ShellObjects.ASSOCIATIONLEVEL.AL_EFFECTIVE, out progID);这给了我"ChromeHTML.FHXQEQDDJYXVQSFWM2SVMV5GNA“。在注册表中,我可以看到这个progid有以下shell/open/命令:
"C:\Users\Paul\AppData\Local\Google\Chrome\Application\chrome.exe" -- "%1"是否有一个API可以传递给ProgId,以及动词和参数,它会运行它吗?
我走过的一条路是使用ShellExecuteEx:
var shellExecuteInfo = new SHELLEXECUTEINFO();
shellExecuteInfo.cbSize = Marshal.SizeOf(shellExecuteInfo);
shellExecuteInfo.fMask = SEE_MASK_CLASSNAME;
shellExecuteInfo.hwnd = IntPtr.Zero;
shellExecuteInfo.lpVerb = "open";
shellExecuteInfo.lpFile = "google.com";
shellExecuteInfo.nShow = SW_SHOWNORMAL;
shellExecuteInfo.lpClass = "http";
ShellExecuteEx(ref shellExecuteInfo);但是,由于窗口对lpFile进行检查而导致的“Windows无法找到”错误会失败,因为这与URL无关(from:http://blogs.msdn.com/b/oldnewthing/archive/2010/07/01/10033224.aspx )。
这就是我想出的解决方案:
private static void Main(string[] args)
{
if (!OpenUrlInDefaultBrowser("google.com"))
Console.WriteLine("An error happened");
}
[DllImport("Shlwapi.dll")]
private static extern int AssocQueryString(ASSOCF flags, ASSOCSTR str, string pszAssoc, string pszExtra, StringBuilder pszOut, ref uint pcchOut);
private enum ASSOCF
{
ASSOCF_NONE = 0x00000000
}
private enum ASSOCSTR
{
ASSOCSTR_COMMAND = 1
}
[DllImport("Shell32.dll", CharSet=CharSet.Auto)]
private static extern int SHEvaluateSystemCommandTemplate(string pszCmdTemplate, out string ppszApplication, out string ppszCommandLine, out string ppszParameters);
private static bool OpenUrlInDefaultBrowser(string url)
{
string browserProgId;
if (!GetDefaultBrowserProgId(out browserProgId))
return false;
string browserCommandTemplate;
if (!GetCommandTemplate(browserProgId, out browserCommandTemplate))
return false;
string browserExecutable;
string parameters;
if (!EvaluateCommandTemplate(browserCommandTemplate, out browserExecutable, out parameters))
return false;
parameters = ReplaceSubstitutionParameters(parameters, url);
try
{
Process.Start(browserExecutable, parameters);
}
catch (InvalidOperationException) { return false; }
catch (Win32Exception) { return false; }
catch (FileNotFoundException) { return false; }
return true;
}
private static bool GetDefaultBrowserProgId(out string defaultBrowserProgId)
{
try
{
// midl "C:\Program Files (x86)\Windows Kits\8.0\Include\um\ShObjIdl.idl"
// tlbimp ShObjIdl.tlb
var applicationAssociationRegistration = new ApplicationAssociationRegistration();
applicationAssociationRegistration.QueryCurrentDefault("http", ShellObjects.ASSOCIATIONTYPE.AT_URLPROTOCOL, ShellObjects.ASSOCIATIONLEVEL.AL_EFFECTIVE, out defaultBrowserProgId);
}
catch (COMException)
{
defaultBrowserProgId = null;
return false;
}
return !string.IsNullOrEmpty(defaultBrowserProgId);
}
private static bool GetCommandTemplate(string defaultBrowserProgId, out string commandTemplate)
{
var commandTemplateBufferSize = 0U;
AssocQueryString(ASSOCF.ASSOCF_NONE, ASSOCSTR.ASSOCSTR_COMMAND, defaultBrowserProgId, "open", null, ref commandTemplateBufferSize);
var commandTemplateStringBuilder = new StringBuilder((int)commandTemplateBufferSize);
var hresult = AssocQueryString(ASSOCF.ASSOCF_NONE, ASSOCSTR.ASSOCSTR_COMMAND, defaultBrowserProgId, "open", commandTemplateStringBuilder, ref commandTemplateBufferSize);
commandTemplate = commandTemplateStringBuilder.ToString();
return hresult == 0 && !string.IsNullOrEmpty(commandTemplate);
}
private static bool EvaluateCommandTemplate(string commandTemplate, out string application, out string parameters)
{
string commandLine;
var hresult = SHEvaluateSystemCommandTemplate(commandTemplate, out application, out commandLine, out parameters);
return hresult == 0 && !string.IsNullOrEmpty(application) && !string.IsNullOrEmpty(parameters);
}
private static string ReplaceSubstitutionParameters(string parameters, string replacement)
{
// Not perfect but good enough for this purpose
return parameters.Replace("%L", replacement)
.Replace("%l", replacement)
.Replace("%1", replacement);
}发布于 2012-08-27 02:34:50
显式类不会删除lpFile引用有效资源(文件或URL)的要求。类指定如何执行资源(而不是从文件类型或URL协议推断类),但您仍然必须传递有效的资源。google.com被视为一个文件名,因为它不是一个URL,并且该文件不存在,因此您将得到"not“错误。
通常情况下,您要做的事情比提取命令行要复杂得多,因为大多数浏览器使用DDE而不是命令行作为它们的主要调用。(当DDE失败时,命令行是回退。)
但是,如果确实希望执行命令行,可以使用AssocQueryString获取ASSOCSTR_COMMAND,然后通过SHEvaluateSystemCommandTemplate执行插入以使命令行执行。
发布于 2012-08-26 18:44:55
这里的基本错误是您从http://中忽略了FileName。加上这些,一切都会好起来的。
shellExecuteInfo.lpFile = "http://google.com";您根本不需要设置lpClass。lpFile以http://开头这一事实决定了这个类。
与其自己打电话给ShellExecuteEx,不如让Process为您做这件事:
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = @"http://google.com";
psi.UseShellExecute = true;
Process.Start(psi);甚至:
Process.Start(@"http://google.com");https://stackoverflow.com/questions/12131100
复制相似问题