Azure Powershell SQL DataBase Export to Storage Container gets "An Error Occurred while Sending the Request" - database

I'd appreciate any help, even if it's just to suggest a way to diagnose the situation. The error message isn't really helping.
I've built a new VM from which I'm running PowerShell scripts to backup my databases. It had worked before on an old server for several months, and worked once on the new server, then I upgraded my Azure PowerShell cmdlets, and haven't been able to get it to work again. Mostly it says "An Error Occurred while sending the request", although twice it's said "Error Copying Content to a Stream" instead.
Below is my source code, with sensitive stuff replaced with ?'s. When I display the $stctx and $dbctx, they seem to have reasonable values. I added the IP address of the server as an exception to the db firewall, and I've installed SQL Server Management Studio and verified that I can connect to the database.
Here are the two error messages that I get:
Start-AzureSqlDatabaseExport : An error occurred while sending the request.
At C:\Users\Public\PublicCmds\test.ps1:29 char:1
+ Start-AzureSqlDatabaseExport -SqlConnectionContext $dbctx -StorageContext $stctx ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Start-AzureSqlDatabaseExport],
HttpRequestException
+ FullyQualifiedErrorId :
Microsoft.WindowsAzure.Commands.SqlDatabase.Database.Cmdlet.StartAzureSqlDatabaseExport
Start-AzureSqlDatabaseExport : Error while copying content to a stream.
At C:\Users\Public\PublicCmds\test.ps1:29 char:1
+ Start-AzureSqlDatabaseExport -SqlConnectionContext $dbctx -StorageContext $stctx ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Start-AzureSqlDatabaseExport], HttpRequestException
+ FullyQualifiedErrorId :
Microsoft.WindowsAzure.Commands.SqlDatabase.Database.Cmdlet.StartAzureSqlDatabaseExport
Here is a sanitized version of the source code:
param($dbname)
if ($dbname -eq $null) {
write-host "Database code must be specified"
return
}
$password = "????????" | ConvertTo-SecureString -asPlainText -Force
$servercredential = new-object System.Management.Automation.PSCredential("????", $password)
$dbsize = 1
$dbrestorewait = 10
$dbserver = "????"
$stacct = $dbcode
$stkey = "????????"
$stctx = New-AzureStorageContext -StorageAccountName $stacct -StorageAccountKey $stkey
$dbctx = New-AzureSqlDatabaseServerContext -ServerName $dbserver -Credential $servercredential
$dt = Get-Date
$timestamp = "_" + $dt.Year + "-" + ("{0:D2}" -f $dt.Month) + "-" + ("{0:D2}" -f $dt.Day) + "-" + ("{0:D2}" -f $dt.Hour) + ("{0:D2}" -f $dt.Minute)
$bkupname = $dbname + $timestamp + ".bacpac"
write-host "db context"
$dbctx
write-host "storage context"
$stctx
write-host "Backup $dbname to $bkupname"
Start-AzureSqlDatabaseExport -SqlConnectionContext $dbctx -StorageContext $stctx - StorageContainerName databasebackup -DatabaseName $dbname -BlobName $bkupname

I made two changes that together fixed the problem:
- There was an error in the filename (wish the error message said as much)
- I changed to using AD security (the free kind)

Related

Could Not Load Assembly MICROSOFT.SQLSERVER.BATCHPARSER on 32-BIT environment

I'm posting my problem here, hoping someone may help me to figure the issue.
So, for one of my clients I've developed a PS script that retrieve a table for a database and export it as a CSV directly to a Blob Storage. My script works fine in a 64-Bit environment. However, I cannot run it in a 32-Bit environment. I need to run it in a 32-Bit environment because the scheduler used by the client is a 32-Bit tool.
On my side, I've tried every thing I've already found around the net on this subject with no luck.
My problem as I said above is that I fail to run my script on a 32-Bit environment. I'm putting a screenshot of booth environment so you can see what I'm having.
The Green square is the expected result. The Yellow one is the error I'm having.
The Blue squares shows booth SqlServer Modules I downloaded (x86 & 64).
I have the same behavior from a CMD SHELL.
So My questions are:
Is there anyway to make this script working on a 32-Bit environment?
Else Is there anyway to force a 32-BIT CMD SHELL to open a 64-Bit session on PowerShell ?
Here is the FUll PS SCript :
param (
[String]$SourceServer="" ,
[String]$SourceDatabase="" ,
[String]$DestinationStorageAccountName = "",
[String]$DestinationStorageAccountContainrerName= "",
[String]$DBUser = "",
[String]$DBUserPWD = ""
)
FUNCTION Write-ToBlobStorage{
[CmdletBinding()]
param (
[Parameter(Mandatory)][String]$ResultString,
[Parameter(Mandatory)][String]$DestinationStorageAccountName,
[Parameter(Mandatory)][String]$DestinationStorageAccountContainrerName,
[Parameter(Mandatory)][String]$FileName
)
write-host "Clear existing identies to keep cache fresh"
Clear-AzContext -force
write-host "Authenticate using the Managed identity"
$account = Connect-AzAccount -identity
if(-not $account.Context.Subscription.Id)
{
write-error "Failed to authenticate with the Managed identity. Ensure VM has a Managed identity enabled and is assigned the correct IAM roles"
return
}
write-host "Get storage context"
$context = New-AZStorageContext -StorageAccountName $DestinationStorageAccountName
write-host "Get storage Container"
$container=Get-AzStorageContainer -Name $DestinationStorageAccountContainrerName -Context $context
write-host "Writing Result to storage"
$content = [system.Text.Encoding]::UTF8.GetBytes($ResultString)
$container.CloudBlobContainer.GetBlockBlobReference("$FileName.csv").UploadFromByteArray($content,0,$content.Length)
}
#Import-Module 'Az.KeyVault' -Force
#Import-Module -Name 'C:\Program Files\WindowsPowerShell\Modules\SqlServer' -Force
Import-Module -Name 'C:\Program Files (x86)\WindowsPowerShell\Modules\SqlServer' -Force
$TLS12Protocol = [System.Net.SecurityProtocolType] 'Ssl3 , Tls12'
[System.Net.ServicePointManager]::SecurityProtocol = $TLS12Protocol
$Query = "SELECT ##SERVERNAME"
$Result = Invoke-Sqlcmd -ServerInstance $SourceServer -Database $SourceDatabase -Query $Query | ConvertTo-Csv -Delimiter '|' -NoTypeInformation
$ResultString = $Result -join "`r`n"
Write-ToBlobStorage -ResultString $ResultString -DestinationStorageAccountName $DestinationStorageAccountName -DestinationStorageAccountContainrerName $DestinationStorageAccountContainrerName -FileName "TMP_Flux"
write-host "--- ALL DONE---"
And Here is The error for the 32-Bit :
Invoke-Sqlcmd : Could not load file or assembly
'Microsoft.SqlServer.BatchParser, Version=15.100.0.0, Culture=neutral,
PublicKeyToken=89845dcd8080cc91' or one of its dependencies. The system cannot
find the file specified.
At C:\temp\ExportToBlobScript\ExportToBlob.ps1:87 char:11
+ $Result = Invoke-Sqlcmd -ServerInstance $SourceServer -Database $Sour ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Invoke-Sqlcmd], FileNotFoundEx
ception
+ FullyQualifiedErrorId : System.IO.FileNotFoundException,Microsoft.SqlServ
er.Management.PowerShell.GetScriptCommand
Write-ToBlobStorage : Cannot bind argument to parameter 'ResultString' because
it is an empty string.
At C:\temp\ExportToBlobScript\ExportToBlob.ps1:91 char:35
+ Write-ToBlobStorage -ResultString $ResultString -DestinationStorageAc ...
+ ~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Write-ToBlobStorage], Parameter
BindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorEmptyStringNotAll
owed,Write-ToBlobStorage
--- ALL DONE---
And Here is the result for the 64-Bit:
Clear existing identies to keep cache fresh
Authenticate using the Managed identity
Get storage context
Get storage Container
Writing Result to storage
--- ALL DONE---
Many Thanks for all of you suggestions.
Not sure. But since you're only using Invoke-SqlCmd to run a query, you can eliminate the dependence on the SqlServer powershell module by using ADO.NET directly from PowerShell. The SQL Server client libraries are part of the .NET framework, so they will be available on any Windows box. So something like:
function Invoke-SqlCmd-Custom{
[CmdletBinding()]
param (
[Parameter(Mandatory)][String]$ServerInstance,
[Parameter(Mandatory)][String]$Database,
[Parameter(Mandatory)][String]$Query
)
$con = new-object System.Data.SqlClient.SqlConnection
$con.ConnectionString = "Server=$ServerInstance;Database=$Database;Integrated Security=true"
try
{
$con.Open()
$cmd = $con.CreateCommand()
$cmd.CommandText = $Query
$dt = new-object System.Data.DataTable
$rdr = $cmd.ExecuteReader()
$dt.Load($rdr)
return $dt.Rows
}
finally
{
$con.Close()
}
}

Connecting to sql database with powershell gives an error: Exception calling "Open" with "0" argument(s): "Login failed for user

I am able to connect using SSMS.
However, when I try to connect via PowerShell it give me an error:
$connString = "Data Source=server;Database=mydb;User ID=myusern;Password=mypass"
#Create a SQL connection object
$conn = New-Object System.Data.SqlClient.SqlConnection $connString
#Attempt to open the connection
$conn.Open()
if($conn.State -eq "Open")
{
# We have a successful connection here
# Notify of successful connection
Write-Host "Test connection successful"
$conn.Close()
}
Error:
Exception calling "Open" with "0" argument(s): "Login failed for user
'username'."
At line:7 char:5
+ $conn.Open()
+ ~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : SqlException
What am I doing wrong here?
Thank you

Errors using DacServices to unregister a data tier

Upgrading my code from DacStore to work in SQL Server 2016 and running into issues with DacServices. The goal here is to unregister the data tier of a preexisting database before updating the schema.
Code snippet:
$serverconnection = New-Object System.Data.SqlClient.SqlConnection
If (!$uid -And !$pwd){
$serverconnection.ConnectionString = "Server = $server; Database = $database; Integrated Security = True;"
}
Else{
$serverconnection.ConnectionString = "server = $server; Database = $database; Integrated Security = False; User ID = $uid; Password = $pwd;"
}
# Load the DAC assembly
$validate = Test-Path $dacfxPath
if (!$dacfxPath){
throw 'No usable version of Dac Fx found.'
}
Add-Type -Path $dacfxPath # Attempt to load DAC assembly
$DacService = New-Object Microsoft.SqlServer.Dac.DacServices($serverconnection)
$dacName = $database
## Only delete the DAC definition from msdb, the associated database remains active.
$DacService.Unregister($dacName)
Error received when creating DacServices object:
New-Object : Exception calling ".ctor" with "1" argument(s): "Format of the initialization string does not conform to
specification starting at index 0."
At C:\Users\Administrator\AppData\Local\Temp\2\_ir_sf_temp_0\UnregisterDataTier.ps1:34 char:15
+ ... acService = New-Object Microsoft.SqlServer.Dac.DacServices($servercon ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [New-Object], MethodInvocationException
+ FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.PowerShell.Commands.NewObjectCommand
My connection string appears correct, and worked in the past. What else could I be doing incorrectly?
Update: Specifying in the DacServices constructor arg that it was a connection string seemed to fix the issue.
$DacService = New-Object Microsoft.SqlServer.Dac.DacServices($serverconnection.Connec‌​tionString)
Having an issue with the Unregister() method now, but one step closer!

SSIS Catalog and Project Deployment with PowerShell

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.

Using PowerShell DataTable to import data into SQL Server table

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.

Resources