2012-03-02 3 views
12

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

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


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

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


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

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

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

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; 
} 
+0

Это где-то в редакторе реестра. Вместе с обработчиками для магнита :, mailto :, call: схемы и т. Д. Это почти в корне, если я правильно помню – f2lollpll

ответ

25

Я хотел бы рекомендовать следующие рекомендации в David's answer НО, так как вы должны обнаружить ассоциацию:

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

Thee DllImport ибо

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

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

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

HKEY_CLASSES_ROOT\AcroExch.Document\shell\open\command 
5

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

+0

Я согласен, что это самый простой. Однако одной из основных проблем с этим подходом является то, что вам нужно как-то скрыть документ, который вы открываете, - вы действительно не хотите, чтобы пользователь его видел. – zmbq

+0

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

+0

@zmbq Если вы не хотите, чтобы пользователь видел документ, вы просто воздерживаетесь от его открытия. –

1

Вы также можете просмотреть реестр, чтобы получить эту информацию.

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

HKEY_CLASSES_ROOT\.extension 

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

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

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

+0

Вы уверены, что этого достаточно? Visual Studio - своего рода магия вуду, где .sln-файлы имеют другой значок на основе версии Visual Studio, которая их создала. Это жуткий и, вероятно, не хранится там, где вы сказали. – zmbq

+0

@zmbq - Если вы видите 'HKEY_CLASSES_ROOT', вы увидите различную defintion для sln-файла, обработанную другой версией VS. Значок определяется в разделе «DefaultIcon». В принципе, вся информация есть. http://stackoverflow.com/questions/4693562/how-does-windows-know-what-version-of-visual-studio-a-sln-file-relates-to – manojlds

1

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

1

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

# 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") 
4

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

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); 
+0

Почему вы использовали StringBuilder (1024) вместо StringBuilder()? – mggSoft

+3

@mggSoft Нативный метод FindExecutable требует, чтобы буфер возвращал исполняемый путь. Документация указывает _This параметр должен содержать допустимое ненулевое значение и предполагается, что он имеет длину MAX_PATH_. Таким образом, хотя 1024 немного перебор, рекомендуется переопределить емкость по умолчанию StringBuilder со значением MAX_PATH (260). – Yaurthek

Смежные вопросы