为本地计算机注册表配置单元安装 Outlook 加载项



我正在使用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插件项目找到了答案!

您所需要的只是几个具有 ComRegisterFunctionAttributeComUnregisterFunctionAttribute 属性的公共静态方法。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);
        }
    }

最新更新