错误429 activex组件在使用自创建引用时无法创建对象

时间:2018-05-30 10:55:52

标签: c# excel vba dll activex

我在C#中为excel创建了一些加载项。它是一个在VBA中使用的公共类。在我的机器上一切正常。当我在测试计算机上安装加载项时(我使用InstallShield 2015限制版为Visual Studio创建安装文件)我无法设置对象。

C#代码

using System;
using Excel = Microsoft.Office.Interop.Excel;
using System.Runtime.InteropServices;
using Microsoft.Win32;

namespace PMTAddin
{
    [Guid("B2350EC1-522E-4B75-BB02-86BB0FD1A60E")]
    [ClassInterface(ClassInterfaceType.AutoDual)]
    [ComVisible(true)]
    public class PublicClass
    {
        public void test()
        {
            System.Windows.Forms.MessageBox.Show(
                        "test."
                    , "test"
                    , System.Windows.Forms.MessageBoxButtons.OK
                    , System.Windows.Forms.MessageBoxIcon.Error
                );
        }

        private int GetWorksheetID(Excel.Workbook wb, string worksheetName)
        {
            int result = 0;


            foreach (Excel.Worksheet ws in wb.Worksheets)
            {
                if (ws.Name == worksheetName)
                {
                    result = ws.Index;
                    break;
                }

            }

            return result;
        }

        [ComRegisterFunctionAttribute]
        public static void RegisterFunction(Type type)
        {
            Registry.ClassesRoot.CreateSubKey(GetSubKeyName(type, "Programmable"));
            RegistryKey key = Registry.ClassesRoot.OpenSubKey(GetSubKeyName(type, "InprocServer32"), true);
            key.SetValue("", System.Environment.SystemDirectory + @"\mscoree.dll", RegistryValueKind.String);
        }

        [ComUnregisterFunctionAttribute]
        public static void UnregisterFunction(Type type)
        {
            Registry.ClassesRoot.DeleteSubKey(GetSubKeyName(type, "Programmable"), false);
        }

        private static string GetSubKeyName(Type type, string subKeyName)
        {
            System.Text.StringBuilder s = new System.Text.StringBuilder();
            s.Append(@"CLSID\{");
            s.Append(type.GUID.ToString().ToUpper());
            s.Append(@"}\");
            s.Append(subKeyName);
            return s.ToString();
        }
    }
}

在VBA项目中,我检查了列表中对它的引用。它叫PMT。

VBA

Sub dsf()
    Dim o As PMT.PublicClass
    Set o = New PMT.PublicClass 'at this lane on other computer I got error 429. On my computer all work smoothly and method test is running.

    o.test
End Sub

我认为这可能是.NET Framework,但它已经安装。有什么想法吗?

修改

我为bittnes创建了两个不同的版本,但是同样的错误。

但我发现了一些新信息。在我的计算机上的注册表中它看起来像这样 Registry on dev machine

并且在测试机上它看起来像这样 Registry on test machine

没有CodeBase值......您认为这是问题吗?如果是,我如何修改RegisterFunction方法来纠正这个问题?

1 个答案:

答案 0 :(得分:1)

经过长时间的寻求,我找到了解决方案。它是部分的,因为对于64位Excel我们需要手动注册库(也许有人知道,如何将bat文件添加到安装文件)。

我在site上找到了答案。

在创建Install Shield安装文件时,我们需要做两件事。

  1. 将.tlb文件添加到应用程序文件(此步骤由我完成,然后在stackoverflow上发布)
  2. 点击右侧的project.Primary输出文件并选择截图中的特性(对于* .tlb文件,我们需要检查相同,但没有" COM Interop") enter image description here
  3. 如果没有此安装程序,安装程序将无法在注册表中正确注册加载项。

    这样创建的安装文件会为 32位excel 注册加载项。如果要在64位Excel中使用它,则需要手动注册库。我创建了这样简单的bat文件:

    c:
    cd C:\Windows\Microsoft.NET\Framework64\v4.0.30319
    regasm.exe "[pathToDLL]\AddInName.dll" /tlb:"[pathToDLL]\AddInName.tlb" /codebase 
    pause
    

    请记住,您需要使用管理员权限运行它。