附加到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加载项在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