我试图创建一个扫描COM DLL并创建必要的注册表项的reg文件的程序,而无需调用regsvr32并且不必具有管理权限。扫描没有管理员权限的COM dll注册表
为此,我使用RegOverridePredefKey重新映射HKEY_CURRENT_USER子项中的Windows注册表配置单元。
https://msdn.microsoft.com/pt-br/library/windows/desktop/ms724901(v=vs.85).aspx
重映射工作。我知道,因为我可以,例如,调用一个Windows API函数来创建一个虚假的注册表项HKEY_LOCAL_MACHINE下,它实际上出现在我的HKEY_CURRENT_USER子项下。不需要管理员权限。
下面是重映射代码:
if (reg::remapRegistry(HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, basekey + "hkcr"))
{
if (reg::remapRegistry(HKEY_LOCAL_MACHINE, HKEY_CURRENT_USER, basekey + "hklm"))
{
if (reg::remapRegistry(HKEY_USERS, HKEY_CURRENT_USER, basekey + "hku"))
{
if (reg::remapRegistry(HKEY_CURRENT_USER, HKEY_CURRENT_USER, basekey + "hkcu"))
{
reg::createKey(HKEY_LOCAL_MACHINE, "Software\\Classes");
reg::createKey(HKEY_CURRENT_USER, "Software\\Classes");
ret = scan(args);
reg::cancelRemapedRegistry(HKEY_CURRENT_USER);
}
reg::cancelRemapedRegistry(HKEY_USERS);
}
reg::cancelRemapedRegistry(HKEY_LOCAL_MACHINE);
}
reg::cancelRemapedRegistry(HKEY_CLASSES_ROOT);
}
参数args给我的扫描功能仅仅是一个结构的路径,我的DLL。 reg ::函数只是windows api的包装。
这里是我的扫描功能:
int scan(const Args &args)
{
typedef HRESULT (__stdcall *pDllRegisterServer) (void);
try
{
HMODULE hDLL = LoadLibrary(args.dll.c_str());
if (hDLL == NULL)
{
LOGERROR("Cannot load dll");
return 1;
}
pDllRegisterServer DllRegisterServer = (pDllRegisterServer) GetProcAddress(hDLL, "DllRegisterServer");
if (DllRegisterServer == NULL)
{
LOGERROR("Cannot find function DllRegisterServer in dll");
FreeLibrary(hDLL);
return 2;
}
HRESULT res = DllRegisterServer();
DWORD err = GetLastError();
switch (res)
{
case S_OK:
LOGINFO("successfully called DllRegisterServer");
return 0;
case SELFREG_E_TYPELIB:
LOGERROR("DllRegisterServer error SELFREG_E_TYPELIB");
return 3;
case SELFREG_E_CLASS:
LOGERROR("DllRegisterServer error SELFREG_E_CLASS");
return 4;
case E_OUTOFMEMORY:
LOGERROR("DllRegisterServer error E_OUTOFMEMORY");
return 5;
case E_UNEXPECTED:
LOGERROR("DllRegisterServer error E_UNEXPECTED");
return 6;
default:
LOGERROR("DllRegisterServer really unexpected error");
}
return 7;
}
catch (...)
{
LOGERROR("unknown error loading dll or function");
return -1;
}
}
中的DllRegisterServer将返回S_OK,但正在创建只有一半的注册表项。我在HKEY_CURRENT_USER \ tempkey \ hkcr下重新映射的HKEY_CLASSES_ROOT包含所有预期的键。但HKEY_CURRENT_USER \ tempkey \ hklm(重映射的HKEY_LOCAL_MACHINE)仅包含我自己创建的空键“Software \ Classes”。它缺少DllRegisterServer应该创建的“TypeLib”和“Interface”键。
这不是重映射或权限问题,因为我可以在没有管理员权限的情况下在HKEY_LOCAL_MACHINE下创建空的“Software \ Classes”。
奇怪的是,在另一台机器DllRegisterServer上测试失败,出现SELFREG_E_TYPELIB。
我也尝试调用LoadTypeLib()和RegisterTypeLib(),我得到错误代码“0x8002801c访问OLE注册表时出错”。
如果我然后以管理员身份重新启动Visual Studio并再次运行该程序,我会得到所有预期的注册表项,包括HKLM下的注册表项。
任何想法,为什么它失败,如何让这个东西工作?
我知道有可能在没有管理员的情况下获取所有注册表项,因为wix的收获工具heat.exe可以成功完成此操作。我已经检查过他们的源代码,我相信我已经在做他们正在做的一切。我不希望将wix工具集作为构建环境的必需条件,因为我需要将它们的文件格式解析为* .reg文件。
您不需要管理员权限即可访问HKCR和HKLM。你真的需要复制一切,而不是只读现有的条目吗? –