如何在 Windows 10 或 11 中调用用于关联文件格式的“打开方式”对话框?

问题描述 投票:0回答:0

我想要什么?

我想调出只用于指定格式文件关联,不会打开文件的打开方式对话框

现有的实现:Bandizip 可以做到!

我尝试了什么?

调用废弃的 Win32 API

MSDN 文档说,从 Windows 10 开始,无法调用

SHOpenWithDialog
来设置指定格式的文件关联。

调用系统命令行

当我尝试调用以下两个命令时,“打开方式”对话框都无法设置文件关联,并且会打开文件。

  • OpenWith.exe "%1"
  • rundll32.exe shell32.dll,OpenAs_RunDLL "%1"

%1 是一个完整的文件路径。

使用 openas 动词

我尝试使用

openas
动词启动一个进程,无论是调用 CreateProcess 还是 ShellExecuteEx,我认为它们最终都会做同样的事情。 “打开方式”对话框将显示一个名为“始终使用此应用程序打开”的复选框,就像从文件的上下文菜单中单击“打开方式”一样。但这将打开文件,并且对于没有设置文件关联的扩展名会抛出异常。

  • 创建进程
public static void ShowOpenWithDialog(string extension)
{
    string tempPath = $"{Path.GetTempPath()}{Guid.NewGuid()}{extension}";
    File.WriteAllText(tempPath, "");
    using(Process process = new Process())
    {
        process.StartInfo = new ProcessStartInfo
        {
            UseShellExecute = true,
            FileName = tempPath,
            Verb = "openas"
        };
        process.Start();
    }
    File.Delete(tempPath);
}
struct ShellExecuteInfo
{
    public int Size;
    public uint Mask;
    public IntPtr hwnd;
    public string Verb;
    public string File;
    public string Parameters;
    public string Directory;
    public uint Show;
    public IntPtr InstApp;
    public IntPtr IDList;
    public string Class;
    public IntPtr hkeyClass;
    public uint HotKey;
    public IntPtr Icon;
    public IntPtr Monitor;
}

[DllImport("shell32.dll")]
static extern bool ShellExecuteEx(ref ShellExecuteInfo lpExecInfo);

const uint SW_NORMAL = 1;

static void ShowOpenWithDialog()
{
    string tempPath = $"{Path.GetTempPath()}{Guid.NewGuid()}{extension}";
    File.WriteAllText(tempPath, "");
    var sei = new ShellExecuteInfo
    {
        sei.Size = Marshal.SizeOf(sei),
        sei.Verb = "openas",
        sei.File = tempPath,
        sei.Show = SW_NORMAL,
    };
    ShellExecuteEx(ref sei);
}

在 UWP 中调用 Launcher.LaunchFileAsync

启动文件的默认应用程序 - 打开方式启动

发现通过这个方法可以调出open with dialog,但是效果和上面的方法没什么区别

async void DefaultLaunch()
{
   // Path to the file in the app package to launch
      string imageFile = @"images\test.png";
   var file = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFileAsync(imageFile);
   if (file != null)
   {
      // Set the option to show the picker
      var options = new Windows.System.LauncherOptions();
      options.DisplayApplicationPicker = true;
      // Launch the retrieved file
      bool success = await Windows.System.Launcher.LaunchFileAsync(file, options);
      if (success)
      {
         // File launched
      }
      else
      {
         // File launch failed
      }
   }
   else
   {
      // Could not find file
   }
}
c# c++ winapi
© www.soinside.com 2019 - 2024. All rights reserved.