Skip to content

Commit bad9698

Browse files
Uwe Jankeclaude
andcommitted
fix+feat: v1.8.3.0 — AlwaysOn primary detection, CollationChange, Collation reports
Sync-sqmLoginsToAlwaysOn: - Fix primary replica detection when running from secondary: replace dm_hadr_availability_replica_states (role_desc=NULL on secondary) with dm_hadr_availability_group_states.primary_replica (always populated) - Fix Write-EventLog AccessDenied leaking to console: add -ErrorAction SilentlyContinue to EventLog writes (EventId 9002/9003) Invoke-sqmCollationChange: - Fix PropertyAssignmentException: remove CreateNoNewWindow=$true (redundant when UseShellExecute=$false + RedirectStandard*=$true) Get-sqmSQLInstanceCheck: - Add Instance Collation check (always Info) - Add Database Collation vs Instance check (Warning, -Detailed only) Compare-sqmServerConfiguration: - Always emit Collation (Instance) row regardless of match (Category=Collation) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 7aad7b3 commit bad9698

6 files changed

Lines changed: 81 additions & 18 deletions

CHANGELOG.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,33 @@
11
# sqmSQLTool — Changelog
22

3+
## [1.8.3.0] — 2026-06-29
4+
5+
### Bugfixes & Erweiterungen
6+
7+
**`Sync-sqmLoginsToAlwaysOn`**
8+
- Fix: Primary-Replica-Erkennung schlaegt auf Secondary-Instanzen nicht mehr fehl.
9+
`sys.dm_hadr_availability_replica_states.role_desc` liefert NULL/RESOLVING wenn von
10+
einer Secondary abgefragt — Umstieg auf `sys.dm_hadr_availability_group_states.primary_replica`,
11+
das auf jeder Replica den aktuellen Primary enthaelt.
12+
- Fix: `Write-EventLog`-Fehler (AccessDenied) leckte auf die Konsole, weil der Setter eine
13+
non-terminating Exception wirft, die `catch { }` nicht abfaengt.
14+
`-ErrorAction SilentlyContinue` ergaenzt (EventId 9002 / 9003).
15+
16+
**`Invoke-sqmCollationChange`**
17+
- Fix: `PropertyAssignmentException` bei `ProcessStartInfo.CreateNoNewWindow = $true` entfernt.
18+
Die Property kann nicht gesetzt werden wenn `UseShellExecute` noch nicht evaluiert wurde.
19+
Redundant: bei `UseShellExecute = $false` + `RedirectStandard* = $true` entsteht ohnehin
20+
kein Konsolenfenster.
21+
22+
**`Get-sqmSQLInstanceCheck`**
23+
- Neu: Check **Instance Collation** (Status `Info`) — meldet `server.Collation` in jedem Lauf.
24+
- Neu: Check **Database Collation vs. Instance** (nur mit `-Detailed`) — listet alle
25+
Benutzerdatenbanken, deren Collation von der Instanz-Collation abweicht, als `Warning`.
26+
27+
**`Compare-sqmServerConfiguration`**
28+
- Neu: **Collation (Instance)** wird jetzt immer im Report ausgegeben (`Category = "Collation"`),
29+
nicht nur bei Abweichung — wichtig fuer Migrationschecks.
30+
331
## [1.8.2.0] — 2026-06-26
432

533
### ✨ Temporäre Sysadmin-Rechte: AD-Login-Anlage, Cleanup & AlwaysOn

Public/Compare-sqmServerConfiguration.ps1

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<#
1+
<#
22
.SYNOPSIS
33
Compares important configuration settings between two SQL Server instances.
44
@@ -92,6 +92,7 @@ function Compare-sqmServerConfiguration
9292
$targetProps = Get-ServerProps $TargetInstance
9393
foreach ($key in $sourceProps.Keys)
9494
{
95+
if ($key -eq 'Collation') { continue }
9596
if ($sourceProps[$key] -ne $targetProps[$key])
9697
{
9798
$results.Add([PSCustomObject]@{
@@ -102,6 +103,15 @@ function Compare-sqmServerConfiguration
102103
})
103104
}
104105
}
106+
107+
# Collation always reported (not just on difference)
108+
$results.Add([PSCustomObject]@{
109+
Setting = "Collation (Instance)"
110+
SourceValue = $sourceProps['Collation']
111+
TargetValue = $targetProps['Collation']
112+
Category = "Collation"
113+
})
114+
105115
if ($CompareDatabases)
106116
{
107117
$sourceDbs = Get-DatabaseSimple $SourceInstance | Where-Object { -not $_.IsSystemObject }

Public/Get-sqmSQLInstanceCheck.ps1

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<#
1+
<#
22
.SYNOPSIS
33
Checks a SQL Server instance against best practices.
44
@@ -322,6 +322,29 @@ function Get-sqmSQLInstanceCheck
322322
Status = if ($isOld) { "Warning" } else { "OK" }
323323
Message = if ($isOld) { "Die Version $version ist veraltet. Upgrade empfohlen." } else { "OK." }
324324
}
325+
326+
# 10. Instance Collation
327+
$instanceCollation = $server.Collation
328+
$results += [PSCustomObject]@{
329+
Check = "Instance Collation"
330+
CurrentValue = $instanceCollation
331+
Recommended = "Unternehmensstandard sicherstellen (z.B. Latin1_General_CI_AS)"
332+
Status = "Info"
333+
Message = "Instanz-Collation: $instanceCollation"
334+
}
335+
336+
if ($Detailed)
337+
{
338+
$allDbs = Get-DbaDatabase -SqlInstance $server -ExcludeSystem -ErrorAction SilentlyContinue
339+
$collationMismatch = @($allDbs | Where-Object { $_.Collation -ne $instanceCollation } | ForEach-Object { "$($_.Name): $($_.Collation)" })
340+
$results += [PSCustomObject]@{
341+
Check = "Database Collation (vs. Instance)"
342+
CurrentValue = if ($collationMismatch.Count -gt 0) { "$($collationMismatch.Count) DB(s) abweichend" } else { "Alle gleich" }
343+
Recommended = "Alle Benutzerdatenbanken sollten Instanz-Collation verwenden ($instanceCollation)"
344+
Status = if ($collationMismatch.Count -gt 0) { "Warning" } else { "OK" }
345+
Message = if ($collationMismatch.Count -gt 0) { "Abweichende Collation: $($collationMismatch -join '; ')" } else { "Alle Benutzerdatenbanken nutzen die Instanz-Collation." }
346+
}
347+
}
325348
}
326349
catch
327350
{

Public/Invoke-sqmCollationChange.ps1

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<#
1+
<#
22
.SYNOPSIS
33
Automatically changes the server collation of a SQL Server instance.
44
@@ -325,10 +325,8 @@ function Invoke-sqmCollationChange
325325
Write-Host " Starte sqlservr.exe im Minimal-Modus mit neuer Collation..." -ForegroundColor Gray
326326
$startInfo = [System.Diagnostics.ProcessStartInfo]::new()
327327
$startInfo.FileName = $sqlBinPath
328-
$sFlag = if ($instanceRegName -ne 'MSSQLSERVER') { " -s`"$instanceRegName`"" } else { '' }
329-
$startInfo.Arguments = "-m -T4022 -T3659$sFlag -q `"$NewCollation`""
328+
$startInfo.Arguments = "-m -T4022 -T3659 -q `"$NewCollation`""
330329
$startInfo.UseShellExecute = $false
331-
$startInfo.CreateNoNewWindow = $true
332330
$startInfo.RedirectStandardOutput = $true
333331
$startInfo.RedirectStandardError = $true
334332
$sqlProc = [System.Diagnostics.Process]::Start($startInfo)

Public/Sync-sqmLoginsToAlwaysOn.ps1

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -278,15 +278,17 @@ ORDER BY name ASC
278278
SELECT
279279
ar.replica_server_name,
280280
ar.availability_mode_desc,
281-
drs.role_desc
281+
ISNULL(
282+
CASE WHEN ar.replica_server_name = ags.primary_replica THEN 'PRIMARY' ELSE 'SECONDARY' END,
283+
'RESOLVING'
284+
) AS role_desc
282285
FROM sys.availability_replicas ar
283-
INNER JOIN sys.dm_hadr_availability_replica_states drs
284-
ON ar.replica_id = drs.replica_id
285-
WHERE ar.group_id IN (
286-
SELECT group_id FROM sys.availability_groups
287-
WHERE name = N'$AvailabilityGroupName'
288-
)
289-
ORDER BY drs.role ASC
286+
INNER JOIN sys.availability_groups ag
287+
ON ar.group_id = ag.group_id
288+
LEFT JOIN sys.dm_hadr_availability_group_states ags
289+
ON ag.group_id = ags.group_id
290+
WHERE ag.name = N'$AvailabilityGroupName'
291+
ORDER BY role_desc ASC
290292
"@
291293

292294
$replicas = Invoke-DbaQuery -SqlInstance $SqlInstance -SqlCredential $srcCred -Query $query -ErrorAction Stop
@@ -598,7 +600,8 @@ ORDER BY sp.name
598600
$evtSrc = 'sqmSQLTool'
599601
if (-not [System.Diagnostics.EventLog]::SourceExists($evtSrc)) { New-EventLog -LogName Application -Source $evtSrc -ErrorAction Stop }
600602
Write-EventLog -LogName Application -Source $evtSrc -EntryType Error -EventId 9002 `
601-
-Message "sqmSQLTool: Login-Sync fehlgeschlagen AG '$AvailabilityGroupName' auf '$SqlInstance' - Failed=$failedCount"
603+
-Message "sqmSQLTool: Login-Sync fehlgeschlagen AG '$AvailabilityGroupName' auf '$SqlInstance' - Failed=$failedCount" `
604+
-ErrorAction SilentlyContinue
602605
}
603606
catch { }
604607
}
@@ -622,7 +625,8 @@ ORDER BY sp.name
622625
$evtSrc = 'sqmSQLTool'
623626
if (-not [System.Diagnostics.EventLog]::SourceExists($evtSrc)) { New-EventLog -LogName Application -Source $evtSrc -ErrorAction Stop }
624627
Write-EventLog -LogName Application -Source $evtSrc -EntryType Warning -EventId 9003 `
625-
-Message "sqmSQLTool: AD-verwaiste Logins auf '$SqlInstance' AG '$AvailabilityGroupName' - Count=$($adOrphans.Count): $orphanNames"
628+
-Message "sqmSQLTool: AD-verwaiste Logins auf '$SqlInstance' AG '$AvailabilityGroupName' - Count=$($adOrphans.Count): $orphanNames" `
629+
-ErrorAction SilentlyContinue
626630
}
627631
catch { }
628632
}

sqmSQLTool.psd1

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<#
1+
<#
22
===========================================================================
33
Created with: SAPIEN Technologies, Inc., PowerShell Studio 2021 v5.8.183
44
Created on: 21.04.2026 15:37
@@ -17,7 +17,7 @@
1717
RootModule = 'sqmSQLTool.psm1'
1818

1919
# Version number of this module.
20-
ModuleVersion = '1.8.2.0'
20+
ModuleVersion = '1.8.3.0'
2121

2222
# ID used to uniquely identify this module
2323
GUID = 'c4b10ba2-aee2-4d8d-ad86-a6e97c346ba6'

0 commit comments

Comments
 (0)