背景信息:我们运行了一些(当前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到sharepoint文件夹。这在我的开发人员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
它在SaveFile(strUrl,strDestination)行上失败,当它生成PDF但无法将其写入sharepoint文件夹时。基础设施人员向我保证,权限设置为允许运行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 \某个文件夹,\ etc中有空格)所以问题是转移到写一个sharepoint文件夹。我们以纯模式运行SSRS,所以有人在从通过代理运行的SQL Server代理作业写入sharepoint文件夹时,有什么想法可能导致“找不到网络路径”错误吗?
还尝试通过文件系统任务移动文件,但即使这样也失败了。 :(任何想法可能是什么问题?
凹凸。可能会在这里回答我自己的问题,但经过一些调查后,我们发现看着Sharepoint的Win2008服务器没有运行WebClient服务。这意味着没有安装WebDAV,因此它无法将sharepoint库“看到”为网络路径(或将驱动器映射到它)。要安装这些组件并报告回来。但如果有人有进一步的信息,将不胜感激!有点像夜晚迷宫中的盲人。 :)
答案 0 :(得分:1)
您知道也要向SharePoint提供,必须为SharePoint集成模式配置SSRS。这与“标准”配置完全相反。
但这甚至不是主要观点。当我阅读你的场景时,我想到了订阅,然后你说他们不是一个选择。为什么?但最糟糕的是,你基本上想出了一个实现订阅功能的实现。您可以及时运行报告并将其保存到文件夹中。我一直这样做,订阅。
好的,我真的不知道你的完整场景,但有两点非常重要:
1 - 用户可以处理非实时数据多长时间?我的意思是,你不要指望这么大的报道(至少你让它们在你的描述中听起来非常重要)是“活的”。我很确定你可以将它们缓存几个小时。您的第一个用户将遇到延迟,但下一个用户将从之前的执行中受益(只要他们具有相同的参数)
2 - 您可以创建预订以预加载缓存。我建议您阅读here中的Preloading the Cache
段落
如果要缓存参数化报表的多个实例(其中使用不同的参数值来生成不同的报表实例),则此功能特别有用。 (看起来像你的情况)