繁体   English   中英

如果文件类型没有关联程序,如何使用 Process.Start 打开文件?

[英]How to open file with Process.Start if there is no associated program for the file type?

当我想使用Process.Start打开一个.ico文件时,它会抛出一个错误System.ComponentModel.Win32Exception ,这是因为没有打开该文件的默认程序。 我需要显示 window 到 select 默认程序而不是抛出异常。 我怎样才能做到这一点?

private void btnOpenFile_Click(object sender, EventArgs e)
{
   Process.Start(txtSavedAs.Text);
}

你想要做的是AssocQueryString API。 文档在这里

我使用该 API 来获取与 shell 动词关联的命令字符串。 因此,例如,如果我使用.txt扩展名,它将返回:

C:\Windows\system32\NOTEPAD.EXE %1

现在我们知道 shell 知道要执行什么程序以及如何为该特定扩展传递命令行参数。

因此,如果有与该扩展名关联的“命令”,则可以安全地假设 shell 将知道如何执行该类型的文件; 因此我们应该能够正常使用 ShellExecute。

如果没有与该文件扩展名关联的“命令”,我们将显示“openas”对话框,允许用户选择他们想要打开文件的应用程序。

这是我为完成这项工作而组装的 class:

AppAssociation.cs

using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;

public static class AppAssociation
{
    private static class Win32Native
    {
        public const int ASSOCF_NONE = 0;
        public const int ASSOCSTR_COMMAND = 1;

        [DllImport("shlwapi.dll", CharSet = CharSet.Unicode,
            EntryPoint = "AssocQueryStringW")]
        public static extern uint AssocQueryString(int flags, int str,
            string pszAssoc, string pszExtra, StringBuilder pszOut, ref uint pcchOut);
    }

    public static Process StartProcessForFile(FileInfo file)
    {
        var command = GetCommandForFileExtention(file.Extension);
        return Process.Start(new ProcessStartInfo()
        {
            WindowStyle = ProcessWindowStyle.Normal,
            FileName = file.FullName,
            Verb = string.IsNullOrEmpty(command) ? "openas" : null,
            UseShellExecute = true,
            ErrorDialog = true
        });
    }

    private static string GetCommandForFileExtention(string ext)
    {
        // query length of the buffer we need
        uint length = 0;
        if (Win32Native.AssocQueryString(Win32Native.ASSOCF_NONE,
                Win32Native.ASSOCSTR_COMMAND, ext, null, null, ref length) == 1)
        {
            // build the buffer
            var sb = new StringBuilder((int)length);
            // ask for the actual command string with the right-sized buffer
            if (Win32Native.AssocQueryString(Win32Native.ASSOCF_NONE,
                    Win32Native.ASSOCSTR_COMMAND, ext, null, sb, ref length) == 0)
            {
                return sb.ToString();
            }
        }
        return null;
    }
}

你会这样称呼它:

AppAssociation.StartProcessForFile(new FileInfo(@"c:\MyFiles\TheFile.txt"));

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM