返回包含数据源名称和ConnectString的文件夹中的所有SSRS报告

时间:2018-01-29 19:41:19

标签: powershell reporting-services

这是我到目前为止所做的。但是,我想列出每个报告的连接字符串。我没有在GetDataSourceContents()方法中看到加入报告和数据源列表的唯一标识符。

$ReportServerUri = "YOUR_SERVER";
$rs = New-WebServiceProxy -Uri $ReportServerUri -UseDefaultCredential -Namespace "SSRS" 
$rs.Url = "YOUR_SERVER"
$rs.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials; 

$BICItems = $rs.ListChildren("/", $true);
$BICFolders = $BICItems | Where { $_.TypeName -eq "Folder"}
$BICDataSources = $BICItems | Where {$_.typename -eq "DataSource"}
$BICDataSourceFolders = $BICFolders | Where {$_.path -like "*Data Source*"}
$BICReports = $BICItems | Where {$_.typename -eq "Report"}

foreach ($DataSource in $BICDataSources)
{
   $BICDataSourceContents = $rs.GetDataSourceContents($DataSource.Path)

   $MyConnectStrings = $BICDataSourceContents | Where {$_.ConnectString -like "*MY_CONNECT_STRING*"} 

   $MyConnectStrings
}

2 个答案:

答案 0 :(得分:2)

  

我没有在GetDataSourceContents方法中看到唯一标识符来加入报表和数据源列表。

不。我也没有。但是当我们查询这些细节时,我们已经知道了一些足够独特的东西。数据源本身的路径。这也是报告将使用的内容,因此应该是一个好的连接器。

我为此目的而做了一系列功能。 Find-SSRSEntitiesGet-SSRSReportDataSourcesGet-SSRSDatasourceDetails是我将在此处尝试和展示的内容。我刚才做的最后一个,因为我没有理由这些细节,但很容易融入我的模块。

查找-SSRSEntities

从SSRS连接返回项目。支持大量过滤选项。

function Find-SSRSEntities{
    [CmdletBinding()] 
    param(
        [Parameter(Position=0,Mandatory=$true)]
        [Alias("Proxy")]
        [Web.Services.Protocols.SoapHttpClientProtocol]$ReportService,

        [Parameter(Position=1)]
        [Alias("Path")]
        [string]$SearchPath="/",

        [Parameter(Position=2)]
        [ValidateSet("All", "Folder", "Report", "Resource", "LinkedReport", "DataSource", "Model")]
        [Alias("Type")]
        [String]$EntityType = "All",

        [Parameter(Position=3)]
        [String]$Match,

        [Parameter(Position=4)]
        [Switch]$Partial=$false
    )
    # Get all of the catalog items that match the criteria passed
    # https://msdn.microsoft.com/en-us/library/reportservice2005.reportingservice2005.listchildren.aspx
    $recursive = $true
    $catalogItems = $ReportService.ListChildren($SearchPath,$recursive)
    Write-Verbose "$($catalogItems.Count) item(s) located in the root path $SearchPath"

    # Limit the results to the catalog types requested
    if($EntityType -ne "All"){$catalogItems = $catalogItems | Where-Object{$_.Type -eq $EntityType}}
    Write-Verbose "$($catalogItems.Count) item(s) found matching the type $EntityType"

    # Set the match string based on parameters
    if(-not $Partial.isPresent -and $Match){$Match = "^$Match$"}
    Write-Verbose "Returning all items matching: '$Match'"

    # If the regex is an empty string all object will be returned.
    return $catalogItems | Where-Object{$_.Name -match $Match}
}

获取-SSRSReportDataSources

当给出有效的报告路径时,它将返回该报告的所有相关数据源。

function Get-SSRSReportDataSources{
    [CmdletBinding()] 
    param(
        [Parameter(Position=0,Mandatory=$true)]
        [Alias("Proxy","SSRSService")]
        [Web.Services.Protocols.SoapHttpClientProtocol]$ReportService,

        [Parameter(Position=1,Mandatory=$true)]
        [Alias("Path")]
        [string]$ReportPath
    )

    # Test the report path to be sure it is for a valid report
    if(Test-SSRSPath -ReportService $ReportService -EntityPath $ReportPath -EntityType Report){
        $ReportService.GetItemDataSources($reportPath) | ForEach-Object{
            [pscustomobject][ordered]@{
                ReportPath = $reportPath
                DataSourceName = $_.name
                Reference = $_.item.reference
            }
        }
    } else {
        Write-Error "$ReportPath is not a valid report path"
    }
}

GET-SSRSDatasourceDetails

当给定有效的数据源路径时,它将返回该数据源的所有细节。还附加一个额外的路径属性。

function Get-SSRSDatasourceDetails{
    [CmdletBinding()] 
    param(
        [Parameter(Position=0,Mandatory=$true)]
        [Alias("Proxy")]
        [Web.Services.Protocols.SoapHttpClientProtocol]$ReportService,

        [Parameter(Position=1,Mandatory=$true,ValueFromPipelineByPropertyName)]
        [Alias("Path")]
        [string]$EntityPath
    )

    process{
        # Split the path into its folder and entity parts
        $SearchPath = Split-SSRSPath $EntityPath -Parent
        $EntityName = Split-Path $EntityPath -Leaf

        # Verify the path provided is to a valid datasource
        if((Find-SSRSEntities -ReportService $ReportService -SearchPath $SearchPath -EntityType DataSource -Match $EntityName -Partial:$false) -as [boolean]){
            Add-Member -InputObject ($ReportService.GetDataSourceContents($EntityPath)) -MemberType NoteProperty -Name "Path" -Value $EntityPath -PassThru
        } else {
            Write-Warning "Could not find a datasource at path: $EntityPath"
        }
    }
} 

如此武装,让我们将文件夹中的所有报告与其数据源连接字符串相匹配。我会注意到所有这些功能都依赖于活动连接来工作。像这样的东西

$ssrsservice = Connect-SSRSService "http://ssrsreports/ReportServer/ReportService2005.asmx" -Credential $credentials
$PSDefaultParameterValues.Add("*SSRS*:ReportService",$ssrsservice)

这将自动将填充的-ReportService $ssrsservice应用于我在下面做的所有SSRS功能。

否则,您可以在下面的代码中添加Find-SSRSEntities -ReportService $rs之类的内容,这样就可以了。

# Lets get all of the Marketing Datasources
$datasources = Find-SSRSEntities -SearchPath "/data sources/marketing" -EntityType DataSource | Get-SSRSDatasourceDetails

# Now gather all of their reports
Find-SSRSEntities -SearchPath "/Marketing" -EntityType Report | 
    # Get the report datasources
    Get-SSRSReportDataSources | ForEach-Object{
        # Attach the connection strings to each object 
        $reportDataSourceDetail = $_
        # Filter the datasource for the individual datasource mapping of this report
        $matchingDatasource = $datasources | Where-Object{$_.path -eq $reportDataSourceDetail.Reference}
        Add-Member -InputObject $_ -MemberType NoteProperty -Name ConnectionString -Value $matchingDatasource.ConnectString -PassThru
}

这会让我看到这样的结果:

ReportPath       : /Marketing/OandD Class Summary By Month
DataSourceName   : Marketing
Reference        : /Data Sources/Marketing/Marketing
ConnectionString : Data Source=SQL08R2VM; Initial Catalog=Marketing;

ReportPath       : /Marketing/OandD Class YTD Summary
DataSourceName   : Marketing
Reference        : /Data Sources/Marketing/Marketing
ConnectionString : Data Source=SQL08R2VM; Initial Catalog=Marketing;

这些和其他功能让我很好。我还没有其他人使用它们,所以你可能遇到我从未遇到过的问题。使用PowerShell v5正常连接到我的SSRS 2008R2服务器

答案 1 :(得分:1)

这是一个T-SQL语句,它将返回数据源名称,路径&具有报告名称和路径的连接字符串。

;WITH 
XMLNAMESPACES  -- XML namespace def must be the first in with clause. 
(
    DEFAULT 'http://schemas.microsoft.com/sqlserver/reporting/2006/03/reportdatasource' 
    ,'http://schemas.microsoft.com/SQLServer/reporting/reportdesigner' 
    AS rd
) 
, 
shared_datasource 
AS 
(
    SELECT 
          DsnSharedName = sds.[Name]
        , DsnPath = sds.[Path] 
        , DEF = CONVERT(xml, CONVERT(varbinary(max), content)) 
    FROM 
        dbo.[Catalog] AS sds 
    WHERE sds.[Type] = 5) --> 5 = Shared Datasource 
, 
data_source_name (DsnPath, DsnSharedName, DsnConnString)
AS
(
    SELECT 
          cn.DsnPath
        , cn.DsnSharedName 
        , cn.DsnConnString 
    FROM 
        (SELECT
              sd.DsnPath
            , sd.DsnSharedName 
            , DsnConnString = dsn.value('ConnectString[1]', 'varchar(150)')
        FROM 
            shared_datasource AS sd 
            CROSS APPLY sd.DEF.nodes('/DataSourceDefinition') AS R(dsn) 
        ) AS cn 
)
SELECT 
      DataSourceName = lk.[Name]
    , dsn.DsnPath
    , dsn.DsnConnString
    , ReportName = c.[Name]
    , ReportFolder = c.[Path]
FROM 
    dbo.[Catalog] c
    INNER JOIN dbo.DataSource ds ON c.ItemID = ds.ItemID
    INNER JOIN dbo.[Catalog] lk ON ds.Link = lk.ItemID
    INNER JOIN data_source_name dsn ON dsn.DsnSharedName = lk.[Name]
WHERE 
    c.[Type] = 2  --> 2 = Reports
    --AND dsn.DsnConnString LIKE '%Initial Catalog%=%DatabaseNameHere%' 

然后你可以在powershell中运行T-SQL脚本文件。 np.dot()

<# Function to Check whether Server is Ping Status of the Server #>
Function Check-Ping()
{
    param
    (
         [string]$HostName
    )
    $PingStatus=Get-WmiObject -Query "Select * from Win32_PingStatus where Address='$HostName'"
    Return $PingStatus
}


<# Function to Check Instance name Present in the Server #>
Function Get-SQLInstances()
{
    param
    (
     [string]$SQLServerName
    )
    $Status=Check-Ping($SQLServerName)
    if($Status.StatusCode -ne 0)
    {
        Return "The Server Is Not Reachable"
    }
    elseif($Status.StatusCode -eq 0)
    {
        $Reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $SQLServerName)
        $RegKey = $Reg.OpenSubKey("SOFTWARE\\Microsoft\\Microsoft SQL Server")
        $Instances=$regKey.GetValue("installedinstances")
        Return $Instances        
     }
}


<# Function To Run TSQL and Return Results within HTML Table Tag #>
Function Run-TSQL()
{
Param
(
  [string]$MachineName,
  [string]$TSQLfilePath

)
    $Assembly=[reflection.assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo") 
    $Instances=Get-SQLInstances($MachineName)  
    $TSQL=Get-Content $TSQLfilePath
    foreach($Instance in $Instances)
    {
        $SQLServiceStatus=Get-Service -ComputerName $MachineName | Where-Object {$_.displayname -like "SQL Server ("+$Instance+")"}
        if($SQLServiceStatus.Status -eq "Running")
        {
            if($Instance -eq "MSSQLSERVER")
            {
                $SQLServer=$MachineName
            }
            Else
            {
                $SQLServer=$MachineName+"\"+$Instance
            }
            $SQLServerObject = new-Object Microsoft.SqlServer.Management.Smo.Server($SQLServer)
            $DatabaseObject = New-Object Microsoft.SqlServer.Management.Smo.Database
            $DatabaseObject = $SQLServerObject.Databases.Item("Master")##The TSQL Script Runs in Master Database
            $OutPutDataSet = $DatabaseObject.ExecuteWithResults($TSQL)
            for($t=0;$t -lt $OutPutDataSet.Tables.Count;$t++)
            {
                $OutString+="<Table Border=2>"
                $OutString+="<Tr>"
                foreach($Column in $OutPutDataSet.Tables[$t].Columns) 
                { 
                    $OutString+="<Th>"
                    $OutString+=$Column.ColumnName
                    $OutString+="</Th>"
                }     
                $OutString+="</Tr>"                   
                for($i=0;$i -lt $OutPutDataSet.Tables[$t].Rows.Count;$i++)
                {
                    $OutString+="<Tr>"
                    for($j=0;$j -lt $OutPutDataSet.Tables[$t].Columns.Count;$j++)
                    {

                        $OutString+="<Td>"                               
                        $OutString+=$($OutPutDataSet.Tables[$t].Rows[$i][$j])
                        $OutString+="</Td>"
                    }
                    $OutString+="</Tr>"                
                }
                $OutString+="</Table>"
                $OutString+="</Br>"
                $OutString+="</Br>"
            }
        }
    }
Return $OutString
}

<# Function To Add Table Tag to with In HTML tags 
Modify Title and Subject as Per yoru Requirement
#>
Function Get-HTMLOut()
{
Param
(
[String]$InputFile,
[String]$OutputFile,
[String]$TSQL
)

$Out+="<Html>"
$Out+="<Title>Run TSQL and Return HTML FIle</Title>" ## Modify 'TiTle' Tag as per your Required
$Out+="<Head><style>body {background-color:lightgray} H3{color:blue}H1{color:green}table, td, th {border: 1px solid green;}th {background-color: green;color: white;}</style></Head>" ## Modify 'Head' Tag as per your Required
$Out+="<Body><H1 Align='Center'>Run TSQL and Return HTML File</H1></Br></Br>" ## Modify 'Body' Tag as per your Required
ForEach($ServerName in Get-Content $InputFile)
{
    $Out+="<H3 align='center'>--------------$ServerName--------------</H3>" ## Modify 'header Text' Tag as per your Required
    $Out+="</Br>"   
    $Out+=Run-TSQL -MachineName $ServerName -TSQLfilePath $TSQL

}
$Out+="</Body></Html>"
Set-Content -Value $Out -Path $OutputFile
}

<# Call Get-HTMLOut Function
It Accepts 3 parameter
a. -InputFile (.txt file each server in a List withOut Instance Name)
b. -OutputFile (.Html File to which Output need to be sent)
c. -TSQL (.sql file which Contains the Script to Run)
#>
Get-HTMLOut -InputFile ".\Servers.txt" -OutputFile .\Status.Html -TSQL '.\TSQL Script.sql'