1 Testdaten
1.1 OU Struktur anlegen
      Beispiel 1: Erstellen einer einfachen OU-Struktur mit der Add-Methode der DirectoryEntry-Klasse
1.2 Computerkonten anlegen
      Beispiel 1: Anlage von Computerkonten mit der Add-Methode der DirectoryEntry-Klasse
      Beispiel 2: Anlage von Computerkonten nit dem cmdlet New-AdComputer
1.3 Userkonten anlegen
      Beispiel 1: Anlage von User konten mit der Add-Methode der DirectoryEntry-Klasse
1.4 Gruppen anlegen
      Beispiel 1: Anlage globaler Gruppen

 

1 Testdaten

Zum Entwickleln von Skripten für ActiveDirectory ist eine einfache, dennoch relativ praxisnahe Struktur am Testsystem aus verschiedenen Objekten wie OUs, Usern undsoweiter recht hilfreich,  Mit den nachfolgenden Beispielen könnt ihr bei Bedarf eine solche Struktur innerhalb einer Domäne anlegen.

Die Gesamtstruktur besteht bei mir aus einer Root (2008R2) und zwei Childdomänen (2008R2 und 2012R2), mit jeweils einem DC.



In den Childdomains lege ich domänenweise im Folgenden eine verschachtelte OU-Struktur nach Standorten (=Städten) an.
 

1.1 OU Struktur anlegen (Add-Methode der DirectoryEntry-Klasse)

Um eine einfache OUStruktur, erstmal ohne Rechte, GPOs oder ähnlichem, zu erstellen, könnt ihr dieses kleine Skript benutzen

Beispiel 1: Erstellen einer OU-Struktur

Set-StrictMode -Version "2.0"
Clear-Host

Function Main{
 
  #Defining parameters for the OUNames
  $Locations = @("Bangkok","Beijing","Dhaka","Tokio")
  $Root = "Scripting"
 
  $DomainDN = ([ADSI]"LDAP://RootDSE").DefaultNamingContext
  $Oudns = $Locations | Create-Oudns $Root 
  Foreach($OuDN in $OuDNs){
      If( [ADSI]::Exists("LDAP://$OUDN,$DomainDN") -ne $True) {
        Create-Ou $DomainDN $OuDn
      }Else{
        Write-Host "$OUDN existiert bereits"
      }
  }
} #End Main
 
Function Create-OU{
  [CmdletBinding()]
  Param($DomainDN,$OuDn)

  $SplittedOus = $OuDN.Split(",")
  $Class = "OrganizationalUnit"
  $ADSI=[ADSI]"LDAP://$DomainDN"

  #Die erste Ou wird extra angelegt, wegen dem Komma im LDAP-Pfad "LDAP://$Path,$DomainDN"
  $NewOU = $ADSI.Create($Class,$SplittedOus[$($SplittedOus.Count)-1])
  If( [ADSI]::Exists($NewOU.Path) -ne $True) {
    $NewOU.CommitChanges()
    Write-Host $SplittedOus[$($SplittedOus.Count)-1] "wurde erfolgreich erstellt (1)"
  }#if
  $Path = $SplittedOus[$($SplittedOus.Count)-1]  
       
  #Anlage aller weiteren OUs
  For ($i = $($SplittedOus.Count)-2;$i -ge 0;$i--){
    $ADSI=[ADSI]"LDAP://$Path,$DomainDN"
    $NewOU = $ADSI.Create($Class,$SplittedOus[$i])
    $Path = $SplittedOus[$i] + "," + $Path
    If( [ADSI]::Exists("LDAP://$Path,$DomainDN") -ne $True) {
      $NewOU.CommitChanges()
      Write-Host $SplittedOus[$i] "wurde erfolgreich erstellt"
    }#if
  }#For
  ""
}#End Create-Ou

Function Create-Oudns{
  Param(
    [Parameter(mandatory=$true)]$Root,
    [Parameter(mandatory=$true, ValueFromPipeline=$true)]$Locations
)
 
  #the Begin-Block runs only once at the beginning
  Begin{
     $Oudns =@()
  }
 
  Process{
   Foreach ($Location in $Locations){
     #ComputerOUs
     $OuDNs += "OU=Subnotebooks,OU=NoteBooks,OU=Computers,OU=$Location,OU=$Root"
     $OuDNs += "OU=Desktops,OU=Computers,OU=$Location,OU=$Root"
    
     #UserOUs
     $OuDNs += "OU=IT,OU=Users,OU=$Location,OU=$Root"
     $OuDNs += "OU=Finance,OU=Users,OU=$Location,OU=$Root"
   
     #GroupOUs
     $OuDNs += "OU=Local,OU=Groups,OU=$Location,OU=$Root"
     $OuDNs += "OU=Global,OU=Groups,OU=$Location,OU=$Root"
     $OuDNs += "OU=Universal,OU=Groups,OU=$Location,OU=$Root"
 
     #ManagedServiceAccountsOU
     $OuDNs += "OU=ManagedServiceAccounts,OU=$Location,OU=$Root"
   } #Foreach
  }#Process
 
  #the Begin-Block runs only once at the end
  End{
    Return $OuDNs
  }  
}#Function Create-Oudns

Main

Das Ergebnis sollte dann etwa so aussehen

 

1.2 Computerobjekte anlegen

Wenn Ihr die OU-Struktur aus Kapitel 1.1 oben angelegt habt, könnt ihr mit dem folgenden Beispiel Objekte darin anlegen

Beispiel 1: Anlage von Computerkonten mit der Add-Methode der DirectoryEntry-Klasse

Clear-Host
Set-StrictMode -Version "2.0"

Function Main{

$Root = "Scripting"
  $Locations = @("Bangkok","Beijing","Dhaka","Tokio")
  $ComputerSubOUs = @("Desktops","Notebooks")
 
  $DomainDN = ([ADSI]"LDAP://RootDSE").DefaultNamingContext
  $CountStart = 1
  $CountEnd = 10
 
  Foreach ($ComputerSubOU in $ComputerSubOus){
    Foreach($Location in $Locations){
      $OuDN = "OU=$ComputerSubOU,OU=Computers,OU=$Location,OU=$Root"
      $Description = "Created by Create-Method"
      For($Count = $CountStart; $Count -le $CountEnd; $Count++){
        $ComputerName = $Location + $ComputerSubOU + $Count.ToString("000")

        #check existence of $computername
        If ( [Bool]([AdsiSearcher]"SamAccountName=$ComputerName$").FindOne() -ne $True )  {
           New-ComputerAccount $DomainDn $Location $OuDn $ComputerName $Description
        }Else{
           Write-Host "$ComputerName existiert bereits"
        }

      }#For count
   }#Foreach  $Location
 }#Foreach ComputerSubOU  
}#End Main

Function New-ComputerAccount{
  Param($DomainDn,$Location,$OuDn,$ComputerName,$Description)
 
  $Class = "Computer"
  $AdsiOU=[ADSI]"LDAP://$OuDN,$DomainDN"
  $AdsiComputer = $AdsiOU.Children.Add("CN=$ComputerName",$Class)
  $AdsiComputer.InvokeSet("Description", $Description)
  $AdsiComputer.InvokeSet("SamAccountName", $ComputerName+"$")
  $AdsiComputer.CommitChanges()
  Write-Host "$Computername wurde angelegt"
}#End Function

Main


MSDN: DirectoryEntries.Add Method

Anstelle der Methode $AdsiOU.Children.Add(...) kann man auch kürzer $AdsiOU.Create(...) skripten.

 

Beispiel 2: Anlage einiger Computerkonten mit dem cmdlet New-ADComputer

Wenn Ihr die OU-Struktur aus Kapitel 1.1 oben angelegt habt, könnt ihr mit dem folgenden Beispiel Objekte darin anlegen

Clear-Host
Set-StrictMode -Version "2.0"
Import-Module ActiveDirectory

Function Main{
  $Root = "Scripting"
  $Locations = @("Bangkok","Beijing","Dhaka","Tokio")
  $Description = "Created by the cmdlet New-AdComputer"
  $CountStart = 11
  $CountEnd = 20
 
  $DomainDN = ([ADSI]"LDAP://RootDSE").DefaultNamingContext
 
  Foreach($Location in $Locations){
      $OuDN = "OU=SubNotebooks,OU=Notebooks,OU=Computers,OU=$Location,OU=$Root"
      For($Count = $CountStart; $Count -le $CountEnd; $Count++){
        $ComputerName = $Location + "SubNB" + $Count.ToString("000")

        #check existence of $computername
        If ( [Bool]([AdsiSearcher]"SamAccountName=$ComputerName$").FindOne() -ne $True )  {
           New-ComputerAccount $DomainDn $Location $OuDn $ComputerName $Description
        }Else{
           Write-Host "$ComputerName already exists, change $countstart and $countend"
        }

      }#For count
   }#Foreach  $Location
}

Function New-ComputerAccount{
  Param($DomainDn,$Location,$OuDn,$ComputerName,$Description)

  $Path = "$OuDn,$DomainDN"
  $Filter = {Name -like $ComputerName}

  #check existence of $computername
  If( [Bool](Get-ADComputer -filter $Filter) -ne $True){
     New-ADComputer -Name $ComputerName -Description $Description -Path $Path
       "$Computername has been created"
  }Else{
     "$Computername already exists"
  }
 
}#Function New-ComputerAccount

Main

Technet: New-ADComputer

 

1.3 Useraccounts anlegen

Wenn Ihr die OU-Struktur aus Kapitel 1.1 oben angelegt habt, könnt ihr mit dem folgenden Beispiel Objekte darin anlegen

Beispiel 1: Anlage einiger Userkonten mit der Add-Methode der DirectoryEntry-Klasse [ADSI]

Clear-Host
Set-StrictMode -Version "2.0"

Function Main{
  $Root = "Scripting"  
  $Locations = @("Bangkok","Beijing","Dhaka","Tokio")
  $UserSubOUs = @("IT","Finance")
  $PrefixName = "User"
  $Password = "Hurra123"
  $Description = "Created by ADD-Method of ADSI"
  $CountStart = 2
  $CountEnd = 20
 
  $DomainDN = ([ADSI]"LDAP://RootDSE").DefaultNamingContext
 
  Foreach ($UserSubOU in $UserSubOus){
    Foreach($Location in $Locations){
      $OuDN = "OU=$UserSubOU,OU=Users,OU=$Location,OU=$Root"
           
      #create random identifier to avoid double samaccountnames
      $ofs = ''
      $Identifier = [string](Get-Random -input $([char[]](65..90)) -count 3)
      $ofs = ' '
            
      For($Count = $CountStart; $Count -le $CountEnd; $Count++){
        $UserName = $PrefixName + $Identifier + $Count.ToString("000")
        If ( [Bool]([AdsiSearcher]"SamAccountName=$UserName").FindOne() -ne $True )  {
           New-UserAccount $DomainDn $Location $OuDn $UserName $Description $Password
        }Else{
           Write-Host "$UserName already exists"
        }
      }#For count
   }#Foreach  $Location
 }#Foreach ComputerSubOU  
}#End Main

Function New-UserAccount{
  Param($DomainDn,$Location,$OuDn,$UserName,$Description)
 
  $Domain = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
  $DomFqdn = $Domain.Name
 
  $Sn = "$UserName"
  $SamAccountname = $UserName
  $UserPrincipalName="$SamAccountName@$DomFQDN"
   
  $Class = "User"
  $AdsiOU=[ADSI]"LDAP://$OuDN,$DomainDN"
  $AdsiUser = $AdsiOU.Children.Add("CN=$UserName",$Class)
  $AdsiUser.InvokeSet("Description", $Description)
  $AdsiUser.InvokeSet("SamAccountName", $SamAccountName)
  $AdsiUser.CommitChanges()
  Write-Host "$Username has been created"
 
  $AdsiUser.InvokeSet("UserPrincipalName",$UserPrincipalName)
  $AdsiUser.InvokeSet("Sn",$Sn)
  $AdsiUser.InvokeSet("Description",$Description)
  $AdsiUser.Invoke("SetPassword",$Password)
  $AdsiUser.InvokeSet("AccountDisabled",$False) #Alternative zu Useraccountcontol
  $AdsiUser.CommitChanges()
}#End Function

Main

MSDN: DirectoryEntries.Add Method

 

Beispiel 2: Anlage einiger Userkonten mit dem cmdlet New-ADUser

Set-StrictMode -Version "2.0"
Clear-Host
Import-Module ActiveDirectory

Function Main{
  $Root = "Scripting"  
  $Locations = @("Bangkok","Beijing","Dhaka","Tokio")
  $UserSubOUs = @("IT","Finance")
  $PrefixName = "User"
  $Password = "Hurra123"
  $SecurePassword = ConvertTo-SecureString $Password -AsPlainText -Force
  $Description = 'created with the cmdlet "AD-NewUser"'
  $CountStart = 2
  $CountEnd = 20
 
  $DomainDN =(Get-ADDomain).DistinguishedName

  Foreach ($UserSubOU in $UserSubOus){
    Foreach($Location in $Locations){
      $OuDN = "OU=$UserSubOU,OU=Users,OU=$Location,OU=$Root"
           
      #create random identifier for avoiding doubled samaccountnames
      $ofs = ''
      $Identifier = [string](Get-Random -input $([char[]](65..90)) -count 3)
      $ofs = ' '
            
      For($Count = $CountStart; $Count -le $CountEnd; $Count++){
        $UserName = $PrefixName + $Identifier + $Count.ToString("000")
        If ( [Bool]([AdsiSearcher]"SamAccountName=$UserName").FindOne() -ne $True )  {
           New-UserAccount $DomainDn $Location $OuDn $UserName $Description $Password
        }Else{
           Write-Host "$UserName already exists"
        }
      }#For count
   }#Foreach  $Location
 }#Foreach ComputerSubOU  
}#End Main

Function New-UserAccount{
  Param($DomainDn,$Location,$OuDn,$UserName,$Description)

  $Path = "$OuDn,$DomainDN"
  $Filter = {Name -like $UserName}
  If( [Bool](Get-ADUser -filter $Filter) -ne $True){
     New-ADUser -Name $UserName -Description $Description -Path $Path -AccountPasswort $SecurePassword -Enabled $True
       "$Username wurde angelegt in $path"
  }Else{
     "$Username already exists"
  }
 
}#Function New-UserAccount

Main 
UserDIU002 wurde angelegt in OU=IT,OU=Users,OU=Bangkok,OU=Scripting,DC=asia,DC=company,DC=intern
UserDIU003 wurde angelegt in OU=IT,OU=Users,OU=Bangkok,OU=Scripting,DC=asia,DC=company,DC=intern
UserDIU004 wurde angelegt in OU=IT,OU=Users,OU=Bangkok,OU=Scripting,DC=asia,DC=company,DC=intern

Als Password muss ein verschlüsselter String an New-ADUser übergeben werden: Verschlüsselung von Strings

Technet: New-ADUser

Technet: Get-ADUser

 

1.4 Gruppen anlegen

Gruppen gibt es im ActiveDirectory in verschiedenen Formen (Local, Global, Universal und Securityenabled, Distribution), insgesamt also sechs Varianten.
Programmiertechnisch unterscheiden sich die Gruppen durch Flags

MSDN: ADS_GROUP_TYPE_ENUM enumeration

Es würde unnötig viel Platz kosten, an dieser Stelle Beispiele für das Erstellen aller Möglichkeiten zu posten.

Seht euch im nächsten Beispiel den rot/ gelb eingefärbten Codeabschnitt an. Dort könnt die Flags aus dem MSDN-Link oben setzen und mit -bor kombinieren, um so Gruppen aller Arten zu erstellen
Auch das Anpassen der Namen dürfte kein Problem sein.

Beispiel 1: Anlage globaler Gruppen

Clear-Host
Set-StrictMode -Version "2.0"

Function Main{

  $Root = "Scripting"
  $Locations = @("Bangkok","Beijing","Dhaka","Tokio")
  $DomainDN = ([ADSI]"LDAP://RootDSE").DefaultNamingContext
  $CountStart = 1
  $CountEnd = 5
 
  Foreach($Location in $Locations){
      $OuDN = "OU=Global,OU=Groups,OU=$Location,OU=$Root"
      
      #create random identifier for avoiding doubled samaccountnames
      $ofs = ''
      $Identifier = [string](Get-Random -input $([char[]](65..90)) -count 3)
      $ofs = ' '
      
      $Description = "Created by Create-Method"
      For($Count = $CountStart; $Count -le $CountEnd; $Count++){
        $GroupName = "Group$Identifier" + $Count.ToString("000")

        #check existence of $computername
        If ( [Bool]([AdsiSearcher]"SamAccountName=$GroupName").FindOne() -ne $True )  {
           New-GroupObject $DomainDn $Location $OuDn $GroupName $Description
        }Else{
           Write-Host "$GroupName existiert bereits"
        }
      }#For count
   }#Foreach  $Location
}#End Main

Function New-GroupObject{
  Param($DomainDn,$Location,$OuDn,$GroupName,$Description)
 
  $ADS_GROUP_TYPE_GLOBAL_GROUP = 0x2
  $ADS_GROUP_TYPE_SECURITY_ENABLED = 0x80000000
  $GG_S_GroupType = $ADS_GROUP_TYPE_GLOBAL_GROUP -bor $ADS_GROUP_TYPE_SECURITY_ENABLED #Global Security Group
  #$GG_D_GroupType = $ADS_GROUP_TYPE_GLOBAL_GROUP #Global Distributiongroup

 
  $GG_S_GroupName = "GG_S_$GroupName"
  #$GG_D_GroupName = "GG_D_$GroupName"
 
  $Class = "Group"
  $AdsiOU=[ADSI]"LDAP://$OuDN,$DomainDN"
  $AdsiGroup = $AdsiOU.Children.Add("CN=$GG_S_GroupName",$Class)
  $AdsiGroup.InvokeSet("Description", $Description)
  $AdsiGroup.InvokeSet("SamAccountName", $GG_S_GroupName)
 
  $AdsiGroup.InvokeSet("Mail", "admin@powershellpraxis.de" )
  $AdsiGroup.InvokeSet("displayName" , "Display$GG_S_GroupName")
  $AdsiGroup.InvokeSet("GroupType" , $GG_S_GroupType )
 
  $AdsiGroup.CommitChanges()
  Write-Host "$GG_S_GroupName has been created in $($OuDN,$DomainDN)"
} #End Function
 
Main