Ошибка невозможно создание объекта контейнером activex. Создание контейнеров элементов управления ActiveX. Базовые функции контейнера


Редактирование реестра Windows вручную с целью удаления содержащих ошибки ключей Ошибка 800A01AD не рекомендуется, если вы не являетесь специалистом по обслуживанию ПК. Ошибки, допущенные при редактировании реестра, могут привести к неработоспособности вашего ПК и нанести непоправимый ущерб вашей операционной системе. На самом деле, даже одна запятая, поставленная не в том месте, может воспрепятствовать загрузке компьютера!

В связи с подобным риском мы настоятельно рекомендуем использовать надежные инструменты очистки реестра, такие как WinThruster [Загрузить] (разработанный Microsoft Gold Certified Partner), чтобы просканировать и исправить любые проблемы, связанные с Ошибка 800A01AD. Используя очистку реестра [Загрузить] , вы сможете автоматизировать процесс поиска поврежденных записей реестра, ссылок на отсутствующие файлы (например, вызывающих ошибку %%error_name%%) и нерабочих ссылок внутри реестра. Перед каждым сканированием автоматически создается резервная копия, позволяющая отменить любые изменения одним кликом и защищающая вас от возможного повреждения компьютера. Самое приятное, что устранение ошибок реестра [Загрузить] может резко повысить скорость и производительность системы.


Предупреждение: Если вы не являетесь опытным пользователем ПК, мы НЕ рекомендуем редактирование реестра Windows вручную. Некорректное использование Редактора реестра может привести к серьезным проблемам и потребовать переустановки Windows. Мы не гарантируем, что неполадки, являющиеся результатом неправильного использования Редактора реестра, могут быть устранены. Вы пользуетесь Редактором реестра на свой страх и риск.

Перед тем, как вручную восстанавливать реестр Windows, необходимо создать резервную копию, экспортировав часть реестра, связанную с Ошибка 800A01AD (например, ActiveX):

  1. Нажмите на кнопку Начать .
  2. Введите "command " в строке поиска... ПОКА НЕ НАЖИМАЙТЕ ENTER !
  3. Удерживая клавиши CTRL-Shift на клавиатуре, нажмите ENTER .
  4. Будет выведено диалоговое окно для доступа.
  5. Нажмите Да .
  6. Черный ящик открывается мигающим курсором.
  7. Введите "regedit " и нажмите ENTER .
  8. В Редакторе реестра выберите ключ, связанный с Ошибка 800A01AD (например, ActiveX), для которого требуется создать резервную копию.
  9. В меню Файл выберите Экспорт .
  10. В списке Сохранить в выберите папку, в которую вы хотите сохранить резервную копию ключа ActiveX.
  11. В поле Имя файла введите название файла резервной копии, например "ActiveX резервная копия".
  12. Убедитесь, что в поле Диапазон экспорта выбрано значение Выбранная ветвь .
  13. Нажмите Сохранить .
  14. Файл будет сохранен с расширением.reg .
  15. Теперь у вас есть резервная копия записи реестра, связанной с ActiveX.

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

Системы и были доступны все связанные . Эта ошибка имеет следующие причины и решения:

    Класс не зарегистрирован. Например, в реестре системы нет упоминаний о классе, или класс упоминается, но указывает на файл неправильного типа или на файл, который не удается найти. По возможности запустите приложение объекта. Если сведения реестра неправильные или устарели, приложение проверит реестр и исправит эти сведения. Если запуск приложения не помогает устранить проблему, повторно запустите программу установки приложения;

    Не удается использовать библиотеку DLL, требуемую объектом, потому что она не найдена или найдена поврежденной. Убедитесь, что все связанные DLL доступны. Например, объект доступа к данным (DAO) требует поддержку DLL, которые отличаются в зависимости от платформы. Если это причина ошибки, вам нужно повторно запустить программу установки такого объекта;

    Объект доступен на компьютере, но является лицензированным , и ему не удается проверить доступность лицензии, необходимой для создания экземпляра объекта.

    Экземпляры некоторых объектов могут быть созданы только после того, как компонент найдет лицензионный ключ, подтверждающий регистрацию этого объекта для создания экземпляра на данном компьютере. При наличии ссылки на объект в правильно установленной или правильный ключ предоставляется автоматически.

    Если попытка создать экземпляр является результатом вызова функций CreateObject или GetObject , объект должен найти ключ. В этом случае он может выполнить поиск в реестре системы или поиск специального файла, который он создает при установке (например, с расширением.LIC). Если ключ не удается найти, экземпляр объекта не может быть создан. Если конечный пользователь неправильно настроил приложение объекта, необратимо удалил нужный файл или изменил реестр системы, объекту не удастся найти свой ключ. Если ключ не удается найти, невозможно создать экземпляр объекта. В этом случае создание экземпляра может работать в системе разработчика, но не в системе пользователя. Пользователю следует переустановить лицензированный объект;

    Вы пытаетесь использовать функцию получения объекта GetObject , чтобы получить ссылку на класс, созданный с помощью Visual Basic. GetObject нельзя использовать для получения ссылки на класс, созданный с помощью Visual Basic;

    Доступ к объекту явным образом запрещен. Например, вы пытаетесь получить доступ к объекту данных, который в настоящее время используется и заблокирован для предотвращения взаимоблокировки. В таком случае, возможно, вы сможете получить доступ к объекту в другое время.

Для получения дополнительных сведений выберите элемент, по которому возник вопрос, и нажмите клавишу F1 (в Windows) или HELP (на компьютере Macintosh).

Александр Костарев
программист технологического отдела R-Style Software Lab.

Создание элементов управления ActiveX достаточно широко освещается в специальной литературе. Однако методики написания ActiveX-контейнеров рассматриваются в ней гораздо реже, в основном лишь в рамках их взаимодействия с объектами ActiveX. Еще меньше публикаций посвящено процедурам разработки контейнеров, поддерживающих собственный программный интерфейс (API), который обеспечивает работу с ними и содержащимися в них объектами из других приложений или скриптовых языков. Примерами подобных контейнеров могут служить такие программные продукты, как Microsoft Visual Basic, Borland Delphi и т. д.

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

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

Предлагаемые решения основаны на опыте разработки инструментального комплекса RS-Forms - нового программного продукта компании R-Style Software Lab. RS-Forms включает в себя средство разработки графического интерфейса пользователя на платформе Windows, среду исполнения программ, созданных при помощи языков RSL*, С и C++, а также систему отладки RSL-программ.

*Object RSL - язык программирования высокого уровня, созданный в компании R-Style Software Lab. Подробнее см. http://www.softlab.ru/products/rsl/ . - Прим. ред.

В рамках проекта реализована первая версия дизайнера форм (рис. 1), позволяющая создавать формы, внедрять в них как стандартные элементы управления, так и произвольные объекты ActiveX, сохранять готовые формы в хранилище на постоянном носителе информации и загружать их из него. При помощи дизайнера можно просматривать свойства, методы и события любого внедренного в форму управляющего элемента, изменять значения свойств.

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

Помимо разработки графического интерфейса пользователя в дизайнер заложен механизм автоматической генерации кода на языках C++ и RSL. Важно отметить, что все операции, выполняемые над формой в дизайнере, доступны и в режиме выполнения из кода программы.

Рис. 1. Дизайнер форм.

Созданные в дизайнере графические формы можно использовать в любом приложении С/С++, а также из любого скриптового языка, например Visual Basic или RSL. При использовании форм в приложениях C++, разрабатываемых с помощью библиотеки MFC, дизайнер можно применять в качестве редактора диалоговых ресурсов.

А теперь обсудим концепцию построения контейнера и принципы работы с элементами управления ActiveX.

Базовые функции контейнера

Любой контейнер элементов управления должен обладать функциональностью, которая позволяла бы создавать объекты ActiveX, обеспечивать их корректную работу, удалять их из оперативной памяти, а также сохранять элементы в хранилище объектов на постоянном носителе информации и загружать их из него*. В состав контейнера входит ряд компонентов (рис. 2), обеспечивающих стандартную (в соответствии с технологией Microsoft ActiveX) функциональность, необходимую для корректной работы элементов управления.

*Общие вопросы построения контейнеров и серверов COM-объектов рассматриваются в книге Д. Чеппела "Технологии ActiveX и OLE" - М.: "Русская Редакция", 1997.

Контейнер поддерживает коллекцию (например, список) объектов связи с элементами ActiveX - по одному объекту связи на каждый управляющий элемент. Кроме того, в программируемом контейнере необходимо предусмотреть стандартный механизм манипуляций с элементами этой коллекции.

Объект связи с элементом управления (control site) отвечает за корректное взаимодействие соответствующего элемента с контейнером. Каждый объект связи содержит подобъект, который расширяет элемент управления за счет стандартных для конкретного контейнера наборов свойств, методов и событий. Такой подобъект называется расширенным элементом управления (extended control). Примером расширенных свойств могут служить имя (Name), местоположение в контейнере (Width, Left) и т.п. Указанные наборы - это свойства контейнера, а не какого-либо отдельно взятого элемента управления, хотя именно так это выглядит для пользователя системы. Существует несколько вариантов реализации расширенного элемента управления. Например, он может представлять собой подобъект объекта связи (см. рис. 2) или реальный COM-объект, агрегирующий исходный элемент управления. Каждый из вариантов имеет свои достоинства и недостатки. В этой статье мы рассматриваем только первый способ.

Каждый расширенный элемент управления содержит в качестве подобъекта объект-приемник событий (event sink) от сопоставленного с ним элемента управления (рис. 2). В его задачи входит первичная идентификация полученных событий (требуется пользовательская обработка события или нет) и при необходимости передача их своему объекту-владельцу (extended control), который обеспечивает маршрутизацию событий по иерархии объектов контейнера.

Сценарий создания элемента управления

Внедрение элемента управления в контейнер состоит из трех фаз: создание объекта ActiveX, его инициализация и активизация.

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

Основное назначение фазы инициализации - передача элементу управления через функцию IOleObject::SetClientSite указателя на интерфейс IOleClientSite объекта связи и вызов функции IPersistStreamInit::InitNew либо IPersistStreamInit::Load (в зависимости от того, загружается объект из хранилища или нет). Передача объекту указателя на интерфейс IOleClientSite может происходить до загрузки/инициализации либо после; момент передачи определяется наличием признака OLEMISC_SETCLIENTSITEFIRST (IOleObject::GetMiscStatus). Это существенно, поскольку от момента передачи указателя зависит, в какой момент времени элемент управления получит значения свойств окружения (ambient properties) от контейнера. Если этот признак проигнорировать, то дальнейшее функционирование объекта ActiveX может быть некорректным.

Затем в рамках рассматриваемой фазы нужно провести начальную инициализацию свойств расширенного элемента управления, дополняющего создаваемый объект ActiveX. К примеру, требуется корректно задать имя объекта (проинициализировать свойство Name, обеспечивающее идентификацию элементов управления в рамках контейнера). Это свойство должен поддерживать любой внедренный в программируемый контейнер элемент управления, но оно тем не менее представляет собой свойство контейнера. Часто по умолчанию объектам присваивают короткое имя класса, к которому они принадлежат (это имя возвращает метод IOleObject::GetUserType для параметра USERCLASSTYPE_SHORT), с добавлением числового индекса, что обеспечивает уникальность имен элементов управления в контейнере. Если получить указанное имя не удается или если оно не удовлетворяет логике контейнера, то можно задать некоторое предопределенное имя с соответствующим индексом.

Активизация элемента управления подразумевает определенную последовательность действий. В первую очередь необходимо установить обратную связь объекта ActiveX с объектом связи в контейнере (control site). Для этого вызывается метод IOleObject::Advise, которому в качестве параметра передается указатель на стандартный интерфейс объекта связи IAdviseSink. Далее требуется корректно запросить интерфейс семейства IViewObject (в соответствии со спецификацией объект ActiveX может поддерживать интерфейсы IViewObject, IViewObject2, IViewObjectEx, состоящие в иерархии наследования) и установить для него обратную связь, вызвав метод IViewObject::SetAdvise с передачей указателя на IAdviseSink. Кроме того, надо сообщить элементу управления имя его контейнера (это реализуется путем вызова метода IOleObject::SetHostName), запросить и сохранить все требуемые для корректной работы с объектом ActiveX интерфейсы (как минимум IOleInPlaceObject и IOleControl). Последнее, что необходимо выполнить для визуального отображения элемента управления, - это вызвать функцию IOleObject::DoVerb* с параметром OLEIVERB_INPLACEACTIVATE.

*В ATL-реализации указанная функция, помимо прочего, отвечает за создание окна для обычных (windowed) элементов управления.

Сценарий удаления элемента управления

Чтобы удалить внедренный в контейнер элемент управления из памяти, требуется исключить из коллекции соответствующий ему объект связи с элементом управления, а затем последовательно выполнить две операции: разрыв обратных связей и освобождение сохраненных указателей на интерфейсы объекта ActiveX.

Для разрыва обратных связей нужно, во-первых, сообщить удаляемому элементу о необходимости освободить (вызовом метода IUnknown::Release) удерживаемые им указатели на интерфейс IAdviseSink объекта связи. Для этого вызываются методы IViewObject::SetAdvise (с передачей в качестве аргумента NULL) и IOleObject::Unadvise, которому нужно предоставить сохраненный на этапе активизации идентификатор связи. Далее требуется активизировать процедуру деинициализации объекта ActiveX (вызвав функцию IOleObject::Close). На следующем шаге элементу управления сообщают о необходимости освободить указатель на интерфейс IOleClientSite, для чего вызывают IOleObject::SetClientSite с параметром NULL.

Фаза освобождения сохраненных указателей на интерфейсы элемента управления заключается в последовательном вызове для них метода Release. Как только освободится последний указатель, объект (в соответствии с технологией COM) будет удален из оперативной памяти.

Сценарий сохранения и загрузки

Сохранение объекта контейнера в хранилище, независимо от типа последнего, - это сохранение свойств контейнера (например, свойств окружения) и коллекции внедренных элементов управления, т. е. идентификаторов и свойств (включая расширенные) каждого принадлежащего коллекции объекта. В качестве идентификатора элемента управления может выступать глобальный уникальный идентификатор класса CLSID. Это позволит на стадии инициализации создать требуемый объект ActiveX и загрузить его данными, содержащимися в хранилище после указанного идентификатора. Для сохранения свойств управляющего элемента, например в поток, вызывается метод Save стандартного интерфейса объектов ActiveX IPersistStreamInit. Для загрузки вызывается метод Load того же интерфейса.

Такая процедура сохранения обеспечивает последующее восстановление объекта контейнера из хранилища. Описанный метод хорошо работает при условии, что с момента сохранения и до момента загрузки не произошло изменения версии или удаления каких-либо элементов управления из системы. Такие ситуации часто возникают при переносе хранилища данных с одного компьютера на другой, где сохраненные объекты ActiveX не были установлены или зарегистрированы. В этом случае загрузка объекта контейнера из хранилища приведет либо к фатальному завершению работы программы, либо станет причиной ошибки загрузки всего контейнера в целом. Для предотвращения ошибок необходимо четко устанавливать границу между данными различных элементов управления, записывая в хранилище после идентификатора объекта размер сохраненной им информации. Это позволит на этапе загрузки точно позиционироваться на начало данных каждого объекта ActiveX, а также пропускать незарегистрированные в системе элементы управления, но загружать объект контейнера в целом.

Интерфейсы коллекции объектов ActiveX

В соответствии со стандартом контейнер элементов управления должен обеспечивать взаимодействие внедренных в него объектов ActiveX. Для этого необходимо поддерживать интерфейс IOleContainer, который позволяет перечислять все вставленные в него элементы управления. При наличии расширенного элемента управления (extended control) перечисление должно проходить именно по его интерфейсам IUnknown, а не по интерфейсам базового объекта.

Для предоставления доступа к коллекции клиентам автоматизации служит стандартный интерфейс коллекции объектов. Стандартная коллекция включает в себя методы Add, Remove, Clear, Item и свойства _NewEnum и Count, обеспечивающие всесторонний перебор элементов. Например, конструкция языка Visual Basic for each использует для перечисления элементов свойство _NewEnum, а конструкция for next предполагает использование свойства Count и метода Item. В языке Object RSL свойство _NewEnum используется при обращении к стандартному методу объекта ActiveX CreateEnum. Это иллюстрирует, например, RSL-программа, распечатывающая с применением указанного метода названия файлов, открытых в приложении Microsoft Excel (ее текст приведен ниже).

import rslx; ob = ActiveX("Excel.Application", null, true); en = ob.Workbooks.CreateEnum; while (en.next) println(en.item.Name) end;

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

* * *

Мы рассмотрели здесь основные вопросы, связанные с построением контейнеров элементов управления: внедрение, визуальное отображение, сохранение и загрузку объекта ActiveX, а также его корректное удаление из оперативной памяти. Однако в процессе создания графической инструментальной среды нам потребовалось реализовать несколько контейнеров, которые отличались бы друг от друга предоставляемыми интерфейсами автоматизации, подмножествами допустимых для внедрения объектов ActiveX, наборами свойств, методов и событий расширенных элементов управления и т.п. Для этого была предложена модель, позволяющая создавать различные контейнерные элементы и хорошо интегрирующаяся с библиотекой ATL. Независимость от конкретных интерфейсов достигается за счет использования шаблонных классов, параметрами которых и являются эти интерфейсы.

*Например, управляющий элемент Tab представляет собой контейнер страниц свойств, которые являются контейнерами общего назначения.

Эта модель позволяет быстро создавать базовые варианты различных объектов ActiveX, которым присуща "контейнерная логика". Кроме того, реализованная инфраструктура позволяет создавать контейнеры, не являющиеся элементами управления. Такой контейнер можно поместить в качестве окна Windows в любую часть разрабатываемого приложения и затем, посылая соответствующие сообщения, внедрять в него различные элементы управления.

В итоге получилась достаточно гибкая архитектура построения контейнеров, с помощью которой можно создать Мастера (Wizard), расширяющего функциональные возможности среды Microsoft Visual Studio до механизма генерации остова контейнера.

Последние материалы раздела:

Почему режется скорость Интернета по WiFi: Бесплатные советы как ускорить передачу данных
Почему режется скорость Интернета по WiFi: Бесплатные советы как ускорить передачу данных

Плохая скорость интернета через роутер - одна из наиболее «популярных» проблем всех любителей беспроводного соединения . В предыдущих статьях мы...

Контекстное меню в Windows
Контекстное меню в Windows

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

Продвижение в Instagram: самая подробная инструкция
Продвижение в Instagram: самая подробная инструкция

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