在新的互操作Excel进程中打开工作簿时抛出异常



我有一个excel.com添加,在excel工作簿上执行一些操作。这个想法是,当一个默认的excel文件被打开,一个暴露的函数在com添加(OpenFile)将从vba在这个工作簿中调用。此时,外接程序将打开一个新的excel进程,并在其中打开用户工作簿。它在大多数情况下都有效,但偶尔会在标记的行抛出以下异常:

INFO, 05:31:12: Message: Thread was being aborted。INFO, 05:31:12:内部异常:INFO, 05:31:12:来源:mscorlibINFO, 05:31:12: HResult: -2146233040INFO, 05:31:12: Target site: Void ThrowExceptionForHRInternal(Int32, IntPtr)INFO, 05:31:12:堆栈跟踪:at System.Runtime.InteropServices.Marshal。ThrowExceptionForHRInternal(Int32 errorCode, IntPtr errorInfo)在System.Dynamic.ComRuntimeHelpers。CheckThrowException(Int32 hresult, ExcepInfo&excepInfo, UInt32 argErr, String message)在CallSite。目标(Closure, CallSite, ComObject, String, Boolean)在System.Dynamic.UpdateDelegates。updateanddexecute3 [T0,T1,T2,TRet](CallSite site, T0 arg0, T1 arg1, T2 arg2)在System.Dynamic.UpdateDelegates。updateanddexecutevoid3 [T0,T1,T2](CallSite site, T0 arg0, T1 arg1, T2 arg2)在VbaApi.AddInApi。OpenFile(String path, Boolean fromVba)

失败时,新创建的进程崩溃并关闭。它似乎是在RealOpen函数中完全随机的位置抛出的,所以它不是函数中特定的失败。有时根本不抛出,工作簿在新进程中打开并正常运行。

下面是产生异常的代码:
public void OpenFile(string path, bool fromVba)
{
if (fromVba)
{
// if called from vba, create a new application object and make visible
Excel.Application singleApp = new Excel.Application();
// show new application
singleApp.Visible = true;

// Get process id
int processId = ExcelFunctions.GetExcelProcessId(singleApp);
// give new app focus
ExcelFunctions.BringMainWindowToFront(processId);
// get ComAddIn in new application instance
COMAddIn addIn = singleApp.COMAddIns.Item(ExcelFunctions.GetVersion(singleApp.Version));

// connect it
addIn.Connect = true;

// automation object
dynamic automationObject = addIn.Object;
try
{
// call open file in new instance                                        
automationObject.OpenFile(path, false); // Exception is thrown here
}
catch (Exception e)
{
LoggerFactory.Logger.Debug(e.StackTrace);
}
// close original application if no other workbooks open
ExcelFunctions.CloseSession(application);              
}
else
{
RealOpen(path);                
}
}
private void RealOpen(string path)
{
try
{
OnRealOpen?.Invoke(path);
if (path.StartsWith("Cannot decode:"))
{
string error = "Error during download.";
LoggerFactory.Logger.Error(error);
AlertUser();
return;
}
dynamic WinHttpReq = VBAFunctions.CreateObject("Microsoft.XMLHTTP");
WinHttpReq.Open("GET", path, false);
WinHttpReq.Send();
string FileName = WinHttpReq.GetResponseHeader("Content-Disposition");
if (FileName == null)
{
AlertUser();
return;
}
FileName = FileName.Substring(10);
FileName = FileName.Substring(0, FileName.Length - 1);
// check if file is already open on this machine           
if (ExcelFunctions.CheckIfWorkbookOpen(FileName))
return;
SavePath = Path.GetTempPath() + FileName;
byte[] caseTemplateWithoutData = WinHttpReq.ResponseBody;
if (WinHttpReq.Status == 200)
{
using (var fs = new FileStream(SavePath, FileMode.Create, FileAccess.Write))
{
fs.Write(caseTemplateWithoutData, 0, caseTemplateWithoutData.Length);
}

GetMetaData("http://test.com", SavePath);
}
else
{
string error = "Cannot open, download file error.";
LoggerFactory.Logger.Error(error + " http status: " + WinHttpReq.Status + " ResponseText: " + WinHttpReq.ResponseText);
AlertUser();
return;
}
SaveDisabled?.Invoke();
// Closing current workbook, and opens case.
ReOpenExcel?.Invoke(SavePath); // It never reaches this point when it fails
// Set focus to ribbon tab.       
ActivateTab();
}
catch (Exception ee)
{
LoggerFactory.Logger.Error($"RealOpen - Error: { ee.Message }.");
}
}

任何关于问题的指导都将非常感谢。

不要创建Excel.Application对象的新实例。还要记住,COM对象具有线程亲和性,因此,如果您在次要线程上创建了一个新的COM对象,请使用Marshal.ReleaseComObject()释放它(及其所有子对象)。

最新更新