使用PowerShell从SSIS目录中获取包XML

时间:2016-11-05 14:59:20

标签: xml powershell ssis

有没有办法从使用PowerShell的SSIS目录中的软件包中获取Package XML,但是没有下载和解压缩项目?我想在XML文档中搜索某些字符串。

################################
########## PARAMETERS ##########
################################ 
$SsisServer = ".\sql2016"



############################
########## SERVER ##########
############################
# Load the Integration Services Assembly
$SsisNamespace = "Microsoft.SqlServer.Management.IntegrationServices"
[System.Reflection.Assembly]::LoadWithPartialName($SsisNamespace) | Out-Null;

# Create a connection to the server
$SqlConnectionstring = "Data Source=" + $SsisServer + ";Initial Catalog=master;Integrated Security=SSPI;"
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection $SqlConnectionstring

# Create the Integration Services object
$IntegrationServices = New-Object $SsisNamespace".IntegrationServices" $SqlConnection

# Check if connection succeeded
if (-not $IntegrationServices)
{
    Throw [System.Exception] "Failed to connect to server $SsisServer "
}



#############################
########## CATALOG ##########
#############################
# Create object for SSISDB Catalog
$Catalog = $IntegrationServices.Catalogs["SSISDB"]

# Check if the SSISDB Catalog exists
if (-not $Catalog)
{
    Throw [System.Exception] "SSISDB catalog doesn't exist!"
}



##########################
########## LOOP ##########
##########################
foreach ($Folder in $Catalog.Folders)
{
    Write-Host $Folder.Name
    foreach ($Project in $Folder.Projects)
    {
        Write-Host " - " $Project.Name
        foreach ($Package in $Project.Packages)
        {
            Write-Host "    - " $Package.Name
            # HOW TO GET PACKAGE XML???

            # Not working:
            # Exception calling "Serialize" with "1" argument(s):
            # "The parameter 'sink.Action' is invalid."
            #$sb = New-Object System.Text.StringBuilder
            #$sw = New-Object System.IO.StringWriter($sb)
            #$writer = New-Object System.Xml.XmlTextWriter($sw)
            #$xml = $Package.Serialize($writer)
        }
    }
}

3 个答案:

答案 0 :(得分:3)

我没有运气尝试此代码的纯对象模型版本,因为我得到了error

  

使用“1”参数调用“Serialize”的异常:“参数'sink.Action'无效。”

超!在尝试通过托管对象模型进入项目之后,我试图通过TSQL路由。我们只需要模拟对SSISDB.catalog.get_project的调用并将其传递给文件夹和项目名称

Function Get-ProjectsTsql
{
    param
    (
        [Microsoft.SqlServer.Management.IntegrationServices.CatalogFolder] $folder
    ,   [string] $serverName = "localhost\dev2016"
    )

    # we want to build an execute procedure call that looks like this
    # exec [SSISDB].[catalog].[get_project] @folder_name=N'FolderName',@project_name=N'ProjectName'

    $connectionString = [String]::Format("Data Source={0};Initial Catalog=msdb;Integrated Security=SSPI;", $serverName)
    $connection = New-Object System.Data.SqlClient.SqlConnection($connectionString)
    $integrationServices = New-Object Microsoft.SqlServer.Management.IntegrationServices.IntegrationServices($connection)
    # The one, the only SSISDB catalog
    $catalog = $integrationServices.Catalogs["SSISDB"]

    #Instance of ProjectInfo
    foreach ($proj in $folder.Projects)
    {
        $projName = $proj.Name
        $folderName = $folder.Name

        $zipOut = "C:\tmp\$projName.zip"

        $query = "exec [SSISDB].[catalog].[get_project] @folder_name=N'$folderName',@project_name=N'$projName'"
        # Write-Host $query

        $command = New-Object System.Data.SqlClient.SqlCommand
        $command.CommandText = $query
        $command.Connection = $connection
        $projectBinary = $command.ExecuteScalar()
        [System.IO.File]::WriteAllBytes($zipOut,$projectBinary)
    }
}

Function Get-CatalogFolders
{
    param
    (
        [string] $serverName = "localhost\dev2012"
    )

    $connectionString = [String]::Format("Data Source={0};Initial Catalog=msdb;Integrated Security=SSPI;", $serverName)

    $connection = New-Object System.Data.SqlClient.SqlConnection($connectionString)

    $integrationServices = New-Object Microsoft.SqlServer.Management.IntegrationServices.IntegrationServices($connection)
    # The one, the only SSISDB catalog
    $catalog = $integrationServices.Catalogs["SSISDB"]

    $catalogFolders = $catalog.Folders

    return $catalogFolders
}

$serverName = "localhost\dev2016"
# Identify all the folders on the server
foreach ($folder in Get-CatalogFolders $serverName)
{
    # Save out all the projects to their zip files
    Get-ProjectsTsql $folder $serverName
}

这是我用.zip扩展名保存的ispac(因为它只是一个zip)。要获取包xml,您需要解压缩文件,找到您的包并从那里开始

答案 1 :(得分:2)

虽然该线程已有几个月的历史,但我认为以下方法直接回答了原始问题。我遇到了类似的情况,我需要从SSISDB中的包访问XML,以作为新包的模板。好吧,在将项目字节读入我的脚本后,

var projectBytes = ssisServer.Catalogs["SSISDB"].Folders[SSISFolderName].Projects[SSISProjectName].GetProjectBytes();

可以通过从项目字节创建内存存档来绕过下载/解压缩。通过遍历存档条目直到找到正确的包(如果知道文件的索引更容易),最后一步是将存档条目读入流并将其传递给package.LoadFromXML方法。

Stream stream = new MemoryStream(projectBytes);

ZipArchive za = new ZipArchive(stream);

foreach (ZipArchiveEntry zipEntry in za.Entries)
{
    if (zipEntry.FullName == SSISPackageName)
    {
         Package pkg = new Package();

         StreamReader sr = new StreamReader(zipEntry.Open());

         pkg.LoadFromXML(sr.ReadToEnd(), null);

         break;

    }

}

答案 2 :(得分:0)

如果目标是读取包中的数据并直接获取xml,那么包的XML代码实际上是作为二进制数据存储在SSISDB.internal.object_versions table.ref的object_data列中。[ 1]

您可以使用 GetSqlBinary 方法检索此数据。我已经看到了一个用于检索SSRS rdl文件的示例。见参考文献[2]有关代码的完整示例。

    # New BinaryWriter; existing file will be overwritten. 
    $fs = New-Object System.IO.FileStream ($name), Create, Write; 
    $bw = New-Object System.IO.BinaryWriter($fs); 

    # Read of complete Blob with GetSqlBinary 
    $bt = $rd.GetSqlBinary(2).Value; 
    $bw.Write($bt, 0, $bt.Length); 
    $bw.Flush(); 
    $bw.Close(); 
    $fs.Close(); 

<强> 参考

  1. msdn forum post

  2. Export all SSRS Reports, DataSources and resources