Приложение.Запуск (макрос) успешно выполняется при отладке, но завершается сбоем при запуске exe-файла из другой папки пути [Приложение WPF]

#c# #excel #wpf #com

#c# #excel #wpf #com

Вопрос:

Я столкнулся со своеобразной проблемой, о которой я вообще не думал, что это трудноразрешимая ошибка.

Я создал кнопку Excel для приложения WPF, и при нажатии на кнопку выполняется следующее:

Способ 1

 //using the OfficeOpenXmland EPPlus packages
public void CreateCopyReportServerNameDB(string sourceFile)
{
    ExcelPackage.LicenseContext = OfficeOpenXml.LicenseContext.NonCommercial;

    FileInfo existingFile = new FileInfo(sourceFile);
    using (ExcelPackage package = new ExcelPackage(existingFile))
    {
        ExcelWorksheet worksheet = package.Workbook.Worksheets["Cover"];
        worksheet.Cells[7, 4].Value = ConnectionDetailsList[0].ToString();
        worksheet.Cells[8, 4].Value = ConnectionDetailsList[1].ToString();

        package.SaveAs(new FileInfo($@"{path}{"file_Report.xlsm"}"));
        package.Dispose();
    }
}
  

Способ 2: выполнить макрос

 public int ExecuteExcelMacro(string sourceFile) //string sourceFile //String.Format("{0}DQTool_Report.xlsm", path)
{
    var destinationFile = @"file_Report";
    Excel.Application ExcelApp = new Excel.Application
    {
        DisplayAlerts = false,
        Visible = false
    };

    Excel.Workbook ExcelWorkBook;

    ExcelWorkBook = ExcelApp.Workbooks.Open(sourceFile);

    string macro = "ThisWorkbook.Run_Code";

    try
    {
        ExcelApp.Run(macro);
        Debug.WriteLine("Macro: "   macro   " executed successfully");

        ExcelApp.DisplayAlerts = false;
        ExcelApp.Visible = false;

        ExcelWorkBook.SaveAs($@"{path}{destinationFile}", Excel.XlFileFormat.xlOpenXMLWorkbook, Type.Missing);

        GC.Collect();
        GC.WaitForPendingFinalizers();

        ExcelWorkBook.Close(0);
        if (ExcelWorkBook != null) { Marshal.ReleaseComObject(ExcelWorkBook); }

        ExcelApp.Quit();
        if (ExcelApp != null) { Marshal.ReleaseComObject(ExcelApp); }

        return 1;
    }
    catch (Exception ex)
    {
        Debug.WriteLine("Macro not run");
        
        //I repeat the Garbage Collector because if the macro fails to execute the excel workbooks remains open.
        GC.Collect();
        GC.WaitForPendingFinalizers();

        ExcelWorkBook.Close(0);
        if (ExcelWorkBook != null) { Marshal.ReleaseComObject(ExcelWorkBook); }

        ExcelApp.Quit();
        if (ExcelApp != null) { Marshal.ReleaseComObject(ExcelApp); }

        MessageBox.Show(ex.ToString());
        return 0;
    }
}
  

Затем я комбинирую методы 1 и 2 одним нажатием кнопки следующим образом:

 
public string path = AppDomain.CurrentDomain.BaseDirectory; //The folder where the .exe file is executed.

private void PreviewExcelReportButton_Click(object sender, RoutedEventArgs e)
{
    try
    {
        Mouse.OverrideCursor = Cursors.Wait;
        
        //Method 1: Create copy of standard report file
        CreateCopyReportServerNameDB($@"{path}file.xlsm");

        //Method 2: Run macro
        if (ExecuteExcelMacro($@"{path}file_Report.xlsm") == 0)
            return;

        Debug.WriteLine("End");
    }
    catch (Exception)
    {
        MessageBox.Show(ex.ToString(), "Error", MessageBoxButton.OK, MessageBoxImage.Error);
        return;
    }
    finally
    {
        Mouse.OverrideCursor = null;
    }
}
  

Несмотря на то, что кнопка запускается полностью успешно при отладке приложения [отладчик запускается в папке рабочего стола (показано также на рисунке ниже)], он скорее завершается с ошибкой, когда я перемещаю папку приложения со всеми DLL-файлами и EXE-файлом в папку, расположенную в C: . Когда конкретная кнопка не выполняет макрос файла Excel, генерируется следующая ошибка:

введите описание изображения здесь

Заранее благодарю вас за любые комментарии или мысли по этому поводу, и я рад поделиться с вами любой дополнительной информацией.

С уважением.

Ответ №1:

Я нашел ответ на свой вопрос.

Excel автоматически отключал все макросы, когда файл Excel был программно открыт из EXE-приложения. Поэтому, чтобы преодолеть это, я использовал следующую команду:

 Excel.Application ExcelApp = new Excel.Application
{
    DisplayAlerts = false,
    Visible = false,
    AutomationSecurity = Microsoft.Office.Core.MsoAutomationSecurity.msoAutomationSecurityLow
};
  

Подробнее о MsoAutomationSecurity здесь