canlot
Goto Top

Bei Event funktioniert das Powershell Script nicht richtig

Hallo liebe Community,

ich habe hier ein Powershell Script geschrieben, dass bei der Erstellung eines User in einer OU automatisch eine Gruppe mit dem Namen der OU erstellt und ihn dann der Gruppe hinzufügt.
Dann noch ein Script, wenn ein User in eine andere OU verschoben wird, dass er dann aus der alten Gruppe gelöscht wird und einer neuen hinzugefügt wird.
Das erste Script funktioniert, das zweite ab und zu mal, ich konnte noch nicht wirklich feststellen warum es manchmal funktioniert und manchmal nicht.

Manuel ausführen funktioniert immer, das Ausführen nach einem Event dagegen sporadisch.
Ausgeführt wird das auf einem DC.

Hier ist der Code, wenn der Benutzer verschoben wurde.
function GetCityName($City)
{
    switch($City)
    {
        "Berlin" {return "BER"}  
        "München" {return "MUN"}  
        "London" {return "LON"}  
        "Madrid" {return "MAD"}  
        "Paris" {return "PAR"}  
        "Warschau" {return "WAR"}  
        default { return $false}


    }
}

function GetGroupName($OuName)
{
    $groupName = ""  

    $OuArray = $OuName.Split(",")  

    $City = GetCityName($OuArray[-6].Split("=")[1])  
    if($City -eq $false)
    {
        return $false
    }
    
    $specialGroup = ""  
    $department = ""  
    if($OuArray[-7].Split("=")[1] -eq "Special Groups")  
    {
        $specialGroup = "SP"  
        $groupName = "GRP_" + $City + "_" + $specialGroup  
        for($counter = $OuArray.Count - 8; $counter -ge 0; $counter--)
        {
            $item = $OuArray[$counter].Split("=")[1]  
            $groupName = $groupName + "_" + $item  
        }
    }
    else
    {
        #$department = $OuArray[-7].Split("=")[1] 
        $groupName = "GRP_" + $City  
        for($counter = $OuArray.Count - 7; $counter -ge 0; $counter--)
        {
            $item = $OuArray[$counter].Split("=")[1]  
            $groupName = $groupName + "_" + $item  
        }
    }
    
    return $groupName
    
}



$BaseOu = "OU=Firma,DC=intern,DC=firma,DC=de"  
$message = Get-EventLog -LogName security -InstanceId 5139 -Newest 1 | select message | Format-List | Out-String #Benutzer erstellt
#$user = ([regex]::Match($message,'Account Name:(.*)').NextMatch().groups[1].Value).Trim("") 

$objectClass = ([regex]::Match($message,'Class:(.*)').Value).Trim("")  
$objectClass = $objectClass.Split(":")[1].Trim(" ")  

if($objectClass -ne "user")  
{
    Exit
}


$OldOu = ([regex]::Match($message,'Old DN:(.*)').Value).Trim("")  
$OldOu = $OldOu.Split(":")[1].Trim(" ")  
$OldOu = $OldOu.Remove(0, $OldOu.IndexOf(',',0)+1)  
$OldOu = $OldOu.Remove(0, $OldOu.IndexOf(',',0)+1)  

if($OldOu -eq $null -or $OldOu -eq "")  
{
    Exit
}

$NewOu = ([regex]::Match($message,'New DN:(.*)').Value).Trim("")  
$NewOu = $NewOu.Split(":")[1].Trim(" ")  
$NewOu = $NewOu.Remove(0, $NewOu.IndexOf(',',0)+1)  
$NewOu = $NewOu.Remove(0, $NewOu.IndexOf(',',0)+1)  

if($NewOu -eq $null -or $NewOu -eq "")  
{
    Exit
}

$userGUID = ([regex]::Match($message,'GUID:(.*)').Value).Trim("")  
$userGUID = $userGUID.Split(":")[1].Trim(" ")  
$userGUID = $userGUID.Trim("{")  
$userGUID = $userGUID.Trim("}")  

$user = Get-ADUser -Identity $userGUID
#Write-Host $userGUID
#Write-Host $user
#Write-Host $message


$OldGroupName = GetGroupName($OldOu)
$NewGroupName = GetGroupName($NewOu)

if($NewGroupName -eq $false)
{
    Exit
}

if(Get-ADPrincipalGroupMembership $user | select name | where name -eq $OldGroupName)
{
    Remove-ADGroupMember -Identity $OldGroupName -Members $user -Confirm: $false
}

if((Get-ADGroup -SearchBase $BaseOu -Filter * | select name | where name -eq $NewGroupName) -ne $true)
{
    New-ADGroup -Name $NewGroupName -Path $NewOu -GroupCategory Security -GroupScope Global
}
Add-ADGroupMember -Identity $NewGroupName -Members $user

Ich bin ratlos, irgendwie habe ich den Verdacht dass diese Zeile dafür verantwortlich ist:
Remove-ADGroupMember -Identity $OldGroupName -Members $user -Confirm: $false

Manchmal wird der Benutzer der neuen Gruppe hinzugefügt aber nicht aus der alten gelöscht. Meistens aber aber passiert nichts und selten wird die alte Gruppe gelöscht und neue hinzugefügt.

Irgendwie veräppelt mich Windows ganz schön.

Liebe Grüße
2017-11-13

Content-Key: 354603

Url: https://administrator.de/contentid/354603

Printed on: April 20, 2024 at 08:04 o'clock

Member: SlainteMhath
Solution SlainteMhath Nov 13, 2017 at 09:28:28 (UTC)
Goto Top
Moin,

dem Script fehlt's an Fehlerbehandlung... Bau um die "kritschen" Befehle einen Try...Catch block 'rum und lass dir dann evtl. Fehlermeldungen in ein Logfile oder ins Eventlog schreiben.

Ich tippe auf ein Timing-Problem. Ggfs. "spricht" das Script mit einem DC, dem die neuen User/Gruppen noch nicht repliziert wurden - gibt doch mal bei den *-AD* Cmdlets die "-Server" Option mit an.

lg,
Slainte
Member: emeriks
Solution emeriks Nov 13, 2017 at 09:29:09 (UTC)
Goto Top
Hi,
als erstes würde ich eine Protokolierung einbauen. Lass das Script jeden seiner Schritte in ein Logfile schreiben. Mit Angabe der Daten, wie z.B. $OldOU, $NewOU usw.
z.B. Zeile 88:
    'Abbruch weil NewOU leer' |  Out-File -FilePath Pfad_zum_Log -append  
Damit bekommst Du heraus, wo er aufhört oder wo ein Fehler auftritt. Alles andere ist doch nur Stochern im Dunkeln.

und selten wird die alte Gruppe gelöscht und neue hinzugefügt.
Gruppe löschen? Oder meinst Du, Benutzer aus der Gruppe entfernen?

E.
Member: canlot
canlot Nov 13, 2017 at 12:43:30 (UTC)
Goto Top
Danke euch,

ich bin einen kleinen Tacken weiter gekommen.
Try Catch Blocks halfen nicht, es kam zu keinem Fehler.
Ich habe aber herausgefunden das $NewOu und $OldOu LEER sind.

Die große Preisfrage ist warum. face-sad
Mitglied: 134464
134464 Nov 13, 2017 at 13:49:24 (UTC)
Goto Top
Zitat von @canlot:

Danke euch,

ich bin einen kleinen Tacken weiter gekommen.
Try Catch Blocks halfen nicht, es kam zu keinem Fehler.
Ich habe aber herausgefunden das $NewOu und $OldOu LEER sind.

Die große Preisfrage ist warum. face-sad
Das hier ist ja auch Blödsinn ...
$message = Get-EventLog -LogName security -InstanceId 5139 -Newest 1 | select message | Format-List | Out-String #Benutzer erstellt
Dazu "subscribed" man das Event oder übergibt im Task-Trigger die passende Variable an das Skript!
Member: canlot
canlot Nov 13, 2017 at 13:59:58 (UTC)
Goto Top
Zitat von @134464:

Zitat von @canlot:

Danke euch,

ich bin einen kleinen Tacken weiter gekommen.
Try Catch Blocks halfen nicht, es kam zu keinem Fehler.
Ich habe aber herausgefunden das $NewOu und $OldOu LEER sind.

Die große Preisfrage ist warum. face-sad
Das hier ist ja auch Blödsinn ...
$message = Get-EventLog -LogName security -InstanceId 5139 -Newest 1 | select message | Format-List | Out-String #Benutzer erstellt
Dazu "subscribed" man das Event oder übergibt im Task-Trigger die passende Variable an das Skript!
Kannst du bitte verraten wie?
Bin für alles offen.
Mitglied: 134464
Solution 134464 Nov 13, 2017 at 14:16:09 (UTC)
Goto Top
Hier steht wie sowas geht (natürlich übertragen auf deine Events)
Windows 2012 R2 RDP-Server - Skript bei Disconnect und Reconnect
Member: colinardo
Solution colinardo Nov 13, 2017 updated at 15:47:29 (UTC)
Goto Top
Servus,
das Skript habe ich jetzt nicht im Detail durgesehen, aber ich würde auch dazu raten die Parameter über den Tasktrigger zu übermitteln, dazu passt du die zu übermittelten Variablen wie im Link von @specht zu sehen ist im Tasktrigger-XML an.
Die Variablen stehen im Abschnitt <ValueQueries>.

Hier ein Beispiel wie du die Daten des Events an ein Powershell-Skript via Parameter übermittelst:
(Achtung XML-Datei als Unicode speichern und dann importieren!)
<?xml version="1.0" encoding="UTF-16"?>  
<Task version="1.4" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">  
  <RegistrationInfo>
    <Date>2017-11-13T15:57:48.6636923</Date>
  </RegistrationInfo>
  <Triggers>
    <EventTrigger>
      <Enabled>true</Enabled>
      <Subscription>&lt;QueryList&gt;&lt;Query Id="0" Path="Security"&gt;&lt;Select Path="Security"&gt;*[System[Provider[@Name='Microsoft-Windows-Security-Auditing'] and EventID=4720]]&lt;/Select&gt;&lt;/Query&gt;&lt;/QueryList&gt;</Subscription>  
      <ValueQueries>
        <Value name="DisplayName">Event/EventData/Data[@Name='DisplayName']</Value>  
        <Value name="Logged">Event/System/TimeCreated/@SystemTime</Value>  
        <Value name="PrimaryGroupId">Event/EventData/Data[@Name='PrimaryGroupId']</Value>  
        <Value name="SamAccountName">Event/EventData/Data[@Name='SamAccountName']</Value>  
        <Value name="SubjectUserName">Event/EventData/Data[@Name='SubjectUserName']</Value>  
        <Value name="UserPrincipalName">Event/EventData/Data[@Name='UserPrincipalName']</Value>  
      </ValueQueries>
    </EventTrigger>
  </Triggers>
  <Principals>
    <Principal id="Author">  
      <UserId>S-1-5-18</UserId>
      <RunLevel>HighestAvailable</RunLevel>
    </Principal>
  </Principals>
  <Settings>
    <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
    <DisallowStartIfOnBatteries>true</DisallowStartIfOnBatteries>
    <StopIfGoingOnBatteries>true</StopIfGoingOnBatteries>
    <AllowHardTerminate>true</AllowHardTerminate>
    <StartWhenAvailable>false</StartWhenAvailable>
    <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
    <IdleSettings>
      <StopOnIdleEnd>true</StopOnIdleEnd>
      <RestartOnIdle>false</RestartOnIdle>
    </IdleSettings>
    <AllowStartOnDemand>true</AllowStartOnDemand>
    <Enabled>true</Enabled>
    <Hidden>false</Hidden>
    <RunOnlyIfIdle>false</RunOnlyIfIdle>
    <DisallowStartOnRemoteAppSession>false</DisallowStartOnRemoteAppSession>
    <UseUnifiedSchedulingEngine>false</UseUnifiedSchedulingEngine>
    <WakeToRun>false</WakeToRun>
    <ExecutionTimeLimit>P3D</ExecutionTimeLimit>
    <Priority>7</Priority>
  </Settings>
  <Actions Context="Author">  
    <Exec>
      <Command>powershell.exe</Command>
      <Arguments>-NoProfile -File "C:\testscript.ps1" -SamAccountName "$(SamAccountName)" -SubjectUserName "$(SubjectUserName)"</Arguments>  
    </Exec>
  </Actions>
</Task>
Und nutzen kannst du die Variablen dann so in einem PS-Skript:
param(
	[string]$SamAccountName,
	[string]$SubjectUserName
)

"Benutzer mit Namen: '$SamAccountName' wurde von Benutzer: '$SubjectUserName' erstellt." | sc 'C:\log.txt'  

Alternativ kann man natürlich auch das Eventlog über ein PS-Skript überwachen. Das müsste dann aber ständig laufen damit die Events dort abgefangen werden können, insofern ist hier ein Tasktrigger die bessere Wahl.

Btw. wenn du es unbedingt via Get-Eventlog auslesen willst wäre
$username = Get-Eventlog -LogName Security -InstanceId 4720 -Newest 1 | %{$_.ReplacementStrings}
oder auch
$username = ([xml](Get-WinEvent -LogName Security -FilterXPath "*[System[Provider[@Name='Microsoft-Windows-Security-Auditing'] and (EventID=4720)]]" -Max 1).toXML()).Event.EventData.Data | ?{$_.Name -eq 'SamAccountName'} | %{$_.'#text'}
die schönere Variante (Bsp zum Auslesen den Usernames bei Useranlage), als erst als Format-Table, dann als String und dann noch mit Regex zu extrahieren, das ist doch sehr unschön face-wink.

Grüße Uwe
Member: canlot
canlot Nov 14, 2017 at 08:00:48 (UTC)
Goto Top
@colinardo

Hallo Uwe,

danke für die Antwort.
Ich habe mein Script jetzt umgeschrieben. Die XML Datei habe ich exportiert und dann die Queries eingefügt.

<?xml version="1.0" encoding="UTF-16"?>  
<Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">  
  <RegistrationInfo>
    <Date>2017-11-13T13:19:02.9719722</Date>
    <Author>Firma\Benutzer</Author>
  </RegistrationInfo>
  <Triggers>
    <EventTrigger>
      <Enabled>true</Enabled>
      <Subscription>&lt;QueryList&gt;&lt;Query Id="0" Path="Security"&gt;&lt;Select Path="Security"&gt;*[System[Provider[@Name='Microsoft-Windows-Security-Auditing'] and EventID=5139]]&lt;/Select&gt;&lt;/Query&gt;&lt;/QueryList&gt;</Subscription>  
      <ValueQueries>
        <Value name="Class">Event/EventData/Data[@Name='ObjectClass']</Value>  
        <Value name="GUID">Event/EventData/Data[@Name='ObjectGUID']</Value>  
        <Value name="NewOU">Event/EventData/Data[@Name='NewObjectDN']</Value>  
        <Value name="OldOU">Event/EventData/Data[@Name='OldObjectDN']</Value>  
      </ValueQueries>
    </EventTrigger>
  </Triggers>
  <Principals>
    <Principal id="Author">  
      <UserId>Firma\Administrator</UserId>
      <LogonType>Password</LogonType>
      <RunLevel>LeastPrivilege</RunLevel>
    </Principal>
  </Principals>
  <Settings>
    <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
    <DisallowStartIfOnBatteries>true</DisallowStartIfOnBatteries>
    <StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>
    <AllowHardTerminate>false</AllowHardTerminate>
    <StartWhenAvailable>false</StartWhenAvailable>
    <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
    <IdleSettings>
      <StopOnIdleEnd>true</StopOnIdleEnd>
      <RestartOnIdle>false</RestartOnIdle>
    </IdleSettings>
    <AllowStartOnDemand>true</AllowStartOnDemand>
    <Enabled>true</Enabled>
    <Hidden>false</Hidden>
    <RunOnlyIfIdle>false</RunOnlyIfIdle>
    <WakeToRun>false</WakeToRun>
    <ExecutionTimeLimit>P3D</ExecutionTimeLimit>
    <Priority>7</Priority>
  </Settings>
  <Actions Context="Author">  
    <Exec>
      <Command>powershell</Command>
      <Arguments>-NoProfile -File "C:\Script\MoveToOtherOu.ps1" -OldOu "$(OldOu)" -NewOu "$(NewOu)" -GUID "$(GUID)" -Class "$(Class)"</Arguments>  
    </Exec>
  </Actions>
</Task>

Und das Script:

Param
(
    [string]$OldOu,
    [string]$NewOu,
    [string]$GUID,
    [string]$Class
)

$OldOu | Out-File -FilePath "C:\Users\Benutzer\Documents\logMoveToOtherOu.txt" -Append  
$NewOu | Out-File -FilePath "C:\Users\Benutzer\Documents\logMoveToOtherOu.txt" -Append  
$GUID | Out-File -FilePath "C:\Users\Benutzer\Documents\logMoveToOtherOu.txt" -Append  
$Class | Out-File -FilePath "C:\Users\Benutzer\Documents\logMoveToOtherOu.txt" -Append  

$BaseOu = "OU=Firma,DC=intern,DC=firma,DC=de"  


if($Class -ne "user")  
{
    Exit
}


$OldOu = $OldOu.Remove(0, $OldOu.IndexOf(',',0)+1)  
$OldOu = $OldOu.Remove(0, $OldOu.IndexOf(',',0)+1)  

if($OldOu -eq $null -or $OldOu -eq "")  
{
    Exit
}

$NewOu = $NewOu.Remove(0, $NewOu.IndexOf(',',0)+1)  
$NewOu = $NewOu.Remove(0, $NewOu.IndexOf(',',0)+1)  

if($NewOu -eq $null -or $NewOu -eq "")  
{
    Exit
}

$userGUID = $userGUID.Trim("{")  
$userGUID = $userGUID.Trim("}")  

$user = Get-ADUser -Identity $userGUID
#Write-Host $userGUID
#Write-Host $user
#Write-Host $message


$OldGroupName = GetGroupName($OldOu)
$NewGroupName = GetGroupName($NewOu)

$OldGroupName | Out-File -FilePath "C:\Users\Benutzer\Documents\logMoveToOtherOu.txt" -Append  
$NewGroupName | Out-File -FilePath "C:\Users\Benutzer\Documents\logMoveToOtherOu.txt" -Append  

if($NewGroupName -eq $false)
{
    $text = "Gruppenname leer"  
    $text | Out-File -FilePath "C:\Users\Benutzer\Documents\logMoveToOtherOu.txt" -Append  
    Exit
}
try
{
    if(Get-ADPrincipalGroupMembership $user | select name | where name -eq $OldGroupName)
    {
        Remove-ADGroupMember -Identity $OldGroupName -Members $user -Confirm: $false
    }
}
catch
{
    $FailMessage = "Fail: " + $_.Exception.Message + " " + $_.Exception.ItemName  
    $FailMessage | Out-File -FilePath "C:\Users\Benutzer\Documents\logMoveToOtherOu.txt" -Append  
}

try
{
    if((Get-ADGroup -SearchBase $BaseOu -Filter * | select name | where name -eq $NewGroupName) -ne $true) 
    {
        New-ADGroup -Name $NewGroupName -Path $NewOu -GroupCategory Security -GroupScope Global
    }
    
}
catch
{
    $FailMessage = "Fail: " + $_.Exception.Message + " " + $_.Exception.ItemName  
    $FailMessage | Out-File -FilePath "C:\Users\Benutzer\Documents\logMoveToOtherOu.txt" -Append  
}
Add-ADGroupMember -Identity $NewGroupName -Members $user

Die Variablen die ich dem Script übergebe bleiben aber leer.

$OldOu | Out-File -FilePath "C:\Users\Benutzer\Documents\logMoveToOtherOu.txt" -Append
$NewOu | Out-File -FilePath "C:\Users\Benutzer\Documents\logMoveToOtherOu.txt" -Append
$GUID | Out-File -FilePath "C:\Users\Benutzer\Documents\logMoveToOtherOu.txt" -Append
$Class | Out-File -FilePath "C:\Users\Benutzer\Documents\logMoveToOtherOu.txt" -Append

In der Datei steht nichts drin.
Mitglied: 134464
Solution 134464 Nov 14, 2017 updated at 08:07:19 (UTC)
Goto Top
Groß und Kleinschreibung der Variablen im Argument beachten, deine stimmen nicht überein...
OldOU ist nicht gleich OldOu.
Member: canlot
canlot Nov 14, 2017 at 08:15:55 (UTC)
Goto Top
Zitat von @134464:

Groß und Kleinschreibung der Variablen im Argument beachten, deine stimmen nicht überein...
OldOU ist nicht gleich OldOu.
Huch, wie hat sich das da eingeschlichen, ich habe eigentlich peinlich genau auf die Groß-Kleinschreibung geachtet.

Danke, aber es geht immer noch nicht, die Variablen bleiben leer.
Mitglied: 134464
Solution 134464 Nov 14, 2017 updated at 08:20:13 (UTC)
Goto Top
Param steht bei dir nicht in der ersten Zeile.
Und für den Rest Binde ein Start-Transcript und Stop-Transcript in dein Skript ein.
Und der Account benötigt natürlich Schreibrechte in den Ziel-Ordner!!
Geht hier problemlos.
Member: emeriks
emeriks Nov 14, 2017 updated at 08:21:31 (UTC)
Goto Top
Wird denn die Logdatei überhaupt um Leerzeilen aktualisiert? Falls nein, dann schreibt er bloß nicht ins Log. In diesem Fall, nimm noch besser einen Pfad ausserhalb der Benutzerprofile, z.B. einen im %ProgramData%.
Member: canlot
canlot Nov 14, 2017 at 11:18:22 (UTC)
Goto Top
Zitat von @134464:

Param steht bei dir nicht in der ersten Zeile.
Und für den Rest Binde ein Start-Transcript und Stop-Transcript in dein Skript ein.
Und der Account benötigt natürlich Schreibrechte in den Ziel-Ordner!!
Geht hier problemlos.
Danke, den Tipp mit den Parametern wusste ich noch nicht, das hat das Problem mit den leeren Variablen gelöst.
Ich hatte aber noch andere Fehler im Script. z.B. habe ich statt $GUID $userGUID verwendet und statt Get-ADGroupMember, Get-ADPrincipalGroupMember.
Member: canlot
canlot Nov 14, 2017 at 11:26:44 (UTC)
Goto Top
Danke noch mal an alle!!!

Ich schreibe hier mal die Lösung, vielleicht benötigt jemand sie mal.

Also wie @colinardo beschrieben hat, das Ereignis exportieren und die Querie-Werte einfügen.
Meine fertige XML-Datei sieht so aus:

<?xml version="1.0" encoding="UTF-16"?>  
<Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">  
  <RegistrationInfo>
    <Date>2017-11-13T13:19:02.9719722</Date>
    <Author>FIRMA\Benutzer</Author>
  </RegistrationInfo>
  <Triggers>
    <EventTrigger>
      <Enabled>true</Enabled>
      <Subscription>&lt;QueryList&gt;&lt;Query Id="0" Path="Security"&gt;&lt;Select Path="Security"&gt;*[System[Provider[@Name='Microsoft-Windows-Security-Auditing'] and EventID=5139]]&lt;/Select&gt;&lt;/Query&gt;&lt;/QueryList&gt;</Subscription>  
      <ValueQueries>
        <Value name="Class">Event/EventData/Data[@Name='ObjectClass']</Value>  
        <Value name="GUID">Event/EventData/Data[@Name='ObjectGUID']</Value>  
        <Value name="NewOu">Event/EventData/Data[@Name='NewObjectDN']</Value>  
        <Value name="OldOu">Event/EventData/Data[@Name='OldObjectDN']</Value>  
      </ValueQueries>
    </EventTrigger>
  </Triggers>
  <Principals>
    <Principal id="Author">  
      <UserId>FIRMA\Administrator</UserId>
      <LogonType>Password</LogonType>
      <RunLevel>LeastPrivilege</RunLevel>
    </Principal>
  </Principals>
  <Settings>
    <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
    <DisallowStartIfOnBatteries>true</DisallowStartIfOnBatteries>
    <StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>
    <AllowHardTerminate>false</AllowHardTerminate>
    <StartWhenAvailable>false</StartWhenAvailable>
    <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
    <IdleSettings>
      <StopOnIdleEnd>true</StopOnIdleEnd>
      <RestartOnIdle>false</RestartOnIdle>
    </IdleSettings>
    <AllowStartOnDemand>true</AllowStartOnDemand>
    <Enabled>true</Enabled>
    <Hidden>false</Hidden>
    <RunOnlyIfIdle>false</RunOnlyIfIdle>
    <WakeToRun>false</WakeToRun>
    <ExecutionTimeLimit>P3D</ExecutionTimeLimit>
    <Priority>7</Priority>
  </Settings>
  <Actions Context="Author">  
    <Exec>
      <Command>powershell</Command>
      <Arguments>-NoProfile -File "C:\Script\MoveToOtherOu.ps1" -OldOu "$(OldOu)" -NewOu "$(NewOu)" -GUID "$(GUID)" -Class "$(Class)"</Arguments>  
    </Exec>
  </Actions>
</Task>
Firma und Benutzer durch die Domäne und euren Benutzer ersetzen. Dann die Datei wieder importieren.

Das PS Script sieht dann so aus:
(
    [string]$OldOu,
    [string]$NewOu,
    [string]$GUID,
    [string]$Class
)

$filePath = "C:\Users\benutzer\Documents\logMoveToOtherOu.txt"  
$BaseOu = "OU=firma,DC=intern,DC=firma,DC=de"  

"                                                  " | Out-File -FilePath $filePath -Append  
"-----------------" + (Get-Date).ToUniversalTime() + "-----------------" | Out-File -FilePath $filePath -Append  
"                                                  " | Out-File -FilePath $filePath -Append  

$OldOu | Out-File -FilePath $filePath -Append
$NewOu | Out-File -FilePath $filePath -Append
$GUID | Out-File -FilePath $filePath -Append
$Class | Out-File -FilePath $filePath -Append




if($Class -ne "user")  
{
    Exit
}


$OldOu = $OldOu.Remove(0, $OldOu.IndexOf(',',0)+1)  
$OldOu = $OldOu.Remove(0, $OldOu.IndexOf(',',0)+1)  

if($OldOu -eq $null -or $OldOu -eq "")  
{
    Exit
}

$NewOu = $NewOu.Remove(0, $NewOu.IndexOf(',',0)+1)  
$NewOu = $NewOu.Remove(0, $NewOu.IndexOf(',',0)+1)  

if($NewOu -eq $null -or $NewOu -eq "")  
{
    Exit
}


$user = Get-ADUser -Identity $GUID

function GetCityName($City)
{
    switch($City)
    {
        "Berlin" {return "BER"}  
        "München" {return "MUN"}  
        "London" {return "LON"}  
        "Madrid" {return "MAD"}  
        "Paris" {return "PAR"}  
        "Warschau" {return "WAR"}  
        default { return $false}


    }
}

function GetGroupName($OuName)
{
    $groupName = ""  

    $OuArray = $OuName.Split(",")  

    $City = GetCityName($OuArray[-6].Split("=")[1])  
    if($City -eq $false)
    {
        return $false
    }
    
    $specialGroup = ""  
    $department = ""  
    if($OuArray[-7].Split("=")[1] -eq "Special Groups")  
    {
        $specialGroup = "SP"  
        $groupName = "GRP_" + $City + "_" + $specialGroup  
        for($counter = $OuArray.Count - 8; $counter -ge 0; $counter--)
        {
            $item = $OuArray[$counter].Split("=")[1]  
            $groupName = $groupName + "_" + $item  
        }
    }
    else
    {
        $groupName = "GRP_" + $City  
        for($counter = $OuArray.Count - 7; $counter -ge 0; $counter--)
        {
            $item = $OuArray[$counter].Split("=")[1]  
            $groupName = $groupName + "_" + $item  
        }
    }
    
    return $groupName
    
}

$OldGroupName = GetGroupName($OldOu)
$NewGroupName = GetGroupName($NewOu)

$OldGroupName | Out-File -FilePath $filePath -Append
$NewGroupName | Out-File -FilePath $filePath -Append

if($NewGroupName -eq $false)
{
    $text = "Gruppenname leer"  
    $text | Out-File -FilePath $filePath -Append
    Exit
}
#Get-ADPrincipalGroupMembership $user | select name | Out-File -FilePath $filePath -Append
try
{
    Remove-ADGroupMember -Identity $OldGroupName -Members $user -Confirm: $false
}
catch
{
    $FailMessage = "Fail: " + $_.Exception.Message + " " + $_.Exception.ItemName  
    $FailMessage | Out-File -FilePath $filePath -Append
}

try
{
    if((Get-ADGroup -SearchBase $BaseOu -Filter * | select name | where name -eq $NewGroupName) -ne $true) 
    {
        New-ADGroup -Name $NewGroupName -Path $NewOu -GroupCategory Security -GroupScope Global
    }
    
}
catch
{
    $FailMessage = "Fail: " + $_.Exception.Message + " " + $_.Exception.ItemName  
    $FailMessage | Out-File -FilePath $filePath -Append
}
try
{
    Add-ADGroupMember -Identity $NewGroupName -Members $user
}
catch
{
    $FailMessage = "Fail: " + $_.Exception.Message + " " + $_.Exception.ItemName  
    $FailMessage | Out-File -FilePath $filePath -Append
}
Leider ohne Kommentare face-sad