Powershell Script Issue with SQL Server 2012/2014 - sql-server

I have a PowerShell script which works well when I run it on server with SQL Server default instance (MSSQLSERVER) but the same script fails on a server with a named instance (MSSQL$instance)
For the default instance (MSSQLSERVER)
[Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo")
$service = Get-service -name 'MSSQLSERVER'
$status = $service.status
$CreateDB = "db-Test"
if ( $status -eq "Running" )
{
'Success' | Out-File -FilePath c:\sqltest.log -Encoding ASCII
$srv = new-Object Microsoft.SqlServer.Management.Smo.Server("(local)")
$db = New-Object Microsoft.SqlServer.Management.Smo.Database($srv, "$CreateDB")
$db.Create()
$db.CreateDate
}
else
{
'Failed' | Out-File -FilePath c:\sqltest.log -Encoding ASCII
}
Above script works very well. But below script throws error :
For named instance :
[Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo")
$service = Get-service -name 'MSSQL$instancename'
$status = $service.status
$CreateDB = "db-Test"
if ( $status -eq "Running" )
{
'Success' | Out-File -FilePath c:\sqltest.log -Encoding ASCII
$srv = new-Object Microsoft.SqlServer.Management.Smo.Server("(local)")
$db = New-Object Microsoft.SqlServer.Management.Smo.Database($srv, "$CreateDB")
$db.Create()
$db.CreateDate
}
else
{
'Failed' | Out-File -FilePath c:\sqltest.log -Encoding ASCII
}
Above script for named SQL instance throws below error :
New-Object : Exception calling ".ctor" with "2" argument(s): "SetParent failed for Database 'Netmagic-Test'. "
At C:\mssql-test.ps1:11 char:7
+ $db = New-Object Microsoft.SqlServer.Management.Smo.Database($srv, "$CreateDB")
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [New-Object], MethodInvocationException
+ FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.PowerShell.Commands.NewObjectCommand
You cannot call a method on a null-valued expression.
At C:\mssql-test.ps1:12 char:1
+ $db.Create()
+ ~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
Error Screen
Thanks,
Viral

Related

Powershell SQL Server stored procedure backup

I am trying to backup one particular stored procedure from a SQL Server database by passing parameters from a Python program. Here is the code that I have tried but I keep getting an error.
param([string]$server='dbsed0898', [string]$dbname='global_hub',[string]$sp='dbo.gs_eligibility')
[System.Reflection.Assembly]::LoadWithPartialName(“Microsoft.SqlServer.SMO”) | out-null
$SMOserver = 'Microsoft.SqlServer.Management.Smo' #-argumentlist $server
$srv = New-Object("$SMOserver.Server") $server
$db = $srv.databases[$dbname]
$Objects = $db.storedprocedures[$sp]
$scripter = new-object ("$SMOserver.Scripter") $srv
$Scripter.Script($Objects) | Out-File
" C:\Users\fthoma15\Documents\backup_03212020.sql"
$db = $SMOserver.databases[$dbname]
$Objects = $db.storedprocedures[$sp]
$Scripter.Script($Objects) | Out-File
"C:\Users\fthoma15\Documents\backup_03212020.sql"
Error:
Multiple ambiguous overloads found for "Script" and the argument count: "1".
At line:12 char:5
+ $Scripter.Script($Objects) | Out-File "C:\Users\fthoma15\Document ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodException
+ FullyQualifiedErrorId : MethodCountCouldNotFindBest
Can someone help me?
Here is what i did.
param([string]$server='test', [string]$dbname='test',[string[]]$sp=('test','test'))
[System.Reflection.Assembly]::LoadWithPartialName(“Microsoft.SqlServer.SMO”) | out-
null
$SMOserver = new-object ("Microsoft.SqlServer.Management.Smo.Scripter") #-argumentlist
$server
$srv = new-Object Microsoft.SqlServer.Management.Smo.Server("$server")
$db = New-Object Microsoft.SqlServer.Management.Smo.Database
$db = $srv.Databases.Item("$dbname")
$Objects = $db.storedprocedures[$sp[1,3]]
$scripter = new-object ("$SMOserver") $srv
$Scripter.Script($Objects) | Out-File
"C:\Users\fthoma15\Documents\backup_03212020.sql"
As suggested by AlwaysLearning, i changed the sp variable to an array list,splitting both schema and sp name.

Issue with Powershell SMO SQL Server restore

I am running into an issue with doing a Powershell SQL restore. I have this code
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO") | Out-Null
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SmoExtended") | Out-Null
[Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.ConnectionInfo") | Out-Null
[Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SmoEnum") | Out-Null
$backupFile = 'C:\Temp\User_20191029152532.bak'
$server = New-Object ("Microsoft.SqlServer.Management.Smo.Server") "(local)"
$backupDevice = New-Object("Microsoft.SqlServer.Management.Smo.BackupDeviceItem") ($backupFile, "File")
$smoRestore = new-object("Microsoft.SqlServer.Management.Smo.Restore")
$smoRestore.NoRecovery = $false;
$smoRestore.ReplaceDatabase = $true;
$smoRestore.Action = "Database"
$smoRestorePercentCompleteNotification = 10;
$smoRestore.Devices.Add($backupDevice)
$smoRestoreDetails = $smoRestore.ReadBackupHeader($server)
"Database Name from Backup Header : " +$smoRestoreDetails.Rows[0]["DatabaseName"]
$smoRestore.Database =$smoRestoreDetails.Rows[0]["DatabaseName"]
$smoRestoreFile = New-Object("Microsoft.SqlServer.Management.Smo.RelocateFile")
$smoRestoreLog = New-Object("Microsoft.SqlServer.Management.Smo.RelocateFile")
$smoRestoreFile.LogicalFileName = $smoRestoreDetails.Rows[0]["DatabaseName"]
$smoRestoreFile.PhysicalFileName = $server.Information.MasterDBPath + "\" + $smoRestore.Database + "_Data.mdf"
$smoRestoreLog.LogicalFileName = $smoRestoreDetails.Rows[0]["DatabaseName"] + "_Log"
$smoRestoreLog.PhysicalFileName = $server.Information.MasterDBLogPath + "\" + $smoRestore.Database + "_Log.ldf"
$smoRestore.RelocateFiles.Add($smoRestoreFile)
$smoRestore.RelocateFiles.Add($smoRestoreLog)
$smoRestore.SqlRestore($server)
Everything works fine if I run this. However, I would like to provide a variable for which backup to restore. So I changed the top part of the code to this:
$path = 'C:\Temp'
$db_name = 'User'
$file = Get-ChildItem $path '*.bak' | Select-Object basename | Where-Object {$_.basename -like $db_name + '*' }
$backupFile = $path + '\' + $file
When I make this change, I start getting the below error.
Exception calling "ReadBackupHeader" with "1" argument(s): "An exception occurred while executing a Transact-SQL statement or batch."
At line:23 char:1
+ $smoRestoreDetails = $smoRestore.ReadBackupHeader($server)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : ExecutionFailureException
Not really sure why it will not accept the $file variable that I am passing. If I look at the variable, it is returning the right value.
Stupid issue on my part. $file did not include the extension. Adding the .bak to $file fixed the issue.

Failed to create SQL script transfer with powershell

I've got next error when I'm trying to create database script:
Exception calling "EnumScriptTransfer" with "0" argument(s): "Script
transfer failed. " At C:\temp\Test.ps1:126 char:5
+ $transfer.EnumScriptTransfer();
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : FailedOperationException
Same script is working properly on the other computer. So I assume that the reason is in SQL server version, or rights.
Any ideas?
Code:
echo "Scripting database $dbname .."
set-psdebug -strict
$ErrorActionPreference = "stop" # you can opt to stagger on, bleeding, if an error occurs
# Load SMO assembly, and if we're running SQL 2008 DLLs load the SMOExtended and SQLWMIManagement libraries
$ms='Microsoft.SqlServer'
$v = [System.Reflection.Assembly]::LoadWithPartialName( "$ms.SMO")
$ver = (($v.FullName.Split(','))[1].Split('='))[1];
$vtmp=$ver.Split('.')[0];
echo " SMO version is $ver"
if ($vtmp -ge 9) {
echo " Running SQL 2008, load the SMOExtended .."
[System.Reflection.Assembly]::LoadWithPartialName("$ms.SMOExtended") | out-null
}
$My="$ms.Management.Smo" #
$s = new-object ("$My.Server") $DataSource
if ($s.Version -eq $null ){Throw "Can't find the instance $Datasource"}
$ver = $s.Version
echo " SQL Server version is $ver"
$db= $s.Databases[$Database]
if ($db.name -ne $Database){Throw "Can't find the database '$Database' in $Datasource"};
$transfer = new-object ("$My.Transfer") $db
if ($transfer -eq $null ){Throw "Can't create transfer object"}
$transfer.Options.ScriptBatchTerminator = $true # this only goes to the file
$transfer.Options.ToFileOnly = $true # this only goes to the file
$transfer.Options.ScriptData = $true;
$transfer.Options.FileName = $BackupFile;
$tmp = $transfer.Options
echo " Transfer options are: $tmp"
echo " $transfer"
$transfer.EnumScriptTransfer();
Output:
Scripting database MyDbName ..
SMO version is 14.0.0.0
SQL Server version is 14.0.1000
Transfer options are: ScriptingOptions: ScriptBatchTerminator, ToFileOnly, SchemaQualify, WithDependencies, AllowSystem
Objects, AgentJobId, NoVardecimal, ScriptSchema, ScriptData, ScriptDataCompression, PrimaryObject
Microsoft.SqlServer.Management.Smo.Transfer
Exception calling "EnumScriptTransfer" with "0" argument(s): "Script transfer failed. "
At C:\temp\Test.ps1:126 char:5
+ $transfer.EnumScriptTransfer();
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : FailedOperationException
Tried to add try-catch block, but this does not work. No idea why:
Try
{
$transfer.EnumScriptTransfer();
}
Catch
{
$msg = $_.Exception.Message;
$innerMsg = $_.Exception.InnerException.Message;
echo $msg
echo $innerMsg
throw;
}

Can connect to SQL Server from SSMS from other computer but Can't connect to SQL Server in a network from powershell

i am trying to connect to a sql server from powershell and getting this error
Exception calling "Open" with "0" argument(s): "The target principal
name is incorrect. Cannot generate SSPI context." At
C:\Users\Musawwir\Downloads\remotely access db.ps1:10 char:1
+ $Connection.Open()
+ ~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: ( [], MethodInvocationException
+ FullyQualifiedErrorId : SqlException Exception calling "Fill" with "1" argument(s):
I can connect to SQL SERVER from other machines through SSMS but can not connect through powershell, also the script runs fine on local machine.
Here is the code i am using :
[string] $Server= "tcp:DESKTOP-J9UQ90E,1433"
[string] $Database = "Eshop"
[string] $SQLQuery= "[dbo].[usp_getCustomerAge]"
$Connection = New-Object System.Data.SQLClient.SQLConnection
$Connection.ConnectionString = "server='$Server';database='$Database';Connection Timeout=300;Integrated Security=TRUE;UID=ali;PWD=1234"
$Connection.Open()
$Command = New-Object System.Data.SQLClient.SQLCommand
$Command.Connection = $Connection
$Command.CommandText = $SQLQuery
$Command.CommandTimeout=500
$adp = New-Object System.Data.SqlClient.SqlDataAdapter $Command
$data = New-Object System.Data.DataSet
$adp.Fill($data) | Out-Null
$data2 = ''
$emp = ''
foreach($Row in $data.Tables.Rows){
[string]$C_name = $Row[0]
$C_name
$data2= $data2+ "|"+$C_name
$C_name = $C_name+"|"
$C_name | out-file "d:\\test4.txt" -Append
}
$Connection.Close()
#$data2 | out-file "d:\\test4.txt"
The user ali wasn't having access to stored procedure .. changed user from ali to sa and integrated security to false solved the problem

Using Invoke-Command to Get Application Pools on Remote Servers

I'm attempting to use Invoke-Command to get a list of application pools on multiple remote servers. So far I have something like:
$servers = Get-Content -Path "C:\Path\to\servers.txt"
$array = New-Object -TypeName 'System.Collections.ArrayList'
foreach ($server in $servers) {
Invoke-Command -ComputerName $server -ScriptBlock {
Import-Module WebAdministration
$sites = Get-ChildItem IIS:\sites
foreach ($site in $sites) {
$array.Add($site.bindings)}}}
However I get the error:
You cannot call a method on a null-valued expression.
+ CategoryInfo : InvalidOperation: (Add:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
+ PSComputerName : computername
I've tried using regular arrays instead of ArrayLists and I get the following error:
Method invocation failed because [Microsoft.IIs.PowerShell.Framework.ConfigurationElement] doesn't contain a method named 'op_Addition'.
+ CategoryInfo : InvalidOperation: (op_Addition:String) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
+ PSComputerName : computername
Can anyone help point me in the right direction?
Your object $arrayis not known on your remote servers. So, one proposition is to send your array to the remote server, then add some values and return it :
$servers = Get-Content -Path "C:\Path\to\servers.txt"
$array = New-Object -TypeName 'System.Collections.ArrayList'
foreach ($server in $servers) {
$array = Invoke-Command -ComputerName $server -ScriptBlock {
param($array)
Import-Module WebAdministration
$sites = Get-ChildItem IIS:\sites
foreach ($site in $sites) {
[void]($array.Add($site.bindings))
}
$array
} -ArgumentList $array
}

Resources