C# Microsoft Excel无法访问Windows Server 2012上的文件
我正在运行一个SSIS包,其中包含一个C脚本,用于在Windows Server 2012 R2上格式化Excel文件 当我运行该软件包时,会出现以下错误Microsoft Office Excel无法访问文件“\\FolderPath\FilePath” 我已经看到这个问题,并检查了我的许可,他们是正确的 我还尝试在最终文件路径周围添加双引号,如C# Microsoft Excel无法访问Windows Server 2012上的文件,c#,ssis,sql-agent-job,C#,Ssis,Sql Agent Job,我正在运行一个SSIS包,其中包含一个C脚本,用于在Windows Server 2012 R2上格式化Excel文件 当我运行该软件包时,会出现以下错误Microsoft Office Excel无法访问文件“\\FolderPath\FilePath” 我已经看到这个问题,并检查了我的许可,他们是正确的 我还尝试在最终文件路径周围添加双引号,如sFile=“\”“+sFile+”\”但这会输出错误Microsoft Excel无法访问文件“'\FolderPath\FilePath”它正在删
sFile=“\”“+sFile+”\”代码>但这会输出错误Microsoft Excel无法访问文件“'\FolderPath\FilePath”它正在删除一个文件\n我真的不明白为什么
下面是原始代码
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();
}
}
这段代码让人觉得对互联网来说太过干净了,因为它似乎不适合你的文件工作
C#观察
转义斜杠是非常痛苦的,因为它还发出控制字符的信号。C#允许您指示字符串是a,然后您不必处理转义所有内容
在你的主要方面,你有
string strExcelDataOutPut = "\\\\FolderPath";
string sPath = "\\filePath";
对这些字符串求值时,您的值为\\FolderPath
和\filePath
您可以在方法调用中将它们组合为
sFile = strExcelDataOutPut + sPath;
它生成一个UNC路径,名为\\FolderPath\filePath
,这很好,但不是文件名。看起来您缺少了实际的文件名,比如
sFile = strExcelDataOutPut + sPath + @"\Something.xlsx";
我有一个技巧可以让你组合路径来创建一个有效的路径——有一个库和方法可以实现这一点。这是非常好的,因为您不必为那里的值做太多的转义
sFile = Path.Combine(strExcelDataOutPut, sPath, "Something.xlsx");
如果找到文件,检查文件是否存在将设置工作表名称,但如果找不到文件,则不执行任何操作。当您试图打开不存在的文件时,这不会导致问题吗?或者,如果Excel将创建该文件,那么当您尝试访问工作表集合中名为(空字符串)的工作表时,将失败
最后,注意在您的方法中使用
SSIS观测
您没有指定在何处运行此包并遇到问题,但我可以看到许多可能出现问题的地方
首先也是最重要的是许可。只要您、您的DBA和管理层了解此实施将要求您为SQL Server实例购买Microsoft Office许可证。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中的变量运行脚本。您可以通过配置或参数化(取决于部署模型)对这些变量进行更改,然后在不更改代码的情况下更改包行为。您正在更新某个存储库中的外部值,而不是代码本身。在我工作的环境中,与代码更改相比,实现这种更改的风险通常要低得多(即使您所做的只是更改变量的值)
除非您已经构建了一个用于使用自定义日志的流程,否则请停止并使用。发出信息、警告或错误消息。否则,您将需要确保SSI可以写入该位置(稍后将详细介绍)
现在,当包运行时,该信息将转储到错误处理程序。如果您使用的是项目部署模型,则该信息将自动记录到SSISDB.catalog.operation_messages表中,并显示在友好的报告中。否则,go和SSIS将把这些事件写入表、平面文件、事件查看器、探查器和/或XML文件。重要的是,除非你有很好的理由,否则不要重新发明轮子
运行此SSIS包时,需要确保使用的dtexec版本与32位或64位版本的Office相对应。这会从背后咬很多人。Office通常默认为32位安装,这是一个遗憾
当此程序包可操作时,即它在SQL Server上运行时,可能作为SQL Agent作业的一部分,运行SQL Agent的帐户可能需要通常授予该帐户的更高级别的权限。它需要网络访问该文件共享到的任何位置。它需要能够实例化一个Excel实例,然后执行必要的操作。SQL代理作业步骤将需要确保已正确标记要运行的SSIS包,而不是64(默认)。如果您没有实现日志记录,并且没有使用项目部署模型,那么包将生成一个错误,错误消息将在SQL代理作业历史记录中捕获。这在某种程度上是有用的。所以我遇到了这个微软。虽然这是非常奇怪的,为什么你需要创建桌面文件夹,但它的工作。如果链接被删除,请参见下面的答案
决议
************·
在C:\Windows\SysWOW64\config\位置的“systemprofile”文件夹中,似乎需要一个“Desktop”文件夹来打开Excel文件
在位置C:\Windows\SysWOW64\config\s下为Windows 2008 Server(x64)创建“桌面”文件夹
Dts.Events.FireError(0, "Excel Writer", "Error Occurred...Please see the error Message :" + ex.Message, String.Empty, 0);