Archiv » Oktober, 2016 «

24 | 10 | 2016

Exchange 2013 CU14 und 2016 CU3: Probleme mit der Suche

Geschrieben von um 23:42 Uhr

Ein Wort der Warnung: Die vor kurzem erschienenen CUs von Exchange 2013 und 2016 haben anscheinend gravierende Probleme bei der Indizierung.

Ein Beispiel hier: https://social.technet.microsoft.com/Forums/en-US/a05ea439-8d7a-4d83-a8c4-fcc7e78904bf/exchnage-2013-cu-14-database-indexing-failed?forum=exchangesvradmin

In Kürze: Der Indexdienst verweigert für einige (in manchen Fällen auch für alle) Datenbanken die Indizierung. Die einzige Lösung ist die Installation eines zusätzlichen Servers mit einem älteren Patch-Stand und Verschiebung der Postfächer dorthin.

Wer also gerade sein Update plant, sollte lieber etwas warten und v2 oder halt ein nächstes CU installieren.

Tags » , , , , , «

+

17 | 10 | 2016

JetPack hat die XING-RSS-Anbindung gefressen :-(

Geschrieben von um 9:38 Uhr

Es kann natürlich auch eine Koinzidenz sein, aber just nach dem Installieren des JetPack-Plugins sagt der RSS-Reader von XING zu meinem Blog:

xing

Bis das geklärt ist, muss ich die Beiträge wohl manuell teilen 🙁

Tags » , , , «

1

16 | 10 | 2016

Das nächste Buch von Daniel Suarez erscheint am 11. April 2017

Geschrieben von um 23:27 Uhr

https://www.amazon.de/Change-Agent-Novel-Daniel-Suarez-ebook/dp/B01J2SU2YO

Tags » , , , , «

+

10 | 10 | 2016

PowerShell Hack: TechNet-Teilnahme eines Users messen oder eine Übung im Web Grabbing

Geschrieben von um 9:04 Uhr

Wenn man im TechNet-Forum (https://social.technet.microsoft.com/Forums/de-de/home) unterwegs ist, kann man ja Punkte verdienen. Hat man eine Frage beantwortet und hat der Fragesteller das bestätigt, gibt es Punkte. Hat jemand den Post für hilfreich erklärt, gibt’s auch Punkte. Ist man in vielen Microsoft-Technologien unterwegs, möchte man manchmal wissen, wo man denn die meiste Contribution geleistet hat. Das Forumsystem selbst gibt da zwar eine sehr detaillierte Auskunft in Form einer Aktivitäten-History, aber man möchte ja eigentlich einfach nur schnell einen Überblick gewinnen. Und vielleicht auch nicht über sich, sondern auch über andere user. Was liegt an einem verregneten Sonntag also näher, als einfach ein Skript zu schreiben, das die Webseite für einen durchgeht und die Daten einsammelt.

Die Grundlage dafür ist das Cmdlet Invoke-WebRequest, welches ein Objekt vom Typ „Microsoft.PowerShell.Commands.HtmlWebResponseObject“ zurück liefert. Dieses hat eine Eigenschaft „ParsedHtml“, die vom Typ „mshtml.IHTMLDocument2“ ist. Damit wären wir schon fast am Ziel, man muss einfach nur an den Perversitäten der Web-Entwickler und der verschahtelten Struktur der DIV-Tags vorbei kommen. In der Thread-Ansicht zum Beispiel hat die Vorschau auf jeden Beitrag die Klasse „threadsnippet“:

paul_thread_snippet

Den Inhalt bekommt man also mit

$page = Invoke-WebRequest -Uri "https://social.technet.microsoft.com/Forums/en-us/user/threads?user=Paul++Cunningham"
$html = $page.ParsedHtml
$html.all.tags("DIV") | foreach {
    if ($_.className) {
        if ($_.className.Trim() -eq "threadsnippet") {
            $snippet = $_
            foreach ($head in $snippet.all.tags("H3")) {
                $thread_topic = $head.innerText.Trim()
                foreach($link in $head.all.tags("A")) {
                    $thread_link = $link.href
                }
            }
        }
    }
}

Am Ende hat man dann in $thread_topic den Header und in $thread_link den Link zum gesamten Thread. Und so weiter.
Ich habe dafür zwei Skripte geschrieben, die in der PSGallery heruntergeladen werden können:

Export-TechNetContributionToCSV.ps1 geht die Beiträge des angegebenen Users durch und macht daraus eine CSV-Dateie mit diversen Informationen inklusive Links zu den einzelnen Threads. Schauen wir uns zum Beispiel die Contribution des bekannten Exchange-MVP Paul Cunningham an (man beachte die zwei Leerzeichen im TechNet-Usernamen):

tn_paul_export

Ist die CSV fertig, so kann man sie mit Measure-TechNetContribution.ps1 nach Foren oder sogar nach einzelnen Subforen zusammenfassen und, je nach Lust und Laune, tabellarisch oder sonst wie darstellen lassen:tn_paul_measureoder nach Hauptforen gegliedert:

tn_paul_measure_main

So kann man herausfinden, in welchen Wissensgebieten sich z.B. ein Kollege betätigt, der gern im TechNet Forum schreibt.

Tags » , , , , «

+

09 | 10 | 2016

PowerShell Hack: Mit RDExSessionInfo RDP-Daten geliefert bekommen

Geschrieben von um 0:01 Uhr

Eigentlich ist es eher ein C#-Hack, aber wir wollen ja nicht zu pingelig sein 😉

Die Schwierigkeit, in PowerShell sinnvolle Daten über RDP-Sitzungen zu bekommen, war mir schon sehr lange ein Dorn im Auge. Ich habe mich aber die ganze Zeit davor gedrückt, die Windows-API anzuzapfen und die Infos von dort zu ziehen, aber nachdem Gernot Meyer in diesem TechNet-Thread) schon mal einen Proof Of Concept vorgenommen hat, konnte ich nun nicht mehr an mich halten und habe ein PowerShell-Modul namens RDExSessionInfo erstellt, das einige wichtige Basisdaten liefert:

  • Username, Domäne, Sitzungs-ID und -Status
  • Zeiten für Logon, Connect, Desconnect und Last Input (als DateTime-Objekt)
  • Upstream und Downstream Bytes
  • Client Build, Name und IP

Das ganze habe ich auf der PSGallery veröffentlicht, viel Spaß damit! Eine Status-Seite und kleine Einführung findet man hier im Blog.

Tags » , , , , «

+

07 | 10 | 2016

MAP in einer Workgroup-Umgebung

Geschrieben von um 22:30 Uhr

Heute mal etwas leichtere Kost, eher als Reminder gedacht.

Das Microsoft Assesment & Planning Toolkit ist ja ein bewährtes Mittel zur systemübergreifenden Performance-Analyse. Zum Beispiel, um eine Konsolidierung von Servern von Physik und „wilder Virtualisierung“ auf geordnete virtuelle Plattformen oder in die Cloud zu modellieren. So auch heute. Die Herausforderung jedoch war, dass nur einer der zu betrachtenden Server tatsächlich Domänen-Mitglied ist – und zwar in einer Domäne, in die der MAP-Server natürlich nicht aufgenommen werden durfte! Alle anderen Server gehören keiner Domäne an, und die meisten von ihnen haben nur den Default-„Administrator“ an Konten eingerichtet. Das Kennwort von diesem Administrator ist zwar nicht überall unterschiedlich, aber auch nicht überall gleich – ca. die Hälfte der Server hatte „Kennwort1“, und der Rest teilte sich in etwa gleichmäßig in „Kennwort2“ und „Kennwort3“.

Landet man in einer solchen Situation, so muss man folgendes berücksichtigen:

  • „.\Administrator“ kann MAP nicht erfassen, nur „Administrator“ oder „<COMPUTER>\Administrator“
  • Jedes Account kann in der exakten Schreibweise nur einmal vorkommen, das Erfassen von „Administrator“ mit unteschiedlichen Passwörtern ist also nicht ohne weiteres möglich
  • Im Inventory-Teil kann man jedem Eintrag, wenn man ihn manuell eingibt, oder jeder Liste, wenn man sie aus Dateien einliest, ein eigenes Konto zuweisen.
  • Im Performance-Sammlungs-Teil gibt es diese Funktion aber nicht – da kann man NUR eine Liste von Accounts zum Durchprobieren erfassen!
  • Die Schreibweise „<COMPUTER>\Administrator“ wird im Performance-Sammlungs-Teil nur für den Computer akzeptiert, der auch tatsächlich da steht. Somit mussten wir die Durchprobier-Liste in Form „Administrator – Kennwort1″,“DomainUser – DomainKennwort“, „SERVER2A\Administrator – Kennwort2“, „SERVER2B\Administrator – Kennwort2″,…“SERVER2Z\Administrator – Kennwort2″,“SERVER3A\Administrator – Kennwort3“,… erfassen. Alles andere hat nicht funktioniert.
  • Im Inventory-Teil (WMI) wird hingegen auch ein „fremder“ Computername angenommen, wenn nur der Benutzername und das Kennwort passen.

Last but not least: Die eingegebenen Accounts werden bei Abmeldung „vergessen“ und stehen beim nächsten Aufruf von MAP nicht zur Auswahl.

In einer Domänen-Umgebung wäre das alles überhaupt kein Problem…

 

Tags » , , «

+

04 | 10 | 2016

Ablaufdatum für moderierte Nachrichten festlegen

Geschrieben von um 23:04 Uhr

Wenn man in Exchange Moderation, z.B. für eine Gruppe, einschaltet, greift ein Expiration-Mechanismus, der nach einer gewissen Zeitspanne die Mails (mit Benachrichtigung) verwirft, falls bis dahin keiner der Moderatoren sie freigegeben oder abgelehnt hat. Das Ganze wird durch den MFA gesteuert, indem die Nachrichten erst mal in einer Arbitration Mailbox liegen, bis sie freigegeben werden. Der MFA schaut gemäß seinem Zeitplan nach, ob sie nicht veraltet sind, und verarbeitet sie dann entsprechend.

Um herauszufinden, wie lange man Zeit hat, eine Mail zu genehmigen, schaut man entweder in die Doku oder in seine Exchange-Installation. Und siehe da – der Blick in die Installation lohnt sich, denn die Doku und die Realität widersprechen sich. Unter https://technet.microsoft.com/en-us/library/dd297936(v=exchg.150).aspx liest man:

If the approver either deletes or ignores the approval message, an expiration message is sent to the sender. This happens after two days in Exchange Online, and after five days in Exchange Server 2013. (In Exchange Server 2013, you can change this time period).

In Wirklichkeit aber sind es on premise auch zwei Tage. Und diese sieht man ganz deutlich hier:

Get-RetentionPolicyTag -IncludeSystemTags | where { $_.SystemTag } | ft Name, AgeLimitForRetention

moderatedEine Nachricht, die am Freitagabend abgesendet wird, nachdem der Approver bereits nach Hause gegangen ist, hat also keine Chance!

Global kann man das Limit (z.B. auf die dokumentierten 5 Tage) erhöhen mit

Get-RetentionPolicyTag moderatedrecipients | Set-RetentionPolicyTag -AgeLimitForRetention 5

Wünscht man sich hingegen mehr Ganularität, muss man anfangen, mit zusätzlichen Arbitration Mailboxen zu arbeiten. Denen weist man dann eine entsprechend präparierte Retention Policy zu:

New-RetentionPolicyTag "LongExpiry" -SystemTag $true -AgeLimitForRetention 10 -RetentionEnabled $true -RetentionAction DeleteAndAllowRecovery
New-RetentionPolicy "LongExpiryPolicy" -RetentionPolicyTagLinks LongExpiry,AutoGroup,AsyncOperationNotification
New-Mailbox -Arbitration "LongExpiryMFA" -UserPrincipalName longexpirymfa@domain.de -RetentionPolicy LongExpiryPolicy

Anschließend muss natürlich die Arbitration Mailbox-Verknüpfung bei den gewünschten Rezipienten angepasst werden:

Get-DistributionGroup "All Employees" | Set-DistributionGroup -ArbitrationMailbox LongExpiryMFA

Tags » , , , , , , «

+

04 | 10 | 2016

PowerShell Hack: UPD-Platte für einen User aushängen

Geschrieben von um 20:57 Uhr

User Profile Disk in RDS ab Server 2012 ist ein cooles Feature, was in der Regel auch super funktioniert. Doch wenn’s mal nicht funktioniert, wird es ärgerlich: Meistens liegt die Ursache nämlich darin, dass eine VHDX mit dem umgeleiteten Benutzerprofil nicht aus dem Session Host oder der VDI-Maschine ausgehängt wurde. Danach manuell zu suchen ist ein ziemlicher Schmerz, aber wenn man Admin-Recht und das AD-Modul in Powershell hat, kann man das recht gut automatisieren.

Wir gehen vom Benutzernamen und den Fileserver aus, auf dem die UPDs liegen:

$user = 'u0003'

$file_server = 'FILESERVER'

Für den Fall, dass jemand den Usernamen als NETBIOS oder UPN eingibt, normalisieren wir ihn noch zu SAMAccountName:

$user_sam = (Get-ADUser $user).SAMAccountName

Als erstes brauchen wir die SID des Users, da nach ihr die Platte benannt ist:

$sid = (Get-ADUser $user).SID.Value

Der nachfolgende Code geht auf die Arbeit von Jeffrey Patton (@jeffpatton) zurück und fragt offene Dateien direkt beim Fileserver ab:

$fs = [adsi]"WinNT://$file_server/LanmanServer"
$fsres = $fs.PSBase.Invoke("Resources")
foreach ($file in $fsres) {
    try {
        $path = $file.GetType().InvokeMember("Path","GetProperty",$null,$file,$null)
        if ($path -like "*$($sid).VHDX") {
            try {
                $rdsh = $file.GetType().InvokeMember("User","GetProperty",$null,$file,$null)
                break
            } catch {}
        }
    } catch {}
}
if ($rdsh -like "*$") { $rdsh = $rdsh.Substring(0, $rdsh.Length - 1) } else { $rdsh = $null; $path = $null }

Wenn also jetzt in $rdsh ein Wert enthalten ist, ist es ein Computername. Jetzt sollte man natürlich prüfen, ob da eine Sitzung offen ist usw., aber für den Proof of Concept schauen wir einfach nur, ob eine Disk für diesen User an diesem Host eingebunden ist:

$disk_id = (Get-WMIObject -ComputerName $rdsh -Class Win32_Volume | where { ($_.Label –like "User Disk") –and ($_.Name –like "C:\Users\$user_sam\") }).DeviceID

Um die Disk nun auszuhängen, muss man auf dem Terminalserver den folgenden Befehl ausführen:

Get-DiskImage –DevicePath $disk_id.Substring(0,$disk_id.Length -1) | Dismount-DiskImage

Das Problem dabei ist, dieser Befehl muss mit erhöhten Rechten ausgeführt werden. Damit scheidet PowerShell-Remoting als Vehikel schon mal aus.
Ein Ansatz wäre es, auf allen Terminalservern einen geplanten Task mit erhöhten Rechten einzurichten, der aus einer Datei die Platten-ID liest und sie dann aushängt. Dann würde man remote die Datei beschreiben und anschließend den geplanten Task anschubsen.
Ich habe ein Skript auf PSGallery veröffentlicht, das alle möglichen Sicherheitsabfragen und Automatismen implementiert und am Ende den Befehl ausgibt, den man am Terminalserver per Copy&Paste eingeben muss: https://www.powershellgallery.com/packages/Disconnect-RDUserProfileDisk

Tags » «

+