Get-ClusterGroup and foreach using imported SQL table - sql-server

I am looking at getting information from a number of servers i.e. clustername, nodename, and state.
I can get the correct ouput when I hardcode the names into a foreach loop like this:
$clusters = "Cluster1", "Cluster2"
foreach ($cluster in $clusters) {
Get-ClusterGroup -Cluster $cluster
}
but when I run this version that pulls the information from a SQL table its coming up with the below error.
$clusters = $SQLServer = "DatawarehouseServer" #use Server\Instance for named SQL instances!
$SQLDBName = "Datawarehouse"
$SqlQuery = "SELECT clusters FROM dbo.clusters"
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "Server=$SQLServer;Database=$SQLDBName;Integrated Security=True"
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.CommandText = $SqlQuery
$SqlCmd.Connection = $SqlConnection
$SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
$SqlAdapter.SelectCommand = $SqlCmd
$DataSet = New-Object System.Data.DataSet
$SqlAdapter.Fill($DataSet)
$SqlConnection.Close()
clear
$DataSet.Tables[0]
foreach ($cluster in $clusters) {
Get-ClusterGroup -Cluster $cluster
}
WARNING: If you are running Windows PowerShell remotely, note that some failover
clustering cmdlets do not work remotely. When possible, run the cmdlet locally
and specify a remote computer as the target. To run the cmdlet remotely, try
using the Credential Security Service Provider (CredSSP). All additional errors
or warnings from this cmdlet might be caused by running it remotely.
Get-ClusterGroup : The cluster service is not running. Make sure that the
service is running on all nodes in the cluster. There are no more endpoints
available from the endpoint mapper
At line:26 char:2
+ {Get-ClusterGroup -Cluster $cluster}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ConnectionError: (:) [Get-ClusterGroup], ClusterCmdletException
+ FullyQualifiedErrorId : ClusterEndpointNotRegistered,Microsoft.FailoverClusters.PowerShell.GetClusterGroupCommand.
I have now been trying this I seem to be getting step closer or a step back depedant on how you look at it. It pulls the correct information out now but for only one cluster:
Thanks to the comments I have managed to get a step further or a step backwards with this:
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "Server=Datawarehouseserver;Database=Datawarehouse;Integrated Security=True"
$SqlConnection.Open()
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.CommandText = "SELECT clusters FROM dbo.clusters"
$SqlCmd.Connection = $SqlConnection
$clustername = $SqlCmd.ExecuteScalar()
$SqlConnection.Close()
#Write-Output "Cluster is " $dbname
clear
foreach ($cluster in $clustername) {
Get-ClusterGroup -Cluster $cluster
}

You need to iterate over the cluster names returned by your SQL query, but your variable $cluster is never assigned that list of names. Use this instead:
foreach ($cluster in $DataSet.Tables[0].clusters) {
...
}

Related

Format Powershell SQL query to print all items in columns

I am using this style of sql connection and want to output the data into a table format but am only getting back the number of items. Having issues installing invoke-sql on old server not sure what the deal is... If any suggestions that would be great, for users that are stuck invoking sql like this :)
$user = "user"
$pwd = "password"
$SQLDBNAME = "database"
$SQLServer = ".\SQLEXPRESS"
$TagTable = "TagTable"
$sqlQuery = "SELECT TOP (10) [TagName] FROM [FactoryTalk_Datalog].[dbo].[TagTable]"
$sqlConnection = New-Object System.Data.SqlClient.SqlConnection
$sqlConnection.ConnectionString = "Server=$SQLServer;Database=$SQLDBName;uid=$user;pwd=$pwd"
#Create and configure a command object
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.CommandText = $SqlQuery
$SqlCmd.Connection = $sqlConnection
#Create and configure a DataAdpater/DataSet pair of objects
$SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
$SqlAdapter.SelectCommand = $SqlCmd
$DataSet = New-Object System.Data.DataSet
#Fill Dataset with Data and close the connection to the database
$SqlAdapter.Fill($Dataset)
Write-Host $DataSet
#$DataSet | Export-Csv -Path "C:\Users\admin\Documents\sqlApplication" -NoTypeInformation -Force
$sqlConnection.Close()
This worked for me :) using .Tables wrote it out perfect.
#Fill Dataset with Data and close the connection to the database
$SqlAdapter.Fill($Dataset)
$DataSet.Tables | Format-Table
write-host $DataSet
#$DataSet | Export-Csv -Path "C:\Users\admin\Documents\sqlApplication" -NoTypeInformation -Force
$sqlConnection.Close()

Connecting to an SQL server using a different domain account

I am currently trying to connect to an SQL server using a different domain/username that has permissions for querying the server. Here is the powershell just to test whether or not the connection works,
$connectionString = "Server=<my_server>;Database=<db>;User ID=<domain>\<testuser>;Password=<password>;Trusted_Connection=False;Encrypt=True;TrustServerCertificate=True;";
$connection = New-Object System.Data.SqlClient.SqlConnection($connectionString);
$connection.Open();
$connection.Close();
I end up getting this error.
Exception calling "Open" with "0" argument(s): "Login failed for user '<testuser>'.
I am certain that the username and password is correct. As that's what's in the Client Settings.
But I am wondering if there's additional arguments needed to add to the connection string?
This task needed to be automated, but the solution was to connect to the server using -Credentials to login to the desired user.
$computerName = 'SQLServer'
$adminUsername = 'username'
$adminPassword = ConvertTo-SecureString 'password' -AsPlainText -Force
$adminCreds = New-Object PSCredential $adminUsername, $adminPassword
Invoke-Command -ScriptBlock {
$SQLServer = "sqlserver"
$SQLDBName = "database"
$uid ="account"
$pwd = "password"
$SqlQuery = "SELECT TOP (12) [attribute1]
FROM [table].[dbo].[AAG00200];"
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "Server = $SQLServer; Database = $SQLDBName; Integrated Security = True; User ID = $uid; Password = $pwd;"
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.CommandText = $SqlQuery
$SqlCmd.Connection = $SqlConnection
$SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
$SqlAdapter.SelectCommand = $SqlCmd
$DataSet = New-Object System.Data.DataSet
$SqlAdapter.Fill($DataSet)
} -ComputerName $computerName -Credential $adminCreds

MSSQl 'GO' handling in Powershell connection String

I have a sql query which is patched with a Go to check the orphan objects in mssql.
use DBName
go
sp_change_users_login 'report'
Now, I am automating the above in Powershell for all the user databases and trying to get the orphan users.
Here is the code:
if($port)
{
$connectionString ="server=$servername,$port;Integrated Security=true;" #uid=$DBUserName; pwd=$dbpwd;Database=$DB;
}
else
{
$connectionString ="server=$servername;Integrated Security=true;"
}
$connection = New-Object System.Data.SqlClient.SqlConnection -ea Stop
$connection.ConnectionString=$connectionString
$connection.Open()
$db_query = #"
Select name from sys.sysdatabases where dbid > 4 and name not in ('ReportServer')
"#
$command = $connection.CreateCommand()
$command.CommandText = $db_query
$result = $command.ExecuteReader()
$object= New-Object System.Data.DataTable
$object.Load($result)
[System.Array]$DBs = $object.name
if($DBs -is [System.Array])
{
foreach($DB in $DBs)
{
## PROBLEM IS HERE ###
$orphan_users_query = #"
use $DB
GO
sp_change_users_login 'report'
"#
$command = $connection.CreateCommand()
$command.CommandText = $orphan_users_query
$result = $command.ExecuteReader()
$object= New-Object System.Data.DataTable
$object.Load($result)
$object | Out-File C:\temp\outfile_property.txt -Append -Force
}
}
Problem is PS cannot identify the go separator because it is specific to MSSQL/SSMS. So, how can I still iterate and run the query in all user databases without creating multiple connections specific to each DB?
Calling ChangeDatabase on the connection is an alternate means of switching databases.
You can then just execute sp_change_users_login as is. No need for GO.

How to get the compatibility level of a database from analysis server?

I searched around and found there is a way to get compatibility level of a database in powershell through something like:
Import-Module SqlServer
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "Server=$Server;Initial Catalog=$DB;Integrated Security=SSPI"
$conn = new-object Microsoft.SqlServer.Management.Common.ServerConnection($sqlConnection)
$srv = new-object Microsoft.SqlServer.Management.Smo.Server($conn)
$db = New-Object Microsoft.SqlServer.Management.Smo.Database
$db = $srv.Databases.Item("$DB")
$comp_lvl = New-Object Microsoft.SqlServer.Management.Smo.CompatibilityLevel
$comp_lvl = $db.CompatiblityLevel
Write-Host "Compatibility level =" $db.CompatibilityLevel
However, I am getting errors trying to get compatibility level of a database that is on an analysis server
Exception getting "Item": "Failed to connect to server ..."
I realized it is probably working for a regular database engine, but something else may be used for an analysis server. I looked around on MS Docs and didnt really find anything helpful.
SO is this even possible?
UPDATE:
I was able to find something on this page: https://technet.microsoft.com/en-us/hh213141(v=sql.100)
Import-Module SqlServer
$as = New-Object Microsoft.AnalysisServices.Server
$as.connect("$Server")
$as.databases
Write-Host "Compatibility level ="$as.DefaultCompatibilityLevel
but this returns ALL databases back...
I want to specify just one database to get the compatibility level of...
I tried this,
$as.databases["$Database"]
but it seems not to return the proper level, because the DB i am passing has a lvl of 1103, not 1200...
I figured it out!
Import-Module SqlServer
$as = New-Object Microsoft.AnalysisServices.Server
$as.connect("$Server")
$c = $as.Databases | Where-Object { $_.ID -eq $Database }
Write-Host "Compatibility level =" $c.CompatibilityLevel

Calling stored procedure using powershell

i am trying to call a stored procedure from powershell by running the following. The name of the stored procedure is sp_sample (residing in ssms). But i am not able to see any output for the code in powershell and neither is the procedure getting triggered. Could someone please correct it.
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "Server=LABVM-
40\RTC;Database=testDB;Integrated Security=True"
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.CommandText ="sp_sample"
$SqlCmd.Connection = $SqlConnection
$sqlConnection.Open()
$Result = $SqlCmd.ExecuteNonQuery()
$sqlConnection.Close()
PS: I dont have knowledge on powershell and i picked the above code from the internet.
Invoke-Sqlcmd -ServerInstance "ServerName" -database "DatabaseName" -Query "EXEC dbo.sp_sample"

Resources