jjzjj

c# - 为 ProgId 动词运行命令

coder 2024-06-09 原文

有没有一种方法可以执行 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/command:

"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);

但是由于 Window 正在检查 lpFile 而失败并出现“Windows 找不到”错误,我不希望发生这种情况,因为它与 URL 无关(来自: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);
    }

最佳答案

显式类不会删除 lpFile 引用有效资源(文件或 URL)的要求。该类指定资源应如何执行(而不是从文件类型或 URL 协议(protocol)推断类),但您仍然必须传递有效的资源。 google.com 被视为文件名,因为它不是 URL,并且该文件不存在,因此您会收到“未找到”错误。

您尝试执行的一般情况比仅提取命令行更复杂,因为大多数浏览器使用 DDE 而不是命令行作为其主要调用。 (命令行是 DDE 失败时的回退。)

但如果真的要执行命令行,可以使用AssocQueryString获取ASSOCSTR_COMMAND,然后通过SHEvaluateSystemCommandTemplate执行插入> 让命令行执行。

关于c# - 为 ProgId 动词运行命令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12131100/

有关c# - 为 ProgId 动词运行命令的更多相关文章

  1. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  2. ruby - 在 Ruby 中编写命令行实用程序 - 2

    我想用ruby​​编写一个小的命令行实用程序并将其作为gem分发。我知道安装后,Guard、Sass和Thor等某些gem可以从命令行自行运行。为了让gem像二进制文件一样可用,我需要在我的gemspec中指定什么。 最佳答案 Gem::Specification.newdo|s|...s.executable='name_of_executable'...endhttp://docs.rubygems.org/read/chapter/20 关于ruby-在Ruby中编写命令行实用程序

  3. ruby - 如何每月在 Heroku 运行一次 Scheduler 插件? - 2

    在选择我想要运行操作的频率时,唯一的选项是“每天”、“每小时”和“每10分钟”。谢谢!我想为我的Rails3.1应用程序运行调度程序。 最佳答案 这不是一个优雅的解决方案,但您可以安排它每天运行,并在实际开始工作之前检查日期是否为当月的第一天。 关于ruby-如何每月在Heroku运行一次Scheduler插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/8692687/

  4. ruby-on-rails - 如何在 ruby​​ 中使用两个参数异步运行 exe? - 2

    exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby​​中使用两个参数异步运行exe吗?我已经尝试过ruby​​命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何ruby​​gems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除

  5. ruby - 无法运行 Rails 2.x 应用程序 - 2

    我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby​​:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r

  6. ruby - Sinatra:运行 rspec 测试时记录噪音 - 2

    Sinatra新手;我正在运行一些rspec测试,但在日志中收到了一堆不需要的噪音。如何消除日志中过多的噪音?我仔细检查了环境是否设置为:test,这意味着记录器级别应设置为WARN而不是DEBUG。spec_helper:require"./app"require"sinatra"require"rspec"require"rack/test"require"database_cleaner"require"factory_girl"set:environment,:testFactoryGirl.definition_file_paths=%w{./factories./test/

  7. ruby-on-rails - 无法让 rspec、spork 和调试器正常运行 - 2

    GivenIamadumbprogrammerandIamusingrspecandIamusingsporkandIwanttodebug...mmm...let'ssaaay,aspecforPhone.那么,我应该把“require'ruby-debug'”行放在哪里,以便在phone_spec.rb的特定点停止处理?(我所要求的只是一个大而粗的箭头,即使是一个有挑战性的程序员也能看到:-3)我已经尝试了很多位置,除非我没有正确测试它们,否则会发生一些奇怪的事情:在spec_helper.rb中的以下位置:require'rubygems'require'spork'

  8. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  9. C# 到 Ruby sha1 base64 编码 - 2

    我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha

  10. ruby-on-rails - before_filter 运行多个方法 - 2

    是否有可能:before_filter:authenticate_user!||:authenticate_admin! 最佳答案 before_filter:do_authenticationdefdo_authenticationauthenticate_user!||authenticate_admin!end 关于ruby-on-rails-before_filter运行多个方法,我们在StackOverflow上找到一个类似的问题: https://

随机推荐