VB: Как связать определённое расширение со своей программой

Ответы на вопросы, чаще всего задаваемые в форумах VBStreets. Для тех, кому лень искать.
areh
Постоялец
Постоялец
 
Сообщения: 530
Зарегистрирован: 02.12.2002 (Пн) 12:28
Откуда: РОССИЯ, Салехард

VB: Как связать определённое расширение со своей программой

Сообщение areh » 25.05.2004 (Вт) 17:18

Итак, сначала немного теории:

MSDN писал(а):1. Расширение файла (file extension) - это строка, добавляемая к имени файла, состоящая из букв и цифр (рекомендуеться использовать англ. буквы)

2. Вы можете использовать в имени файла несколько периодов (частей разделенных точкой), но только символы рассположенные за последней точкой являються расширением. Все остальные периоды являются частью имени файла.

! НЕ ИСПОЛЬЗУЙТЕ ПРОБЕЛЫ В РАСШИРЕНИЯХ ФАЙЛОВ !

3. Когда вы создаете или изменяете ассоциирование файлов, важно оповестить систему о том что вы внесли изменения. Используйте SHChangeNotify, с событием SHCNE_ASSOCCHANGED. Если вы не оповестите систему, изменения могут быть не приняты (т.е. не работать) до того момента, пока система не будет перезагружена.

Итак, чтобы связать своё приложение с каким-либо типом файлов необходимо в реестре, в ветке HKEY_CLASSES_ROOT создать два раздела, имена которых представляют собой: 1. расширение, которое вы хотите зарегистрировать, 2. название вашей программы.

Например, для того чтобы ассоциировать файлы с расширением ".myp" с программой "MyProgram" необходимо создать следующие разделы реестра:

HKEY_CLASSES_ROOT

.myp - со значением по умолчанию MyProgram.1 (рекомендуеться ставить .1 для того чтобы была возможность создавать новые версии приложения, которые могли бы быть одновременно установленными на одном компьютере)

MyProgram.1 - со значением по умолчанию MyProgram Application (на самом деле сюда следует записывать полное название вашей программы)

так же вы можете привязать к определённому расширению каку-либо иконку, для этого надо создать дополнительный раздел MyProgram.1\DefaultIcon и присвоить его значению по умолчанию путь к файлу иконки, например:
"C:\Program Files\MyProgram\icon.ico" (здесь указываеться файл иконки),
так же можно воспользоваться строкой вида:
"C:\Program Files\MyProgram\myprog.exe,20" (данная строка подразумевает, что у ваc в файле программы, в ресурсах присутствует не менее 20 иконок, причем иконка по умолчанию будет именно 20-ая, если данной иконки не существует, то будет отображаться ярлык "неопозннаого" документа)

Так же необходимо создать ключ "MyApp.1\shell\open\command" и его значением по умолчанию установить строку вида:
"C:\Program Files\MyProgram\myprog.exe %1". Именно это строка отвечает за то, каким приложением будет открываться файл такого типа.

! Так же вы можете сменить "open" на другую строку, и именно она будет появляться при счелчке правой кнопкой мыши по файлу с ассоциированным расширением.

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


Оповещение системы, о внесении изминений в ассоциирование файлов. Необходимо вызвать ф-ию SHChangeNotify с wEventId равным SHCNE_ASSOCCHANGED, и uFlags равным SHCNF_IDLIST.

Вот описание данной ф-ии и констант для VB 6:

MSDN писал(а):Private Declare Sub SHChangeNotify Lib "shell32.dll" _
(ByVal wEventId As Long, _
ByVal uFlags As Long, _
dwItem1 As Any, _
dwItem2 As Any)

Const SHCNE_ASSOCCHANGED = &H8000000
Const SHCNF_IDLIST = &H0&


а вот для VB.NET
MSDN писал(а):Private Declare Sub SHChangeNotify Lib "shell32.dll" (ByVal wEventId As Integer, ByVal uFlags As Integer, ByVal dwItem1 As Integer, ByVal dwItem2 As Integer)
Const SHCNE_ASSOCCHANGED = &H8000000
Const SHCNF_IDLIST = &H0&


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

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

Код: Выделить всё
' Функции API необходимые для работы с реестром
Private Declare Function RegCreateKey Lib "advapi32.dll" Alias "RegCreateKeyA" (ByVal hKey As Long, ByVal lpSubKey As String, phkResult As Long) As Long
Private Declare Function RegSetValue Lib "advapi32.dll" Alias "RegSetValueA" (ByVal hKey As Long, ByVal lpSubKey As String, ByVal dwType As Long, ByVal lpData As String, ByVal cbData As Long) As Long

Private Declare Sub SHChangeNotify Lib "shell32.dll" (ByVal wEventId As Long, ByVal uFlags As Long, dwItem1 As Any, dwItem2 As Any)

Const SHCNE_ASSOCCHANGED = &H8000000
Const SHCNF_IDLIST = &H0&


' Возможные варианты результатов функций работы с реестром
Const ERROR_SUCCESS = 0&

Const ERROR_BADDB = 1&
Const ERROR_BADKEY = 2&
Const ERROR_CANTOPEN = 3&
Const ERROR_CANTREAD = 4&
Const ERROR_CANTWRITE = 5&
Const ERROR_OUTOFMEMORY = 6&
Const ERROR_INVALID_PARAMETER = 7&
Const ERROR_ACCESS_DENIED = 8&

Private Const HKEY_CLASSES_ROOT = &H80000000
Private Const MAX_PATH = 260&
Private Const REG_SZ = 1

'
Sub AssExtension()

Dim sKeyName As String
Dim sKeyValue As String

Dim ret as Long
Dim lphKey as Long

'Создание раздела программы
sKeyName = "MyApp.1" ' Название приложения
sKeyValue = "My Application 1" ' Полное название, так же возможно краткое описание
ret = RegCreateKey(HKEY_CLASSES_ROOT, sKeyName, lphKey)
ret = RegSetValue(lphKey, "", REG_SZ, sKeyValue, 0&)


'Создание раздела, для использования иконки.
sKeyName = "MyApp.1\DefaultIcon" ' Название приложения
sKeyValue = "C:\Program Files\MyProgram\myprog.exe,0"  ' Путь к используемой иконке
ret = RegCreateKey(HKEY_CLASSES_ROOT, sKeyName, lphKey)
ret = RegSetValue(lphKey, "", REG_SZ, sKeyValue, 0&)


'Создание раздела, относящегося к расширению
sKeyName = ".myp" ' Регистрируемое расширение
sKeyValue = "MyApp.1" ' Приложение, с которым связываеться данное расширение
ret = RegCreateKey(HKEY_CLASSES_ROOT, sKeyName, lphKey)
ret = RegSetValue(lphKey, "", REG_SZ, sKeyValue, 0&)


'Коммандная линия для приложения"MyApp".
sKeyName = "MyApp.1"
sKeyValue = "C:\Program Files\MyProgram\myprog.exe %1"
ret = RegCreateKey(HKEY_CLASSES_ROOT, sKeyName, lphKey)
ret = RegSetValue(lphKey, "shell\open\command", REG_SZ, sKeyValue, MAX_PATH)

Call SHChangeNotify (SHCNE_ASSOCCHANGED, SHCNF_IDLIST, 0, 0)

End Sub




Итак: процедура регистрации расширения на VB.NET.
В данной процедуре, при внутренних ошибках вызывается (а так же ошибках доступа к реестру и др.) исключение, содержащие описание ошибки (в поле Message).


Код: Выделить всё
  Private Declare Sub SHChangeNotify Lib "shell32.dll" (ByVal wEventId As Integer, ByVal uFlags As Integer, ByVal dwItem1 As Integer, ByVal dwItem2 As Integer)
  Const SHCNE_ASSOCCHANGED = &H8000000
  Const SHCNF_IDLIST = &H0&

  Public Sub AssociateExtension(ByVal Extension As String, ByVal ProgramName As String, ByVal Description As String, ByVal DefaultIcon As String, ByVal CommandLine As String, ByVal RemoveExistingAssociation As Boolean)
    'Передаваемые параметры:
    'Extension - имя расширения
    'ProgramName - название программы
    'Description - описание программы
    'DefaultIcon - путь к иконке, для регистрируемого расширения
    'CommandLine - путь к программе, для открытия файлов такого типа
    'RemoveExistingAssociation - если параметр будет равен True, тогда предыдущее
    'асоциирование с данным расширением будет удалено (если оно конечно есть)


    'Переменные для работы с реестром
    Dim RegHKCR As Microsoft.Win32.RegistryKey
    Dim RegTempKey, RegTempKey2 As Microsoft.Win32.RegistryKey

    'Исключение, вызываемое при каких-либо ошибках
    Dim AssociateExtensionExeption As Exception

    Try
      RegHKCR = Microsoft.Win32.Registry.ClassesRoot
    Catch ex As Exception
      If Not RegHKCR Is Nothing Then RegHKCR.Close()
      AssociateExtensionExeption = New Exception(ex.Message)
      Throw AssociateExtensionExeption
    End Try



    'Сначала проверяем параметры на допустимость

    'Удаляем все пробелы из имени расширения и названия программы
    Extension = Extension.Replace(" ", "")
    ProgramName = ProgramName.Replace(" ", "")


    'Удаляем все точки перед и после названия программы
    Do While ProgramName.Length > 0
      If ProgramName.Chars(0) = "." Then
        ProgramName = ProgramName.Remove(0, 1)
      ElseIf ProgramName.Chars(ProgramName.Length - 1) = "." Then
        ProgramName = ProgramName.Remove(0, 1)
      Else
        Exit Do
      End If
    Loop

    'Имя программы не должно представлять собой нулевую строку, а так же его
    'длинна не должна превышать 255 символов
    If ProgramName.Length = 0 Or ProgramName.Length > 255 Then
      RegHKCR.Close()
      AssociateExtensionExeption = New Exception("Недопусимое имя программы.")
      Throw AssociateExtensionExeption
    End If

    'Проверяем: возможно программа с таким именем уже существует
    Try
      RegTempKey = RegHKCR.OpenSubKey(ProgramName, True)
    Catch ex As Exception
      RegHKCR.Close()
      AssociateExtensionExeption = New Exception(ex.Message)
      Throw AssociateExtensionExeption
    End Try

    If Not RegTempKey Is Nothing Then
      RegTempKey.Close()
      RegHKCR.Close()
      AssociateExtensionExeption = New Exception("Программа с таким именем уже существует")
      Throw AssociateExtensionExeption
    End If


    'Предварительно убераем все точки в имени расширения
    Extension = Extension.Replace(".", "")

    'Предполагается, что расширение (без точек) не может быть нулевой строкой,
    'а так же превышать 5 символов.
    If Extension.Length = 0 Or Extension.Length > 5 Then
      RegHKCR.Close()
      AssociateExtensionExeption = New Exception("Недопусимое имя расширения.")
      Throw AssociateExtensionExeption
    End If

    'Далее ставим точку перед расширением
    Extension = "." & Extension

    'Проверяем: возможно такое расширение уже существует
    Try
      RegTempKey = RegHKCR.OpenSubKey(Extension, True)
    Catch ex As Exception
      RegHKCR.Close()
      AssociateExtensionExeption = New Exception(ex.Message)
      Throw AssociateExtensionExeption
    End Try

    If Not RegTempKey Is Nothing Then
      RegTempKey.Close()

      If RemoveExistingAssociation Then
        Try
          RegHKCR.DeleteSubKeyTree(Extension)
        Catch ex As Exception
          RegHKCR.Close()
          AssociateExtensionExeption = New Exception(ex.Message)
          Throw AssociateExtensionExeption
        End Try
      Else
        RegHKCR.Close()
        AssociateExtensionExeption = New Exception("Такое расширение уже существует")
        Throw AssociateExtensionExeption
      End If
    End If


    'Убераем лишние пробелы из описания и пути к иконке по умолчанию
    Description = Trim(Description)
    DefaultIcon = Trim(DefaultIcon)


    'Если описание программы представляет собой нулевую строку, то записыаем
    'в него имя программы
    If Description.Length = 0 Then Description = ProgramName



    ' *************************************************************************
    ' ! Сейчас в коде нет проверки описания и пути (к иконке) на корректность !
    ' ! так же не производится проверка командной строки на запуск приложения !
    ' ! возможно, что всё появится в ближайшее вермя, просто пока писать лень !
    ' *************************************************************************


    'Итак на данный момент не существует программы и расширения с заданными именами
    'так что можно спокойно начинать записывать необходимые разделы и значения

    'Создаем раздел с именем расширения, и записываем его значением по умолчанию
    'имя программы
    Try
      RegTempKey = RegHKCR.CreateSubKey(Extension)
      RegTempKey.SetValue("", ProgramName)
      RegTempKey.Flush()
    Catch ex As Exception
      RegHKCR.Close()
      AssociateExtensionExeption = New Exception(ex.Message)
      Throw AssociateExtensionExeption
    Finally
      If Not RegTempKey Is Nothing Then
        RegTempKey.Close()
        RegTempKey = Nothing
      End If
    End Try

    Try
      'Создаем раздел с названием программы
      RegTempKey = RegHKCR.CreateSubKey(ProgramName)
      RegTempKey.SetValue("", Description)
      RegTempKey.Flush()

      'Создаем раздел с иконкой для файлов
      If DefaultIcon.Length <> 0 Then
        RegTempKey2 = RegTempKey.CreateSubKey("DefaultIcon")
        RegTempKey2.SetValue("", DefaultIcon)
        RegTempKey2.Flush()
        RegTempKey2.Close()
        RegTempKey2 = Nothing
      End If

      'Создаем раздел, отвечающий за запуск файлов
      If CommandLine.Length <> 0 Then

        'Указанная здесь строка будет отображаться при счелчке правой кнопкой мыши по
        'файлу с регистрируемым расширением
        Dim CommandName As String = "open"

        RegTempKey2 = RegTempKey.CreateSubKey("shell" & CommandName & "\command")
        RegTempKey2.SetValue("", CommandLine)
        RegTempKey.Flush()
        RegTempKey2.Close()
        RegTempKey2 = Nothing
      End If

    Catch ex As Exception
      AssociateExtensionExeption = New Exception(ex.Message)
      Throw AssociateExtensionExeption
    Finally
      If Not RegTempKey Is Nothing Then RegTempKey.Close()
      If Not RegTempKey2 Is Nothing Then RegTempKey2.Close()
      RegHKCR.Close()
    End Try

    SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, 0, 0)
  End Sub



---
Все замечания и дополнения пишите в личные сообщения, или сюда: FAQ.VBStreets@areh.ru


vbskb_assoc vbskb_reg vbskb_tricks

Вернуться в Популярные вопросы

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 8

    TopList