Foto im Active Directory hinterlegen und bei Benutzeranmeldung anzeigen
Aus znilwiki
Changelog:
- 28.05.2015: Erste Version
- 01.06.2015: Version 1.0.0.5: Erkennt ob das Bild im AD als .PNG oder .JPEG gespeichert ist und speichert es mit der entsprechenden Dateiendung
Vorwort
Bei der Anmeldung an Windows wird seit Windows Vista ein kleines Bildchen gezeigt - welches er sich auch selbst setzen kann:
Die Bilder der Benutzer liegen dabei immer lokal unter
C:\ProgramData\Microsoft\User Account Pictures
Da liegen auch schon 2 Dateien, die
user.bmp
wird dabei immer für neue Benutzer genommen wenn dieser sich kein eigenes Bild setzt.
Wenn Ihr also dieses Bild austauscht (Bitte mit gleichen Abmessungen und Format etc.) würde alle Benutzer dieses Bild erhalten.
Foto im Active Directory hinterlegen
Nun gibt es seit Windows Server 2008 und der dazu gehörigen Active Directory Version die Möglichkeit bei jedem Benutzer 2 Bilder im AD zu hinterlegen.
Diese werden in den Attributen
thumbnailPhoto jpegPhoto
hinterlegt. Exchange ab 2007 bzw. Outlook verwendet ausschließlich das Bild welches unter thumbnailPhoto hinterlegt wird.
Wir verwenden deshalb in diesen Artikel auch ausschließlich dieses Attribut.
Leider gibt es keine direkte Möglichkeit in der GUI diese Bilder zu bearbeiten - zu mindest ab Werk.
Unter Exchange gibt es entsprechende PowerShell CMDlets hierfür ... aber gerade hierbei bevorzuge ich doch die Optische Kontrolle.
Nachfolgend stelle ich 3 Möglichkeiten vor die mir sehr gut gefallen haben - und die Ihr beide parallel einsetzen könnt.
AD Photo Edit
Unter
http://www.cjwdev.co.uk/Software/ADPhotoEdit/Info.html
Könnt Ihr das Programm AD Photo Edit herunterladen.
Für erste Gehversuche reicht die Free Edition. Die kostenpflichtige Bulk Edition kann per Kommandozeile gesteuert werden und bietet sich zum Massenimport an.
In der Free Version könnt Ihr die Benutzer nur einzeln bearbeiten.
Ihr müsst die Anwendung als ein Domänen-Administrator starten!
Nach dem Start der Anwendung könnt Ihr unter Name den Benutzernamen des Benutzer angeben den Ihr bearbeiten wollt.
Lasst Ihr das Feld leer und klickt dann auf Search so zeigt er alle Benutzer an.
Markiert links einen Benutzer und klickt dann rechts auf EditImage:
CodeTwo Active Photos
Das Tool ist Kostenlos auch bei einem Massenimport (im Gegensatz zum vorherigen) und kann auf der Webseite des Herstellers heruntergeladen werden:
http://www.codetwo.de/freeware/active-directory-photos/ http://www.codetwo.de/downloads/C2ADPhotosSetupEN.exe
Man kann damit komfortabel seine AD-Struktur durchforsten:
Der Rest funktioniert ähnlich wie zuvor.
ADExt von Oli Dewdney
Oli Dewdney hat eine Erweiterung für die 'Active Directory-Benutzer und Computer geschrieben.
Leider ist seine Webseite nicht mehr erreichbar, deshalb bin ich mal so frei und biete den Download hier einmal an:
ADExt.zip
Die Installation ist auch als Textdatei in dem Archiv enthalten.
Kopiert die
adExt.dll
nach
C:\Windows\System32
auf einem Server / Computer auf dem auch die Active Directory Verwaltungstools installiert sind, typischerweise also z.B. einen Domänencontroller.
Startet danach eine Eingabeaufforderung und ruft folgenden Befehl auf:
C:\Windows\Microsoft.NET\Framework64\v2.0.50727\InstallUtil.exe C:\Windows\System32\adExt.dll
Wenn Ihr nun die Konsole Active Directory-Benutzer und Computer öffnet und einen Benutzer bearbeitet so habt Ihr einen weiteren Karteireiter Photo:
Im Gegensatz zum AD Photo Edit rechnet der Bilder hierbei zwingend auf 96x96 Pixel herunter.
Windows 10
Das nächste Kapitel funktioniert unter Windows 7 / Server 2008 R2. Für Windows 10 habe ich das hier gefunden:
heineborn.com/tech/ad-user-pictures-in-windows-10
Eine eigene Umsetzung durch mein AutoIt Tool steht noch aus. Mache ich wenn ich es in einem Projekt brauche.
Foto auf Rechner und Servern bei der Anmeldung nutzen
So, die Bilder liegen also im Active Directory ... damit Windows diese aber bei der Anmeldung nutzt müssen diese im richtigen Format und Namen im Ordner
C:\ProgramData\Microsoft\User Account Pictures
hinterlegt werden ... einem Ordner auf den der Benutzer gar keine Schreibrechte hat.
Nun, die Lösung ist etwas bei der Anmeldung zu tun - per Script - welches das Bild ausliest und für den Benutzer setzt.
Nach etwas suchen fand ich mehrere Ansätze im Internet:
* PowerShell: http://www.reddit.com/r/sysadmin/comments/1dqv74/load_users_thumbnailphoto_attribute_to_windows/ * PowerShell: https://gallery.technet.microsoft.com/scriptcenter/Set-Windows-7-User-Tile-to-044f16d2
Die PowerShell Scripte haben wieder den Nachteil das diese einen Fehler auswerfen wenn die Powershell selbst nicht mit den richtigen Parametern gestartet werden.
Zudem muss die Ausführen nicht- oder selbstsignierter Scripte erlaubt werden usw. ... mag ich alles nicht
Dem Scripten konnte ich aber entnehmen das man eine DLL-Funktion aufrufen kann um das Bild für den Benutzer zu setzen.
Mit Regshot stellte ich fest dazu hierzu keinerlei Informationen in der Registry abgelegt werden - es wird nur eine
DOMAIN+USERNAME.dat
erstellt und abgelegt, wenn die Domäne ZNIL und der Anmeldename Bernhard ist also eine Datei
ZNIL+Bernhard.dat
Und dem Betriebssystem wird mitgeteilt das es die Daten hierzu einmal neu einlesen soll.
Dazu enthält die shell32.dll die Funktionen SetUserTile / ChangeUserTile.
Wie fast immer wollte ich mir etwas passendes in AutoIt nachprogrammieren - doch das hatte schon bereits jemand umgesetzt:
* AutoIt: https://www.autoitscript.com/forum/topic/127691-change-windows-profile-icon-tile/
Das ist allerdings ein sehr rudimentäres Beispiel ohne Fehlerbehandlung.
Wird es zum Beispiel von einem nicht-Domänenbenutzer aufgerufen oder passt sonst etwas nicht erscheint eine Warnfenster über einen Script-Fehler.
Aus gibt es sonst keinerlei Ausgaben über Erfolg oder Misserfolg etc.
Ich habe deshalb eine eigene Variante anhand des Beispiels erstellt:
Download: ADProfilePicture.zip
Das Tool kann einfach in ein Anmeldekript aufgenommen werden - oder einfach von Hand testen:
Es sucht sich das AD-Objekt des aktuell angemeldeten Benutzers, extrahiert das Bild und speichert es im Benutzerprofil und setzt es als Benutzerbild lokal auf dem Rechner.
Die Änderungen werden unmittelbar übernommen - Ihr könnt also das Bild im Active Directory ändern und danach das Tool einfach noch mal starten.
Download
Download: ADProfilePicture.zip
Quellcode
Hier mein Quellcode dazu:
#NoTrayIcon
#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Icon=Icon256-32.ico
#AutoIt3Wrapper_UseUpx=y
#AutoIt3Wrapper_Change2CUI=y
#AutoIt3Wrapper_Res_Comment=2015 Bernhard Linz
#AutoIt3Wrapper_Res_Fileversion=1.0.0.6
#AutoIt3Wrapper_Res_Fileversion_AutoIncrement=y
#AutoIt3Wrapper_Res_SaveSource=y
#AutoIt3Wrapper_Res_Language=1031
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
#include <FileConstants.au3>
Opt('MustDeclareVars', 1)
; 2015 von Bernhard Linz für http://znil.net
; Bernhard@znil.de
; Bernhard.Linz@datagroup.de
; Holt sich aus dem Active Directory das dort hinterlegte Profilbild aus der Eigenschaft "thumbnailPhoto" und hinterlegt diese lokal auf dem Rechner
; unter C:\ProgramData\Microsoft\User Account Pictures bzw. setzt dieses so das es dort gespeichert wird.
; Dann wird im Startmenü und bei der Anmeldung eben dieses Bild gezeigt
; gefunden unter https://www.autoitscript.com/forum/topic/127691-change-windows-profile-icon-tile/
; ergänzt um eine Fehlerbehandlung / Fehlermeldungen und Statusmeldungen etc.
; #####################################################################################
; Vraibalen definieren
; $h_ = Handle / Zeiger
; $o_ = Objekt
; $s_ = String / Text
; $i_ = "Integer" = Zahl / Nummer
; $b_ = Boolean
; $a_ = Array
Global $o_MyError ; Zeiger auf die eigene Fehlerbehandlungsroutine
Global $h_thumbnailPhotoFile ; Handle auf Datei mit dem Profilbild
Global $s_thumbnailPhotoDATA ; Die Bildaten aus dem Active Directory
Global $o_ActiveDirectoryConnection ; Zeiger auf die Active Directory Verbindung
Global $s_DNSDomain ; DNS-Domänenname
Global $s_DomainController ; DNS-Hostname eines Domänencontrollers
Global $s_AD_Query ; Abfrageergebnis der Suche nach dem Benutzer im AD
Global $o_Command ; Objekt für Befehl gegen das Active Directory
Global $o_RootDSE ; Objekt für das Active Directory der Benutzerdomäne
Global $o_RecordSet ; Objekt für den Benutzereintrag im Active Directory
Global $o_LDAP ; Objekt für die eigentlichen Werte
Global $h_thumbnailPhotoDLLPath ; DLL Struktur mit dem Zeiger auf das Bild für DLL-Funktionsaufruf
Global $h_UserNameDLL ; DLL Struktur mit dem Zeiger auf den Benutzernamen für den DLL-Funktionsaufruf
Global $a_Return ; Array mit dem Ergebnis des DLL-Aufrufes
Global $s_Fileextension ; Daten könne als PNG oder JPEG hinterlegt sein
; #####################################################################################
; Funktionen
Func oMyError()
ConsoleWrite(@ScriptName & " - Error Reading or Setting Profile Picture" & @CRLF)
EndFunc
; #####################################################################################
; Hauptprogramm
; Eigene Fehlerbehandlungsroutine setzen - greift bei Problemen und unterdrückt Fehlerdialoge
$o_MyError = ObjEvent("AutoIt.Error", "oMyError") ; Install a custom error handler
; Verbindung zum Active Directory herstellen
ConsoleWrite(@ScriptName & " - Connecting Active Directory ... ")
$o_ActiveDirectoryConnection = ObjCreate ( "ADODB.Connection" )
$o_ActiveDirectoryConnection.Provider = "ADsDSOObject"
$o_ActiveDirectoryConnection.Open ( "Active Directory Provider" )
; Set AD connection for command ... wofür auch immer das gebraucht wird
$o_Command = ObjCreate ( "ADODB.Command" )
If Not IsObj ( $o_Command ) Then
ConsoleWrite(@ScriptName & " - Could not startup the Active Directory Provider" & @CRLF)
Exit 1
EndIf
$o_Command.ActiveConnection = $o_ActiveDirectoryConnection
ConsoleWrite("connected!" & @CRLF)
; Daten aus AD ermitteln:
ConsoleWrite(@ScriptName & " - Query Active Directory for User " & @UserName & @CRLF)
$o_RootDSE = ObjGet ( "LDAP://RootDSE" )
If @Error Then
ConsoleWrite("No Connection to Active Directory possible" & @CRLF)
Exit
EndIf
$s_DNSDomain = $o_RootDSE.Get ( "defaultNamingContext" ) ; Retrieve the current AD domain name
$s_DomainController = $o_RootDSE.Get ( "dnsHostName" )
ConsoleWrite(@ScriptName & " - Domain Name : " & $s_DNSDomain & @CRLF)
ConsoleWrite(@ScriptName & " - Domain Controller : " & $s_DomainController & @CRLF)
$s_AD_Query = "<LDAP://" & $s_DomainController & "/" & $s_DNSDomain & ">;(sAMAccountName=" & @UserName & ");distinguishedName;subtree"
$o_RecordSet = $o_ActiveDirectoryConnection.Execute ($s_AD_Query)
$o_LDAP = ObjGet ( "LDAP://" & $o_RecordSet.fields (0).value )
$s_thumbnailPhotoDATA = $o_LDAP.thumbnailPhoto
$o_ActiveDirectoryConnection.Close ( )
; Prüfen on denn Bilddaten vorliegen
If $s_thumbnailPhotoDATA = "" Then
; Keine Bilddaten!
ConsoleWrite(@ScriptName & " - User " & @UserName & " have no thumbnailPhoto stored in Active Directory!" & @CRLF)
Exit 1
EndIf
; Kopie des Bildes im Benutzerprofil-Verzeichnis speichern
If StringInStr(BinaryToString($s_thumbnailPhotoDATA), "PNG") > 0 Then
$s_Fileextension = ".png"
Else
$s_Fileextension = ".jpg"
EndIf
ConsoleWrite(@ScriptName & " - save Copy of thumbnailPhoto in Userprofil (" & @UserProfileDir & "\thumbnailPhoto" & $s_Fileextension & ")" & @CRLF)
$h_thumbnailPhotoFile = FileOpen ( @UserProfileDir & "\thumbnailPhoto" & $s_Fileextension, $FO_OVERWRITE + $FO_BINARY)
FileWrite ( $h_thumbnailPhotoFile, $s_thumbnailPhotoDATA )
FileClose ( $h_thumbnailPhotoFile )
; DLL-Routine aufrufen um das Bild für den Benutzer lokal auf dem Rechner/Server zu setzen:
ConsoleWrite(@ScriptName & " - activate thumbnailPhoto at local System ... ")
DLLCall("ole32.dll","int","CoInitialize","ptr",0)
$h_thumbnailPhotoDLLPath = DLLStructCreate("wchar[128]")
DllStructSetData($h_thumbnailPhotoDLLPath, 1, @UserProfileDir & "\thumbnailPhoto" & $s_Fileextension)
$h_UserNameDLL = DLLStructCreate("wchar[128]")
DllStructSetData($h_UserNameDLL, 1, @LogonDomain & "\" & @UserName)
$a_Return = DllCall(@SystemDir & "\shell32.dll", "long", 262, "ptr", DllStructGetPtr($h_UserNameDLL), "int", 0, "ptr", DllStructGetPtr($h_thumbnailPhotoDLLPath))
ConsoleWrite("done!" & @CRLF)
Exit 0