CoCreateInstance CLSID_IConverterSession 在 Office 2016 中失败
CoCreateInstance CLSID_IConverterSession fails with Office 2016
我正在使用 IConverterSession 从 mhtm 文件创建邮件项目。这适用于小于 2016 的 Outlook 版本。对于 Office 2016,无法创建 IConverterSession。
如果您使用的是 运行ning C2R(点击运行)版本的 Outlook 2016,所有注册表项都已虚拟化 - 请参阅下面的注册表项(%s 需要替换为Outlook 版本,例如 16.0
)。由于 COM 系统不在那里查找,您将需要实现您自己的 CoCreateInstance 版本,该版本从键中读取默认值以找出 dll 文件名,然后调用 LoadLibrary / GetProcAddress("DllGetClassObject") / DllGetClassObject(..., IID_IClassFactory, ...) / IClassFactory.CreateInstance
.
SOFTWARE\Microsoft\Office\%s.0\ClickToRun\REGISTRY\MACHINE\Software\Classes\CLSID\%s\InprocServer32
SOFTWARE\Microsoft\Office\%s.0\ClickToRun\REGISTRY\MACHINE\Software\Classes\Wow6432Node\CLSID\%s\InprocServer32
SOFTWARE\Microsoft\Office\ClickToRun\REGISTRY\MACHINE\Software\Classes\CLSID\%s\InprocServer32
SOFTWARE\Microsoft\Office\ClickToRun\REGISTRY\MACHINE\Software\Classes\Wow6432Node\CLSID\%s\InprocServer32
您不必自己实施 CoCreateInstance(),而必须启用注册表重定向以启用 Outlook 的 C2R(点击-运行)虚拟化,它使用迂回的方式将调用重定向到 RegOpenKey() .启用该重定向后,只需使用普通的 CoCreateInstance()。
你自己实现 CoCreateInstance() 不起作用的原因是,转换器也会在内部调用 CoCreateInstance() 并且会像你原来的调用一样失败,因为它在正常情况下找不到 CLSID注册表的配置单元。
我自己通过查看 jitv.dll 导出找到了代码。参数可能有误,但作为第一次启动它没有崩溃。要找出参数,我必须调试 Office 应用程序并查看反汇编(或任何志愿者?)。
这里是对我有用的实验代码:
HMODULE jitv = ::LoadLibrary(TEXT("jitv.dll"));
if (jitv) {
FARPROC efv = ::GetProcAddress(jitv, "EnableFullVirtualization");
if(efv)
efv();
// call CoCreateInstance(guid::CLSID_IConverterSession)
// and do your work
}
if (jitv)
FreeLibrary(jitv);
jitv.dll 中还有一些其他导出项,其名称大多不言自明:
- "APIExportForDetours"
- "DisableVirtualizationOnThread"
- "EnableVirtualizationOnThread"
- "IsCurrentThreadVirtualized"
感谢 nickekallen 的 this posting,他提到了那个 dll 并让我想到了那个想法。
我正在使用 IConverterSession 从 mhtm 文件创建邮件项目。这适用于小于 2016 的 Outlook 版本。对于 Office 2016,无法创建 IConverterSession。
如果您使用的是 运行ning C2R(点击运行)版本的 Outlook 2016,所有注册表项都已虚拟化 - 请参阅下面的注册表项(%s 需要替换为Outlook 版本,例如 16.0
)。由于 COM 系统不在那里查找,您将需要实现您自己的 CoCreateInstance 版本,该版本从键中读取默认值以找出 dll 文件名,然后调用 LoadLibrary / GetProcAddress("DllGetClassObject") / DllGetClassObject(..., IID_IClassFactory, ...) / IClassFactory.CreateInstance
.
SOFTWARE\Microsoft\Office\%s.0\ClickToRun\REGISTRY\MACHINE\Software\Classes\CLSID\%s\InprocServer32
SOFTWARE\Microsoft\Office\%s.0\ClickToRun\REGISTRY\MACHINE\Software\Classes\Wow6432Node\CLSID\%s\InprocServer32
SOFTWARE\Microsoft\Office\ClickToRun\REGISTRY\MACHINE\Software\Classes\CLSID\%s\InprocServer32
SOFTWARE\Microsoft\Office\ClickToRun\REGISTRY\MACHINE\Software\Classes\Wow6432Node\CLSID\%s\InprocServer32
您不必自己实施 CoCreateInstance(),而必须启用注册表重定向以启用 Outlook 的 C2R(点击-运行)虚拟化,它使用迂回的方式将调用重定向到 RegOpenKey() .启用该重定向后,只需使用普通的 CoCreateInstance()。
你自己实现 CoCreateInstance() 不起作用的原因是,转换器也会在内部调用 CoCreateInstance() 并且会像你原来的调用一样失败,因为它在正常情况下找不到 CLSID注册表的配置单元。
我自己通过查看 jitv.dll 导出找到了代码。参数可能有误,但作为第一次启动它没有崩溃。要找出参数,我必须调试 Office 应用程序并查看反汇编(或任何志愿者?)。
这里是对我有用的实验代码:
HMODULE jitv = ::LoadLibrary(TEXT("jitv.dll"));
if (jitv) {
FARPROC efv = ::GetProcAddress(jitv, "EnableFullVirtualization");
if(efv)
efv();
// call CoCreateInstance(guid::CLSID_IConverterSession)
// and do your work
}
if (jitv)
FreeLibrary(jitv);
jitv.dll 中还有一些其他导出项,其名称大多不言自明:
- "APIExportForDetours"
- "DisableVirtualizationOnThread"
- "EnableVirtualizationOnThread"
- "IsCurrentThreadVirtualized"
感谢 nickekallen 的 this posting,他提到了那个 dll 并让我想到了那个想法。