Microsoft Excel не может получить доступ к файлу в Windows Server 2012

Я использую пакет служб SSIS, содержащий скрипт C#, который форматирует файл Excel в Windows Server 2012 R2.

Когда я запускаю пакет, он дает мне эту ошибку Microsoft Office Excel не может получить доступ к файлу '\\FolderPath\FilePath'

Я видел этот вопрос. Microsoft Office Excel не может получить доступ к файлу 'c:\inetpub\wwwroot\Timesheet\App_Data\Template.xlsx' и проверил мои разрешения, и они верны.

Я также попытался добавить двойные кавычки вокруг конечного FilePath, как это sFile = "\"" + sFile + "\""; но это выдает ошибку Microsoft Excel не может получить доступ к файлу "\FolderPath\FilePath", который он удаляет \ я действительно не понимаю, почему.

Ниже приведен оригинальный код

using System;
using System.Data;
using Microsoft.SqlServer.Dts.Runtime;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Data.SqlClient;
using Excel = Microsoft.Office.Interop.Excel;
using System.IO;
using System.Text;
using System.Diagnostics;
using System.Reflection;

public int Main()
    {

     StringBuilder sb = new StringBuilder();
     string LogFilePath = "\\\\LogFilePath";
     string  strExcelDataOutPut = "\\\\FolderPath"; 
     string sPath = "\\filePath";

    try {
        FormatFile(strExcelDataOutPut,sPath);

    } catch (Exception ex) {

using (System.IO.StreamWriter outfile = new System.IO.StreamWriter(LogFilePath))
       {
   sb.AppendLine("Error Occured ..Please see the error Message :" + ex.Message);
   outfile.Write(sb.ToString());

       }
   }

    }
 public void FormatFile(string strExcelDataOutPut, string sPath)
                {
                    Microsoft.Office.Interop.Excel.Application objExcelApp = new Excel.Application();
                    Microsoft.Office.Interop.Excel.Workbook objExcelWbk = default(Excel.Workbook);
                    Microsoft.Office.Interop.Excel.Worksheet objWrksheet = default(Excel.Worksheet);

                    object missing = Missing.Value;
                    Excel.Range crange1;

                    string sFile = string.Empty;
                    string sWorkSheet = string.Empty;

                    //--Month in English/French
                    string sMonthYear = string.Empty;

                    try
                    {
                        objExcelApp.DisplayAlerts = false;
                        objExcelApp.Visible = false;

                        sFile = strExcelDataOutPut + sPath;

                        //--Check if the file exists ---------------------------------------------------------
                        if (System.IO.File.Exists(sFile))
                        {
                            sWorkSheet = "Sheet1";
                        }

                        objExcelWbk = objExcelApp.Workbooks.Open(sFile.Trim(), missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, true);
                        objWrksheet = (Excel.Worksheet)objExcelWbk.Worksheets[sWorkSheet];
                        ((Microsoft.Office.Interop.Excel._Worksheet)objWrksheet).Activate();

                        //--Format
                        sMonthYear = "Report as at: " + DateTime.Today.ToString("MMMM") + " " + DateTime.Today.Day.ToString() + ", " + DateTime.Today.Year.ToString();
                        objWrksheet.PageSetup.LeftHeader = "&8&F";
                        //objWrksheet.PageSetup.CenterFooter = @"&12&""Arial,Bold" + sMonthYear;
                        objWrksheet.PageSetup.CenterFooter = " " + sMonthYear;

                        crange1 = (Excel.Range)objWrksheet.Cells[1, 1];
                        crange1.Select();

                        //objExcelWbk.SaveAs(sFile, missing, missing, missing, missing, missing, Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlExclusive, missing, missing, missing, missing, missing);
                        //objExcelWbk.Close(true, missing, missing);
                        objExcelWbk.Save();
                        objExcelWbk.Close(true, sFile, missing);                
                        objExcelApp.Quit();
                    }
                    catch
                    {
                        throw;
                    }
                    finally
                    {
                        objWrksheet = null;
                        objExcelWbk = null;
                        objExcelApp = null;
                        System.GC.Collect();
                    }
                }

2 ответа

Решение

Итак, я наткнулся на этот блог Microsoft. Хотя это очень странно, поэтому вам нужно создавать папки рабочего стола, но это работает. Если ссылка удалена, смотрите ответ ниже.

Разрешение ************ ·

Папка "Рабочий стол", по-видимому, необходима в папке "systemprofile" в папке C:\Windows\SysWOW64\config\, чтобы открыть файл Excel.

Создайте папку "Рабочий стол" для Windows 2008 Server (x64) в папке C:\Windows\SysWOW64\config\systemprofile ·

А для 32-битного Windows 2008 Server создайте папку "Рабочий стол" в папке C:\Windows\System32\config\systemprofile ·

После создания папки задания SQL Server должны успешно выполняться

Код кажется, что он слишком очищен для интернета, так как он не совсем подходит для вашей работы с файлами.

C# наблюдения

Избежать косой черты совершенно больно, потому что это также сигнализирует о контрольном персонаже. C# позволяет вам указать, что строка является дословной строкой, и тогда вам не нужно иметь дело с экранированием всего.

В вашем главном у вас есть

string strExcelDataOutPut = "\\\\FolderPath"; 
string sPath = "\\filePath";

Когда эти строки будут оценены, вы получите значения \\FolderPath а также \filePath

Вы объединяете их в вызове метода как

sFile = strExcelDataOutPut + sPath;

который генерирует путь UNC как \\FolderPath\filePath это нормально, но это не имя файла. Кажется, что вы пропустили фактическое имя файла, как

sFile = strExcelDataOutPut + sPath + @"\Something.xlsx";

У меня есть хитрость для вас, чтобы объединить пути для создания правильного пути - для этого есть библиотека и метод. System.IO.Path.Combine Это вдвойне приятно, так как вам не нужно делать столько экранирования для значений там.

sFile = Path.Combine(strExcelDataOutPut, sPath, "Something.xlsx");

Ваша проверка существования файла устанавливает имя листа, если файл найден, но ничего не делает, если файл не найден. Разве это не вызовет проблем при попытке открыть несуществующий файл? Или, если Excel создаст файл, то при попытке доступа к рабочему листу с именем (пустая строка) в коллекции рабочих таблиц произойдет сбой.

Наконец, остерегайтесь использования двойных точек в вашем методе.

Наблюдения SSIS

Вы не указываете, где вы запускаете этот пакет и сталкиваетесь с проблемами, но я вижу ряд вещей, которые могут пойти не так.

В первую очередь это лицензирование. Пока вы, ваши администраторы баз данных и руководство понимаете, что для этой реализации потребуется приобрести лицензию Microsoft Office для ваших экземпляров SQL Server. Office требует более частых исправлений с потенциальными перезагрузками, чем ваши обычные продукты уровня сервера. Это означает, что если в ваших установках SQL Server установлен жесткий SLA, эта реализация может нарушить это окно.

215 долларов за дверь (по данным CDW для домашней и деловой лицензии), и наши серверы теперь исправляются чаще. Круто, теперь сервер FolderPath умирает, или общий ресурс изменяется, или что-то происходит, и теперь вам нужно изменить этот путь - вы смотрите, как открыть пакет, отредактировать значение скрипта, сохранить его, проверить его в системе управления версиями (вы используйте контроль версий, верно?), а затем отправьте его в любой процесс контроля изменений, который есть у вашего работодателя. Это много потерянного времени в моем мире.

Вместо этого вы можете сделать

 string LogFilePath = "\\\\LogFilePath";
 string  strExcelDataOutPut = "\\\\FolderPath"; 
 string sPath = "\\filePath";

в нечто вроде

 string LogFilePath = Dts.Variables["LogPath"].Value.ToString();
 string strExcelDataOutPut = Dts.Variables["ExcelPath"].Value.ToString();
 string sPath = Dts.Variables["FilePath"].Value.ToString();

Что это тебе? Теперь вы запускаете свой скрипт на основе переменных в SSIS. Вы можете внести изменения в эти переменные либо через Configuration, либо через Parameterization (в зависимости от модели развертывания), а затем поведение вашего пакета изменится без изменений кода. Вы обновляете внешнее значение в каком-то хранилище вместо самого кода. В средах, в которых я работаю, это, как правило, намного менее рискованное изменение для реализации по сравнению с изменением кода (даже если все, что вы сделали, это изменили значение переменной).

Если у вас уже не создан процесс для использования вашей пользовательской регистрации, остановите и используйте собственный инструментарий. Поднимите Информацию, Предупреждение или Сообщение об ошибке. В противном случае вам необходимо убедиться, что SSIS может выполнять запись в это место (подробнее об этом позже).

Dts.Events.FireError(0, "Excel Writer", "Error Occurred...Please see the error Message :" + ex.Message, String.Empty, 0); 

Теперь, когда ваш пакет работает, эта информация будет сброшена в обработчик ошибок. Если вы используете модель развертывания проекта, эта информация будет автоматически занесена в таблицу SSISDB.catalog.operation_messages и отображена в ваших дружественных отчетах. В противном случае перейдите к настройке ведения журнала, и SSIS запишет эти события в таблицу, плоский файл, средство просмотра событий, профилировщик и / или файл XML. Важно то, что вы не изобретаете велосипед, если у вас нет веских причин.

Когда вы запускаете этот пакет служб SSIS, вам необходимо убедиться, что вы используете правильную версию dtexec относительно вашей 32- или 64-разрядной версии Office. Это кусает многих людей в задней части. Office обычно по умолчанию использует 32-битную установку, что очень жаль.

Когда этот пакет введен в эксплуатацию, т. Е. Работает на SQL Server, вероятно, как часть задания агента SQL, учетной записи, на которой запущен агент SQL, вероятно, потребуется более высокий уровень разрешений, который обычно предоставляется учетной записи. Ему понадобится доступ к сети, где бы этот файл не использовался. Потребуется InteractWithDesktop, чтобы иметь возможность создавать экземпляр экземпляра Excel, а затем выполнять необходимые действия. На шаге задания агента SQL необходимо убедиться, что он правильно пометил пакет служб SSIS как 32-разрядный вместо 64 (по умолчанию). Если вы не внедрили ведение журнала и не используете модель развертывания проекта, тогда пакет сгенерирует ошибку, сообщение об ошибке будет записано в истории заданий агента SQL. Это будет полезно в какой-то момент.

Другие вопросы по тегам