TL;DR - I have a window in the ISE where I somehow got my script to work. If I start a new window (aka session?) in the ISE and copy/paste the code, the script fails. I'm trying to figure out what is different between the sessions so that I can get it to reliably work. I'm hoping there's some setting or something that I set in one that's not in the other, but I'm clearing variables between runs (see below) so I just don't know.
Long version:
I have a Powershell SMO/SQLServer script that works in one window in the ISE that uses ScriptTransfer(), which is a module inside the SQLServer module.
When I create a new window (aka new session) and copy/paste the code and run it against one particular server/database, the scripttransfer fails. I have no idea how I managed to get it working, but I want to duplicate that. The code works on most of my databases, but fails on one particular one, and there's no easy way to figure out what's going wrong inside that module, and the error message I get back is:
Exception calling "ScriptTransfer" with "0" argument(s): "Script transfer failed. "
At line:68 char:1
+ $transfer.ScriptTransfer()
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : FailedOperationException
Here's the code. It works on most databases, but I've got one DB that's causing these errors. Including it here just to be complete.
Remove-Variable -Name * -ErrorAction SilentlyContinue #allows us to run repeatedly in same session for testing.
import-module sqlserver #yes, necessary, at least so that you know if the scripttransfer fails, you need to get a newer version.
$servername = "mydb"
$databasename = "myserver"
$workingdirectory ="c:\temp\backup"
"servername is $servername"
"databasename is $databasename"
"uploadtos3 is $uploadtoS3"
"accesskey is $accesskey"
"secretkey is $secretkey"
"workingdirectory is $workingdirectory"
"bucketname is $bucketname"
"regionname is $regionname"
"s3path is $s3path"
####################
# 0 - Declarations #
####################
$credentials = set-awscredentials -accesskey $accesskey -secretkey $secretkey
$sql_server = $servername
$DBToScript = $databasename
$path = $workingdirectory #I'd use a UNC path here
################################
# 1 - Scripting out the CREATE #
################################
$SMOServer = New-Object -TypeName Microsoft.SqlServer.Management.Smo.Server -ArgumentList "$sql_server"
$db = $SMOServer.Databases[$DBToScript]
$create_database = $db.Script() -replace("\d+KB","100mb") -replace("\d+mb","100mb") -replace("\d+GB","100mb")
#while I couldn't get it to script out the GO terminators (ScriptBatchTerminator), it doesn't need it for the create.
$create_database |Out-File "$path\$($dbtoscript)_db_create.sql" -Force -Encoding ascii -Append
#using out-file since I can't figure out which setting uses filename.
#####################################
# 2 - Scripting out all the objects #
#####################################
#using transfer as it seems more straightforward.
$transfer = new-object -TypeName Microsoft.SqlServer.Management.Smo.Transfer #-ArgumentList $db
$transfer.Database = $db
$transfer.CopyAllObjects = $true
$transfer.CopySchema = $true
$transfer.CopyAllSchemas= $true
$transfer.Options.Indexes = $true
$transfer.Options.ScriptBatchTerminator = $true # this only goes to the file
$transfer.Options.filename = "$path\$($dbtoscript)_db_objects.sql"
$transfer.Options.ExtendedProperties= $true # yes, we want these
$transfer.Options.DRIAll= $true # and all the constraints
$transfer.Options.Indexes= $true # Yup, these would be nice
$transfer.Options.Triggers= $true # This should be included when scripting a database
$transfer.Options.ScriptBatchTerminator = $true # this only goes to the file
$transfer.Options.IncludeHeaders = $false #pshaw
$transfer.Options.ToFileOnly = $true #no need of string output as well
$transfer.Options.IncludeIfNotExists = $false # not necessary but it means the script can be more versatile
"test"
# This first ScriptTransfer MUST stay! Otherwise it leaves out the WITH EXECUTE AS CALLER on CLR SPs
$transfer.ScriptTransfer() |out-null
$transfer.ScriptTransfer()
I want to get a copy of all .rdl files in one server.
I can do the download manually one report at the time, but this is time consuming especially that this server has around 1500 reports.
Is there any way or any tool that allows me to download all the .rdl files and take a copy of them?
There is a complete & simpler way to do this using PowerShell.
This code will export ALL report content in the exact same structure as the Report server. Take a look at the Github wiki for other options & commands
#------------------------------------------------------
#Prerequisites
#Install-Module -Name ReportingServicesTools
#------------------------------------------------------
#Lets get security on all folders in a single instance
#------------------------------------------------------
#Declare SSRS URI
$sourceRsUri = 'http://ReportServerURL/ReportServer/ReportService2010.asmx?wsdl'
#Declare Proxy so we dont need to connect with every command
$proxy = New-RsWebServiceProxy -ReportServerUri $sourceRsUri
#Output ALL Catalog items to file system
Out-RsFolderContent -Proxy $proxy -RsFolder / -Destination 'C:\SSRS_Out' -Recurse
I've created this powershell script to copy them into a ZIP. You have to provide the SQL server database details.
Add-Type -AssemblyName "System.IO.Compression.Filesystem"
$dataSource = "SQLSERVER"
$user = "sa"
$pass = "sqlpassword"
$database = "ReportServer"
$connectionString = "Server=$dataSource;uid=$user; pwd=$pass;Database=$database;Integrated Security=False;"
$tempfolder = "$env:TEMP\Reports"
$zipfile = $PSScriptRoot + '\reports.zip'
$connection = New-Object System.Data.SqlClient.SqlConnection
$connection.ConnectionString = $connectionString
$connection.Open()
$allreports = $connection.CreateCommand()
$allreports.CommandText = "SELECT ItemID, Path, CASE WHEN Type = 2 THEN '.rdl' ELSE '.rds' END AS Ext FROM Catalog WHERE Type IN(2,5)"
$result = $allreports.ExecuteReader()
$reportable = new-object "System.Data.DataTable"
$reportable.Load($result)
[int]$objects = $reportable.Rows.Count
foreach ($report in $reportable) {
$cmd = $connection.CreateCommand()
$cmd.CommandText = "SELECT CAST(CAST(Content AS VARBINARY(MAX)) AS XML) FROM Catalog WHERE ItemID = '" + $report[0] + "'"
$xmldata = [string]$cmd.ExecuteScalar()
$filename = $tempfolder + $report["Path"].Replace('/', '\') + $report["Ext"]
New-Item $filename -Force | Out-Null
Set-Content -Path ($filename) -Value $xmldata -Force
Write-Host "$($objects.ToString()).$($report["Path"])"
$objects -= 1
}
Write-Host "Compressing to zip file..."
if (Test-Path $zipfile) {
Remove-Item $zipfile
}
[IO.Compression.Zipfile]::CreateFromDirectory($tempfolder, $zipfile)
Write-Host "Removing temporarly data"
Remove-Item -LiteralPath $tempfolder -Force -Recurse
Invoke-Item $zipfile
If you just need this for backup purposes or something similar, this might be useful: Where does a published RDL file sit?
The relevant query from that thread is:
select convert(varchar(max), convert(varbinary(max), content))
from catalog
where content is not null
The original answer was using 2005, and I've used it on 2016, so I imagine it should work for 2008 and 2012.
When I had to use this, I added in the Path to the query as well, so that I knew which report was which.
CAVEAT: prior to SSMS v18, Results to Grid is limited to 64KB per tuple and Results to Text are limited to 8,192 characters per tuple. If your report definition is larger than these limits you will not be able to get the entire definition.
In SSMS v18, those limits have been increased to 2MB per tuple for both Reports to Grid as well as Results to Text.
This is based on SQL2016/SSRS2016 but I think it should work for 2012.
SELECT 'http://mySQLServerName/reports/api/v1.0/catalogitems(' + cast(itemid as varchar(256))+ ')/Content/$value' AS url
FROM ReportServer.dbo.Catalog
This will give you a list of URL's, one for each report.
If the above did not work in SSRS 2012 then go to the report manager and do as if you were going to download the file from there. Check the URL on the download button and you'll probably see a URL with and item id embedded int it. Just adjust the above code to match that url structure.
What you do with then after this is up to you.
Personally I would use the Chrome extension called 'Tab Save' available in the Chrome store here. You can simply copy and paste all the URL's created above into it and hit the download button...
Found and used this without any issues. Nothing to install, just added my url, and pasted into Powershell.
https://microsoft-bitools.blogspot.com/2018/09/ssrs-snack-download-all-ssrs-reports.html
In case the link breaks, here's the code from the link:
###################################################################################
# Download Reports and DataSources from a SSRS server and create the same folder
# structure in the local download folder.
###################################################################################
# Parameters
###################################################################################
$downloadFolder = "c:\temp\ssrs\"
$ssrsServer = "http://myssrs.westeurope.cloudapp.azure.com"
###################################################################################
# If you can't use integrated security
#$secpasswd = ConvertTo-SecureString "MyPassword!" -AsPlainText -Force
#$mycreds = New-Object System.Management.Automation.PSCredential ("MyUser", $secpasswd)
#$ssrsProxy = New-WebServiceProxy -Uri "$($ssrsServer)/ReportServer/ReportService2010.asmx?WSDL" -Credential $mycreds
# SSRS Webserver call
$ssrsProxy = New-WebServiceProxy -Uri "$($ssrsServer)/ReportServer/ReportService2010.asmx?WSDL" -UseDefaultCredential
# List everything on the Report Server, recursively, but filter to keep Reports and DataSources
$ssrsItems = $ssrsProxy.ListChildren("/", $true) | Where-Object {$_.TypeName -eq "DataSource" -or $_.TypeName -eq "Report"}
# Loop through reports and data sources
Foreach($ssrsItem in $ssrsItems)
{
# Determine extension for Reports and DataSources
if ($ssrsItem.TypeName -eq "Report")
{
$extension = ".rdl"
}
else
{
$extension = ".rds"
}
# Write path to screen for debug purposes
Write-Host "Downloading $($ssrsItem.Path)$($extension)";
# Create download folder if it doesn't exist (concatenate: "c:\temp\ssrs\" and "/SSRSFolder/")
$downloadFolderSub = $downloadFolder.Trim('\') + $ssrsItem.Path.Replace($ssrsItem.Name,"").Replace("/","\").Trim()
New-Item -ItemType Directory -Path $downloadFolderSub -Force > $null
# Get SSRS file bytes in a variable
$ssrsFile = New-Object System.Xml.XmlDocument
[byte[]] $ssrsDefinition = $null
$ssrsDefinition = $ssrsProxy.GetItemDefinition($ssrsItem.Path)
# Download the actual bytes
[System.IO.MemoryStream] $memoryStream = New-Object System.IO.MemoryStream(#(,$ssrsDefinition))
$ssrsFile.Load($memoryStream)
$fullDataSourceFileName = $downloadFolderSub + "\" + $ssrsItem.Name + $extension;
$ssrsFile.Save($fullDataSourceFileName);
}
I'vr tried several permutations of this script and keep getting the "can't create proxy connection" error. Here's the one that "should" work:
#------------------------------------------------------
#Prerequisites
#Install-Module -Name ReportingServicesTools
#------------------------------------------------------
#Lets get security on all folders in a single instance
#------------------------------------------------------
#Declare SSRS URI
$sourceRsUri = "http://hqmnbi:80/ReportServer_SQL08/ReportService2010.asmx?wsdl"
#Declare Proxy so we dont need to connect with every command
$proxy = New-RsWebServiceProxy -ReportServerUri $sourceRsUri
#Output ALL Catalog items to file system
Out-RsFolderContent -Proxy $proxy -RsFolder / -Destination 'C:\Users\arobinson\source\Workspaces\EDW\MAIN\SSRS\HQMNBI' -Recurse
This is the error I'm getting:
Failed to establish proxy connection to http://hqmnbi/ReportServer_SQL08/ReportService2010.asmx : The HTML document does not contain
Web service discovery information.
At C:\Program Files\WindowsPowerShell\Modules\ReportingServicesTools\0.0.6.6\Functions\Utilities\New-RsWebServiceProxy.ps1:136 char:9
throw (New-Object System.Exception("Failed to establish proxy ...
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CategoryInfo : OperationStopped: (:) [], Exception
FullyQualifiedErrorId : Failed to establish proxy connection to http://hqmnbi/ReportServer_SQL08/ReportService2010.asmx : The
HTML document does not contain Web service discovery information.
I've tried the URI with htttp:// and without, I've tried including the port number. etc. Still can't get this to actually work. We have two other SSRS instances that I was able to run this against no problem.
From this question: SQL Reporting Services - COPY reports to another folder
I found this tool can both download and upload reports. Plus it lists out folders and subfolders.
http://code.google.com/p/reportsync/
I'm trying to create a ssis catalog with power-shell
i'm getting a weird error. this is the code i'm running:
i took the code from msdn
$SQLserver = "BM-ELAD\DRC_BUG_RESTORE"
$Link = "false"
$pass = "123456"
# Load the IntegrationServices Assembly
[Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.Management.IntegrationServices")
# Store the IntegrationServices Assembly namespace to avoid typing it every time
$ISNamespace = "Microsoft.SqlServer.Management.IntegrationServices"
# Create a connection to the server
$sqlConnectionString = "Data Source=$SQLserver;Initial Catalog=master;Integrated Security=SSPI;"
$sqlConnection = New-Object System.Data.SqlClient.SqlConnection $sqlConnectionString
# Create the Integration Services object
$integrationServices = New-Object $ISNamespace".IntegrationServices" $sqlConnection
# Provision a new SSIS Catalog
$catalog = New-Object $ISNamespace".Catalog" ($integrationServices, "SSISDB", "$pass")
$catalog.Create()
and this is the error i'm getting:
GAC Version Location
--- ------- --------
True v2.0.50727 C:\Windows\assembly\GAC_MSIL\Microsoft.SqlServer.Management.IntegrationServices\13.0.0.0__89845dcd8080cc91\Microsoft.SqlServer.Management.IntegrationServices.dll
New-Object : The term 'New-Object' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify
that the path is correct and try again.
At line:13 char:18
+ $sqlConnection = New-Object System.Data.SqlClient.SqlConnection $sqlConnectionSt ...
+ ~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (New-Object:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Has anyone ever encountered this problem? am i missing a file?
i tried this fix: failed fix and it didn't work.
my powershell version is 4.0
when i do this manually, it works.
I need to import a .csv file with 350 columns into a SQL Server 2008 R2 database.
Surfing the internet I came up with a function called Out-DataTable from Chad Miller: link to script on Technet
I have used this to complete the PowerShell script as follows:
#----------------------------------------------------------------
$logNaam=MylogFileName
TRY
{
$ConnectionString = "Data Source=mySQLServer; Initial Catalog=MyDB; Trusted_Connection=True;";
. ".\Out-DataTable.ps1"
$csvDataTable = Import-CSV -Path "MyCSV_FileAndPath" | Out-DataTable
$bulkCopy = new-object ("Data.SqlClient.SqlBulkCopy") $ConnectionString
$bulkCopy.DestinationTableName = "to_MyTableName"
$bulkCopy.WriteToServer($csvDataTable)
}
Catch
{
$ErrorMessage = $_.Exception.Message
$FailedItem = $_.Exception.ItemName
"Error: Job starten lukt niet : ($ErrorMessage) " | out-file $logNaam -append
"Error: Job starten lukt niet : ($FailedItem) " | out-file $logNaam -append
}
Finally
{}
#----------------------------------------------------------------
Running this code in the PowerShell command prompt, I get this error:
Unexpected token 'data' in expression or statement.
At .\MyScript.ps1:20 char:27
+ $ConnectionString = "Data <<<< Source=MySQLServer; Initial Catalog=MyDB
; Trusted_Connection=True;";
+ CategoryInfo : ParserError: (data:String) [], ParseException
+ FullyQualifiedErrorId : UnexpectedToken
I'm stuck with this and have no clue where to start. Changing Data Source=MySQLServer to Server=MySQLServer does not solve it. The message only changed pointing to the position following MySQLServer<<<.
Also adding the Windows server-name to it (MyWinServer\MySQLServer) did not help, either.
Any advise, directions, explanation or help to code this script would by much appreciated.
Here is a powershell script:
[string] $server = "devserver\mssql"; # SQL Server Instance
[string] $database = "ftg"; # Database with the tables to script out.
[string] $folder = "d:\FT\FTProject\"; # Path to export to
[string] $SQLLogin = "Sa";
[string] $SQLPass = "Sa1234";
# Reference to SMO
[void][System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.SMO');
Write-Output ((Get-Date -format yyyy-MM-dd_HH-mm-ss) + ": Started ...");
$con = New-Object Microsoft.SqlServer.Management.Common.ServerConnection($server, $SQLLogin, $SQLPass);
$srv = New-Object Microsoft.SqlServer.Management.SMO.Server($con);
$db = New-Object Microsoft.SqlServer.Management.SMO.Database($srv, $database);
#Use SMO Transfer Class by specifying source database
#you can specify properties you want either brought over or excluded, when the copy happens
$ObjTransfer = New-Object -TypeName Microsoft.SqlServer.Management.SMO.Transfer;
$ObjTransfer.Database = $db
At last line an error occurs:
Exception setting "Database": "Cannot convert the "[ftg]" value of type "Microsoft.SqlServer.Management.Smo.Database" to type "Microsoft.SqlServer.Managem
ent.Smo.Database"."
At D:\FT\FTProject\Setup\transfer.ps1:31 char:1
+ $ObjTransfer.Database = [Microsoft.SqlServer.Management.SMO.Database] $db
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], SetValueInvocationException
+ FullyQualifiedErrorId : ExceptionWhenSetting
I also tryed to set $db as follows:
$db = $srv.Databases[$database]
What is wrong?
Try the following:
$db = $srv.Databases[$database]
...
$ObjTransfer = New-Object -TypeName Microsoft.SqlServer.Management.SMO.Transfer -ArgumentList $db
This should create the Transfer object using $db as the Source Database.
See example at MSDN: Transferring Schema and Data from One Database to Another in PowerShell
I think it because different versions of Microsoft.SqlServer.Smo.dll and Microsoft.SqlServer.SmoExtended.dll were loaded.
I get the same error when i loaded first assembly in 10 version and another one in 12.
When i loaded both of them explicitly in the same version everything worked fine.
Add-Type -path "C:\Windows\assembly\GAC_MSIL\Microsoft.SqlServer.Smo\12.0.0.0__89845dcd8080cc91\Microsoft.SqlServer.Smo.dll"
Add-Type -path "C:\Windows\assembly\GAC_MSIL\Microsoft.SqlServer.SmoExtended\12.0.0.0__89845dcd8080cc91\Microsoft.SqlServer.SmoExtended.dll"