我正在尝试创建一个程序来扫描com dll并创建必要注册表键的reg文件,而无需致电regsvr32,而不必具有管理权限。p>为此,我正在使用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 SUBKEY下。无需管理特权。
这是重建代码:
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_classes_root包含所有预期的键。但是hkey_current_user tempkey hklm(rempaped hkey_local_machine(仅包含我创建自己的空键"软件类"。它缺少DllRegisterServer应该创建的" Typelib"one_answers"接口"键。
这不是重新设计或权限问题,因为我可以在没有管理员权利的情况下在HKEY_LOCAL_MACHINE下创建空的"软件类"。
奇怪的是,在另一台计算机上测试dllRegisterserver失败了。
我还尝试调用LoadTypelib((和registertypelib((,我将获得错误代码" 0x8002801c错误访问OLE注册"。"
如果我然后重新启动Visual Studio作为管理员并再次运行该程序,我将获得所有预期的注册表密钥,包括HKLM下的注册表密钥。
关于为什么失败以及如何使此东西工作的任何想法?
我知道可以在无需担任管理员的情况下获取所有注册表键,因为Wix的Harvest Tool Heat.exe成功地做到了。我已经检查了他们的源代码,我相信我已经在做他们正在做的所有事情。而且我不想将WIX Toolset作为我的构建环境的要求,也只是因为我需要将其文件格式解析到 *.reg文件中。
我找到了解决方案:我们必须在进行重新映射之前调用函数oaenableperusertlibregistration((。
。https://msdn.microsoft.com/en-us/library/windows/desktop/cc713570(v = vs.85(.aspx
调用该函数后,com dll的回调dllregisterserver((将尝试在HKCR下而不是HKLM下创建Typelib键。