C# 在C中等待Excel Interlop退出#
我正在开发一个工具,它将为我自动执行一些操作。其中一个操作是下载excel文件,在其上运行宏,然后邮寄该文件。在某些情况下,我希望该工具只运行excel宏,然后在x秒后退出excel并发送文件。这一切都很好,因为我可以等一段固定的时间。但是,在某些情况下,我希望能够检查和更改excel宏检索到的数据。在这种情况下,我希望保持excel处于打开状态,直到使用的手动关闭excel。当我检测到excel不再打开时,我想邮寄文件 最后一个案子给我带来了一些麻烦。因为我使用excel interlop打开excel,所以我无法像在正常进程中一样使用WaitForExit()。当我手动关闭excel时,流程也会在process explorer中保持运行 我曾在互联网上寻找解决方案,但没有一个真正有效。我有没有办法用一种简单的方法来实现这一点 更新 非常感谢你的回复,它真的帮助了我。等待excel现在可以正常工作。我使用了以下代码:C# 在C中等待Excel Interlop退出#,c#,excel,wait,exit,C#,Excel,Wait,Exit,我正在开发一个工具,它将为我自动执行一些操作。其中一个操作是下载excel文件,在其上运行宏,然后邮寄该文件。在某些情况下,我希望该工具只运行excel宏,然后在x秒后退出excel并发送文件。这一切都很好,因为我可以等一段固定的时间。但是,在某些情况下,我希望能够检查和更改excel宏检索到的数据。在这种情况下,我希望保持excel处于打开状态,直到使用的手动关闭excel。当我检测到excel不再打开时,我想邮寄文件 最后一个案子给我带来了一些麻烦。因为我使用excel interlop打开
if (Settings.ExitExcel)
{
System.Threading.Thread.Sleep(Settings.ExcelTimeout * 1000);
//Close Excel
excelWorkbook.Close();
excelApp.Quit();
}
else
{
Excel.AppEvents_WorkbookBeforeCloseEventHandler Event_BeforeBookClose;
Event_BeforeBookClose = new Excel.AppEvents_WorkbookBeforeCloseEventHandler(WorkbookBeforeClose);
excelApp.WorkbookBeforeClose += Event_BeforeBookClose;
//Wait until excel is closed
while (!isClosed)
{
Thread.Sleep(1000);
}
//Show message
MessageBox.Show("excel closed");
}
//Clean up excel.
Marshal.FinalReleaseComObject(excelSheets);
Marshal.FinalReleaseComObject(excelWorksheet);
Marshal.FinalReleaseComObject(excelWorkbook);
Marshal.FinalReleaseComObject(excelApp);
excelApp = null;
excelWorkbook = null;
excelWorksheet = null;
excelSheets = null;
GC.Collect();
现在唯一的问题是excel仍然在进程中运行。我没有正确地关闭它吗?您可以使用BeforeClose事件来完成此操作。基本上,您需要按照以下思路做一些事情:
//Outside main
private static bool isClosed = false;
....
//Let's say your Workbook object is named book
book.WorkbookBeforeClose += new Excel.AppEvents_WorkbookBeforeCloseEventHandler(app_WorkbookBeforeClose);
if(isClosed)
sendMailMethod();
...
private static void app_WorkbookBeforeClose(Excel.Workbook wb, ref bool cancel)
{
closed = !cancel;
}
这种方法不需要先终止进程。但是,您应该释放COM对象,并在Excel工作完成后结束该过程
编辑:要关闭流程,请尝试Application.Quit()方法。如果您还没有找到解决方案,下面是我编写的适合我的解决方案
private async void OnOpenWorkSheetImportCommand(object sender, ExecutedRoutedEventArgs e)
{
try
{
if (e.Parameter is IWorkSheetImportViewModel model)
{
if (WorksheetDictionaries.OfType<WorksheetDictionary>().FirstOrDefault(a => a.Header.Equals(model.Header)) is WorksheetDictionary worksheetDictionary)
{
Type officeType = Type.GetTypeFromProgID("Excel.Application", true);
if (officeType != null)
{
BeforeWorkbookDictionary = worksheetDictionary.WorkbookDictionary;
OpenInteropWorkbookDictionary(worksheetDictionary.WorkbookDictionary, worksheetDictionary, true);
}
else
{
throw new ArgumentException("Microsoft Excel is not installed!");
}
}
}
}
...
..
.
}
注意:
#region RoutedEventArgs Properties
private IDisposable disposableClosingEvent;
public IDisposable DisposableClosingEvent
{
get => this.disposableClosingEvent; set => SetProperty(ref disposableClosingEvent, value, nameof(DisposableClosingEvent));
}
private IObservable<EventPattern<object, EventArgs>> exitedEventArgs;
public IObservable<EventPattern<object, EventArgs>> ExitedEventArgs
{
get => exitedEventArgs; set => SetProperty(ref exitedEventArgs, value, nameof(ExitedEventArgs));
}
private IDisposable disposableExited;
public IDisposable DisposableExited
{
get => this.disposableExited; set => SetProperty(ref disposableExited, value, nameof(DisposableExited));
}
#endregion
private async void OnWorkbookDeactivate(Microsoft.Office.Interop.Excel.Workbook Wb)
{
try
{
ProgressController = default(ProgressDialogController);
if (ExcelApplication != null && ExcelApplication.Visible == true)
{
int excelProcessId = -1;
GetWindowThreadProcessId(new IntPtr(ExcelApplication.Hwnd), ref excelProcessId);
Process ExcelProc = Process.GetProcessById(excelProcessId);
if (ExcelProc != null)
{
ExitedEventArgs = Observable.FromEventPattern<object, EventArgs>(ExcelProc, MethodParameter.Exited);
DisposableExited = ExitedEventArgs.Subscribe(evt => OnExitedEvent(evt.Sender, evt.EventArgs));
ExcelProc.EnableRaisingEvents = true;
ProgressController = await _dialogCoordinator.ShowProgressAsync(this, string.Format("Workbook {0}", BeforeWorkbookDictionary.ExcelName), "Please wait! Processing any changes...");
ProgressController.SetIndeterminate();
ExcelApplication.Quit();
if (ExcelApplication != null) Marshal.FinalReleaseComObject(ExcelApplication);
if (ExcelWorkbook != null) Marshal.FinalReleaseComObject(ExcelWorkbook);
if (ExcelWorksheet != null) Marshal.FinalReleaseComObject(ExcelWorksheet);
if (ExcelWorksheets != null) Marshal.FinalReleaseComObject(ExcelWorksheets);
ExcelApplication = null;
ExcelWorkbook = null;
ExcelWorksheet = null;
ExcelWorksheets = null;
ExcelProc.WaitForExit();
ExcelProc.Refresh();
}
}
}
catch (Exception msg)
{
...
..
.
}
}
和:
#region RoutedEventArgs Properties
private IDisposable disposableClosingEvent;
public IDisposable DisposableClosingEvent
{
get => this.disposableClosingEvent; set => SetProperty(ref disposableClosingEvent, value, nameof(DisposableClosingEvent));
}
private IObservable<EventPattern<object, EventArgs>> exitedEventArgs;
public IObservable<EventPattern<object, EventArgs>> ExitedEventArgs
{
get => exitedEventArgs; set => SetProperty(ref exitedEventArgs, value, nameof(ExitedEventArgs));
}
private IDisposable disposableExited;
public IDisposable DisposableExited
{
get => this.disposableExited; set => SetProperty(ref disposableExited, value, nameof(DisposableExited));
}
#endregion
#区域路由目标属性
私人IDisposable可处置ClosingEvent;
公共IDisposable可处置ClosingEvent
{
get=>this.disposableClosingEvent;set=>SetProperty(ref disposableClosingEvent,value,nameof(disposableClosingEvent));
}
私有IObservable exitedEventArgs;
公共IObservable ExitedEventArgs
{
get=>exitedEventArgs;set=>SetProperty(ref exitedEventArgs,value,nameof(exitedEventArgs));
}
私人可转让可处置资产退出;
公共IDisposable可处置退出
{
get=>this.disposableExited;set=>SetProperty(ref disposableExited,value,nameof(disposableExited));
}
#端区
最后:调用OnExitedEvent以在最后一分钟进行一些处理
private async void OnExitedEvent(object sender, EventArgs e)
{
try
{
DisposableExited.Dispose();
using (SpreadsheetDocument s = SpreadsheetDocument.Open(SelectedWorkbookDictionaryImport.FilePath, false))
{
foreach (Sheet workbookSheet in s.WorkbookPart.Workbook.Sheets)
{
if (WorkbookDictionaryImports.OfType<WorkbookDictionary>().FirstOrDefault(d => d.ExcelName.Equals(SelectedWorkbookDictionaryImport.ExcelName)) is WorkbookDictionary workbookDictionary)
{
if (workbookDictionary.WorksheetDictionaryItems.OfType<WorksheetDictionary>().FirstOrDefault(d => d.Id.Equals(workbookSheet.Id)) == null)
{
Application.Current.Dispatcher.Invoke(() =>
{
WorksheetDictionary worksheetDictionary = new WorksheetDictionary()
{
WorksheetDictionaryId = Guid.NewGuid().ToString(),
IsSelected = false,
Id = workbookSheet.Id,
SheetId = workbookSheet.SheetId,
Name = workbookSheet.Name,
Header = workbookSheet.Name,
HeaderInfo = GetSheetStateValues(workbookSheet.State),
Code = GetSheetCodeValues(workbookSheet.Name.ToString()).ToString(),
Description = BeforeWorkbookDictionary.Subject,
WorkbookDictionary = BeforeWorkbookDictionary
};
workbookDictionary.WorksheetDictionaryItems.Add(worksheetDictionary);
});
}
}
}
}
}
catch (Exception msg)
{
...
..
.
}
finally
{
if (ProgressController != null)
{
await ProgressController.CloseAsync();
ProgressController = default(ProgressDialogController);
}
}
}
private async void OnExitedEvent(对象发送方,事件参数e)
{
尝试
{
DisposableExited.Dispose();
使用(SpreadsheetDocument s=SpreadsheetDocument.Open(SelectedWorkbookDictionaryImport.FilePath,false))
{
foreach(s.WorkbookPart.Workbook.Sheets中的工作表工作簿)
{
如果(WorkbookDictionaryImports.OfType().FirstOrDefault(d=>d.ExcelName.Equals(SelectedWorkbookDictionaryImport.ExcelName))是WorkbookDictionary WorkbookDictionary)
{
if(workbookDictionary.WorksheetDictionaryItems.OfType().FirstOrDefault(d=>d.Id.Equals(workbookSheet.Id))==null)
{
Application.Current.Dispatcher.Invoke(()=>
{
工作表字典工作表字典=新工作表字典()
{
WorksheetDictionaryId=Guid.NewGuid().ToString(),
IsSelected=false,
Id=工作薄。Id,
SheetId=工作薄。SheetId,
Name=工作薄。Name,
页眉=工作簿。名称,
HeaderInfo=GetSheetStateValues(workbookSheet.State),
Code=GetSheetCodeValues(workbookSheet.Name.ToString()).ToString(),
Description=在WorkBookDictionary.Subject之前,
WorkbookDictionary=BeforeWorkbookDictionary
};
workbookDictionary.WorksheetDictionaryItems.Add(worksheetDictionary);
});
}
}
}
}
}
捕获(异常消息)
{
...
..
.
}
最后
{
如果(ProgressController!=null)
{
等待ProgressController.CloseAsync();
ProgressController=默认值(ProgressDialogController);
}
}
}
希望这将有助于您和其他人进行更改,以满足您的加工需求 非常感谢您的回复。这对我帮助很大。但是我还有一个问题,所以我更新了我的帖子。再次感谢你的快速回复。我尝试添加excelApp.Quit()一个妙招
private async void OnExitedEvent(object sender, EventArgs e)
{
try
{
DisposableExited.Dispose();
using (SpreadsheetDocument s = SpreadsheetDocument.Open(SelectedWorkbookDictionaryImport.FilePath, false))
{
foreach (Sheet workbookSheet in s.WorkbookPart.Workbook.Sheets)
{
if (WorkbookDictionaryImports.OfType<WorkbookDictionary>().FirstOrDefault(d => d.ExcelName.Equals(SelectedWorkbookDictionaryImport.ExcelName)) is WorkbookDictionary workbookDictionary)
{
if (workbookDictionary.WorksheetDictionaryItems.OfType<WorksheetDictionary>().FirstOrDefault(d => d.Id.Equals(workbookSheet.Id)) == null)
{
Application.Current.Dispatcher.Invoke(() =>
{
WorksheetDictionary worksheetDictionary = new WorksheetDictionary()
{
WorksheetDictionaryId = Guid.NewGuid().ToString(),
IsSelected = false,
Id = workbookSheet.Id,
SheetId = workbookSheet.SheetId,
Name = workbookSheet.Name,
Header = workbookSheet.Name,
HeaderInfo = GetSheetStateValues(workbookSheet.State),
Code = GetSheetCodeValues(workbookSheet.Name.ToString()).ToString(),
Description = BeforeWorkbookDictionary.Subject,
WorkbookDictionary = BeforeWorkbookDictionary
};
workbookDictionary.WorksheetDictionaryItems.Add(worksheetDictionary);
});
}
}
}
}
}
catch (Exception msg)
{
...
..
.
}
finally
{
if (ProgressController != null)
{
await ProgressController.CloseAsync();
ProgressController = default(ProgressDialogController);
}
}
}