Archiv der Kategorie: Windows

Detect duplicate SusClientIds on WSUS side

In a large environment with many active directory domains and some servers which are not domain members, it is difficult to find all duplicate SusClientIds. Remote registry queries are not an option because there are many systems in protected networks behind firewalls.

So I decided to use the IIS Failed Request Log to detect duplicate SusClientIds.

Install IIS Tracing

Start the Server-Manager and install the following role service:
Tracing (under World Wide Web Services – Health and Diagnostics – Tracing)

Enable Failed-Request Tracing

  1. Open the Internet Information Services (IIS) Manager
  2. In the Connections pane, expand the machine name, expand Sites, and then click on the Site, where WSUS runs.
  3. In the Actions pane, under Configure, click Failed Request Tracing…

FailedRequestSettings

  • Select the Enable check box.
  • Set Maximum number of trace files to [number of WSUS clients x 5]

Configure Failed Request Tracing Rule

  1. Double-click Failed Request Tracing Rules.
  2. In the Actions pane, click Add…

    FailedRequestRule1

  3. In the Add Failed Request Tracing Rule wizard, on the Specify Content to Trace page, select Custom and enter the value ReportingWebService.asmx. Click Next.
    FailedRequestRule2
  4. On the Define Trace Conditions page, select the Status code(s) check box and enter 200 as the status code to trace. Click Next.FailedRequestRule3
  5. On the Select Trace Providers page, under Providers, select the WWW Server check box. Under Areas, select the Compression check box and clear all other check boxes. Compression is not what we are looking for, but it is required to select at least one Area.
  6. Under Verbosity, select Verbose.
  7. Click Finish.

Analyze Logfiles

After some logging (minimum 24h) in the Path C:\inetpub\logs\FailedReqLogFiles\W3SVC[xxxxxxxxx] are many new xml-files are created. This is the work directory for the following steps.

To analyze this files, I wrote the script get-susclientids.ps1 to get a list of all IPs and SusClientIds.

$list = @()
Foreach ($file in (Get-ChildItem *.xml)){
    $entry = New-Object -TypeName PSObject
    $filecontent = Get-Content $file.name
    $SCIline = ($filecontent | ? { $_ -like "*;<Sid>*"})
    $remoteaddrline = ($filecontent | ? { $_ -like "*<Data Name=""RemoteAddress"">*"})
    $remoteaddr = $remoteaddrline.Substring($remoteaddrline.IndexOf("""RemoteAddress"">")+16,$remoteaddrline.Length-36)
    If($SCIline -and $SCIline.IndexOf(";&lt;Sid&gt;") -gt 0){
        Add-Member -InputObject $entry -MemberType NoteProperty -Name RemoteAddr -Value $remoteaddr
        Add-Member -InputObject $entry -MemberType NoteProperty -Name SusClientId -Value $SCIline.substring($SCIline.IndexOf(";&lt;Sid&gt;")+12,36)
        If(@($list | ? { $_.remoteaddr -eq $remoteaddr }).count -lt 1){
            $list += $entry
        }
    }
}
$list | export-csv -path susclientids.csv

The result can be queried with this command:
Import-Csv .\susclientids.csv

Example output:

RemoteAddr                              SusClientId
----------                              -----------
10.0.0.1                                aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee
10.0.0.2                                ffffffff-0000-1111-2222-333333333333
10.0.0.7                                aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee

Finding Duplicates

To find duplicate SusClientIds I wrote the script get-duplicate.ps1:

$duplicates = Import-Csv .\susclientids.csv | sort susclientid | group susclientid | ? { $_.count -gt 1}
$list = @()
foreach ($duplicateSCI in $duplicates){
    foreach ($system in $duplicateSCI.Group){
        $entry = New-Object -TypeName PSObject
        Add-Member -InputObject $entry -MemberType NoteProperty -Name RemoteAddr -Value $system.remoteaddr
        try {
            $fqdn = ([System.Net.Dns]::GetHostEntry($system.remoteaddr).Hostname)
        } catch {
            $fqdn = ""
        }
        Add-Member -InputObject $entry -MemberType NoteProperty -Name FQDN -Value $fqdn
        Add-Member -InputObject $entry -MemberType NoteProperty -Name SusClientId -Value $system.SusClientId
        $list += $entry
    }
}
$list

Example output:

RemoteAddr     FQDN               SusClientId
----------     ----               -----------
10.0.0.1       host1.domain.com   aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee
10.0.0.7       host7.domain.com   aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee

Now it’s time to reset the SusClientId on the listed systems.

Bearbeitung von Gruppenrichtlinie schlägt fehl: „Der Datenträger einer Datei wurde extern so geändert, dass die geöffnete Datei nicht mehr gültig ist.“

Es gibt schon komische Fehlermeldungen, zum Beispiel die obenstehende. Über diese bin ich gestolpert, als ich versucht habe in einer Domäne die Default Domain Controller Policy zum bearbeiten zu öffnen. Vollständig sah das Ganze so aus:


Das Gruppenrichtlinienobjeckt konnte nicht geöffnet wererror_edit_gpoden. Möglicherweise verfügen Sie nicht über die erforderlichen Rechte.
Details:
Der Datenträger einer Datei wurde extern so geändert, dass die geöffnete Datei nicht mehr gültig ist.


Eigentlich würde man meinen, wenn es nur eine einzige Policy betrifft, dann kann man die ja einfach mal neu erstellen. Da es sich hier aber um die Default Domain Controller Policy handelt, war ich von dem Gedanken nicht unbedingt angetan.

Nach ein paar Tests mit Procmon habe ich festgestellt, dass sich die Konsole an einer leeren registry.pol-Datei im Unterordner USER der Policy stört. Beim bearbeiten einer Default Domain Controller Policy einer anderen Domäne wurde für die genannte Datei ein „NOT FOUND“ geloggt. Bei der „beschädigten“ Policy hingegen nicht und relativ kurz darauf brach er mit oben genanntem Fehler ab.

Lösung:
Einfach die 0kb große Datei \\domain.loc\SYSVOL\domain.loc\Policies\{policy-guid}\USER\registry.pol in registry.old.pol umbenennen.

Betroffen davon scheint auch nur Windows Server 2012 bzw. 2012 R2. Auf einem Windows Server 2008 R2 konnte ich das Problem nicht nachstellen.

check the version including update rollup of all Exchange servers in organization

After I realized that there is no Exchange 2010 cmdlet to determine the complete version number of all Exchange servers, I decided to write a script for this.

The result is one ps1 script and a csv file with the version numbers and the version name. I got the version informations from this Article.

The version csv looks like this:

Version,Text
"14.0.639.21","Microsoft Exchange Server 2010 RTM"
"14.0.682.1","Microsoft Exchange Server 2010 RTM Update Rollup 1"
"14.0.689.0","Microsoft Exchange Server 2010 RTM Update Rollup 2"
.........
"14.3.210.2","Microsoft Exchange Server 2010 SP3 Update Rollup 7"
"14.3.224.2","Microsoft Exchange Server 2010 SP3 Update Rollup 8-v2"

To check the version, the script gets the installation path from registry and reads the file info of the exsetup.exe via smb (admin shares).

And this is the script:

# read versions and versiontext from csv
$versions = @{}
$csvversions = (Import-Csv -Path .\get-ExchangeServerVersion.csv)
$csvversions | foreach { $versions[($_.version)] = $_.Text }

# create list object for output
$output = @()

$version ="UNKNOWN!"

# get exchange servers in the organization filtered by version 14.*
$exServers = Get-ExchangeServer | ? { $_.AdminDisplayVersion -like "Version 14.*"} | sort fqdn | select name,fqdn
foreach ($exServer in $exServers){
    Write-Debug $exserver
    # create PowerShell object for output line
    $outputEx = New-Object -TypeName PSObject

    # get Exchange installation path
    $Reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $exServer.fqdn)
    $RegKey= $Reg.OpenSubKey("SOFTWARE\\Microsoft\\ExchangeServer\\V14\\Setup")
    $InstallPath = $RegKey.GetValue("MsiInstallPath")
    $ExSetupPath=("\\"+$exServer.fqdn+"\"+($InstallPath).replace(":\","$\").Replace("""",""))+"bin\ExSetup.exe"

    # get Version from Exchange binary
    $version = ([Version](Get-Item ($ExSetupPath)).VersionInfo.ProductVersion).tostring()

    # add server name to ps object
    Add-Member -InputObject $outputEx -MemberType NoteProperty -Name Name -Value $exServer.fqdn

    # add version to ps object, if the version is not in the version list, use the version instead of text
    If($versions["$($version)"]){
        Add-Member -InputObject $outputEx -MemberType NoteProperty -Name Version -Value $versions["$($version)"]
    } else {
        Add-Member -InputObject $outputEx -MemberType NoteProperty -Name Version -Value $version
    }

    # reset Version to unknown for next loop
    $version ="UNKNOWN!"
    $ExSetupPath = ""

    # add ps object to output
    $output+=$outputEx

}
$output

downloads

get-ExchangeServerVersion.ps1
get-ExchangeServerVersion.csv

Server-Manager hängt bei „Installation wird gestartet…“

Windows bringt einen schon manchmal zum verzweifeln. Hier habe ich mal wieder ein Beispiel, was mich einiges an Nerven gekostet hat.

Bei der Installation einer Rolle oder eines Features unter Windows Server 2012 hatte ich das Problem, dass er immer am Punkt „Installation wird gestartet…“ hängen blieb.

Nach etwas Recherche bin ich darüber gestolpert, dass WinRM die Ursache sein könnte. Also versuchte ich es wie gewohnt über die Kommandozeile mit „winrm quickconfig“ zu aktivieren, was in folgender Fehlermeldung resultierte:

Der WinRM-Dienst wird auf diesem Computer bereits ausgeführt.
WSManFault
    Message = Der WinRM-Client hat einen Status in Bezug auf einen HTTP-Serverfehler (500) empfangen, 
aber der Remotedienst hat keine anderen Informationen zur Fehlerursache bereitgestellt.

Fehlernummer:  -2144108176 0x80338170
Der WinRM-Client hat einen Status in Bezug auf einen HTTP-Serverfehler (500) empfangen, aber der 
Remotedienst hat keine anderen Informationen zur Fehlerursache bereitgestellt.

Nach weiterer Suche ist mir dann aufgefallen, dass im Server-Manager unter Lokaler Server bei dem Punkt Remoteverwaltung nur „Unbekannt“ stand. Beim Klick darauf sah das ganze dann so aus:

Remoteverwaltung-Fehler

Die genaue Fehlermeldung lautete hier:

Interner Fehler beim Lesen des Remotingzustands: Der WinRM-Client hat einen Status in Bezug auf einen HTTP-Serverfehler (500) empfangen, 
aber der Remotedienst hat keine anderen Informationen zur Fehlerursache bereitgestellt.

Hier hat es geholfen, die Remoteverwaltung zu deaktivieren, mit OK zu bestätigen und wieder erneut zu aktivieren.

Allerdings muss ich dabei anmerken, dass das Problem einige Tage später, eventuell nach einem Neustart, wieder auftrat.

HP Version Control Agent und Umlaute

Seit einiger Zeit habe ich mich mit zwei HP-Servern rumgeärgert, bei denen ich über den Version Control Agent Updates installieren wollte. Das Ergebnis war immer ein Absturz der vcagent.exe. Im Eventlog sah das Ganze dann so aus:

Ereignistyp:      Fehler
Ereignisquelle:   Application Error
Ereigniskennung:  1000
Beschreibung:
Fehlgeschlagene Anwendung vcagent.exe, Version 7.0.0.900, fehlgeschlagenes Modul vcagent.exe, Version 7.0.0.900, Fehleradresse 0x0003acff.

Ein Versuch den Server über das aktuellste Proliant Support Pack zu aktualisieren schlug auch fehl. Hier erhielt ich einfach nur „Discovery Failed“.

Ein Blick in den Ordner %temp%\hp_sum brachte einige Logfiles zum Vorschein. Hier z.B. die OpMan.trace. In dieser konnte ich folgenden Hinweis finden:

Target.cpp[1398]: Target 0: Error Reading Core Data: FindTextNode: Required tag servertype not found

Eine runde googeln macht mich auch nicht schlauer. Nach mehreren Stunden suchen gab ich vorerst auf.

Letzten Freitag stolperte ich wieder über den gleichen Fehler bei einem anderen Server. Auffällig war, dass es sich bei allen 3 Servern um Exchange 2003 Server handelte. Ich machte mich erneut auf Ursachenforschung.

Scheinbar musste die Ursache in den Scanresultaten des hpsum liegen. Also betrachtete ich die jeweiligen Ergebnis-XML-Dateien von einem der betroffenen Server und im Vergleich dazu einem nicht betroffenen Server. In der hwdiscovery2.xml wurde ich dann fündig. Der Internet Explorer wies mich kurz vor Dateiende darauf hin, dass ein Abschnitt des Files fehlerhaft wäre. Ein Blick in den Quelltext förderte die Ursache zu Tage.

Ein Umlaut!

Um genau zu sein in der PATH-Variable „C:\Programme\McAfee\GroupShield für Exchange\bin\“.

Nachdem ich diesen Pfad durch „C:\Programme\McAfee\GroupS~1\bin\“ ersetzt hatte, konnte ich endlich den Server Updaten. Sowohl via Proliant Support Pack als auch über den Version Control Agent.

Perfomance Counter übersetzen

Performance Counter sind toll! Man kann relativ einfach Werte auslesen. Dumm nur, dass Microsoft alles übersetzt, selbst die Performance Counter Objekte.

Man findet im Technet viele tolle Beschreibungen, welche Counter sinnvoll zum Überwachen bestimmter Dienste wären.

Hier wird natürlich immer auf die englische Variante verwiesen.

Man findet in der Registry sowohl deutsche als auch englische Beschreibungen, ansprechen kann man aber scheinbar nur die deutschen.

Daher habe ich ein Powershell Script geschrieben. Welches alle Counter englisch und deutsch ausgiebt.

Alternativ kann auch über folgende Syntax ein bestimmter Counter in der Originalsprache gesucht werden:

PS C:\Scripting> .\perflib-translator.ps1 "Current % Processor Time"
Current % Processor Time
Aktuelle Prozessorzeit (%)
===============================================================================

Hier nun das doch recht simple Script:

$english = "009"
$german = "007"

$translatefrom = $english
$translateto   = $german

$langfrom = (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\$($translatefrom)").Counter
$langto = (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\$($translateto)").Counter
$translation = @{}
For ($x=0; $x -lt $langto.length; $X=$x+2){
    $translation.Add($langto[$x],$langto[$x+1])
}
For ($x=0; $x -lt $langfrom.length; $X=$x+2){
    If($args[0]){
        If($langfrom[$x+1] -match $args[0]){
            $langfrom[$x+1]
            $translation[($langfrom[$x])]
            "==============================================================================="
        }
    } else{
        $langfrom[$x+1]
        $translation[($langfrom[$x])]
        "==============================================================================="
    }
}

Remote Desktop Einstellungen nach Upgrade verschwunden

Neulich hat ein Kollege einem Windows Server 2008 R2 mit SP1 ein Upgrade von Standard auf Enterprise verpasst.

Das Ganze hat er mit folgendem Befehl erledigt:

dism /online /Set-Edition:ServerEnterprise /ProductKey:<Lizenzschlüssel>

Dummerweise wollte dieser anschließend keine RDP Verbindungen mehr entgegennehmen.

Ein Blick in die Computereigenschaften brachte links stehendes Bild hervor, was mich doch sehr verwunderte.

Ursache scheint wohl eine unvollständige Aktivierung. Ein erneutes eingeben des Lizenzschlüssels brachte keinen Erfolg.

Letztendlich war eine Zurücksetzung der Aktivierung erforderlich:

slmgr /rearm

Anschließend Lizenzschlüssel neu eingeben, neustarten, RDP deaktivieren, neustarten, RDP aktivieren und siehe da, RDP funktioniert wieder!