donderdag 24 maart 2011

scanning sql instances on your network

Andre Kamman posted a powershell script on how to scan your network for instances of sqlserver, it gives back the edition and version installed and can be found here.
Robert Hartskeerl changed it to his likings also, which can be found here.

Based on these 2 versions we changed the script to our needs also a bit, also we cheated a little by using quest tools.
Below the prerequirements and steps to run our version.

  • Install .net framework 4.0
  • Register 4.0 by adding 2 configfiles (powershell_ise.exe.config and powershell.exe.config) in the powershell folder, if not already there, usually in folder ..\WINDOWS\system32\windowspowershell\v1.0\.
    Add the 4.0 reference to these config files. (check google for details if needed)
  • Install the quest activeroles tooling, which can be found here.
    Our script still uses a textfile with all the names from computers present in the network/domain.
  • Create this textfile by running the below code, first line needs to run also if the quest tooling wasn't previously loaded.
#add-PSSnapin quest.activeroles.admanagement $FilePath = "d:\tmp\computers.csv" $Computers = Get-QADComputer -searchroot 'DC=domainname,DC=nl' -SizeLimit 0 -OSName 'Windows*' $Computers | Select-Object Name | Export-Csv $FilePath
  • Open the newly created textfile and delete the first line with all the column info, also remove the "" quotes from all the computernames.
  • Almost there, now run the real script which scans the network, see below.
Props goes to my colleague Paul Woudwijk who added some code to this script (pong function) which makes sure this script skips offline computers.
Also his aura usually makes this stuff work faster also.
#add-PSSnapin quest.activeroles.admanagement
$Count = 0
$Count2 = 0
$instances2 = @()
$Computers = Get-Content D:\tmp\Powdershell\computers.csv
$FilePath2 = "D:\tmp\Powdershell\result3.csv"

function Pong{
Param([string]$srv,$port=135,$timeout=100,[switch]$verbose)
$ErrorActionPreference = "SilentlyContinue"
$tcpclient = new-Object system.Net.Sockets.TcpClient
$iar = $tcpclient.BeginConnect($srv,$port,$null,$null)
$wait = $iar.AsyncWaitHandle.WaitOne($timeout,$false)
if(!$wait)
{
$tcpclient.Close()
if($verbose){Write-Host "Connection Timeout"}
Return $false
}
else
{
$error.Clear()
$tcpclient.EndConnect($iar) | out-Null
if(!$?){if($verbose){write-host $error[0]};$failed = $true}
$tcpclient.Close()
}
if($failed){return $false}else{return $true}
}

function Get-SqlInstances($hostName)
{
$ErrorActionPreference = "SilentlyContinue"
$instances = @()
$reg = $null
#$reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $hostname)
$Hive = "LocalMachine"
$reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey([Microsoft.Win32.RegistryHive]$Hive,$hostName,[Microsoft.Win32.RegistryView]::Registry64)
IF ($reg)
{
$regkey = $null
$regkey = $reg.OpenSubkey("SOFTWARE\\Microsoft\Microsoft SQL Server")
IF ($regkey)
{
foreach ($regInstance in $regkey.GetValue('InstalledInstances'))
{
IF ($regInstance -eq "MSSQLServer")
{
$versionKey = $reg.OpenSubKey("SOFTWARE\\Microsoft\MSSQLServer\\Setup")
$serviceName = $regInstance
}
ELSE
{
$versionKey = $reg.OpenSubkey("SOFTWARE\\Microsoft\Microsoft SQL Server\\$regInstance\\Setup")
$serviceName = "MSSQL`$$regInstance"
}
IF ($versionKey)
{
$version = $versionKey.GetValue('PatchLevel')
$edition = $versionKey.GetValue('Edition')
if($version)
{
$instanceName = $hostName
$clusterKey = $reg.OpenSubKey("SOFTWARE\\Microsoft\Microsoft SQL Server\\$regInstanceData\\Cluster")
if($clusterKey)
{
$hostName = $clusterKey.GetValue('ClusterName')
}
if($regInstance -ne 'MSSQLSERVER')
{
$instanceName = "$hostName\$regInstance"
}
$serviceStatus = Get-Service -name $serviceName
$instance = New-Object System.Object
$instance | Add-Member -type NoteProperty -name Name -value $instanceName
$instance | Add-Member -type NoteProperty -name DisplayName -value $regInstance
$instance | Add-Member -type NoteProperty -name Version -value $version
$instance | Add-Member -type NoteProperty -name Edition -value $edition
$instance | Add-Member -type NoteProperty -name InstanceName -value $instanceName
$instance | Add-Member -type NoteProperty -name InstanceID -value $regInstance
$instance | Add-Member -type NoteProperty -name ServiceName -value $serviceName
$instance | Add-Member -type NoteProperty -name Status -value $serviceStatus.Status
$instances += $instance
}
}
}
$regkey = $null
$regkey = $reg.OpenSubKey("SOFTWARE\\Microsoft\\Microsoft SQL Server\\Instance Names\\SQL")
IF ($regkey)
{
foreach ($regInstance in $regkey.GetValueNames())
{
$regInstanceData = $regKey.GetValue($regInstance)
$versionKey = $reg.OpenSubKey("SOFTWARE\\Microsoft\Microsoft SQL Server\\$regInstanceData\\Setup")
$version = $versionKey.GetValue('PatchLevel')
$edition = $versionKey.GetValue('Edition')
$instanceName = $hostName
$serviceName = $regInstance
$clusterKey = $reg.OpenSubKey("SOFTWARE\\Microsoft\Microsoft SQL Server\\$regInstanceData\\Cluster")
if($clusterKey)
{
$hostName = $clusterKey.GetValue('ClusterName')
}
if($regInstance -ne 'MSSQLSERVER')
{
$instanceName = "$hostName\$regInstance"
$serviceName = "MSSQL`$$regInstance"
}
$serviceStatus = Get-Service -name $serviceName
$instance = New-Object System.Object
$instance | Add-Member -type NoteProperty -name Name -value $instanceName
$instance | Add-Member -type NoteProperty -name DisplayName -value $regInstance
$instance | Add-Member -type NoteProperty -name Version -value $version
$instance | Add-Member -type NoteProperty -name Edition -value $edition
$instance | Add-Member -type NoteProperty -name InstanceName -value $instanceName
$instance | Add-Member -type NoteProperty -name InstanceID -value $regInstanceData
$instance | Add-Member -type NoteProperty -name ServiceName -value $serviceName
$instance | Add-Member -type NoteProperty -name Status -value $serviceStatus.Status
$instances += $instance
}
}
}
}
$instances
}
#Get-SqlInstances('sal0005')

foreach($Comp in $Computers)
{
#Write-host $Count.ToString()
#Get-SqlInstances($Comp.Name)
IF(pong($Comp))
{
$instances2 += Get-SqlInstances($Comp)
}# else {Write-host 'Offline'}
$Count = $count + 1
IF($Count -eq 999)
{
$Count2 = $Count2 + 1000
Write-host $Count2.ToString() ' found ' $instances2.Count.ToString() ' SQLServers'
$Count = 0
}
}
$instances2 | Select-Object Name, DisplayName, Version, Edition, InstanceName, InstanceID, ServiceName, Status | Export-Csv $FilePath2
$instances2 | Select-Object Name, DisplayName, Version, Edition, InstanceName, InstanceID, ServiceName, Status | ft

woensdag 16 maart 2011

Tips / Links for working with SQLIO

SQLIO is a tool provided by Microsoft which can also be used to determine the I/O capacity of a given configuration.
It can be downloaded here.

Brent Ozar has a nice introduction about its features and a walkthrough on how to use it here.

SQLIO's output comes in a textfile which isnt ordered nicely yet.
I found a powershell script to directly import it into Excel.
Its from
jonathan kehayias and can be found/downloaded here.

A few sqlio parameters for my own reference below:

Creating:
sqlio -kW -s10 -fsequential -o8 -b8 -LS -Fparam.txt timeout /T 10

Generating output, example/baseline set:
sqlio -kW -t2 -s120 -dH -o1 -frandom -b64 -BH -LS Testfile.dat
sqlio -kW -t2 -s120 -dH -o1 -fsequential -b64 -BH -LS Testfile.dat
sqlio -kR -t2 -s120 -dH -o1 -frandom -b64 -BH -LS Testfile.dat
sqlio -kR -t2 -s120 -dH -o1 -fsequential -b64 -BH -LS Testfile.dat

sqlio -kW -t8 -s120 -dH -o1 -frandom -b64 -BH -LS Testfile.dat
sqlio -kW -t8 -s120 -dH -o1 -fsequential -b64 -BH -LS Testfile.dat
sqlio -kR -t8 -s120 -dH -o1 -frandom -b64 -BH -LS Testfile.dat
sqlio -kR -t8 -s120 -dH -o1 -fsequential -b64 -BH -LS Testfile.dat

sqlio -kW -t32 -s120 -dH -o1 -frandom -b64 -BH -LS Testfile.dat
sqlio -kW -t32 -s120 -dH -o1 -fsequential -b64 -BH -LS Testfile.dat
sqlio -kR -t32 -s120 -dH -o1 -frandom -b64 -BH -LS Testfile.dat
sqlio -kR -t32 -s120 -dH -o1 -fsequential -b64 -BH -LS Testfile.dat

sqlio -kW -t64 -s120 -dH -o1 -frandom -b64 -BH -LS Testfile.dat
sqlio -kW -t64 -s120 -dH -o1 -fsequential -b64 -BH -LS Testfile.dat
sqlio -kR -t64 -s120 -dH -o1 -frandom -b64 -BH -LS Testfile.dat
sqlio -kR -t64 -s120 -dH -o1 -fsequential -b64 -BH -LS Testfile.dat

Scripting jobs sql2008, fun issue

Ofcourse always know what you are doing when well...when u do anything but never assume stuff...

Like i did with this example, if u decide to copy a job in the sqlserveragent (sql2008) by scripting the job and then run it under a different name on the same instance (change jobname in script) then u have 2 jobs which have the same jobsteps / schedules.
Only difference is the name.

Don't assume u can change the schedule in the newly created job and it will only apply for that job.
Nope, the fact that u scripted it from an existing job makes it have the same schedule_id and thus if u change the schedule properties for job 2 u will also change the schedule properties for job 1.
U can delete the schedule of a job, the schedule itself will still exist but will not be referenced to that job anymore.

Its a different discussion on why u want to do this in the first place (getting a base layout for a new job with lots of jobsteps in our case) but don't assume its a different and unique object all together.