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.
Related
We are trying to replace a backup location in a SQL Backup Jobs step (running power shell through several servers)
Below is a PS script i would like to use it:
# $Server is a file with SERVERNAME names
$Jobs = Get-SQLAgentJob -ServerInstance
$Servers Foreach ($job in $Jobs.Where{$_.Name -like 'DatabaseBackup' -and $_.isenabled -eq $true}) {
foreach ($Step in $Job.jobsteps.Where{$_.Name -like 'DatabaseBackup'}) {
$Step.Command = $Step.Command.Replace("Directory = N'C:\Backup\oldname1\oldname2\SERVERNAME'", "Directory = N'C:\Backup2\newname1\newname2\SERVERNAME'")
$Step.Alter()
}
}
It seems like this should work. The only potential problems I see are the following:
named SQL instances: The $servers variable will need to have the servername\instancename format if not using the default instance name
Job and step names: If your job names and job step names are not exactly databasebackup, case excluded, then the -like operator combined with the exact string will not find a match. If the names contain the databasebackup string, you will be safer to use -match "databasebackup" or -like with asterisks on both sides of the string.
Otherwise, this code should just work provided there are not network connectivity or permissions issues.
I need database counts for every SQL server instance (PROD/Non PROD) in an environment.
If I logged into each and every SQL Server then it is very tedious task for me, so I need to automate it.
Is there any t-sql or powershell script from which I can get consolidated report for database counts for all servers at one place.
You can use Azure Functions with Timer schedule to automate what you want.
https://learn.microsoft.com/en-us/azure/azure-functions/functions-bindings-timer
And you can use stored procedures with azure functions.
Take a look at the SqlServer module documentation, specifically the Get-SqlDatabase cmdlet. You can import your server names from a file or define them in an array and then iterate through them.
#get your credential
$credentials = get-credential
#read server names from a file
$servers = get-content "C:\Some\Path\servers.txt"
#use calculated properties
$servers | select-object `
#{Name='ServerName';Expression={$_}},
#{Name='DatabaseCount';Expression={
#force to array to ensure .count exists
#(Get-SqlInstance -MachineName $_ -Credential $credential | Get-SqlDatabase).Count
}}
If you are unable to install the SqlServer module you can do it with the SMO
#load the assembly
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO")
#read server names from a file
$servers = get-content "C:\Some\Path\servers.txt"
#use calculated properties
$servers | select-object `
#{Name='ServerName';Expression={$_}},
#{Name='DatabaseCount';Expression={
(New-Object Microsoft.SqlServer.Management.SMO.Server $_).Databases.Count
}}
Output:
ServerName DatabaseCount
---------- -------------
ServerOne 12
ServerTwo 22
ServerThree 6
Note that there is no error checking and I am assuming that you are running in a context that has rights to the server and DB engine.
Strictly speaking, the question is, I use this solution and it works, but is there a better way?
With the following caveats.
1) I don't want to do a network wide search for SQL instances, I am interrogating known SQL servers, but I want to grab the instance names on each.
2) The code assumes Microsoft will never change the display name for the SQL Server Service.
function getSQLInstance ([string]$SERVER) {
$services = Get-Service -Computer $SERVER
# Filter for SQL services
$services = $services | ? DisplayName -like "SQL Server (*)"
# Remove MSSQL$ qualifier to get instance name
try {
$instances = $services.Name | ForEach-Object {($_).Replace("MSSQL`$","")}
}catch{
# Error if none found
return -1
}
return $instances
}
getSQLInstance "YOUR_SERVER"
Rather than re-invent the wheel, take a look at how SQL Power Doc discovers instances on a server. Which, from looking at NetworkScan.psm1, appears to be very similar to your approach:
$ManagedComputer.Services | ForEach-Object {
if (($_.Name).IndexOf('$') -gt 0) {
$InstanceName = ($_.Name).Substring(($_.Name).IndexOf('$') + 1)
$IsNamedInstance = $true
$ManagedComputerServerInstanceName = $InstanceName
} else {
$InstanceName = $null
$IsNamedInstance = $false
$ManagedComputerServerInstanceName = $_.Name
}
Or, just use SQL Power Doc and point it at specific server names to collect this and more data about the instances.
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
I would like to add a bunch of SQL (mixture of 2000-2005) server instances on different servers to my SSMS (SQL Managment Studio) Registered servers, I was following this tutorial here but this only adds one server at a time not all at the same time.
The list is currently in Excel but can be imported to notepad or any other document format as long as it can be recognized by the PowerShell command. Also, another thing to note is where can i change the login to use sql authentication? and specify username and password?
New-Item $(Encode-Sqlname "SERVERNAME\INSTANCENAME") -itemtype registration -Value “server=MyServer;integrated security=true”
tks
ERROR
New-Object : Cannot convert argument "1", with value: "", for "PSCredential" to
type "System.Security.SecureString": "Cannot convert the "" value of type "Sys
tem.String" to type "System.Security.SecureString"."
At line:4 char:32
+ -Credential (New-Object <<<< System.Management.Automation.PSCredenti
al("sa", "")) }
+ CategoryInfo : InvalidOperation: (:) [New-Object], MethodExcept
ion
+ FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.Power
Shell.Commands.NewObjectCommand
If you save the Excel spreadsheet as a CSV file, you can easily import it in PowerShell using the Import-Csv cmdlet and automatically register the servers in the list by their names.
Assuming your CSV file looks like this:
|Name |
|Server1 |
|Server2 |
|Server3 |
The following command will import its content as a list of objects, one for each row in the CSV file, all having a Name property, which contains the actual value. Those names are then used within the string passed to the New-Item cmdlet to actually do the registration:
Import-Csv ServersToRegister.csv | ForEach-Object { `
New-Item $(Encode-Sqlname $_.Name) -ItemType Registration `
-Value ("server=$($_.Name);integrated security=true") }
You can specify the username and password to use to connect to the SQL Server instance by passing a PSCredential object to the New-Item cmdlet. So the complete command would be:
Import-Csv ServersToRegister.csv | ForEach-Object { `
New-Item $(Encode-Sqlname $_.Name) -ItemType Registration `
-Value ("server=$($_.Name);integrated security=true") `
-Credential (New-Object System.Management.Automation.PSCredential("username", "password")) }