【问题标题】:Get Package XML from SSIS Catalog with PowerShell使用 PowerShell 从 SSIS 目录获取包 XML
【发布时间】:2016-11-05 14:59:20
【问题描述】:

有没有办法使用 PowerShell 从 SSIS 目录中的包中获取包 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)
        }
    }
}

【问题讨论】:

标签: xml powershell ssis


【解决方案1】:

尽管该线程已有几个月的历史,但我相信以下方法可以直接回答原始问题。我遇到了类似的情况,我需要从 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】:

    当我得到error 时,我没有运气尝试这个代码的纯对象模型版本

    使用“1”个参数调用“序列化”的异常:“参数'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,您需要解压缩文件,找到您的包并从那里开始

    【讨论】:

    • 谢谢,在使用 Serialize 时遇到了同样的错误 :-( 试图避免的下载和解压缩解决方法在没有 TSQL 的情况下也可以使用:$Project.GetProjectBytes()(参见: microsoft-ssis.blogspot.com/2016/04/…)
    • 我应该想到你会在上面发一个帖子;)你这周在雷德蒙德吗?如果没有,我可以举报 SSIS 团队,看看他们是否对错误有任何见解
    • 是的,本周将在雷德蒙德。让我们试试看 SSIS 团队是否有解决方案。感谢您迄今为止的帮助。
    • 得到一个答案:不下载是不可能的,因为他们不在目录中存储单独的包
    【解决方案3】:

    如果目标是读取包中的数据并直接获取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

    【讨论】:

    • 您好 sqlchow,感谢您的回复! SSISDB.[internal].[object_versions] 表包含项目的各种版本 (ispac)。您可以将其加入 SSISDB.[internal].[projects](在 project_id = object_id 上)。它包含与 $Project.GetProjectBytes() 相同的数据,但也来自所有以前的项目版本。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多