我正在使用regasm.exe在最终用户的计算机上安装我的Outlook插件。但是,我注意到在终端服务器环境中,我的插件不会为所有用户加载。我发现加载项注册表项是在当前用户配置单元下创建的,而不是在本地计算机配置单元下创建的。
我可以在我的插件中添加一些东西,使 regasm 能够在用户安装或卸载插件时创建/删除 HKLM 下的密钥以及当前用户?
我在regasm.exe
方面遇到了其他但类似的问题,因为我想在注册加载项时避免在窗口中使用 UAC,所以我自己编写了一个 com 注册器,它执行正确的注册表项来注册 com 插件。
您必须相应地更改此代码,以便在这些位置拥有所需的注册表项,并且显然具有类似的代码来在卸载加载项时回滚这些更改
class ComAddinRegistrar
{
private static string CLSID = "{CLSID}";
private static string ASSEMBLY_NAME = "Outlook.Addin";
private static string ASSEMBLY_DLL = "Outlook.Addin.dll";
private static string VERSION = "1.0.0.0";
private static string IMPLEMENTED_CATEGORY = "{CATEGORY_ID}";
public static void RegisterAddin(bool is64Bit)
{
// Get path of dll:
var apPpath = System.Reflection.Assembly.GetExecutingAssembly().Location;
apPpath = Path.GetDirectoryName(apPpath);
var path = ASSEMBLY_DLL;
var dllPath = Path.Combine(apPpath, path);
// Com registration
RegistryKey rkey;
if (is64Bit)
rkey = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Registry64)
.OpenSubKey("Software").OpenSubKey("Classes", true);
else
rkey = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Registry32)
.OpenSubKey("Software").OpenSubKey("Classes", true);
var comAssemblyNameKey = rkey.CreateSubKey(ASSEMBLY_NAME); //HKCU/Software/Classes/Outlook.Addin
comAssemblyNameKey.SetValue("", ASSEMBLY_NAME); // default value
var clsidAssemblyNameComKey = comAssemblyNameKey.CreateSubKey("CLSID"); //HKCU/Software/Classes/Outlook.Addin/{CLSID}
clsidAssemblyNameComKey.SetValue("", CLSID); // default value
RegistryKey clsidComKey;
if (is64Bit)
clsidComKey = rkey.CreateSubKey("CLSID").CreateSubKey(CLSID); //HKCUSoftwareClassesCLSID{CLSID}
else
clsidComKey = rkey.CreateSubKey("Wow6432Node").CreateSubKey("CLSID").CreateSubKey(CLSID); //HKCUSoftwareClassesCLSID{CLSID}
clsidComKey.SetValue("", ASSEMBLY_NAME); // default value
var inProcServerKey = clsidComKey.CreateSubKey("InprocServer32"); //HKCUSoftwareClassesCLSID{CLSID}InProcServer32
inProcServerKey.SetValue("", "mscoree.dll");
inProcServerKey.SetValue("ThreadingModel", "Both");
inProcServerKey.SetValue("Class", "Outlook.Addin.Addin");
inProcServerKey.SetValue("Assembly", $"Outlook.Addin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null");
inProcServerKey.SetValue("RuntimeVersion", "v4.0.30319");
inProcServerKey.SetValue("CodeBase", dllPath);
var versionKey = inProcServerKey.CreateSubKey(VERSION); //HKCUSoftwareClassesCLSID{CLSID}InProcServer321.0.0.0
versionKey.SetValue("Class", "Outlook.Addin.Addin");
versionKey.SetValue("Assembly", $"Outlook.Addin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null");
versionKey.SetValue("RuntimeVersion", "v4.0.30319");
versionKey.SetValue("CodeBase", dllPath);
var progIdKey = clsidComKey.CreateSubKey("ProgId"); //HKCUSoftwareClassesCLSID{CLSID} ProgId
progIdKey.SetValue("", ASSEMBLY_NAME);
var implementedCategoryKey = clsidComKey.CreateSubKey("ImplementedCategories"); //HKCUSoftwareClassesCLSID{CLSID}ImplementedCategories
implementedCategoryKey.CreateSubKey(IMPLEMENTED_CATEGORY);
//AddIn registration
//HKEY_CURRENT_USERSOFTWAREMicrosoftOfficeOutlookAddinsOutlook.Addin
var okey = Registry.CurrentUser.OpenSubKey("SOFTWARE")
.OpenSubKey("Microsoft")
.OpenSubKey("Office")
.OpenSubKey("Outlook")
.OpenSubKey("Addins", true);
var addinKey = okey.CreateSubKey(ASSEMBLY_NAME);
addinKey.SetValue("FileName", dllPath);
addinKey.SetValue("FriendlyName", "My addin");
addinKey.SetValue("Description", "some addin description");
addinKey.SetValue("LoadBehavior", 3, RegistryValueKind.DWord);
}
}
通过挖掘我的示例NetOffice Outlook插件项目找到了答案!
您所需要的只是几个具有 ComRegisterFunctionAttribute
和 ComUnregisterFunctionAttribute
属性的公共静态方法。Regasm.exe 将在安装或卸载插件时自动执行这些方法中的代码。
请参阅下面的代码,了解我正在使用的代码,该代码从模板略有修改以支持 HKLM 注册表项。将这些方法添加到您的 Outlook 加载项类中。
如果您希望手动处理这些,可以使用 Alek 的答案。
[ComRegisterFunctionAttribute]
public static void RegisterFunction(Type type)
{
try
{
// add codebase value
Assembly thisAssembly = Assembly.GetAssembly(typeof(OutlookPlugin));
RegistryKey key = Registry.ClassesRoot.CreateSubKey("CLSID\{" + type.GUID.ToString().ToUpper() + "}\InprocServer32\1.0.0.0");
key.SetValue("CodeBase", thisAssembly.CodeBase);
key.Close();
key = Registry.ClassesRoot.CreateSubKey("CLSID\{" + type.GUID.ToString().ToUpper() + "}\InprocServer32");
key.SetValue("CodeBase", thisAssembly.CodeBase);
key.Close();
// add bypass key
// http://support.microsoft.com/kb/948461
key = Registry.ClassesRoot.CreateSubKey("Interface\{000C0601-0000-0000-C000-000000000046}");
string defaultValue = key.GetValue("") as string;
if (null == defaultValue)
key.SetValue("", "Office .NET Framework Lockback Bypass Key");
key.Close();
// add outlook addin key
Registry.ClassesRoot.CreateSubKey(@"CLSID{" + type.GUID.ToString().ToUpper() + @"}Programmable");
Registry.CurrentUser.CreateSubKey(_addinOfficeRegistryKey + _prodId);
RegistryKey rk = Registry.CurrentUser.OpenSubKey(_addinOfficeRegistryKey + _prodId, true);
rk.SetValue("LoadBehavior", Convert.ToInt32(3));
rk.SetValue("FriendlyName", _addinFriendlyName);
rk.SetValue("Description", _addinDescription);
rk.Close();
//Add registry key under HKLM
RegistryKey regHKLM = Registry.LocalMachine;
regHKLM = regHKLM.CreateSubKey(@"SOFTWAREMicrosoftOfficeOutlookAddins" + _prodId);
regHKLM.SetValue("Friendly Name", _addinFriendlyName);
regHKLM.SetValue("Description", _addinDescription);
regHKLM.SetValue("LoadBehavior", 3, RegistryValueKind.DWord);
}
catch (System.Exception ex)
{
string details = string.Format("{1}{1}Details:{1}{1}{0}", ex.Message, Environment.NewLine);
MessageBox.Show("An error occured." + details, "Register " + _prodId, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
[ComUnregisterFunctionAttribute]
public static void UnregisterFunction(Type type)
{
try
{
Registry.ClassesRoot.DeleteSubKey(@"CLSID{" + type.GUID.ToString().ToUpper() + @"}Programmable", false);
Registry.CurrentUser.DeleteSubKey(_addinOfficeRegistryKey + _prodId, false);
Registry.LocalMachine.DeleteSubKey(@"SOFTWAREMicrosoftOfficeOutlookAddins" + _prodId);
}
catch (System.Exception throwedException)
{
string details = string.Format("{1}{1}Details:{1}{1}{0}", throwedException.Message, Environment.NewLine);
MessageBox.Show("An error occured." + details, "Unregister " + _prodId, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}