How can I get version Information for multiple computers? -Powershell - sql-server

I am trying to write a script to determine whether or not a server is running MSSQLSERVER or MSSQL$* (some instance of SQL Server) by going through a text file of server names separated by a new line. The code works for the first server and outputs the correct version and engine edition, but for all of the other servers it will only tell me whether or not they running SQL Server, and not output the version and engine edition. What am I doing wrong?
Thanks in advance for any and all help!
Clear-Host
$Name1 = "MSSQLSERVER"
$Name2 = "MSSQL$*"
$computers = Get-Content "E:\computers.txt"
$saveAs = 'E:\SQL_Report.txt'
foreach ($computer in $computers) {
try{
$Service1 = Invoke-Command -ComputerName $computer {Get-Service MSSQLSERVER}
$Service2 = Invoke-Command -ComputerName $computer {Get-Service MSSQL$*}
if($Service1 -Match $Name1 -Or $Service2 -Match $Name2){
"$computer Running MSSQL"
[reflection.assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo") | out-null
$srv = New-Object "Microsoft.SqlServer.Management.Smo.Server" "$computer"
$srv.Version
$srv.EngineEdition
}
else{
"$computer Not running MSSQL"
}
}
catch{
"$computer, Not Accessable, $_"
continue
}
}
Here is an example of current output:
Database_name1 Running SQL Server
Major Minor Build Revision
10 50 6220 -1
EnterpriseOrDeveloper
Database_name2 Not running SQL Server
Cannot find any service with service name 'MSSQLSERVER'.
+ CategoryInfo : ObjectNotFound: (MSSQLSERVER:String) [Get-Service], ServiceCommandException
+ FullyQualifiedErrorId : NoServiceFoundForGivenName,Microsoft.PowerShell.Commands.GetServiceCommand
Database_name3 Running SQL Server
Cannot find any service with service name 'MSSQLSERVER'.
+ CategoryInfo : ObjectNotFound: (MSSQLSERVER:String) [Get-Service], ServiceCommandException
+ FullyQualifiedErrorId : NoServiceFoundForGivenName,Microsoft.PowerShell.Commands.GetServiceCommand

Related

Invoke-Sqlcmd error in Loop, No error once?

If I run this .ps1 script-
$secID = Invoke-Sqlcmd -ServerInstance "MyDBServer" -Database "MyDataBase"-Query "SELECT SysID FROM dbo.SecurityLevels WHERE LEVELNAME LIKE '%User%';"
Write-Host "MyDataBase"
Write-Host $secID.SysID
I get the following on the console with no error -
MyDataBase
18
However if I try this same query in a for loop in a larger script -
$dbservers = #('DataBaseServer1', 'DataBaseServer2')
foreach ($dbserver in $dbservers)
{
$databases = Get-SqlDatabase -ServerInstance $dbserver | Where-Object { $_.Name -Match '\d{3,4}' -and $_.Name -notlike '*test*'}
foreach ($database in $databases)
{
$secID = Invoke-Sqlcmd -ServerInstance $dbserver.Name -Database $database.Name -Query "SELECT SysID FROM dbo.SecurityLevels WHERE LEVELNAME LIKE '%User%';"
Write-Host $database.Name
Write-Host $secID.SysID
}
}
I get the correct query result but errors preceding it on the console -
Invoke-Sqlcmd : A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that
the instance name is correct and that SQL Server is configured to allow remote connections. (provider: Named Pipes Provider, error: 40 - Could not open a connection to SQL Server)
At \SQL.ps1:28 char:13
+ ... $secID = Invoke-Sqlcmd -ConnectionString $ConnectionString -Query ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Invoke-Sqlcmd], SqlException
+ FullyQualifiedErrorId : SqlExceptionError,Microsoft.SqlServer.Management.PowerShell.GetScriptCommand
Invoke-Sqlcmd :
At \SQL.ps1:28 char:13
+ ... $secID = Invoke-Sqlcmd -ConnectionString $ConnectionString -Query ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ParserError: (:) [Invoke-Sqlcmd], ParserException
+ FullyQualifiedErrorId : ExecutionFailureException,Microsoft.SqlServer.Management.PowerShell.GetScriptCommand*
MyDataBase
18
Why do I get errors when running it in the loop versus running it one time? Also why does the query work even though I get an error? I think I am missing something any help would be greatly appreciated!
I think its because you are calling property Name on a String, effectively returning nothing. try this (I just deleted the calling of the property $dbserver.Nameto $dbserver):
$dbservers = #('DataBaseServer1', 'DataBaseServer2')
foreach ($dbserver in $dbservers)
{
$databases = Get-SqlDatabase -ServerInstance $dbserver | Where-Object { $_.Name -Match '\d{3,4}' -and $_.Name -notlike '*test*'}
foreach ($database in $databases)
{
$secID = Invoke-Sqlcmd -ServerInstance $dbserver -Database $database.Name -Query "SELECT SysID FROM dbo.SecurityLevels WHERE LEVELNAME LIKE '%User%';"
Write-Host $database.Name
Write-Host $secID.SysID
}
}
The error must be because its looking for a DB instance "" and it doesn't find it, and the query might still go though because the the first server might not have an instance, or because those values were already loaded into the properties from before. But I'm just speculating, haven't really used this cmdlets.
PS: if you want to avoid calling empty properties add Set-StrictMode -Version 2 to your script, example:
PS > $text = "This is just a string"
PS > $text.AnyProperty
PS > Set-StrictMode -Version 2
PS > $text.AnyProperty
The property 'AnyProperty' cannot be found on this object. Verify that the property exists.
At line:1 char:1
+ $text.AnyProperty
+ ~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], PropertyNotFoundException
+ FullyQualifiedErrorId : PropertyNotFoundStrict
Hope it helps.

Error thrown while taking backup of SQL Server content database using PowerShell

I am trying to take a backup of SQL Server content database using PowerShell.
Here is my code:
$dt = Get-Date -Format yyyyMMddHHmmss
$null =
[Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo");
$srvrvinstancename= "srvr-04\mssqlserver1"
$svr = New-Object
Microsoft.SqlServer.Management.Smo.Server($srvrvinstancename);
#Write-Output $svr WSS_Content_2d426b353ded49aa8ace920d4178c298
$bdir = "C:"
$svnm = $svr.Name
$db =
$svr.Databases['WSS_Content_2d426b353ded49aa8ace920d4178c298']
$dbname = $db.Name
$dt = get-date -format yyyyMMddHHmmss
$bfil = "$bdir\$($dbname)_db_$($dt).bak"
Backup-SqlDatabase -ServerInstance $svnm -Database $dbname -
BackupFile $bfil
but when I run the code I get the error:
Backup-SqlDatabase : The 'Backup-SqlDatabase' command was found in the module 'SQLPS', but the module could not be loaded. For more information, run 'Import-Module SQLPS'.
At line:19 char:1
+ Backup-SqlDatabase -ServerInstance $svnm -Database $dbname -BackupFile $bfil
+ ~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Backup-SqlDatabase:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CouldNotAutoloadMatchingModule
After that, I ran
import-module sqlps
But this also ran into error state:
Import-Module : File C:\Program Files (x86)\Microsoft SQL Server\110\Tools\PowerShell\Modules\SQLPS\Sqlps.ps1 cannot be loaded because running scripts is disabled on this system.
For more information, see about_Execution_Policies at http://go.microsoft.com/fwlink/?LinkID=135170.
At line:1 char:1
+ Import-Module SQLPS
+ ~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : SecurityError: (:) [Import-Module], PSSecurityException
+ FullyQualifiedErrorId : UnauthorizedAccess,Microsoft.PowerShell.Commands.ImportModuleCommand
What am I doing wrong?
I think you need to load a couple off Assembly:
# Load SQL server assemblies
#
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO") | Out-Null
# SmoExtended
#
[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
UPDATE.
For scripts which can't be executed you need to do (as administrator in Powershell)
Set-ExecutionPolicy remotesigned

Error "You cannot call a method on a null-valued expression." while taking backup of SQL Files

I want to take backup of a few user databases on SQL Server 2008 R2.
I am running the following script on Powershell v2.0.
#load SQL snap-in
Add-pssnapin SqlServerCmdletSnapin100
Add-pssnapin SqlServerProviderSnapin100
#pull the current date
$date = Get-Date -Format yyyyddMM
#set location of backup files
$directory = "F:\sql\backup"
#Grab the database names
$dbname = dir 'SQLSERVER:\SQL\MyServer\DEFAULT\Databases\MyDataBase' | Select Name
#Backup each user database found.
$dbname | foreach { $_.Name.ToString() } | foreach {$bakfile = "$directory" + $_ + "_" + $date + ".bak";
"Backing up Database: $_"; Invoke-Sqlcmd -SuppressProviderContextWarning -Query
"BACKUP DATABASE $_ TO DISK=N'$bakfile' WITH INIT";
}
But this script shows me the following error in succession:
You cannot call a method on a null-valued expression.
At F:\sql\backup.ps1:40 char:21
+ $dbname | foreach { $_.Name.ToString() } | foreach {$bakfile = "$directory" + $_ ...
+ ~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
What exactly is this error?
Where is it occurring?
How to correct this?
what changes should I make if I want to save the backup
file in '.sql' form?
Is there any other simpler way?

Change DNS Search Order with Powershell with different settings on different server

Hi dear lord(s) of Powershell :)
I have 380 server to modify.
Some DNS server in forest and domain have changed and I need to change the Dns search order parameter.
If my server have following DNSsearchOrder : 172.xx.xx.1 I want to change to 172.xx.xx.2
If my server have following DNSsearchOrder : 172.xx.xx.1 AND 172.xx.xx.10 I want to change only the first IP to 172.xx.xx.2 and let the 2nd
etc etc (I Have 10dns server moving and they're used on different domain and server)
I retrieve all my server export to CSV file with the following command :
Import-csv "C:\Julien\Script\CheckNchangeRegKeyValue\listOfcomputerOS_OK.csv" -Delimiter ";" |
Foreach-object{
$ServerToAnalyse=$_.Server
Get-WmiObject Win32_NetworkAdapterConfiguration -Filter "ipenabled='true'" -ComputerName $ServerToAnalyse |Where-Object {$_.DNSServerSearchOrder -ne $null}| Where-Object {$_.DNSServerSearchOrder -ine "127.0.0.1"} |`
select DNSHostName,#{Name="DNSParam"; Expression={$(($_.DNSServerSearchOrder))}},MACAddress,description,caption,index
} | Export-csv "C:\Julien\Script\CheckNchangeRegKeyValue\ListOfDNSSettingsAndHostName.csv" -notypeinformation -delimiter ";"
first file is a csv contain data like that :
"Caption";"Server"
"Microsoft(R) Windows(R) Server 2003, Standard Edition";"d0001doi.Mydomain.com"
"Microsoft(R) Windows(R) Server 2003, Standard Edition";"d0001ira.Mydomain.com"
"Microsoft Windows Server 2008 R2 Standard ";"D0005DLF.Mydomain.com"
"Microsoft(R) Windows(R) Server 2003, Standard Edition";"d0001ath.Mydomain.com"
"Microsoft Windows Server 2008 R2 Enterprise ";"D0002TEH.Mydomain.com"
"Microsoft Windows Server 2008 R2 Standard ";"D0003MAD.Mydomain.com"
The output CSV is like that :
"DNSHostName";"DNSParam";"MACAddress";"description";"caption";"index"
"v1068bel";"172.19.1.3";"xx:xx:xx:xx:xx";"VMware Accelerated AMD PCNet Adapter";"[00000010] VMware Accelerated AMD PCNet Adapter";"10"
The output file contain the actual settings and my idea is to modify this file with the following command to use this output file to modify the settings of my server :
[io.file]::readalltext("C:\Julien\Script\CheckNchangeRegKeyValue\ListOfDNSSettingsAndHostName.csv").replace("172.19.1.1","172.19.16.211").replace("172.18.37.8","172.19.17.52").replace("172.19.1.5","172.19.16.211").replace("172.19.1.3","172.19.16.28").replace("172.18.37.4","172.19.16.28").replace("172.19.1.6","172.19.16.27").replace(" ",",") | Out-File "C:\Julien\Script\CheckNchangeRegKeyValue\ListOfDNSSettingsAndHostName.csv" -Encoding ascii –Force
After this modification I try to use the following command :
Import-Csv "C:\Julien\Script\CheckNchangeRegKeyValue\ListOfDNSSettingsAndHostName.csv" -Delimiter ";" |
ForEach-Object{
$Server=$_.DNSHostName
$DNS=$_.DNSParam
$DNS=$DNS -replace "$DNS","`"$DNS`""
$DNS=($DNS -replace ",","`",`"")#.tostring()
$DNSIP=#("$DNS")
#$DNS=#($DNS)
#$DNS.GetType().fullname
#= New-Object System.Object
Write-Host "settings to put : $DNS"
(Get-WmiObject Win32_NetworkAdapterConfiguration -ComputerName $server).SetDNSServerSearchOrder(("$DNSIP"))#|Out-Null
$ActualDNS = (Get-WmiObject Win32_NetworkAdapterConfiguration -ComputerName $server)|Where-Object {$_.DNSServerSearchOrder -ne $null}| Where-Object {$_.DNSServerSearchOrder -ine "127.0.0.1"} |select #{Name="actualSettings"; Expression={$(($_.DNSServerSearchOrder))}}
Write-Host "actual settings $ACtualDNS"
}
If I put manually SetDNSServerSearchOrder((“198.102.234.125",”198.102.234.126")) instead of .SetDNSServerSearchOrder(("$DNSIP"))
it's working
but with $dnsip variable the result is 70 (bad IP address)
__GENUS : 2
__CLASS : __PARAMETERS
__SUPERCLASS :
__DYNASTY : __PARAMETERS
__RELPATH :
__PROPERTY_COUNT : 1
__DERIVATION : {}
__SERVER :
__NAMESPACE :
__PATH :
ReturnValue : 70
PSComputerName :
actual settings #{actualSettings=172.19.1.1}
anyone can help me ?
Thanks a lot
Regards
Julien
According to this article you really need a string array so you should replace $DNSIP=#("$DNS") by $DNSIP.split(',').
Explanation : when you write “198.102.234.125",”198.102.234.126" you create an array, because in PowerShell , is the array operator. $DNSIP=#("$DNS") just create an array of one string which is not an IP address.

How to get SQL Server Management Studio tab messages in PowerShell?

With Powershell, I execute a SQL script which returns a generated script in the tab "Messages" of SQL Server Management Studio. But I can't get it in PowerShell.
When I do this :
$ps = [PowerShell]::Create()
[ref]$e = New-Object System.Management.Automation.Runspaces.PSSnapInException
$ps.Runspace.RunspaceConfiguration.AddPSSnapIn( "SqlServerCmdletSnapin100", $e ) | Out-Null
$ps.AddCommand( "Invoke-Sqlcmd" ).AddParameter( "ServerInstance", "localhost").AddParameter( "Database", "MyDatabase").AddParameter("InputFile", "D:\MyScript.sql").AddParameter("Verbose")
$ps.Invoke()
$ps.Streams
$ps.Streams.Verbose | % { $_.Message | Out-File -Append D:\SqlLog.txt }
I get this error :
PS D:\NEMO\Scripts\Database> $ps.Invoke()
Exception calling "Invoke" with "0" argument(s): "Object reference not set to an instance of an object."
At line:1 char:11
+ $ps.Invoke <<<< ()
+ CategoryInfo : NotSpecified: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : DotNetMethodException
Thank you for your help.
So make Powershell to output messages is not that simple and it works only in command-line i think. Try this
write-host $line
Start-Transcript $outputfilepath
$ScriptParams = "DatabaseName=$line" "
Invoke-Sqlcmd -ServerInstance $SQLInstance -Username $SQLAdminUser -Password $SQLAdminPwd -InputFile "D:\File.sql" -verbose -Variable $ScriptParams
Stop-Transcript

Resources