【问题标题】:How to prompt the "Choose a default program" in code?如何在代码中提示“选择默认程序”?
【发布时间】:2015-04-10 23:55:14
【问题描述】:

我正在编写一个包含项目的列表框的程序,当您右键单击项目时,将弹出上下文菜单并选择调用“打开方式”,我的问题是如何使“选择”显示一个默认程序”窗口,如下图所示。

http://postimg.org/image/8ykfrzmjv/

我知道你需要 Process.Start() 才能打开它,但我不知道 exe 名称。

【问题讨论】:

    标签: c# winforms


    【解决方案1】:

    您可以使用这种方式直接显示“打开方式”对话框:

    string FilePath = "C:\\Text.txt";//Your File Path
    System.Diagnostics.Process proc = new System.Diagnostics.Process();
    proc.EnableRaisingEvents = false;
    proc.StartInfo.FileName = "rundll32.exe";
    proc.StartInfo.Arguments = "shell32,OpenAs_RunDLL " + FilePath;
    proc.Start();
    

    【讨论】:

    • 此入口点未记录,并不总是按预期工作,如有更改,恕不另行通知。 KeithS 的 OpenWithDialog 解决方案是正确的方法。
    【解决方案2】:

    Windows Shell 中的“打开方式...”对话框是 explorer.exe 的一部分,不是它自己的程序。您过去可以使用“openas”动作动词来实现它,但从 Vista 开始,它已被重新定义为“以管理员身份运行”。

    还有一些技巧。其他答案已经演示了 OpenAs_RunDLL 方法;但是应该知道this is an undocumented entry point and does not always work,尤其是在Windows Vista 和更高版本上。 API 中记录的(因此受支持的)入口点是 shell32.dll 中称为 SHOpenWithDialog 的另一个函数。下面是可以解决问题的基于 P/Invoke 的代码:

    public static class OpenWithDialog
    {
        [DllImport("shell32.dll", EntryPoint = "SHOpenWithDialog", CharSet = CharSet.Unicode)]
        private static extern int SHOpenWithDialog(IWin32Window parent, ref OpenAsInfo info);
    
        private struct OpenAsInfo
        {
            [MarshalAs(UnmanagedType.LPWStr)]
            public string FileName;
            [MarshalAs(UnmanagedType.LPWStr)]
            public string FileClass;
            [MarshalAs(UnmanagedType.I4)]
            public OpenAsFlags OpenAsFlags;
        }
    
        [Flags]
        public enum OpenAsFlags
        {
            None = 0x00,
            AllowRegistration = 0x01,
            RegisterExt = 0x02,
            ExecFile = 0x04,
            ForceRegistration = 0x08,
            HideRegistration = 0x20,
            UrlProtocol = 0x40,
            FileIsUri = 0x80,
        }
    
        public static int Show(string fileName, IWin32Window parent = null, string fileClass = null, OpenAsFlags openAsFlags = OpenAsFlags.ExecFile)
        {
            var openAsInfo = new OpenAsInfo
                                 {
                                     FileName = fileName,
                                     FileClass = fileClass,
                                     OpenAsFlags = openAsFlags
                                 };
    
            return SHOpenWithDialog(parent, ref openAsInfo);
        }
    }
    

    在打开的窗口中,如果您从没有附加消息循环的线程运行程序,“浏览”按钮将冻结程序;还建议您传入一个 Form 实例(或 some simple WPF interop magic)作为“父”参数。

    以 HideRegistration 开头的标志是 Vista+,最后一个 (FileIsUri) 是 Windows 8+;它们将在以前的版本中被忽略,这可能会导致不良行为。默认情况下,“openAsFlags”参数设置为使用所选程序打开文件,这是 RunDLL 解决方案并不总是有效的原因之一(此值是 OpenAs_RunDLL 的第二个参数的一部分,不包含在runDLL 命令行)。返回值应为零或正数;负值是符合 WinAPI HRESULT 标准的错误。

    【讨论】:

    • 有没有办法只设置应用程序,设置后不打开?我试图只设置应用程序而不是之后实际打开程序。例如如果我将所有 .txt 文件设置为使用记事本打开,我不希望它使用 txt 文件打开记事本,而只是设置它。这可能吗?
    • 这可能最好通过编辑注册表来完成;在“打开方式”对话框中所做的选择存储在 HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\ 中。您的程序需要完全信任才能执行此操作。
    • Zer0>这可能吗?不可靠。用户的默认设置由 Windows 管理,我上次听到的(故意)未记录的方式/位置,其实施可能会发生变化,恕不另行通知。如果没有 API 来设置它(也不应该有),那么不,你不应该破解系统来直接设置它。这样做会使您与恶意软件及其不那么直接邪恶的用户体验(用户无法控制的表亲)无法区分。应用程序滥用了直接设置用户的默认值,因此 Windows 采取了一些措施来保护它免受直接操纵。
    猜你喜欢
    • 2019-08-15
    • 2013-11-28
    • 2014-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多