2

I'm trying to output a custom object to a csv formatted text file as I loop through a for each. One object per line.

But nothing is written to the file.

Is it something with types to be converted ?

$rechten = Get-ADGroupMember -Identity $v -Recursive -ERRORACTION silentlycontinue | Get-ADUser -Property DisplayName -ERRORACTION silentlycontinue | Select-Object Name

Write-Host -ForegroundColor Yellow "ADgroup $v wordt uitgevlooid."

foreach ($rechtenhouder in $rechten) {
    $objResults = New-Object PSObject
    $objResults | Add-Member -MemberType NoteProperty -Name DirectoryPath -Value $objPath
    $objResults | Add-Member -MemberType NoteProperty -Name Identity -Value    $rechtenhouder.name
    $objResults | Add-Member -MemberType NoteProperty -Name Systemrights -Value $accessRight.FileSystemRights
    $objResults | Add-Member -MemberType NoteProperty -Name systemrightstype -Value $accessRight.accesscontroltype
    $objResults | Add-Member -MemberType NoteProperty -Name isinherited -Value $accessRight.isinherited
    $objResults | Add-Member -MemberType NoteProperty -Name inheritanceflags -Value $accessRight.inheritanceflags
    $objResults | Add-Member -MemberType NoteProperty -Name rulesprotected -Value $objACL.areaccessrulesprotected
    $objResults | Add-Member -MemberType NoteProperty -Name Adtype -Value "User"

    $arrResults += $objResults
    Add-Content $exportpathtxtappend $objresults
}
3
  • Instead of writing hundreds of lines adding noteproperties, you could just create your object with $objResult = New-Object psobject @{DirectoryPath = $objPath; Identity = "and so on...."} Commented Nov 28, 2017 at 10:25
  • And don't use Add-Content for that. Export-CSV is your friend. Commented Nov 28, 2017 at 10:26
  • I wanted to use ac because if script is interrupted for what cause possible, I'd would have already some output in the file. Commented Nov 28, 2017 at 10:34

2 Answers 2

1

For your specific use exporting all objects at once or in batches would be the most efficient, but there are times were it would make sense to export a record one at a time to a CSV file which is what led me to this question, so I want to post my solution.

Use Export-CSV -Append to continually add to the end of a csv file.

foreach ($rechtenhouder in $rechten) {
    $objResults = New-Object PSObject -Property @{
        DirectoryPath    = $objPath;
        Identity         = $rechtenhouder.name;
        Systemrights     = $accessRight.FileSystemRights;
        systemrightstype = $accessRight.accesscontroltype;
        isinherited      = $accessRight.isinherited;
        inheritanceflags = $accessRight.inheritanceflags;
        rulesprotected   = $objACL.areaccessrulesprotected;
        Adtype           = "User";
    }

    $objResults | Export-CSV $csvPath -Append -NoTypeInformation
}

This is useful if you are continually polling at set time intervals, but less so if you are iterating over a collection of objects, just export them all at once. For example, I would use this method of exporting for a script like below:

while($true){
    $procs = Get-Process | Select-Object Name,CPU
    $procs | Add-Member -type NoteProperty -Name "Timestamp" -Value $(Get-Date)

    $procs | Export-CSV $csvPath -Append -NoTypeInformation

    sleep -Seconds 60
}
Sign up to request clarification or add additional context in comments.

Comments

0

First, I suggest you to create your object in a decent smarter way:

foreach ($rechtenhouder in $rechten) {
    $objResults = New-Object PSObject -Property @{
        DirectoryPath    = $objPath;
        Identity         = $rechtenhouder.name;
        Systemrights     = $accessRight.FileSystemRights;
        systemrightstype = $accessRight.accesscontroltype;
        isinherited      = $accessRight.isinherited;
        inheritanceflags = $accessRight.inheritanceflags;
        rulesprotected   = $objACL.areaccessrulesprotected;
        Adtype           = "User";
    }
    $arrResults += $objResults
}

With this done, your $arrResults now contains your objects. This can easily exported to CSV files with PowerShells builtin Export-CSV:

$arrResults | Export-Csv -Path "C:/temp/text.csv"

Using Add-Content on every loop iteration is IMHO ineffective regarding performance. If your script runs for a long time and you want to save your current state in intervals, you could e.g. start an asynchronous job - let's say every 10th iteration - exporting your current array:

$i = 0
foreach ($rechtenhouder in $rechten) {
    $objResults = New-Object PSObject -Property @{
        DirectoryPath    = $objPath;
        Identity         = $rechtenhouder.name;
        Systemrights     = $accessRight.FileSystemRights;
        systemrightstype = $accessRight.accesscontroltype;
        isinherited      = $accessRight.isinherited;
        inheritanceflags = $accessRight.inheritanceflags;
        rulesprotected   = $objACL.areaccessrulesprotected;
        Adtype           = "User";
    }
    $arrResults += $objResults
    if ($i % 10 -eq 0) {
        Start-Job -ScriptBlock {
            param($T, $Path)
            $T | Export-Csv -Path $Path
        } -ArgumentList @($arrTest, "Path/to/script")
    }
    $i++
}

3 Comments

like that async job idea! I've never worked with start-job. Only one line is added in text.csv. I must be messing / missing in the scriptblock parameters. $arrResults | out-file $exportPathtxt did fil up as expeted another textfile.
Glad to hear! Please keep in mind - if the loop is faster than I expect, it's possible, that you must adjust every 10th job to every 20th job or so. If not, you'll run into concurrency issues. Also, don't forget to export after the loop a last time. If not, you'll miss some entries. Hope it helps.
I added a path argument to the scriptblock.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.