背景信息:我们运行了一些(目前是 9 个)核心 SSRS 报告,这些报告是大量参数化的,但重要的是 StartDate、EndDate 和 Department。这些将在每日、每周、每月、每季度、每年和临时(交互式)的基础上运行。自动报告将保存到 Sharepoint 中的特定文件夹。
到目前为止我所做的:将所有报告放入这样的表格中,它们不会“等待”参数,而是生成仅包含相同三个参数的报告。因此,可以仅使用它们的 URL 调用它们:
http://server/ReportServer?/Folder/Report1&Department=DEPT1&ContactFromDate=01/01/2012&ContactToDate=31/01/2012+23:59:59&rs:Command=Render&rs:Format=PDF
http://server/ReportServer?/Folder/Report5&Department=DEPT8&ContactFromDate=01/04/2012&ContactToDate=06/01/2012+23:59:59&rs:Command=Render&rs:Format=PDF
..等等。
大约有 20 个部门,需要 5 种报告类型中的每一种,因此设置订阅并不是一个真正的选择,而这正是 SSIS 的用武之地。
我创建了一个包,它基本上从 SQL 表中读取报告标题和部门,为每个部门/报告填充 ADO.Net 枚举器,然后运行嵌套的 For..Each 循环并尝试触发 WebRequest 并将生成的 PDF 保存到一个共享点文件夹。这在我的开发人员 PC 上运行良好,但在 SQL Server 上作为作业运行时(通过 SQL Server 中设置的代理)失败并出现“找不到网络名称”错误。
这是我的 Visual Basic 代码:
//Microsoft SQL Server Integration Services Script Task
//Write scripts using Microsoft Visual Basic
//The ScriptMain class is the entry point of the Script Task.
Imports System
Imports System.Data
Imports System.Math
Imports Microsoft.SqlServer.Dts.Runtime
Imports System.ComponentModel
Imports System.Diagnostics
<System.AddIn.AddIn("ScriptMain", Version:="1.0", Publisher:="", Description:="")> _
<System.CLSCompliantAttribute(False)> Partial Public Class ScriptMain
Inherits Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTARTScriptObjectModelBase
Enum ScriptResults
Success = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success
Failure = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Failure
End Enum
Protected Sub SaveFile(ByVal url As String, ByVal localpath As String)
Dim loRequest As System.Net.HttpWebRequest
Dim loResponse As System.Net.HttpWebResponse
Dim loResponseStream As System.IO.Stream
Dim loFileStream As New System.IO.FileStream(localpath, System.IO.FileMode.Create, System.IO.FileAccess.Write)
Dim laBytes(256) As Byte
Dim liCount As Integer = 1
Try
loRequest = CType(System.Net.WebRequest.Create(url), System.Net.HttpWebRequest)
loRequest.Credentials = System.Net.CredentialCache.DefaultCredentials
loRequest.ImpersonationLevel = Security.Principal.TokenImpersonationLevel.Impersonation
loRequest.Timeout = 600000
loRequest.Method = "GET"
loResponse = CType(loRequest.GetResponse, System.Net.HttpWebResponse)
loResponseStream = loResponse.GetResponseStream
Do While liCount > 0
liCount = loResponseStream.Read(laBytes, 0, 256)
loFileStream.Write(laBytes, 0, liCount)
Loop
loFileStream.Flush()
loFileStream.Close()
Catch ex As Exception
End Try
System.Threading.Thread.Sleep(2000)
End Sub
Public Sub Main()
Dim strUrl, strUrlSP, strDestination As String
--New destination for monthly
strDestination = Dts.Variables("varDestinationPathSP").Value.ToString + "\" + Dts.Variables("varDepartmentName").Value.ToString + "\Monthly\" + Dts.Variables("varCrmReportTitles").Value.ToString + " " + Format(Now, "yyyyMM") + ".pdf"
--New Url for Monthly reports.
strUrl = "http://server/ReportServer?/Scheduled+Reporting/" + Dts.Variables("varCrmReportTitles").Value.ToString + "&Department=" + Dts.Variables("varDepartmentCode").Value.ToString + "&ContactFromDate=" + Format(Dts.Variables("varDatPreviousMonthStart").Value, "dd/MMM/yyyy").ToString + "&ContactToDate=" + Format(Dts.Variables("varDatPreviousMonthEnd").Value, "dd/MMM/yyyy").ToString + "+23:59:59&rs:Command=Render&rs:Format=PDF"
strUrlSP = "http://intranet/ProjectBusinessSystems/ContactManagement/DocumentLibrary/Forms/AllItems.aspx?RootFolder=/ProjectBusinessSystems/ContactManagement/DocumentLibrary/Scheduled+Reports/" + Dts.Variables("varDepartmentName").Value.ToString + "/Monthly"
strUrl = fnPadSpaces(strUrl)
strUrlSP = fnPadSpaces(strUrlSP)
--Set up the file path so the next step can copy to local drive (Testing purposes only)
Dts.Variables("varFullReportPathToCopy").Value = strDestination
Dts.Variables("varDestinationURL").Value = strUrlSP
SaveFile(strUrl, strDestination)
Dts.TaskResult = ScriptResults.Success
End Sub
Public Function fnPadSpaces(ByVal StringToEncode As String, Optional ByVal UsePlusRatherThanHexForSpace As Boolean = True) As String
Dim TempAns As String
Dim CurChr As Integer
CurChr = 1
TempAns = ""
Do Until CurChr - 1 = Len(StringToEncode)
Select Case Asc(Mid(StringToEncode, CurChr, 1))
Case 32 -- Replace Spaces
If UsePlusRatherThanHexForSpace = True Then
TempAns = TempAns & "+"
Else
TempAns = TempAns & "%" & Hex(32)
End If
Case Else -- Otherwise pass it through
TempAns = TempAns & Mid(StringToEncode, CurChr, 1)
End Select
CurChr = CurChr + 1
Loop
fnPadSpaces = TempAns
End Function
End Class
当它生成 PDF 但未能将其写入共享点文件夹时,它在 SaveFile(strUrl, strDestination) 行上失败。基础设施人员向我保证,权限已设置为允许运行 SSIS 作业的帐户写入文件夹,并且当我在开发盒上的 Vis Studio 中运行该作业时,它一直有效。
varDestinationPath 就像:
\\sharepoint\ProjectBusinessSystems\ContactManagement\DocumentLibrary\Some Reports
其中 sharepoint 是服务器名称,而不是别名。
来自日志文件查看器的实际(非常详细的)错误消息如下所示:
Date 06/06/2012 13:52:30
Log Job History (Scheduled Reports MONTHLY)
Step ID 1
Server DevServer
Job Name Scheduled Reports MONTHLY
Step Name Run Package
Duration 00:00:04
Sql Severity 0
Sql Message ID 0
Operator Emailed
Operator Net sent
Operator Paged
Retries Attempted 0
Message
Executed as user: WinFarm\crmreporter. Microsoft (R) SQL Server Execute Package Utility Version 10.50.2500.0 for 64-bit Copyright (C) Microsoft Corporation 2010. All rights reserved. Started: 13:52:31 Error: 2012-06-06 13:52:34.46 Code: 0x00000001 Source: Script Task - Render Report Description: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.IO.IOException: The network name cannot be found. at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath) at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy) at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options, String msgPath, Boolean bFromProxy) at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access) at ScriptTask_f689e2ad4d3f481a87e3678e2d746c39.vbproj.ScriptMain.SaveFile(String url, String localpath) at ScriptTask_f689e2ad4d3f481a87e3678e2d746c39.vbproj.ScriptMain.Main() --- End of inner exception stack trace --- at System.RuntimeMethodHandle._InvokeMethodFast(Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) at System.RuntimeType.InvokeMember(String name, BindingFlags bindingFlags, Binder binder, Object target, Object[] providedArgs, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParams) at Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTATaskScriptingEngine.ExecuteScript() End Error DTExec: The package execution returned DTSER_FAILURE (1). Started: 13:52:31 Finished: 13:52:34 Elapsed: 3.183 seconds. The package execution failed. The step failed.
任何想法我做错了什么或我应该尝试什么?如果我需要提供更多信息,请询问,我会回复。我确信脚本 99% 已完成,但在我认为的服务器上的某些凭据/权限问题上失败了。:/
更新:我可以确认代码将写入本地区域 (C:\Temp),并且它还将写入网络共享上的文件夹(\someserver\some folder with space in\etc),因此问题在某种程度上转移到写入共享点文件夹。我们在本机模式下运行 SSRS,所以有没有人知道从通过代理运行的 SQL Server 代理作业写入共享点文件夹时可能导致“找不到网络路径”错误的原因?
还尝试通过文件系统任务移动文件,但即使这样也失败了。:( 任何想法可能是什么问题?
撞。可能在这里回答我自己的问题,但经过一些调查,我们发现查看 Sharepoint 的 Win2008 服务器没有运行 WebClient 服务。这意味着未安装 WebDAV,因此它无法将共享点库“视为”网络路径(或将驱动器映射到它).. 将安装这些组件并报告回来。但是,如果有人对此有更多信息,将不胜感激!分分钟有点像迷宫里的盲人。:)