โŒ

Normal view

There are new articles available, click to refresh the page.
Before yesterdayMain stream

How do I get a Windows batch file to work under Powershell and normal cmd.exe?

I have a batch that performs normal operations. One line of this script runs a Powershell-specific command like this:

powershell -Command "& {Get-FileHash myfile.fwpkg -Algorithm MD5}"

This works when I run the command via the normal Windows Command Prompt cmd.exe.

However, if I run this command under Powershell, this line (ironically) fails:

Get-FileHash : The term 'Get-FileHash' is not recognized as the name of a cmdlet, function, script file, or operable
program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At line:1 char:4
+ & {Get-FileHash myfile.fwpkg -Algorithm MD5}
+    ~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (Get-FileHash:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

How can I get this batch file to work under both Powershell and cmd.exe?

Error: Resource type '/microsoft.operationalinsights/workspace' is invalid for property 'properties.workspaceId'

I'm trying to create a function app and update the diagnostic settings through PowerShell script to existing Log Analytics Workspace that is residing in different subscription. However throwing error while updating with below error,

ERROR: Resource type '/microsoft.operationalinsights/workspace' is invalid for property'properties.workspaceId'. Expected types are 'microsoft.operationalinsights/workspaces.

It has something to do with the workspace ID as I noticed hardcoding the workspace ID successfully retrieves and update the diagnostic settings.

PowerShell Script:

[CmdLetBinding()]

param(

[string] $SubscriptionId,
[string] $BusinessFunAppRGName,
[string] $BusinessFunAppName,
[string] $laWorkspaceRGName,
[string] $laWorkspaceName,
[string] $lawSubscriptionId

)

$ResourceId = "/subscriptions/$SubscriptionId/resourceGroups/$BusinessFunAppRGName/providers/Microsoft.Web/sites/$BusinessFunAppName"

$diagSettings = Get-AzDiagnosticSetting -ResourceId $ResourceId

if($diagSettings) { Write-Host "Diagnostics Settings Found" } else { Write-Host "Diagnostics Settings Not Found, Applying settings..."

$metric = @()
$log = @()
$metric += New-AzDiagnosticSettingMetricSettingsObject -Enabled $true -Category AllMetrics
$log += New-AzDiagnosticSettingLogSettingsObject -Enabled $true -Category FunctionAppLogs

New-AzDiagnosticSetting -Name "DiagnosticSettings" `
    -ResourceId $ResourceId `
    -Log $log -Metric $metric `
    -WorkspaceId "/subscriptions/$lawSubscriptionId/resourceGroups/$laWorkspaceRGName/providers/microsoft.operationalinsights/workspaces/$laWorkspaceName" `


                  
        
Write-Host "Done"

}

Workflow file sample:

    - name: 'Update diagnostics settings' 
  uses: azure/powershell@v1
  with:
      azPSVersion: "latest"
      inlineScript: |

        arm-templates/business-subscription-afna/update-diagnostics.ps1 `
          -SubscriptionId ${{ github.event.inputs.businessSubscriptionId }} `
          -BusinessFunAppRGName ${env:parameters.resourceGroup.value} `
          -BusinessFunAppName ${env:parameters.funcAppName.value} `
          -laWorkspaceRGName ${env:parameters.mgmtlaWorkspaceRGName.value} `
          -laWorkspaceName ${env:parameters.mgmtlaWorkspaceName.value} `
          -lawSubscriptionId ${env:parameters.mgmtlawSubscriptionId.value} 
      failOnStandardError: $true

unable to capture the output of a remote command in powershell

I am connecting to a windows device from the host using Open-Device in Powershell. i have to run a command in remote PC and capture the output into a variable to process further, unable to do so. tried redirecting using 'Out-String', 'Tee' Operation, Redirect the out put to a file, extract data from STDOUT etc. nothing seems to be working.

Output is printing onto the STDOUT but could not extract

Code i tried.

Open-Device <Device Serial Number>
cmdd dir

GetAccessTokenForRequestAsync fails to return a token for "https://www.googleapis.com/auth/spreadsheets"

Every other scope I try works with out issue. It is possible to interact with the API directly through the Google.Apis.Sheets.v4.SheetsService, but I want to extract the token.

I realize there may be another way to accomplish this, but I am trying to determine why this singular scope is behaving this way.

($SheetsService.HttpClientInitializer.GetAccessTokenForRequestAsync()).Result

returns nothing if the scope specified in Google.Apis.Auth.OAuth2.ServiceCredential that the SheetsService is generated from is https://www.googleapis.com/auth/spreadsheets, but again fails in no other identifiable circumstance.

Why will the second code block in powershell not execute?

The first Script-block is executing without any issues however I am unsure why the second Script-block is not executing.

Import-Module ThreadJob

$streamMonitor = @(
    @{
        directoryPath       = "C:\path\stream1"
        scriptToRestartPath = "C:\path\stream1.bat"
    }
    @{
        directoryPath       = "C:\path\stream2"
        scriptToRestartPath = "C:\path\stream2.bat"
    }

)


$streamMonitor | ForEach-Object {
    Start-ThreadJob -ScriptBlock {
        . C:\Users\luke_linwood_lopez\Desktop\ffmpeg-6.0-essentials_build\bin\streamMonitor.ps1
        streamMonitor @using:_
    } -ArgumentList @($directoryPath, $scriptToRestartPath)
} | Receive-Job -Wait -AutoRemoveJob


#This is the Block that will not execute
Start-ThreadJob -ScriptBlock {
    while ($true) {
        1..3 | ForEach-Object {
            $directory = "C:\nginx\srv\hls\stream$_"
            Get-ChildItem $directory -Recurse -File | Where-Object {($_.Extension -ne ".m3u8") -and $_.CreationTime -lt (Get-Date).AddSeconds(-30)} | Remove-Item -Force
        }
        Write-Host "Completed cleaning directories."
        Start-Sleep -Seconds 30  # Wait for 30 seconds before running the command again
    }
} | Receive-Job -Wait -AutoRemoveJob

Create Grouped Averages from CSV data using Powershell

I have a CSV file similar to this:

Name,Dates,Sortino,RoMDD,PctWins
AAL,2017-06-01 - 2018-06-01,-0.47,-0.26,66.67%
AAL,2017-09-01 - 2018-06-01,0.03,0.02,66.67%
AAL,2017-12-01 - 2018-06-01,-1.05,-0.69,50.00%
AAL,2018-03-01 - 2018-06-01,-2.99,-2.32,33.33%
AAPL,2017-06-01 - 2018-06-01,2.01,1.79,66.67%
AAPL,2017-09-01 - 2018-06-01,1.89,1.68,66.67%
AAPL,2017-12-01 - 2018-06-01,1.66,1.64,66.67%
AAPL,2018-03-01 - 2018-06-01,3.1,3.86,66.67%
ADBE,2017-06-01 - 2018-06-01,3.88,6.09,75.00%
ADBE,2017-09-01 - 2018-06-01,4.16,7.03,77.78%
ADBE,2017-12-01 - 2018-06-01,3.92,8.34,83.33%
ADBE,2018-03-01 - 2018-06-01,4.58,10.29,100.00%

The Dates column is irrelevant and just added for context.

I need to create averages grouped by name, equivalent to an Excel pivot table with Rows: Name and Values: Average of [RoMDD,PctWins,Sortino].

Those results then need to be filtered by Top 20 Sortino, then Top 20 RoMDD, and Top 20 PctWins, all within the previous level (each filter builds on the filtering of the previous level). But that is perhaps a subject for a 2nd post. Otherwise I'll Google (add rank to a list of numbers?)

Here is what I've written so far:

$csv = import-csv -path C:\Temp\Example.CSV | Select-Object -Property Name,Sortino,RoMDD,PctWins | ForEach {$_.PctWins=$_.PctWins.Replace("%","");$_}
$collection = $csv | group-object -property Name
$avg = $collection | Foreach {
    $avg = $_.group|measure -Property Sortino -Average | select -expand average
    add-member -inputobject $_.group[0] -notepropertyname AvgSortino -notepropertyvalue $avg -PassThru
    $avg = $_.group|measure -Property RoMDD -Average | select -expand average
    add-member -inputobject $_.group[0] -notepropertyname AvgRoMDD -notepropertyvalue $avg -PassThru
    $avg = $_.group|measure -Property PctWins -Average | select -expand average
    add-member -inputobject $_.group[0] -notepropertyname AvgPctWins -notepropertyvalue $avg -PassThru
} | Select Name,AvgSortino,AvgRoMDD,AvgPctWins

This is close, but adds each average to a new object, instead of additional columns in the one object.

Would creating a new PSCustomObject be a better approach here? Or using Datatable and Linq? I don't know Linq but I know SQL quite well.

The final output will be written back to a new CSV file including new (Avg) column headers.

Zlib compression in Powershell

I need to compress a string to Zlib in PowerShell.

Is there a way we can compress using the ZLibStream class in PowerShell?

https://learn.microsoft.com/en-us/dotnet/api/system.io.compression.zlibstream?view=net-8.0

I was able to compress using the class DeflateStream and GZipStream, but the external system which uses the data was not able to decode it.

This is the powershell script I tried with

$stringToCompress  = 'string to compress'

$memStream = New-Object System.IO.MemoryStream
$deflateStream = New-Object System.IO.Compression.GZipStream($memStream, [System.IO.Compression.CompressionMode]::Compress)
$streamWriter = New-Object System.IO.StreamWriter($deflateStream)
$streamWriter.Write($stringToCompress)
$streamWriter.Close();
$encodedCompressedString = [System.Convert]::ToBase64String($memStream.ToArray())
Write-Output $encodedCompressedString 

In C#, DirectoryEntry is returning empty AuditRules collection, even though audit rules do exist

I am attempting to create a C# console application to manage audit permissions on a domain (not file system). My problem is that I cannot read the existing audit rules in C#, I only get an empty collection, even though I am certain there are audit rules in the domain.

I am needing to manage over 100+ independent domains, so I want to come up with a programmatic solution to help manage them.

I can do this without issue in PowerShell using the following command.

$acl = Get-Acl -Path "DC=mydomain,DC=local" -Audit
$acl.Audit

This returns a collection of 5 audit rules. However, when trying to perform the same operation in C#, the audit rules are not returned.

string path = "LDAP://mydomain.local/DC=mydomain,DC=local";
DirectoryEntry domain = new DirectoryEntry(path);
               
AuthorizationRuleCollection authorizationRuleList1 = domain.ObjectSecurity.GetAuditRules(true, true, typeof(NTAccount));
AuthorizationRuleCollection authorizationRuleList2 = domain.ObjectSecurity.GetAuditRules(true, true, typeof(System.Security.Principal.SecurityIdentifier));

Console.WriteLine("Authorization Rules 1: " + authorizationRuleList1.Count);
Console.WriteLine("Authorization Rules 2: " + authorizationRuleList2.Count);

Running the above shows aa count of 0 audit rules. Oddly, the access rules are returned without issue.

I have tried

  1. Explicitly applying a password for the DirectoryEntry initialization
  2. Running "run as administrator"
  3. Verifying the audit permissions exist by using LDAP explorer

Any pointers would be much appreciated.

Updated code using ActiveDs to get security descriptor.

string path = "LDAP://demo.local/DC=demo,DC=local";
DirectoryEntry domain = new DirectoryEntry(path);
var ntSecurityDescriptor = domain.Properties["ntSecurityDescriptor"];

ActiveDs.ADsSecurityUtility secUtility = new ActiveDs.ADsSecurityUtility();
ActiveDs.IADsSecurityDescriptor sd = (IADsSecurityDescriptor)ntSecurityDescriptor[0];
ActiveDs.IADsAccessControlList aclList =  ActiveDs.IADsAccessControlList)sd.DiscretionaryAcl;

why if in C# i invoke a script with powershell an i capture the buffer is completely different running from windows terminal PS

why if in C# i invoke a script with powershell an i capture the buffer is completely different running from windows terminal PS

i run this on C# application open with elevated privileges:


string command = "docker-compose -p wsdd-projects -f C:\Docker-Structure\init.yml up -d --build"

string policy = "Set-ExecutionPolicy -Scope Process -ExecutionPolicy Unrestricted -Force";

string arguments = $"-NoProfile -Command \"{policy} ; '{command}'\"";

ProcessStartInfo processBuilder = new("powershell")
{
    Arguments = arguments,
    RedirectStandardOutput = true,
    RedirectStandardError = true,
    UseShellExecute = false,
    Verb = "runas",
    CreateNoWindow = true,
    StandardOutputEncoding = Encoding.UTF8,
    StandardErrorEncoding = Encoding.UTF8
};

capture output with:

Process process = new() { StartInfo = processBuilder };

process.OutputDataReceived += (sender, e) =>
{
    if (!string.IsNullOrEmpty(e.Data))
    {
        if (showOutput) { terminal.AddToTerminal(e.Data); }
        output.AppendLine(e.Data);
    }
};

process.ErrorDataReceived += (sender, e) =>
{
    if (!string.IsNullOrEmpty(e.Data))
    {
        if (showOutput) { terminal.AddToTerminal(e.Data); }
        output.AppendLine(e.Data);
    }
};

process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();

await process.WaitForExitAsync();

i get this output from PS invoke from C#:

 reverse-proxy Pulled
 phpmyadmin Pulled
 faef57eae888 Pull complete
 989a1d6c052e Pull complete
 0705c9c2f22d Pull complete
 621478e043ce Pull complete
 98246dcca987 Pull complete
 bfed8c155cb6 Pull complete
 7a7c2e908867 Pull complete
 d176994b625c Pull complete
 2d8ace6a2716 Pull complete
 c70df516383c Pull complete
 15e1b44fe4c7 Pull complete
 65e50d44e95a Pull complete
 77f68910bc0a Pull complete
 605dd3a6e332 Pull complete
 99ce27188f07 Pull complete
 74d64e32c5d5 Pull complete
 ef5fc9928b9f Pull complete
 163f3256e112 Pull complete
 8a1e25ce7c4f Pull complete
 e78b137be355 Pull complete
 39fc875bd2b2 Pull complete
 035788421403 Pull complete
 87c3fb37cbf2 Pull complete
 c5cdd1ce752d Pull complete
 33952c599532 Pull complete
 80bad5b02d6c Pull complete
 b86cede81497 Pull complete
 876ba35ce95b Pull complete
 ac8fec215cc8 Pull complete
 7795496aa545 Pull complete
 4f4fb700ef54 Pull complete

Instead of this output in Terminal PS Windows:

[+] Running 33/33
 โœ” reverse-proxy 13 layers [โฃฟโฃฟโฃฟโฃฟโฃฟโฃฟโฃฟโฃฟโฃฟโฃฟโฃฟโฃฟโฃฟ]      0B/0B      Pulled                   14.3s
   โœ” 8a1e25ce7c4f Pull complete                                                      8.1s
   โœ” e78b137be355 Pull complete                                                      8.5s
   โœ” 39fc875bd2b2 Pull complete                                                      6.9s
   โœ” 035788421403 Pull complete                                                      7.6s
   โœ” 87c3fb37cbf2 Pull complete                                                      8.1s
   โœ” c5cdd1ce752d Pull complete                                                      8.6s
   โœ” 33952c599532 Pull complete                                                      8.7s
   โœ” 80bad5b02d6c Pull complete                                                      9.0s
   โœ” b86cede81497 Pull complete                                                      9.4s
   โœ” 876ba35ce95b Pull complete                                                      9.8s
   โœ” ac8fec215cc8 Pull complete                                                      9.6s
   โœ” 7795496aa545 Pull complete                                                      10.1s
   โœ” 4f4fb700ef54 Pull complete                                                      10.2s
 โœ” phpmyadmin 18 layers [โฃฟโฃฟโฃฟโฃฟโฃฟโฃฟโฃฟโฃฟโฃฟโฃฟโฃฟโฃฟโฃฟโฃฟโฃฟโฃฟโฃฟโฃฟ]      0B/0B      Pulled                  18.4s
   โœ” faef57eae888 Pull complete                                                      2.3s
   โœ” 989a1d6c052e Pull complete                                                      0.5s
   โœ” 0705c9c2f22d Pull complete                                                      4.7s
   โœ” 621478e043ce Pull complete                                                      1.0s
   โœ” 98246dcca987 Pull complete                                                      3.0s
   โœ” bfed8c155cb6 Pull complete                                                      2.8s
   โœ” 7a7c2e908867 Pull complete                                                      3.5s
   โœ” d176994b625c Pull complete                                                      4.3s
   โœ” 2d8ace6a2716 Pull complete                                                      4.1s
   โœ” c70df516383c Pull complete                                                      5.1s
   โœ” 15e1b44fe4c7 Pull complete                                                      4.8s
   โœ” 65e50d44e95a Pull complete                                                      5.3s
   โœ” 77f68910bc0a Pull complete                                                      5.4s
   โœ” 605dd3a6e332 Pull complete                                                      5.9s
   โœ” 99ce27188f07 Pull complete                                                      6.1s
   โœ” 74d64e32c5d5 Pull complete                                                      6.5s
   โœ” ef5fc9928b9f Pull complete                                                      6.4s

where is the line this: [+] Running

and the characters: โœ” and [โฃฟโฃฟโฃฟโฃฟโฃฟโฃฟโฃฟโฃฟโฃฟโฃฟโฃฟโฃฟโฃฟ]

How to get the mailbox statistics data for more than 70,000 shared mailboxes in bulk

I'm using cloud environment.

I initially tried to get the total mailbox count to execute the script of retreiving mailbox statistics in batches using below code... But it gives me a server side error.

Help me to solve this error. Is there any alternative ways to get mailbox statistics data. Because Get-Mailbox throws error each time I run it.

PS C:\WINDOWS\system32> ***Get-Mailbox -ResultSize unlimited -RecipientTypeDetails SharedMailbox | Measure-Object***
Write-ErrorMessage : A server side error has occurred because of which the operation could not be completed. Please try again after some time. 
If the problem still persists, please reach out to MS support.
At C:\Users\Afasdf\AppData\Local\Temp\tmpEXO_caglfdam.ak2\tmpEXO_caglfdam.ak2.psm1:1191 char:13
             Write-ErrorMessage $ErrorObject
            ~~~
     CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
     FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Write-ErrorMessage
 

***Count    : 65000
Average  : 
Sum      : 
Maximum  : 
Minimum  : 
Property :***

I'm expecting to return the count of the total shared mailboxes in my tenant, so that I am able to batch the process of retrieving the mailbox statistics data using for loops.

Get the Services and it names List By Location in Azure Subscription

I'm able to get all the available locations in my current subscription using REST API now iam trying to get the services and it names in specified location including Resources Groups, Vnets, Vm's etc using python sdk's or powershell. Is there any possible way to achieve the same Assist me to resolve or the Documents. Thanks in Advance! [![enter image description here][1]][1] list all resources available in the azure subscription based on the location here location should be param.


from azure.identity import DefaultAzureCredential
from azure.mgmt.resource import ResourceManagementClient

def list_resources_by_location(subscription_id, location):
    # Authenticate with Azure using DefaultAzureCredential
    credential = DefaultAzureCredential()

    # Initialize the ResourceManagementClient
    resource_client = ResourceManagementClient(credential, subscription_id)

    # Get resources by location
    resources = resource_client.resources.list_by_location(location)

    # Print resource details
    print(f"List of resources in location '{location}':")
    for resource in resources:
        print(f"ID: {resource.id}")
        print(f"Name: {resource.name}")
        print(f"Type: {resource.type}")
        

subscription_id = "subscription_id"

# Specify the location you want to list resources from
location = "westus2"


list_resources_by_location(subscription_id, location)

Below example in EastUS i have 50 Vnets created need that list for other services aswell [1]: https://i.stack.imgur.com/ZCB8R.png

Can I get Powershell to check if a system was restarted?

I'm currently modifying some code, and below is what the current unmodified code is. For privacy reasons, actual file paths are replaced with "File Path".

Clear-Host
       $YN = Read-Host -Prompt "CONFIRM REBOOT [Y/N]"

       if(($YN -eq "Y") -or ($YN -eq "y"))
       {
           Get-ChildItem -Path "File Path" -Recurse -File | Move-Item -Destination "File Path\Archive" -Force

           $ScriptDir = Split-Path $script:MyInvocation.MyCommand.Path
           $Log = New-Item "File Path\$(Get-Date -f yyyy-MM-dd_hh-mm-ss) Restarts.txt" -ItemType File -Force
           $date = Get-Date -Format "dd-MMM-yyyy hh:mm:ss"

           Clear-Host
           Write-Host `n `n `n
           Write-Host "Rebooting all servers and verifying reboot status..." `n `n
           Write-Host "Please standby, process may take up to 30 minutes..." `n `n

           Restart-Computer -ComputerName $Servers -Wait -For PowerShell -Delay 2 -Force -Timeout 1800

           "----------------------------------Script executed on $date----------------------------------" + "`r`n" | Out-File $Log -Append

           foreach($computer in $Servers)
           {
               $PingRequest = Test-Connection -ComputerName $computer -Count 1 -Quiet
               if($PingRequest -eq $true)
               {
                   Add-Content -Path $Log -Value "$computer`: Reboot Successful." # Issue is here
               }
               else
               {
                   Add-Content -Path $Log -Value "$computer`: Please manually check server."
               }
           }

           Add-Content -Path $Log -Value "`n"
           Clear-Host
           Write-Host `n `n `n
           Write-Host "All done!" `n
           Write-Host "Please review logs, as script may have run into problems." `n `n
           Log-Location
           Pause
       }
       else
       {
           Clear-Host
           Write-Host `n `n `n
           Write-Host "Server Reboots Aborted." `n `n
           Pause
       }

My issue is the script as it currently stands, it simply does a ping request, which only confirms if the server is turned ON, not if it actually restarted. Is there a way for me to get PowerShell to check if the server has actually been restarted, or is this the best that PowerShell can do?

Microsoft Graph SDK PowerShell, uploading files, is there a way to define conflict behaviour e.g., fail if file already exists?

I am using Microsoft Graph SDK for PowerShell (v2.9.0, also tried v2.15.0) to upload files to a drive (SharePoint Document Library). I use the following command to upload files.

Set-MgDriveItemContent -DriveId <String> -DriveItemId <String> [-Data <Stream>] -InFile <String> [-Break]
    [-HttpPipelineAppend <SendAsyncStep[]>] [-HttpPipelinePrepend <SendAsyncStep[]>] [-Proxy <Uri>] [-ProxyCredential
    <PSCredential>] [-ProxyUseDefaultCredentials] [-WhatIf] [-Confirm] [<CommonParameters>]

The command uses this endpoint

PUT    /drives/{drive-id}/items/{driveItem-id}/content

Question: Is there a way to use this parameter @microsoft.graph.conflictBehavior with the above command? I can use this parameter in Postman, with the above mentioned endpoint, to specify what happens if the file already exists in the SP document library. It could have one of the following values -> fail, replace, rename. However, so far, I haven't been able to find a way to this with Set-MgGraphDriveItemContent. Is there no way to do this?

The documentation https://learn.microsoft.com/en-us/graph/api/driveitem-put-content?view=graph-rest-1.0&tabs=powershell mentions the parameter 'BodyParameter' for this command, which may have been the solution for my problem. However, this parameter does not exist, at least not in the newer versions of Graph SDK for PowerShell >2.8.0.

Is there a way to specify this parameter @microsoft.graph.conflictBehavior with the command Set-MgDriveItemContent? or the only solution left for me is to make a separate GET call first to check if the file already exists or switch to creating upload session?

Any help on this would be highly appreciated.

PowerShell Windows License Type

I am trying to pull the Windows license type, I can do it with the following command but it takes forever, is there a quicker PowerShell command for accomplishing this?

See code below for what I've tried.

(Get-CimInstance SoftwareLicensingProduct |
  Where-Object -FilterScript { 
    ($_.Description -like "W*" -and 
    $_.licensestatus -eq 1 ) 
  } |
    Select-Object -First 1 -ExpandProperty Description
) -replace '.*(VOLUME_MAK|OEM_SLP|RETAIL|OEM_COA_NSLP|OEM_COA_SLP).*', '$1'

I get the expected result but it is slow.

Deleting users from Active Directory OU

My organization uses Novell as its primary Directory Service. We are in the process of moving to an Active Directory Domain. I initially used a Windows 2003 Server to import all the accounts from Novell into AD using the Microsoft Directory Services Migration Tool. Weekly I import new accounts from the Novell using the same tool and selecting only the OUs that have either added or disable users.

Last week I was off. Another administrator attempted to do the weekly migration and accidentally imported the users to the wrong OU. This created duplicates in the directory structure. I am now tasked with removing those duplicated.

I have created a list of the users to be removed by exporting all the users from the correct target OU. I am now trying to use that list to target the incorrect OU and remove those LogonNames. I cannot use the SamAccountName as some accounts are longer than 20 characters and the SamAccountName has a 0 on the end of all the duplicates.

What I have so far in PowerShell is

Import-Module ActiveDirectory Import-Csv .\test.csv | ForEach-Object { Remove-ADUser $_.LogonName -Identity ou=WRONGOU,DC=MyDomain, dc=edu -Confirm:$false }

But I cannot get this to work.

What would be even more elegant would be a way to compare the two OUs and if the name appears in both delete it from the wrong OU.

โŒ
โŒ