Краткая информация: я использую Visual Studio 2008, Windows 8 (64-разрядная версия).
Я пытаюсь создать обработчик автозапуска, который будет отображаться при подключении к компьютеру устройства WPD. Если выбрана моя опция автозапуска, все, что я хочу, это просто запустить мое приложение.
Поскольку в последнее время не было примеров реализации AutoPlay для Windows, я надеялся, что кто-нибудь может мне помочь и ответить на пару вопросов:
1). Я создал проект ATL с COM-объектом, который реализует интерфейс IHWEventHandler. Первоначально все, что я пытаюсь заставить COM-объект сделать, это создать файл .txt на моем диске C, чтобы указать, что он был успешно вызван. Я пытался заставить мое событие автозапуска указывать на этот COM-объект, но ничего не происходит, когда я выбираю свою запись автозапуска. Вот мой код .h для моего класса COM:
class ATL_NO_VTABLE CSimpleAutoPlayCom :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CSimpleAutoPlayCom, &CLSID_SimpleAutoPlayCom>,
public IHWEventHandler
//public ISimpleAutoPlayCom
{
public:
CSimpleAutoPlayCom()
{
ofstream myfile;
myfile.open ("C:\\AutoPlayExerciseWorked.txt");
myfile << "Called from Constructor.\n";
myfile.close();
}
DECLARE_REGISTRY_RESOURCEID(IDR_SIMPLEAUTOPLAYCOM)
DECLARE_NOT_AGGREGATABLE(CSimpleAutoPlayCom)
BEGIN_COM_MAP(CSimpleAutoPlayCom)
//COM_INTERFACE_ENTRY(ISimpleAutoPlayCom)
COM_INTERFACE_ENTRY(IHWEventHandler)
END_COM_MAP()
DECLARE_PROTECT_FINAL_CONSTRUCT()
HRESULT FinalConstruct()
{
return S_OK;
}
void FinalRelease()
{
}
public:
// IHWEventHandler
STDMETHODIMP Initialize(__RPC__in LPCWSTR pszParams);
STDMETHODIMP HandleEvent(__RPC__in LPCWSTR pszDeviceID, __RPC__in LPCWSTR pszAltDeviceID, __RPC__in LPCWSTR pszEventType);
STDMETHODIMP HandleEventWithContent(__RPC__in LPCWSTR pszDeviceID, __RPC__in LPCWSTR pszAltDeviceID, __RPC__in LPCWSTR pszEventType, __RPC__in LPCWSTR pszContentTypeHandler, __RPC__in_opt IDataObject *pdataobject);
};
Это .cpp:
// CSimpleAutoPlayCom
STDMETHODIMP CSimpleAutoPlayCom::Initialize(__RPC__in LPCWSTR pszParams)
{
ofstream myfile;
myfile.open ("C:\\AutoPlayExerciseWorked.txt");
myfile << "Called from Initialize\n";
myfile.close();
return S_OK;
}
STDMETHODIMP CSimpleAutoPlayCom::HandleEvent(__RPC__in LPCWSTR pszDeviceID, __RPC__in LPCWSTR pszAltDeviceID, __RPC__in LPCWSTR pszEventType)
{
ofstream myfile;
myfile.open ("C:\\AutoPlayExerciseWorked.txt");
myfile << "Called from HandleEvent.\n";
myfile.close();
return S_OK;
}
STDMETHODIMP CSimpleAutoPlayCom::HandleEventWithContent(__RPC__in LPCWSTR pszDeviceID, __RPC__in LPCWSTR pszAltDeviceID, __RPC__in LPCWSTR pszEventType, __RPC__in LPCWSTR pszContentTypeHandler, __RPC__in_opt IDataObject *pdataobject)
{
ofstream myfile;
myfile.open ("C:\\AutoPlayExerciseWorked.txt");
myfile << "Called from HandleEventWithContent.\n";
myfile.close();
return S_OK;
}
В целом, эта реализация выглядит правильно? Нужно ли мне реализовывать какой-либо дополнительный интерфейс, чтобы событие AutoPlay вызывало этот COM-объект?
Я понимаю, что когда я строю проект, Visual Studio автоматически регистрирует мой COM-объект. Я создаю свой COM-объект для 64-битных окон и регистрирую .dll с помощью regsvr32.exe, но это, похоже, не помогает.
2). Кроме того, я подозреваю, что, возможно, я неправильно зарегистрировал ключи реестра для автозапуска. Сначала я вручную добавил свой обработчик событий Autoplay:
HKEY_LOCAL_MACHINE> ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ> Microsoft> Windows> CurrentVersion> Explorer> AutoPlayHandlers> Обработчики> MyAutoPlayHandler
MyAutoPlayHandler содержит следующее:
Действие REG_SZ MyAction
DefaultIcon REG_SZ (каталог со значком моего приложения)
InvokeProgID REG_SZ (имя ключа в HKEY_CLASSES_ROOT, созданного моим проектом ATL: AutoPlayExericesCom.SimpleAutoPlayCom.1)
InvokeVerb REG_SZ открыть
Провайдер REG_SZ Myself
Затем я добавил MyAutoPlayHandler к следующему:
HKEY_LOCAL_MACHINE> ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ> Microsoft> Windows> CurrentVersion> Explorer> AutoPlayHandlers> EventHandlers> WPD> Функция> {2D8A6512-A74C-448E-BA8A-F4AC07C49399}, то есть WPD_FUNCTIONAL_CATEGORY_ALL
Круто, поэтому я подключаю устройство Android и вижу свою запись автозапуска в списке автозапуска. Я нажимаю на него, и ничего не происходит (на диске C не было создано txt-файла, как я ожидал).
Поэтому я дополнительно создаю еще один ключ, подобный следующему:
HKEY_CLASSES_ROOT> MyAutoPlayDropHandler> shell> open> DropTarget
Где DropTarget Содержит значение CLSID с идеей CLSID созданного мной COM-объекта. Я изменяю InvokeProgID, чтобы указать на этот ключ, но все равно ничего не происходит.
Для экспериментов я попытался добавить свой обработчик под ключом ShowPicturesOnArrival, и при подключении USB-накопителя, содержащего изображения, а затем при выборе записи автозапуска я получил следующее сообщение об ошибке:
«У этого файла нет программы, связанной с ним, чтобы выполнить это действие. Пожалуйста, установите программу или, если она уже установлена, создайте ассоциацию в панели управления программами по умолчанию».
Так что теперь у меня есть какой-то ответ об ошибке на ключ ShowPicturesOnArrival, но почему ничего для WPD? Я подозреваю, что где-то что-то упустил, чтобы заставить это работать, но у меня заканчиваются идеи. Буду очень признателен за любые предложения, которые я мог бы попытаться исправить.
Я знаю, что это было какое-то время, но для любого другого, кто найдет этот пост, я решил эту проблему, которая возникла у меня, скопировав, как VLC выполняет AutoPlay Events. Он не позволяет вам вызывать исполняемый код, но, по крайней мере, позволит вам вызывать ваше приложение с любыми аргументами командной строки, которые вы пожелаете.
Просто добавьте следующие ключи реестра на свой компьютер, заменив VLC своим приложением.
HKEY_CLASSES_ROOT
VLC
shell
import
Open
command
Default = "[Path]\vlc.exe" --started-from-file dvd:///%1
HKEY_LOCAL_MACHINE
SOFTWARE
Microsoft
Windows
CurrentVersion
Explorer
AutoplayHandlers
EventHandlers
PlayDVDMovieOnArrival
VLCPlayDVDMovieOnArrival [REG_SZ]
Handlers
VLCPlayDVDMovieOnArrival
Action [REG_SZ]= Play DVD Movie
DefaultIcon [REG_EXPAND_SZ]= [somepath]\VLC.exe, 0
InvokeProgID [REG_SZ]= VLC.DVDMovie
InvokeVerb [REG_SZ]= Open
Provider [REG_SZ]= VideoLanVLC media player
Других решений пока нет …