Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/336.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/excel/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在C中等待Excel Interlop退出#_C#_Excel_Wait_Exit - Fatal编程技术网

C# 在C中等待Excel Interlop退出#

C# 在C中等待Excel Interlop退出#,c#,excel,wait,exit,C#,Excel,Wait,Exit,我正在开发一个工具,它将为我自动执行一些操作。其中一个操作是下载excel文件,在其上运行宏,然后邮寄该文件。在某些情况下,我希望该工具只运行excel宏,然后在x秒后退出excel并发送文件。这一切都很好,因为我可以等一段固定的时间。但是,在某些情况下,我希望能够检查和更改excel宏检索到的数据。在这种情况下,我希望保持excel处于打开状态,直到使用的手动关闭excel。当我检测到excel不再打开时,我想邮寄文件 最后一个案子给我带来了一些麻烦。因为我使用excel interlop打开

我正在开发一个工具,它将为我自动执行一些操作。其中一个操作是下载excel文件,在其上运行宏,然后邮寄该文件。在某些情况下,我希望该工具只运行excel宏,然后在x秒后退出excel并发送文件。这一切都很好,因为我可以等一段固定的时间。但是,在某些情况下,我希望能够检查和更改excel宏检索到的数据。在这种情况下,我希望保持excel处于打开状态,直到使用的手动关闭excel。当我检测到excel不再打开时,我想邮寄文件

最后一个案子给我带来了一些麻烦。因为我使用excel interlop打开excel,所以我无法像在正常进程中一样使用WaitForExit()。当我手动关闭excel时,流程也会在process explorer中保持运行

我曾在互联网上寻找解决方案,但没有一个真正有效。我有没有办法用一种简单的方法来实现这一点

更新 非常感谢你的回复,它真的帮助了我。等待excel现在可以正常工作。我使用了以下代码:

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事件来完成此操作。基本上,您需要按照以下思路做一些事情:

  • 创建一个变量来跟踪状态,即Excel是否打开或关闭
  • 为WorkbookBeforeClose事件创建事件处理程序
  • 在处理程序中,检查工作簿是否已关闭,并相应地更新状态跟踪变量的值
  • 如果工作簿已关闭,请执行邮件发送操作
  • 代码可以是这样的:

    //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
    
  • Excel工作簿。关闭前先调用,然后调用
  • Excel应用程序。WorkbookDeactivateExcel完全关闭之前最后调用
  • 所以在ExcelApplication中,WorkbookDeactivate是我设置并使用进程等待它自动终止的地方
  • 额外:我使用反应式捕捉一次关闭事件
  • 重要提示:当用户关闭工作簿时,我将关闭Excel 因此,在OnWorkbookDeactivate中:

    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);
            }
        }
    }