Как правильно получить команду открытия, связанную с расширением в Windows?

Я пытаюсь выяснить исполняемый файл, используемый для открытия файлов с заданным расширением, чтобы я мог отобразить значок этого исполняемого файла, если у расширения его нет.

Мне известно об открытом глаголе в разделе реестра HKEY_CLASSES_ROOT для типа файла, но я обнаружил, что его значение не всегда является правильным.

Например, в настоящее время я использую Windows в Parallels на OS X. По умолчанию ассоциация PDF-файлов была Safari. Я изменил стандартную ассоциацию через обозреватель Adobe Reader. Открытый глагол в реестре по-прежнему Safari, но когда я дважды щелкаю файл PDF, он открывается с помощью Adobe Reader. И 32-разрядный, и 64-разрядный реестр имеют одинаковые значения.

Есть ли лучший способ получить связь с типом файла, с .NET или winapi?

2

Решение

Ваш лучший выбор, вероятно, использовать Assoc* группа функций, таких как AssocQueryKey() а также AssocQueryString() через PInvoke. Однако я не знаю, подходит ли вам один из многих классов, поставляемых с .NET framework во многих его воплощениях. Но Shell API дает вам возможность получить эту информацию.

Также обратите внимание на раздел примечаний, в котором говорится, что вышеуказанные функции являются обертками для IQueryAssociations интерфейс, который делает еще более вероятным, что у вас есть еще один более прямой путь к тому, что вы хотите из .NET.

Функция старого стиля была такой: FindExecutable(). Не используйте его, хотя. Он использует ту же ошибочную магию кода ошибки, что и ShellExecute(),

Также смотрите ответы на Windows: список и запуск приложений, связанных с расширением

3

Другие решения

Мой код, который включает проверку, чтобы предотвратить некоторые распространенные ошибки … Надеюсь, это поможет 🙂

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

namespace HQ.Util.Unmanaged
{
/// <summary>
/// Usage: string executablePath = FileAssociation.GetExecFileAssociatedToExtension(pathExtension, "open");
/// Usage: string command FileAssociation.GetExecCommandAssociatedToExtension(pathExtension, "open");
/// </summary>
public static class FileAssociation
{
/// <summary>
///
/// </summary>
/// <param name="ext"></param>
/// <param name="verb"></param>
/// <returns>Return null if not found</returns>
public static string GetExecCommandAssociatedToExtension(string ext, string verb = null)
{
if (ext[0] != '.')
{
ext = "." + ext;
}

string  executablePath = FileExtentionInfo(AssocStr.Command, ext, verb);

// Ensure to not return the default OpenWith.exe associated executable in Windows 8 or higher
if (!string.IsNullOrEmpty(executablePath) && File.Exists(executablePath) &&
!executablePath.ToLower().EndsWith(".dll"))
{
if (executablePath.ToLower().EndsWith("openwith.exe"))
{
return null; // 'OpenWith.exe' is th windows 8 or higher default for unknown extensions. I don't want to have it as associted file
}
return executablePath;
}
return executablePath;
}

/// <summary>
///
/// </summary>
/// <param name="ext"></param>
/// <param name="verb"></param>
/// <returns>Return null if not found</returns>
public static string GetExecFileAssociatedToExtension(string ext, string verb = null)
{
if (ext[0] != '.')
{
ext = "." + ext;
}

string executablePath = FileExtentionInfo(AssocStr.Executable, ext, verb); // Will only work for 'open' verb
if (string.IsNullOrEmpty(executablePath))
{
executablePath = FileExtentionInfo(AssocStr.Command, ext, verb); // required to find command of any other verb than 'open'

// Extract only the path
if (!string.IsNullOrEmpty(executablePath) && executablePath.Length > 1)
{
if (executablePath[0] == '"')
{
executablePath = executablePath.Split('\"')[1];
}
else if (executablePath[0] == '\'')
{
executablePath = executablePath.Split('\'')[1];
}
}
}

// Ensure to not return the default OpenWith.exe associated executable in Windows 8 or higher
if (!string.IsNullOrEmpty(executablePath) && File.Exists(executablePath) &&
!executablePath.ToLower().EndsWith(".dll"))
{
if (executablePath.ToLower().EndsWith("openwith.exe"))
{
return null; // 'OpenWith.exe' is th windows 8 or higher default for unknown extensions. I don't want to have it as associted file
}
return executablePath;
}
return executablePath;
}

[DllImport("Shlwapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern uint AssocQueryString(AssocF flags, AssocStr str, string pszAssoc, string pszExtra, [Out] StringBuilder pszOut, [In][Out] ref uint pcchOut);

private static string FileExtentionInfo(AssocStr assocStr, string doctype, string verb)
{
uint pcchOut = 0;
AssocQueryString(AssocF.Verify, assocStr, doctype, verb, null, ref pcchOut);

Debug.Assert(pcchOut != 0);
if (pcchOut == 0)
{
return "";
}

StringBuilder pszOut = new StringBuilder((int)pcchOut);
AssocQueryString(AssocF.Verify, assocStr, doctype, verb, pszOut, ref pcchOut);
return pszOut.ToString();
}

[Flags]
public enum AssocF
{
Init_NoRemapCLSID = 0x1,
Init_ByExeName = 0x2,
Open_ByExeName = 0x2,
Init_DefaultToStar = 0x4,
Init_DefaultToFolder = 0x8,
NoUserSettings = 0x10,
NoTruncate = 0x20,
Verify = 0x40,
RemapRunDll = 0x80,
NoFixUps = 0x100,
IgnoreBaseClass = 0x200
}

public enum AssocStr
{
Command = 1,
Executable,
FriendlyDocName,
FriendlyAppName,
NoOpen,
ShellNewValue,
DDECommand,
DDEIfExec,
DDEApplication,
DDETopic
}}
}
0

Вам также необходимо проверить HKEY_USERS \ {User} \ Software \ Classes. Пользователи могут переопределить свое собственное приложение по умолчанию.

-1
По вопросам рекламы [email protected]