2

背景信息:我们运行了一些(目前是 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,因此它无法将共享点库“视为”网络路径(或将驱动器映射到它).. 将安装这些组件并报告回来。但是,如果有人对此有更多信息,将不胜感激!分分钟有点像迷宫里的盲人。:)

4

1 回答 1

1

您知道,同样交付到 SharePoint,SSRS 必须配置为 SharePoint 集成模式。这与“标准”配置完全相反。

但这甚至不是重点。当我阅读您的方案时,我想到了订阅,然后您说它们不是一种选择。为什么?但更糟糕的是,您基本上想出了一个实现订阅功能的实现。您及时运行报告并将其保存到文件夹中。我一直这样做,订阅。

好的,我真的不知道你的全部情况,但这里有两件事非常重要:

1 - 用户可以处理非实时数据多长时间?我的意思是,你不期望这么大的报道(至少你让它们在你的描述中听起来真的很大)是“活的”。我很确定您可以将它们缓存几个小时。您的第一个用户会遇到延迟,但下一个用户将受益于之前的执行(只要他们具有相同的参数)

2 - 您可以创建订阅以预加载缓存。我建议您从此处阅读该Preloading the Cache段落 如果您要缓存参数化报表的多个实例,其中不同的参数值用于生成不同的报表实例,此功能特别有用。(好像你的情况)

于 2012-06-06T15:03:48.613 回答