Aktionen

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

Important.png
Hinweis:Das ganz habe ich damals für Windows 7 geschrieben - unter W10 braucht man das eigentlich nicht mehr.

Bei der Anmeldung an Windows wird seit Windows Vista ein kleines Bildchen gezeigt - welches er sich auch selbst setzen kann:

UserAccountPictures-001.png


Die Bilder der Benutzer liegen dabei immer lokal unter

C:\ProgramData\Microsoft\User Account Pictures

UserAccountPictures-002.png

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.

UserAccountPictures-003.png


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.

UserAccountPictures-004.png


Markiert links einen Benutzer und klickt dann rechts auf EditImage:

UserAccountPictures-005.png


UserAccountPictures-006.png




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:

UserAccountPictures-008.png


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:

UserAccountPictures-007.png


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:

UserAccountPictures-009.png


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




Kommentare

Loading comments...