C # HRESULT 0x800AC472 при создании новых книг с Excel Interop - PullRequest
0 голосов
/ 28 января 2019

До недавнего времени это запланированное консольное приложение C # работало довольно хорошо, но примерно через 2 недели оно зависало в начале кода, когда я начинаю использовать Excel Interop.

При запуске самостоятельно оно работает хорошо,но когда я пытаюсь выполнить его с помощью диспетчера запланированных задач (одна и та же проблема как на Windows Server 2008 r2 , так и на Windows Server 2016 , у обоих правильно установлен Excel и действующий лицензионный ключ)сбой сразу после того, как я попытался его запустить.

(Извините, если есть ошибки или нет, я не очень-то привык писать «настоящий» английский, если что-то не понятно, не бойтесь проситьобъяснение).

Диспетчер запланированных задач указывает, что программа возвращает ошибку 0xE0434352.Я уже немного искал это и обнаружил, что на самом деле это общий номер ошибки.Поэтому я добавил ловушку AppDomain, чтобы получить правильный номер ошибки в файле журнала.Теперь я знаю, что истинной ошибкой является «HRESULT: 0x800AC472» и выбрасываю в:

wb = xlApp.Workbooks.Add (XlWBATemplate.xlWBATWorksheet);

Iуже протестировано для объявления пустой книги, затем добавьте в нее лист или используйте «XlSheetType.xlWorksheet» вместо «XlWBATemplate.xlWBATWorksheet», но все равно.Только один раз он прошел, но получил ту же ошибку:

ws.Name = "Name";

Я также читал об ошибке stackoverflow, но есть только один процесс Excelсоздал, и я попытался добавить Thread.Sleep (50 // 500 // 5000), но это ничего не изменило.Вот часть кода, где происходит сбой, я не думаю, что нужна какая-то другая часть кода:

        object misValue = System.Reflection.Missing.Value;
        String part = "";
        String pathD = "";
        List<Part> partList = new List<Part>();
        int ligne = 1;
        Workbook wb = null;
        Worksheet ws = null;

        Microsoft.Office.Interop.Excel.Application xlApp = new Microsoft.Office.Interop.Excel.Application();
        if (xlApp == null)
        {
            Console.WriteLine("EXCEL could not be started. Check that your office installation and project references are correct.");
            return;
        }
        xlApp.Visible = false;
        xlApp.DisplayAlerts = false;

        foreach (StockRow stockRow in Requete.getStockRows())
        {
            if (stockRow.Part != part)
            {
                partList.Add(new Part(stockRow.PartCode, stockRow.Part));
                if (wb != null)
                {
                    ws.Range[ws.Cells[1, 1], ws.Cells[ligne, 9]].entirecolumn.autofit();
                    ws.Range[ws.Cells[1, 1], ws.Cells[ligne, 9]].entirerow.autofit();
                    ws.Range[ws.Cells[1, 1], ws.Cells[ligne, 9]].verticalalignment = XlVAlign.xlVAlignCenter;
                    if (!Directory.Exists(pathD))
                    {
                        Directory.CreateDirectory(pathD);
                    }
                    wb.SaveAs(pathD + "\\Stock_" + DateTime.Now.ToString("dd-MM-yyyy_HH") + "h.xlsx", XlFileFormat.xlOpenXMLWorkbook, misValue, misValue, false, false,
                        XlSaveAsAccessMode.xlNoChange, XlSaveConflictResolution.xlUserResolution, true, misValue, misValue, misValue);
                    wb.Close();
                }

                pathD = path + stockRow.PartCode;
                wb = xlApp.Workbooks.Add(XlWBATemplate.xlWBATWorksheet);
                ws = (Worksheet)wb.ActiveSheet;
                ws.Name = "Name";
                ws.PageSetup.Zoom = false;
                ligne = 1;
                ws.Cells[ligne, 1] = "Column Name";
                ws.Cells[ligne, 2] = "Column Name";
                ws.Cells[ligne, 3] = "Column Name";
                ws.Cells[ligne, 4] = "Column Name";
                ws.Cells[ligne, 5] = "Column Name";
                ws.Cells[ligne, 6] = "Column Name";
                ws.Cells[ligne, 7] = "Column Name";
                ws.Cells[ligne, 8] = "Column Name";
                ws.Cells[ligne, 9] = "Column Name";

                //codes continue ...
            }
            // codes continue ...
        }
        // codes continue ...

Я бы, конечно, хотел бы выяснить, почему это больше не работает, и даже если вы неУ меня нет идеального ответа, даже намек будет очень полезен.

Большое спасибо за чтение до здесь.

Ответы [ 2 ]

0 голосов
/ 28 января 2019

Вы ДОЛЖНЫ освободить COM-объекты после окончания их использования, иначе это может привести к тому, что процесс останется в живых даже после того, как вы вызвали close.

Если вы приобрели слишком много COM-объектов без освобождения, Excel полностью взорвется (повреждение кучи, нарушение доступа, повреждение памяти и т. Д.).

например

xlApp.Workbooks.Add

приведет к гарантированной утечке COM.xlApp.Workbooks получит Workbooks COM-объект, но вы не сохраните ссылку на него.

вы хотели бы сделать

var workbooks = xlApp.Workbooks;
wb = workbooks.Add(...);

, а затем, когда вы закончите, используя рабочие книги

Marshal.ReleaseComObject(workbooks);
Marshal.ReleaseComObject(wb);

Сделайте это на каждом полученном вами COM-объекте.То есть все, что принадлежит пространству имен Interop.Excel

Самый простой способ выяснить, есть ли у вас утечка COM, - это проверить диспетчер задач, чтобы убедиться, что процесс вашего приложения остается активным после выхода.(при условии, что вы не совершаете силовое убийство, например Environment.Exit или Process.Kill)

0 голосов
/ 28 января 2019

Запустите Excel вручную на сервере и выполните шаги, которые ваше приложение выполняет вручную.Обязательно используйте ту же учетную запись, которую использует планировщик задач для запуска вашей программы.Настоятельно рекомендуется использовать реальную учетную запись пользователя вместо какой-либо встроенной служебной учетной записи.

Если вам действительно нужно использовать встроенную учетную запись, например "SYSTEM", вам необходимо убедиться, что в этом нет ничего плохогоC: \ Windows \ System32 \ config \ systemprofile, как отсутствующая папка рабочего стола.

Возможно, Excel вылетел и попытался попросить вас восстановить последний документ, тем самым заблокировав любой прогресс.Иногда происходят странные вещи, когда вы используете автоматизацию без пользовательского интерфейса.Комментарии о том, что следует избегать автоматической автоматизации, особенно на серверах, являются правильными.Более стабильный способ - использовать библиотеку, которая может получать доступ к документам XLSX и вносить в нее изменения.Мы используем серверную автоматизацию офиса для публикации Word и PowerPoint в файлах PDF и XPS, и это уже случайно происходит сбой всякий раз, когда Office чувствует себя так.

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

Если вы не можете получить доступ к серверу, на котором работает Excel,у вас нет возможности воспроизвести поведение, и вам не повезло.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...