附加到Office应用程序的运行实例时发生C#.NET错误

本文关键字:错误 NET 实例 运行 Office 应用程序 | 更新日期: 2023-09-27 18:22:03

我正在使用C#Visual Studio 2012开发Excel加载项。我正在尝试获取Excel的应用程序对象的实例,以便跟踪当前活动的工作簿和工作表(ActiveWorkbook,ActiveWorksheet)。

我看到SO上的大多数其他相关问题都有建议使用以下内容的回复:

(Excel.Application)Marshal.GetActiveObject("Excel.Application");

我也尝试过使用这个:

(Excel.Application)Globals.ThisAddIn.Application;

在这两种情况下,我都会得到NullReferenceException。查看了此处建议的解决方法后:http://support.microsoft.com/kb/316125/en-us,我尝试了以下两种方法进行测试。

public CurrentSpreadSheet()
    {
        try
        {
            this.CurrentApplication = (Excel.Application)Globals.ThisAddIn.Application;
        }
        catch (NullReferenceException)
        {
            MessageBox.Show("Excel application object not registered. Trying plan B..");
            //Getting Excel's application object instance
            int iSection = 0, iTries = 0;
        tryAgain:
            try
            {
                iSection = 1; //Attempting GetActiveObject
                this.CurrentApplication = (Excel.Application)Marshal.GetActiveObject("Excel.Application");
                iSection = 0; //GetActiveObject succeeded so resume or go for normal error handling if needed
                this.CurrentApplication.Visible = true;
            }
            catch (Exception err)
            {
                System.Console.WriteLine("Visual C# .NET Error Attaching to Running Instance of Office Application .. yet.");
                if (iSection == 1)
                {
                    //GetObject may have failed because the
                    //Shell function is asynchronous; enough time has not elapsed
                    //for GetObject to find the running Office application. Wait
                    //1/2 seconds and retry the GetObject. If we try 20 times
                    //and GetObject still fails, we assume some other reason
                    //for GetObject failing and exit the procedure.
                    iTries++;
                    if (iTries < 20)
                    {
                        System.Threading.Thread.Sleep(500); // Wait 1/2 seconds.
                        goto tryAgain; //resume code at the GetObject line
                    }
                    else
                    {
                        MessageBox.Show("GetObject still failing.  Process ended.");
                    }
                }
                else
                {
                    //iSection == 0 so normal error handling
                    MessageBox.Show(err.Message);
                }
            }
        }

    }

输出为:

Excel application object not registered. Trying plan B..
GetObject still failing.  Process ended.

在极少数情况下,"B计划"确实有效;我看不到第二个消息框。CurrentSpreadSheet是一个单例,我打算在启动期间从提供的类ThisAddIn更新它。

在这个插件中,我有一些类似的东西:

private CurrentSpreadSheet css = CurrentSpreadSheet.Instance;
private void ThisAddIn_Startup(object sender, System.EventArgs e)
    {
        ///...Some code
        css.updateCurrentSpreadSheet();
}

有没有更好的方法来获取Application对象?如果在启动过程中无法做到这一点,有没有更好的方法可以让我从excel/我的加载项启动时就跟踪当前活动的工作表/工作簿?目前,我依靠应用程序对象(例如(Excel.Workbook)this.CurrentApplication.ActiveWorkbook;)和一些事件处理程序来跟踪当前工作簿和工作表。

我尝试使用ExcelDNA:

this.CurrentApplication = (Excel.Application)ExcelDna.Integration.ExcelDnaUtil.Application;

这在某些情况下有效,但大多数情况下会出现以下错误:

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> ExcelDna.Integration.XlCallException: Exception of type 'ExcelDna.Integration.XlCallException' was thrown.

附加到Office应用程序的运行实例时发生C#.NET错误

请记住,Office加载项在Office进程内运行。所以你永远不想找到一个外部过程。当您使用Office项目模板时得到的样板ThisAddIn类会将您要查找的应用程序对象放在银盘上,使用其Application属性。第一次使用它是在"启动"事件中,请确保不要提前尝试。因此,不要在构造函数中做任何激烈的操作,也不要用初始化表达式初始化类成员,等待启动启动。

相关的MSDN页面在这里,"访问主机应用程序的对象模型"部分。

您可以仔细查看http://netoffice.codeplex.com/在那里你可以找到更多关于Word/Excel/Powerpoint加载项的内容。加载加载项时还要记住GuidAttribute,因为根据您的Office版本,它将不再工作,此外,请检查以保持您的项目是否为32/64位,最好是Any CPU。此外,请记住将外接程序注册到注册表中以供进一步使用。如果你想了解更多信息,请随时给我写信。

http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.guidattribute.aspx