如何调用Windows10/11中仅用于设置文件格式关联的「打开方式」对话框?
需求说明
我希望调用仅用于指定文件格式关联、不会打开文件的「打开方式」对话框。
Win10中的样式如下:
Win11中的样式如下:
这个对话框在系统设置中修改默认应用时会显示,已有第三方软件(如Bandizip)实现了此功能:
已尝试方法
调用已废弃的Win32 API
MSDN文档指出,从Windows 10开始,无法通过调用SHOpenWithDialog来设置指定格式的文件关联。
调用系统命令行
我尝试执行以下两个命令,弹出的「打开方式」对话框均无法设置文件关联,且会打开文件:
OpenWith.exe "%1"rundll32.exe shell32.dll,OpenAs_RunDLL "%1"
%1为文件的完整路径。
使用openas动词
我尝试通过CreateProcess或ShellExecuteEx启动带有openas动词的进程,二者最终效果一致:弹出的「打开方式」对话框会显示「始终使用此应用打开」复选框,和右键菜单中点击「打开方式」的效果相同,但会打开文件,且无关联的扩展名会抛出异常。
CreateProcess实现代码
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); }
ShellExecuteEx实现代码
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 { Size = Marshal.SizeOf(sei), Verb = "openas", File = tempPath, Show = SW_NORMAL, }; ShellExecuteEx(ref sei); }
调用UWP中的Launcher.LaunchFileAsync
通过该方法调用「打开方式」对话框,但效果与上述方法一致:
async void DefaultLaunch() { // 应用包内要启动的文件路径 string imageFile = @"images test.png"; var file = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFileAsync(imageFile); if (file != null) { // 设置显示选择器的选项 var options = new Windows.System.LauncherOptions(); options.DisplayApplicationPicker = true; // 启动选中的文件 bool success = await Windows.System.Launcher.LaunchFileAsync(file, options); if (success) { // 文件已启动 } else { // 文件启动失败 } } else { // 未找到文件 } }
内容的提问来源于stack exchange,提问作者蓝点lilac
相关产品推荐
相关产品推荐

