Creating a CSV file from results from for each

Tagged: 

This topic contains 2 replies, has 3 voices, and was last updated by Profile photo of Curtis Smith Curtis Smith 8 months ago.

  • Author
    Posts
  • #37540
    Profile photo of Wei-Yen Tan
    Wei-Yen Tan
    Participant

    I am writing a bit of code and came across a situation where I have some output from foreach but I cannot figure out how I can export to a csv.

    the code i have is as follows:

    
    $servers = import-csv D:\server_list.csv
    
            foreach ($server in $servers){
            $servername = $server.computername        
                try {
                Get-ADComputer $servername -properties description | select name, description -ErrorVariable SilentlyContinue
    
                } catch{
           
                    $testpath = test-path d:\15393848.txt
    
                        if ($testpath -eq $false){
    
                            New-item -itemtype file -name 15393848.txt -path d:\
            
                            }
    
                        Add-Content -Path d:\15393848.txt -value "$servername"
    
                }
        }
    
    

    It outputs correctly and puts the text in the error log if the computer doesnt exist but need to have the display output in a csv. I had a look around the web and tried to use whats there and i saw one example of one guy use objects (http://goo.gl/VN7Imr)
    but I don't think I am understanding the core concept in regards to this.

    Any help appreciated.

  • #37542
    Profile photo of Yuan Li
    Yuan Li
    Participant

    You can define a customized object if you want, but if you just want the result, you can assign a variable to to your for loop. Get-ADComputer has returned an ADObject for you already.

    $servers = import-csv D:\server_list.csv
    
         $result=  foreach ($server in $servers){
            $servername = $server.computername        
                try {
                Get-ADComputer $servername -properties description | select name, description -ErrorVariable SilentlyContinue
    
                } catch{
           
                    $testpath = test-path d:\15393848.txt
    
                        if ($testpath -eq $false){
    
                            New-item -itemtype file -name 15393848.txt -path d:\
            
                            }
    
                        Add-Content -Path d:\15393848.txt -value "$servername"
    
                }
        }
    
    $result | export-csv c:\temp\server.csv 
    
    

    Also,in your url example, that's the old way to define a customized object- you define a hash table structure and then convert it to an object. After Powershell v3, you can directly use [pscustomobject] to create one in your loop.

    Btw, I think you're Chinese from your name. If you can read Chinese, you can see my blog for more examples. http://beanxyz.blog.51cto.com/5570417/1737512

    Cheers
    Yuan

  • #37554
    Profile photo of Curtis Smith
    Curtis Smith
    Participant

    You can also change your code a little to use the ForEach-Object Cmdlet rather than the ForEach statement

    Example:

    ForEach ($dir in @("C:\","C:\Users","C:\Windows")){
        Get-ChildItem $dir
    }
    

    Using the above example, if I added a Pipe to export after the ForEach, I get an error.

    ForEach ($dir in @("C:\","C:\Users","C:\Windows")){
        Get-ChildItem $dir
    } | Export-Csv C:\Temp\Export.csv
    
    At line:4 char:3
    + } | Export-Csv C:\Temp\Export.csv
    +   ~
    An empty pipe element is not allowed.
        + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
        + FullyQualifiedErrorId : EmptyPipeElement
    

    This is because statements in and of themselves do not export object to the pipeline. In order to get the above code to work, I would need to add the Export on the cmdlet that actually exports the object for Export-CSV to work on.

    ForEach ($dir in @("C:\","C:\Users","C:\Windows")){
        Get-ChildItem $dir | Export-Csv C:\Temp\Export.csv -Append
    }
    

    This works OK, but since it is inside the loop, I have to use the -Append parameter so the previous data does not get over-written each time through the loop. That also means additional IO which will cause the script to run slower and use more resources on the system.

    What I can do instead is change this to use the ForEach-Object cmdlet to continue the pipeline.

    @("C:\","C:\Users","C:\Windows") | ForEach-Object {
        Get-ChildItem $_
    } | Export-Csv C:\Temp\Export.csv
    

    Since ForEach-Object is a cmdlet that outputs objects to the Pipeline, Export-CSV will gladly take those objects as input.

You must be logged in to reply to this topic.