Powershell Funktion mit [ref] Parameter aufrufen

Habe schon lange nichts mehr gepostet, liegt daran, dass ich zur Zeit nichts erwähnenswertes habe. Seit kurzem Beschäftige ich mich mit der Powershell. Anfangs eher skeptisch, bin ich nun totaler Freund der PS!

Ein wenig Erfahrung in Programmierung und .Net-Framework kann übrigens nicht schaden 🙂 

Eine Funktion kann mit „call by reference“ aufgerufen werden. Wichtig ist dabei, dass sowohl in der Funktion, als auch imAufruf der Parameter [ref] verwendet wird.

Funktionen werden einfach per Namen angegeben und deren Parameter übergeben.
Beispiele:
MyFunction($x,$y,$z)
MyFunction($x)($y)($z)
(ist identisch mit der vorherigen Variante)

Bei Verwendung von referenzierten Werten (auch wenn nur ein Ref-Wert dabei ist), müssen alle Aufrufparameter so angegeben werden:
MyFuntion([ref]$x)($y)($z)

Der Aufruf mit
MyFunction([ref]$x, $y, $z) geht nicht!!!!

Da würde dann folgender Fehler auftreten:
Reference type is expected in argument. MyFunction(< <<<<  )

Auf den Referenzierten Wert kann man innerhalb der Funktion nur über $Variable.Value zugreifen. Alles andere geht schief.

(Das funktioniert auch bei referenzierten Objekten.)

Beispiel:

FUNCTION ChangeValue([ref]$a) {
$a.Value=“Neuer Wert in Function“
}

Aufruf: 

$Input=“Grundwert“
changevalue([ref]$Input)
Write-host $Input

liefert „Neuer Wert in Function“

Übergabe mehrerer Parameter muss explizit angegeben werden. Das sieht dann in etwa so aus:

FUNCTION Swap([ref]$Var1, [ref] $var2) {
$var1.Value=“Neuer Wert Variable1″
$var2.Value=“Neuer Wert Variable2″
}

Aufruf erfolgt dann so:

Swap([ref]$In1)([ref]$In2)
 

Über ADSystemInfo den Benutzer DN ermitteln

So kann man relativ leicht auf Benutzerinfos des angemeldeten Benutzers zugreifen:

Set oRootDSE = GetObject(ldap://RootDSE/)
Set oADSystemInfo = CreateObject(”ADSystemInfo”)
Set oUser = GetObject(”LDAP://” & oADSystemInfo.UserName)

bzw. noch mehr Infos:

Set objADSysInf = CreateObject(„ADSystemInfo“)
WScript.Echo objADSysInf.UserName
WScript.Echo objADSysInf.ComputerName
WScript.Echo objADSysInf.DomainDNSName
WScript.Echo objADSysInf.DomainShortName
WScript.Echo objADSysInf.SiteName
WScript.Echo objADSysInf.PDCRoleOwner
WScript.Echo objADSysInf.IsNativeMode

strSrv = objADSysInf.GetAnyDCName
WScript.Echo strSrv
WScript.Echo objADSysInf.GetDCSiteName(strSrv)
WScript.Echo Join(objADSysInf.GetTrees, „; „)

Damit kann man dann sofort auf das User-Objekt zugreifen, ohne erst lange anhand des Anmeldenames im ADS den Benutzer zu suchen.

In VB.Net folgende Deklaration verwenden(IADsADSystemInfo):

Dim adSys as New ADSystemInfo

Wie immer: Vorher lesen, dann ausprobieren!

Default Computercontainer für neue Computer umbenennen

Neue Computer werden per Default in den Container CN=Computers aufgenommen. Dumm nur, dass hier keine Policy gesetzt werden kann, das geht nämlich nur auf Organisationseinheiten. Der Admin hat dann zus. noch den Computer in die gewünschte Ziel OU zu verschieben.

Oder:

Redircmp.exe „DN-Pfad der OU“

Leitet den Ordner quasi um. Damit kann man eine Organisationseinheit festlegen, wo die neuen Computer immer landen.

Beispiel:

Redircmp.exe OU=Clients,OU=Computer,DC=Meine-Domain,DC=int

Für User gibt’s das auch, was dafür der Grund ist weiß ich aber nicht. Ich lege Benutzer sowieso immer manuell an, dann muss ich auch die OU auswählen. Für User heißt der Befehl übrigens RedirUsr.exe.

Hier der Link zum MS-Artikel: http://support.microsoft.com/kb/324949/en-us

Das ganze funktioniert erst in Windows 2003 Domänen.

 

 

Group Policy anhand lokaler Admingruppenmitgliedschaft zuweisen

Diese kleine Herausforderung kommt von einem Kunden, der den Local Admin Manager einsetzt. LAM v3.2 steuert zentral die Mitgliedschaft in der lokalen Admingruppe am Client. D.h. ein Benutzer kann gezielt an nur einem PC als lokaler Administrator eingetragen werden. So weit recht praktisch. Der Kunde setzt zwei Policies ein, eine für lokale Administratoren, eine für normale Benutzer (ohne Adminrechte). Dementsprechend soll der Desktop angepasst sein. Folglich kommt der Benutzer in die Sicherheitsgruppe für die Admin-Policy. Die „normale“ Policy wird im verweigert, ebenfalls über eine Sicherheitsgruppe.

Nun kann der Benutzer, der z.B. am PC100 lokaler Admin ist, sich aber auch an PCs anmelden, an denen er nicht lokaler Administrator ist und erhält trotzdem seine Group Policy als Administrator. Er hat zwar keine Rechte an dem PC, dennoch sind die ein oder anderen Optionen für Admins freigeschalten, so dass er diese auswählen könnte.

Die Herausforderung ist, dass der Benutzer NUR an dem PC die Group Policy als lokaler Admin bekommt, wo er auch in der lokalen Gruppe „Administratoren“ eingetragen ist. An allen anderen PCs soll die normale Group Policy ziehen.

Zur Info: Group Policies werden auf OU Ebene gesetzt und ziehen für den Benutzer/Computer innerhalb dieser OU-Struktur. Als weitere Einschränkung ist es noch möglich, die Zuweisung der Policy durch Gruppenmitgliedschaften zu „filtern“. D.h. nur Mitglieder in einer bestimmten Sicherheitsgruppe können die Policy anwenden.

Über WMI Filter können noch weitere Zuweisungsoptionen gesetzt werden. Dazu muss man sich in WMI jedoch ein bischen auskennen 🙂

In mehreren verschiedenen Versuchen habe ich feststellen dürfen, dass es mit lokalen Gruppen nicht funktioniert. WMI Filter waren kaum zu erstellen, da ja das Ergebnis eines Filters nur TRUE oder FALSE zurückliefern darf. Der WMI Abfragestring darf auch nicht sehr umfassend sein, sonst kann WMI damit nicht umgehen. UND (die größte Hürde!): Ich kann auch lokaler Admin sein, ohne direkt in der Admingruppe Mitglied zu sein…..

Eine Lösung muss es aber geben!

Nachdem ich mich nach langer Pause mit diesem Thema wiedermal beschäftigt habe, bin ich auf folgende Lösung gestoßen:

  1. es kann nur mit dem WMI Filter gehen, lokale Sicherheitsgruppen ziehen nicht. (können nicht mal eingegeben werden), etwas anderes „lokales“ kann ich nicht auswerten
  2. Welcher WMI Filter macht Sinn? Am Besten eine einfache Abfrage, die TRUE oder FALSE zurückliefert.
  3. Ich habe ein Logonscript, welches einen Wert in die Registry schreibt. Das geht aber nur, wenn ich lokaler Admin bin!
  4. Die Reihenfolge der Policies muss berücksichtigt werden.

Daraus ist erst mal dieses Script entstanden: „Group Policy anhand lokaler Admingruppenmitgliedschaft zuweisen“ weiterlesen

User Printer Manager UPM

User Printer Manager mappt beim Anmelden an den PC die zugewiesenen/definierten Drucker. Die Drucker können an folgende Objekte zugewiesen werden:

  1. Benutzer
  2. Computer
  3. Organisationseinheit

Wer also an einen Computer einen Drucker binden möchte, weil dort z.B. die Ausgangslieferscheine gedruckt werden, der definiert den Drucker an das Computerobjekt. Egal wer sich dann dort anmeldet, er bekommt immer den Drucker zugewiesen.

Am Benutzer Drucker zu definieren erklärt sich ja von selbst. Das bedeutet, der Benutzer bekommt immer die definierten Drucker gemappt, egal wo er sich anmeldet.

Das Zuweisen auf OU Ebene ist eine Besonderheit und kann für „allgemeine“ Druckermappings verwendet werden. Wer z.B. eine geografische OU Struktur einsetzt, kann für Räume, Etagen oder Gebäude spezielle Drucker definieren, die immer gemappt werden sollen. Dto. auch für organistorische OU Strukturen (Abteilungen, Bereiche usw.)

Jeder Benutzer kann sich natürlich auch noch selbst Drucker hinzufügen (Es soll ja Benutzer geben, die das können 😉 !) Der Administrator hat jedoch die Möglichkeit, dass bereits gemappte Drucker vor dem Zuweisen der definierten Drucker entfernt werden. So kann der Admin sicherstellen, dass keine „verwaisten“ Drucker am Benutzer zurückbleiben und dadurch Performanceprobleme bei Applikationen (Word) hervorrufen. (Wysiwyg benötigt ja vorher die Druckerdefinition, wie es ausgedruckt werden könnte. Wenn der Drucker aber gar nicht mehr existiert, dann versucht Word so lange auf den Drucker zuzugreifen, bis ein Time Out eintritt.)

Wenn die auf OU Ebene zugewiesenen Drucker nicht verwendet werden sollen/können, dann gibt es noch die Möglichkeit, die Vererbung der zugewiesenen Drucker zu unterbrechen und für das Objekt neue Drucker festzulegen.

Bis hierher nix neues.

Ab sofort sind folgende Features zus. verfügbar:

  1. Individuelle Default Drucker Einstellungen für den jeweiligen Benutzer vorgeben (damit sind nicht die Default Printing Preferences durch den Druckertreiber gemeint!)
  2. Eigenschaften des Druckers können direkt aufgerufen werden (Kein Wechsel der Adminkonsolen nötig)
  3. Druckerwarteschlange öffnen
  4. Druckserver Eigenschaften direkt aus der Konsole anzeigen

Damit soll die Druckeradministration noch mehr in den UPM integriert werden, ohne jedesmal die Konsolen zu wechseln.

upm-contextmenu.JPG

 

 

Wo stehen die Benutzerdefinierten Druckeinstellungen?

HKCU\Printers\Connections\Druckername oder HKCU\Printers\DevModes2

 

Mapping der Drucker am PC und welche Auswirkungen hat das Ganze

Beispiel: Der Benutzer Hans, Matthias meldet sich am PC an.

Ein Logonscript, welches über eine Group Policy auf die OU (oder Domäne) gemappt wurde, läuft ab und ermittelt erst mal, welcher User sich an welchem Computer anmeldet. Dann wird noch geprüft, welcher Default Drucker eingestellt ist.

Wenn das Flag „vor Zuweisung löschen“ gesetzt ist, dann werden jetzt alle Netzwerkdrucker gelöscht. Lokale Drucker bleiben erhalten!

Anschließend werden die definierten Drucker vom Computer, OU und dann noch vom User ausgelesen und zugewiesen.

Wenn der Benutzer an diesem Computer noch nie angemeldet war, dann hatte er an diesem PC auch noch nie einen Default Drucker. Durch das Häckchen am entsprechenden Drucker (in der UPM Managementkonsole) wird ihm der Defaultdrucker vorgegeben.

Sollte der User schon einen Defaultdrucker (oder sagen wir „Lieblingsdrucker“) ausgewählt haben, wird am Ende des Logonscriptes ihm dieser wieder als Defaultdrucker eingestellt. Die Häckchen in der Managementkonsole haben dann keine Bedeutung mehr.

Sollte durch den Administrator noch die Druckereinstellung vorgegeben worden sein, dann wird diese jetzt auch noch eingetragen.

(Druckereinstellungen für den Benutzer sind z.B. Zuführungsschacht, Ausgabeschacht Papierart/typ die von den Standards abweichen sollen.)

MH

 

Active Directory Benutzer in einen Exchange öffentlichen Ordner importieren

Eigentlich ist das Globale Adressbuch von Outlook genau der Inhalt aller Mailbenutzer aus dem Active Directory. Ich hatte allerdings einen Kunden, der VoIP verwendet, und die Rufnummern aus dem globalen Adressbuch verwenden wollte. Da die TAPI Schnittstelle das aber nicht unterstützt (im globalen Adressbuch sind es keine IPM.Contact Elemente), sollten die ADS User in einen öffentlichen Ordner importiert werden. Dort sind die Kontakte dann IPM.Contact Elemente, mit denen konnte VoIP wieder was anfangen.

Über den Sinn/Unsinn läßt sich natürlich wieder diskutieren (haben wir auch 🙂 ). Der Sinn solcher Kundenwünsche muss sich mir ja nicht immer erschließen, es reicht ja, wenn der Kunde weiß was er damit machen will. Außerdem war es mal eine neue Herausforderung, das ganze via Script zu machen. „Active Directory Benutzer in einen Exchange öffentlichen Ordner importieren“ weiterlesen

Einen deaktivierten Benutzer wieder aktivieren (oder anders herum)

Ein deaktivierter Benutzer kann im ADS sehr einfach scriptgesteuert aktiviert werden. Es geht auch anders herum; so dass ein Benutzer via Script einfach deaktiviert wird. Es gibt mehrere Provider mit denen man das durchführen kann, da ich aber quick and dirty jetzt diese Funktion brauche, habe ich mich für den WinNT Provider entschieden. Da muss ich nur den samAccountNamen haben, schon kann ich loslegen. Wenn es über LDAP gemacht werden soll, dann muss ich den kompletten Distinguished Namen des Objektes kennen. Das ist mir jetzt aber zu viel Aufwand, das jedesmal zu ermitteln.

Über Parameter kann man das Script ganz einfach erweitern. z.B. kann über eine Inputbox der samAccountName abgefragt werden.

Set objUser = GetObject(„WinNT://NETBIOSDOMÄNE/aetest“)

objUser.AccountDisabled = False
objUser.SetInfo

Msgbox „Account wurde aktiviert!“,vbokonly+vbinformation,“Enable Account“
 

 

Bei Scripten gilt immer: Erst den Quellcode lesen, dann ausprobieren.

 

CommonDialog mit VB Script verwenden

Mit VB Script kann auch auf das CommonDialog Objekt von Windows zugegriffen werden. Es stehen nicht alle Methoden zur Verfügung, aber zum Auswählen von Dateien reicht es allemal!

Mit VB Script kann auch auf das CommonDialog Objekt von Windows zugegriffen werden. Es stehen nicht alle Methoden zur Verfügung, aber zum Auswählen von Dateien reicht es allemal! „CommonDialog mit VB Script verwenden“ weiterlesen

extraColumns in der ADS MMC

Die Spalten, die in der ADS MMC angezeigt werden, können seit Windows 2003 ADS durch eigene Spalten ergänzt werden. Es können (fast) alle Attribute von allen Objekten hinzugefügt werden. Das macht natürlich nur Sinn, wenn die Werte auch brauchbare Inhalte haben. Ich verwende typischerweise eigene Attribute, die mit Werten beim Starten des Computers oder beim Anmelden eines Benutzers durch Scripte geschrieben werden.

Kleines Beispiel: Ein Kunde wollte die MAC Adresse der primären Netzwerkkarte dort stehen haben, um WOL zu verwenden. Es kann aber auch einfach nur die Betriebssystemversion/bezeichnung hinzugefügt werden. Hier die Kurzversion, wie’s geht: (Erfahrung im ADS wird vorausgesetzt! Wenn nicht, lass‘ einfach die Finger davon, sonst kannst Du mehr kaputt machen, als dir lieb ist!)

The Add/Remove Columns dialog box displays only the columns that are contained in the extraColumns attribute of the displaySpecifier object of the container type that is being displayed. If the extraColumns attribute does not contain any values, the Add/Remove Columns dialog box will display a fixed set of columns. A copy of the fixed set of columns is contained in the extraColumns attribute of the default-Display object.   To add one or more columns to the list of columns for a specific object, you must copy all of the extraColumns values from the default-Display object to the target object and then add the custom columns. If you specify the extraColumns attribute on a given class, then that class will use those columns and will not merge them with the columns that are specified in the default-Display class. Therefore, further changes to the default-Display class will have no effect on that object. To display a custom column for all container types that do not have any custom columns registered, add a value for the column to the extraColumns attribute of the default-Display object.

Am Beispiel:

For example, to add a column that will display the canonical name for objects in an organizational unit, a value for the canonicalName attribute is added to the extraColumns attribute of the organizationalUnit-Display object in the display specifiers container. The string added to the extraColumns attribute of the organizationalUnit-Display object will look like the following.
 
  canonicalName,Canonical Name,0,150,0

Aufbau des Attributes extraColums im Allgemeinen:

     Ldapdisplayname , column header , default visibility , width , unused    

 

Zugriff auf Active Directory Daten

Welche Möglichkeiten gibt es, auf die ADS Informationen zuzugreifen?

  • ds-Programme von Microsoft (sind bei Windows dabei, wie z.B. dsadd.exe usw.)
  • ADS Management Tools (Users and Computers, usw.)
  • adsiedit.msc, Attribut Editor von Microsoft
  • ADODB, Active Data Objects for Data Bases, also via Microsoft Provider wie z.B. „ADsDSOObject“
  • ADSI-SDK Schnittstelle (ADSI 2.5)

Ich bevorzuge die beiden Varianten ADODB und ADSI-Schnittstelle. Diese Varianten kann ich Scriptieren oder in Programme einbauen. „Zugriff auf Active Directory Daten“ weiterlesen