Связано ли приложение с данным расширением? - PullRequest
12 голосов
/ 03 марта 2012

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

System.Diagnostics.Process.Start("Filename.pdf");


Чтобы открыть изображение, вы просто должны использовать тот же код с другим именем файла:

System.Diagnostics.Process.Start("Filename.gif");


Некоторые расширения (например, .gif) всегда имеют обработчик по умолчанию, даже в базовой установке Windows. Однако некоторые расширения (например, .pdf) часто не имеют установленного приложения для их обработки.

В этих случаях было бы желательно определить, связано ли приложение с расширением файла, который вы хотите открыть, прежде чем выполнять вызов Process.Start (fileName).

Мне интересно, как вам лучше всего реализовать что-то вроде этого:

static bool ApplicationAssociated(string extension)
{
    var extensionHasAssociatedApplication = false;

    var condition = // Determine if there is an application installed that is associated with the provided file extension.;
    if (condition)
    {
        extensionHasAssociatedApplication = true;
    }

    return extensionHasAssociatedApplication;
}

Ответы [ 6 ]

26 голосов
/ 03 марта 2012

Я бы порекомендовал следовать совету в Ответ Дэвида НО, поскольку вам необходимо обнаружить ассоциацию:

Чтобы проверить, имеет ли файл связь, вы можете использовать встроенную функцию FindExecutable, которая в основном используется Windows Explorer для внутреннего использования ... она выдает хороший код ошибки (SE_ERR_NOASSOC), если есть это не ассоциация В случае успеха он дает путь к соответствующему исполняемому файлу.

Тебе DllImport, потому что это

[DllImport("shell32.dll")]
static extern int FindExecutable(string lpFile, string lpDirectory, [Out] StringBuilder lpResult);

Другим вариантом может быть, например, обход реестра (не рекомендуется, поскольку он сложен из-за нескольких вариантов, таких как WoW64 и т. Д.):

Реальная ассоциация хранится в ключе, на который указывает HKEY_CLASSES_ROOT\.pdf - в моем случае AcroExch.Document, поэтому мы проверяем HKEY_CLASSES_ROOT\AcroExch.Document. Там вы можете увидеть (и изменить), какая команда будет использоваться для запуска файла такого типа:

HKEY_CLASSES_ROOT\AcroExch.Document\shell\open\command
5 голосов
/ 03 марта 2012

В такой ситуации лучше всего попытаться открыть документ и обнаружить ошибку. Попытка предсказать, имеет ли место файловая ассоциация, просто приводит к повторной реализации API выполнения оболочки. Очень трудно понять это совершенно правильно и довольно ненужно, поскольку они уже существуют!

4 голосов
/ 03 марта 2012

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

public static bool HasExecutable(string path)
{
    var executable = FindExecutable(path);
    return !string.IsNullOrEmpty(executable);
}

private static string FindExecutable(string path)
{
    var executable = new StringBuilder(1024);
    FindExecutable(path, string.Empty, executable);
    return executable.ToString();
}

[DllImport("shell32.dll", EntryPoint = "FindExecutable")]
private static extern long FindExecutable(string lpFile, string lpDirectory, StringBuilder lpResult);
1 голос
/ 03 марта 2012

Эта информация есть в реестре. Например:

# Mount the HKCR drive in powershell
ps c:\> new-psdrive hkcr registry hkey_classes_root
ps c:\> cd hkcr:\.cs

# get default key for .cs
PS hkcr:\.cs> gp . ""
(default)    : VisualStudio.cs.10.0
...

# dereference the "open" verb
PS hkcr:\.cs> dir ..\VisualStudio.cs.10.0\shell\open

    Hive: hkey_classes_root\VisualStudio.cs.10.0\shell\open

Name                           Property
----                           --------
Command                        (default) : "C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\devenv.exe" /dde
ddeexec                        (default) : Open("%1")
1 голос
/ 03 марта 2012

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

1 голос
/ 03 марта 2012

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

Вы можете следовать из:

HKEY_CLASSES_ROOT\.extension

и это обычно приводит к чему-то вроде HKEY_CLASSES_ROOT\extfile\Shell\Open\Command

и вы придете к команде, чтобы открыть тип файла.

В зависимости от того, что вы делаете, может быть идеально просто попросить прощения (то есть просто открыть файл и посмотреть)

...