ranbo
ranbo

Reputation: 187

PowerShell Script Performance Optimization

I am running a PowerShell script that gets some information from a csv file, stores it in an object array and then does some action depending on what's on the file. It actually only does one thing:

If one column has a AD group it copies the row for every member of that group.

The thing is I am really new at scripting and at the beginning the files were small, so everything went ok. Now I have huge files and the script is taking hours to execute.

$file = "c:\Report.csv" 
$fileContent = Import-csv $file | select *, UserName

foreach($item in $fileContent)
{
    $LoginName = $item.LoginName
    $LoginNameClean = $LoginName.split("\")
    $LoginNameClean = $LoginNameClean[1].trimstart("_")
    $ObjectClass = (Get-ADObject -filter {SamAccountName -eq $LoginNameClean}).ObjectClass
    $UserName = $null

    if($ObjectClass -eq "user")
    {
        $UserName = Get-ADUser -identity $LoginNameClean -properties DisplayName

        if($UserName)
        {
            $item.UserName = $UserName.DisplayName
        }
    }

    elseif($ObjectClass -eq "group")
    {   
        $GroupUsers = Get-ADGroupMember -identity $LoginNameClean -Recursive

        foreach($user in $GroupUsers)
        {
            $UserInsideGroup = Get-ADUser -identity $user -properties DisplayName 
            $UserInsideGroupName =  $UserInsideGroup.DisplayName
            $newRow = New-Object PsObject -Property @{"URL" = $item.URL; "SiteListFolderItem" = $item.SiteListFolderItem; "TitleName" = $item.TitleName; "PermissionType" = $item.PermissionType;  "LoginName" = $item.LoginName; "Permissions" = $Item.Permissions; "UserName" = $UserInsideGroup.DisplayName;}
            $fileContent += $newRow
        }
    }
}   


$fileContent | Export-Csv -NoTypeInformation -Path "c:\ReportUpgraded.csv" 

Any tips on how to improve the performance of this is much appreciated

Thanks in advance.

edit: I am using PS 2.0

As commentaries suggested, I am trying to replace the fileContent += newRow.

I am trying to use add member but it's giving me this error:

Add-Member : Cannot add a member with the name "URL" because a member with that name already exists. If you wan t to overwrite the member anyway, use the Force parameter to overwrite it. At line:1 char:26 + $fileContent | Add-Member <<<< -MemberType NoteProperty -Name "URL"-Value "teste" + CategoryInfo : InvalidOperation: (@{SiteListFolde...me=; URL=teste}:PSObject) [Add-Member], Inv
alidOperationException + FullyQualifiedErrorId : MemberAlreadyExists,Microsoft.PowerShell.Commands.AddMemberCommand

How I can I use this properly? Add-member is not adding but replacing members

Upvotes: 1

Views: 2088

Answers (1)

ranbo
ranbo

Reputation: 187

I manage to reduce 30 times the execution time with a couple of things.

First, I switched array to a array list so that I could use theArray.Add() method. Then, in order to stop making requests to the AD all the time, I am saving the information in excel sheets with the name of the group, so that it will only request AD once per group.

Here is the script:

$file = "ReportBefore.csv" 
$fileContent = Import-csv $file | select *, UserName
[System.Collections.ArrayList]$ArrayList = $fileContent


foreach($item in $fileContent)
{
    $LoginName = $item.LoginName
    $LoginNameClean = $LoginName.split("\")
    $LoginNameClean = $LoginNameClean[1].trimstart("_")
    $ObjectClass = (Get-ADObject -filter {SamAccountName -eq $LoginNameClean}).ObjectClass
    $UserName = $null

    if($ObjectClass -eq "user")
    {
        $UserName = Get-ADUser -identity $LoginNameClean -properties DisplayName

        if($UserName)
            {
            $item.UserName = $UserName.DisplayName
            }
    }

    elseif($ObjectClass -eq "group")
    {   
        $exportString = "\\folder\username$\Desktop\ADGroups\" + $LoginNameClean + ".csv" 

        if([System.IO.File]::Exists($exportString))
        {
          $GroupUsers = Import-csv $exportString | select *            
        }
        else
        {
        $GroupUsers = Get-ADGroupMember -identity $LoginNameClean -Recursive | Select samAccountName,Name, @{Name="DisplayName";Expression={(Get-ADUser $_.distinguishedName -Properties Displayname).Displayname}}
        $GroupUsers | Export-Csv -NoTypeInformation -Path $exportString
        }
        foreach($user in $GroupUsers)
        {

            $UserInsideGroupName =  $user.DisplayName
            $newRow = New-Object PsObject -Property @{"URL" = $item.URL; "SiteListFolderItem" = $item.SiteListFolderItem; "TitleName" = $item.TitleName; "PermissionType" = $item.PermissionType;  "LoginName" = $item.LoginName; "Permissions" = $Item.Permissions; "UserName" = $UserInsideGroupName;}
            #$filecontent += $newRow
            $ArrayList.Add($newRow)
        }
     }
}   
$ArrayList | Export-Csv -NoTypeInformation -Path "\ReportAfter.csv" 

Upvotes: 2

Related Questions