Powershell Array to csv - arrays

I'm pretty new to powershell and I cant figure out how to get my array into a csv file, where each string goes onto a new row. Below is some example code.
$ServerList = "E:\Coding Projects\Powershell\ServerNameList.txt"
$ServerNames = Get-content $ServerList
write-host $ServerNames
$OutputPath = "E:\Coding Projects\Powershell\Output.csv"
$Names = #()
$Outcome = #()
foreach ($Server in $ServerNames){
$Names += $Server
if ($Server -match "Joe"){
$Outcome += "pass"
}else{
$Outcome += "Fail"
}
}
$Names
$Outcome
$csv = New-object psobject -property #{
'User' = $Names -join ','
'Groups' = $Outcome -join ','
}
write-host $csv
$csv | Select-Object -property User, Groups | Export-csv -path $OutputPath -NoTypeInformation
When I check the csv file, all of the outputs appear on one row instead of iterating down the rowin its specific column.
Any help would be very useful and appreciated

Right now you're creating 2 separate arrays of string values - instead, you'll want to create a single array of objects with two properties:
$ServerList = "E:\Coding Projects\Powershell\ServerNameList.txt"
$ServerNames = Get-content $ServerList
write-host $ServerNames
$OutputPath = "E:\Coding Projects\Powershell\Output.csv"
$serversWithOutcome = #()
foreach ($Server in $ServerNames){
$serversWithOutcome += [pscustomobject]#{
User = $Server
Groups = $Server -match "Joe"
}
}
$serversWithOutcome | Export-csv -path $OutputPath -NoTypeInformation

Related

Duplicate SQL results from Powershell CSV export

I am trying to output SQL results to a .csv file using Powershell separated by its respective column.
The script I wrote works, but it will duplicate the same result three times in the csv. Even if I have only 1 result from the Select statement from the table, it will output it three times in the .csv file.
I tried using pscustomobject as well. But it throws me an error and does not output anything.
Clear-Variable Results
Clear-Variable Report
[string] $query = "Select Name, Value From options with(nolock) where Name IN('ExportFolder','ImportFolder','GlobalExportFolder'); Select ##ROWCOUNT AS AffectedRows"
[string[]] $servers = #('sqlinstance=mytestdb')
foreach($server in $servers)
{
$instance = ($server -split '=')[0]
$db = ($server -split '=')[1]
Try{
$Results = Invoke-Sqlcmd -ServerInstance $instance -Database $db -Query $query
$ExportFolder = ($Results.ItemArray[1])
$GlobalExportFolder = ($Results.ItemArray[3])
$ImportFolder = ($Results.ItemArray[5])
$Array = '$ExportFolder','$GlobalExportFolder','ImportFolder'
$mail = $Array | Select-Object #{n="SQLServer";e={$instance}},#{n="DBName";e={$db}}, #{n="ExportFolder";e={$ExportFolder}}, #{n="GlobalExportFolder";e={$GlobalExportFolder}}, #{n="ImportFolder";e={$ImportFolder}}
$mail | Export-Csv -Path "C:\Users\localadmin\Documents\Logs\HostNameCheck.csv" -NoTypeInformation -Append -Verbose
$Report += $Results
$Report | Select Name, Value | Export-Csv -Path "C:\Users\localadmin\Documents\Logs\SFTPHostnameModificationCheck.csv" -NoTypeInformation -Append -Verbose
Clear-Variable Results
Clear-Variable Report
}
Catch {
Write-Host ("Error: Data retrieval failed against instance $instance for $db" + " - " + (Get-Date)) -ForegroundColor Red
Write-Output ("Error: Data retrieval failed against $instance on $db" + " - " + (Get-Date)) | Out-File -FilePath $PathFailedLogs -Append
}
}
$attachment = Get-ChildItem -Path "C:\Users\localadmin\Documents\Logs" -Include *.csv -Recurse -Force
Send-MailMessage -From "test#test.com" -To "localadmin#nonprod.com" -Subject "SFTPHostnameCheck" -SmtpServer "localrelay#local.com" -Attachments $attachment
Using PSCustomObject
$obj = New-Object [PSCustomObject] -Property #{
'SQLServer' = $instance
'DBName' = $db
'ExportFolder' = "$ExportFolder
'GlobalExportFolder' = $GlobalExportFolder
'ImportFolder' = $ImportFolder"
}
$list += $obj
$list | Export-Csv -Path "C:\Users\localadmin\Documents\Logs\HostNamecheck.csv" -NoTypeInformation -Append -Verbose

What is the best format to export bigger output?

I have a big file server, with a big files and folder tree and I need export the NTFS permissions. I used a following script:
$FolderPath = Get-ChildItem -Path C:\FS -Filter * -Recurse -Force
ForEach ($Folder in $FolderPath) {
$Acl = Get-Acl -Path $Folder.FullName
ForEach ($Access in $Acl.Access) {
$Properties = [ordered]#{'Folder Name'=$Folder.FullName;'Group/User'=$Access.IdentityReference;'Permissions'=$Access.FileSystemRights;'Inherited'=$Access.IsInherited}
New-Object -TypeName PSObject -Property $Properties
}
}
What kind of format recommend me to get out the result from the script, I think CSV is a very good format, but I don´t know if is the correct file format.
You can write to CSV format and it will be easier to process them later in excel or another place.
$FolderPath = Get-ChildItem -Path C:\FS -Filter * -Recurse -Force
$collection = #() #Define collection
ForEach ($Folder in $FolderPath) {
$Acl = Get-Acl -Path $Folder.FullName
ForEach ($Access in $Acl.Access) {
$Properties = [ordered]#{'Folder Name'=$Folder.FullName;'Group/User'=$Access.IdentityReference;'Permissions'=$Access.FileSystemRights;'Inherited'=$Access.IsInherited}
$collection += New-Object -TypeName PSObject -Property $Properties
}
}
$collection | Export-Csv -LiteralPath C:\ACLInformation.csv -NoTypeInformation -Encoding UTF8

Issue creating an array of objects from a csv file

I'm fairly new with Powershell, so this is likely a rookie mistake, but I am trying to take a CSV document containing only user display names, query AD for the required information, and populate that information into object properties using a hash table.
Here is what i have right now
$Path = "C:\Scripts\Generate-CSRSpreadsheets\Roster-Jpay.csv"
$Table = Import-csv -Path $Path -Header EmployeeDisplayName
$Array = #()
$ADUser = Get-ADUser -Properties DisplayName,Manager -Filter {DisplayName -eq $_.EmployeeDisplayname}
ForEach($User in $Table){
$Object = New-Object PSObject -Property #{
DisplayName = $ADUser.DisplayName
GivenName = $ADUser.GivenName
Surname = $ADUser.Surname
Email = $ADUser.Mail
}
$Array += $Object
}
This seems to me like it should work fine, but when I check my output it looks something like this:
Example Output Image
Let's say in this example I have 9 total users, but it's only outputting the information from the last user in the csv. I've been pouring over this code, but I can't see what's wrong with it. Any help would be appreciated.
Thank you
You need to move your Get-ADUser inside the loop:
$Path = "C:\Scripts\Generate-CSRSpreadsheets\Roster-Jpay.csv"
$Table = Import-csv -Path $Path -Header EmployeeDisplayName
$Array = #()
ForEach($User in $Table){
$ADUser = Get-ADUser -Filter "DisplayName -eq '$($User.EmployeeDisplayName)'" -Properties DisplayName,Manager
$Object = New-Object PSObject -Property #{
DisplayName = $ADUser.DisplayName
GivenName = $ADUser.GivenName
Surname = $ADUser.Surname
Email = $ADUser.Mail
}
$Array += $Object
}

Export csv via pscustomobject displaying incorrectly powershell

I have the following code:
function realtest
{
$files = Get-ChildItem -Path 'D:\data\' -Filter *.csv
$tester = [PSCustomObject]#{
foreach ($file in $files)
{
$tempName = $file.BaseName
$temp = Import-Csv $file
$tester | Add-Member -MemberType NoteProperty -Name $tempName -Value $temp.$tempName
}
$tester
$tester | Export-Csv "D:\result.csv" -NoTypeInformation
}
I am trying to export a bunch of data to CSV however when it is display the data on csv it is shown as below
"E0798T102","E0798T103"
"System.Object[]","System.Object[]"
but when i do it as a print on console it displays as the below
E0798T102 E0798T103
--------- ---------
{0, 0, 0, 0...} {0, 0, 0, 0...}
Ultimately, I want E0798T102 and E0798T103 as seperate columns in the result.csv
just to note, I will have 50 csv to loop through and each should display as its own column
Here is an incredibly inefficient answer to your question. If left as is, it assumes your CSV files already have a header with the CSV file basename:
$CSVs = Get-ChildItem -path 'D:\data\' -filter "*.csv" -file
$headers = $CSVs.basename
$table = [System.Data.DataTable]::new("Files")
foreach ($header in $headers) {
$table.Columns.Add($header) | out-null
}
foreach ($CSV in $CSVs) {
#$contents = Import-Csv $CSV -Header $CSV.basename # If CSV has no header
$contents = Import-Csv $CSV # If CSV contains header
$rowNumber = 0
foreach ($line in $Contents) {
$rowcount = $table.rows.count
if ($rowNumber -ge $rowCount) {
$row = $table.NewRow()
$row[$CSV.basename] = $line.$($CSV.basename)
$table.Rows.Add($row)
}
else {
$row = $table.rows[$rowNumber]
$row[$CSV.basename] = $line.$($CSV.basename)
}
$rowNumber++
}
}
$table | Export-Csv output.csv -NoTypeInformation
You can uncomment the commented $contents line if your CSV files do not have a header. You will just have to comment out the next $contents variable assignment if you uncomment the first.
Based on your snippet, this can be significantly simplified:
function Get-Csv {
$col = foreach ($file in Get-ChildItem -Path D:\data -Filter *.csv) {
$csv = Import-Csv -Path $file.FullName
[pscustomobject]#{
$csv.($file.BaseName) = $csv
}
}
$col | Export-Csv D:\result.csv -NoTypeInformation
return $col
}
However, a csv file seems like the wrong approach because you're trying to embed objects under a header. This doesn't really work in a tabular format as you only get one layer of depth. You should either expand all the properties on your objects, or use a different format that can represent depth, like json.
The reason for your formatting woes is due to how the serialization works. You're getting a string representation of your objects.
Converting to json isn't difficult, you just trade your Export-Csv call:
$col | ConvertTo-Json -Depth 100 | Out-File -FilePath D:\result.json
Note: I specify -Depth 100 because the cmdlet's default Depth is 2.

Powershell Array: HOWTO Dedup Output

When I run this parser script on my contacts.xml, which shows one line per user, I get multiple instances of the same data. I only want a single entry for the same data. How do I dedup the data before it writes to the CSV?
#https://stackoverflow.com/questions/29999682/powershell-parsing-a-text-file
$input = Get-Content $env:USERPROFILE\Downloads\contacts.xml\Downloads\contacts.xml
$array = #()
$input | % {
$writeobj = $false
$obj = New-Object System.Object
if ($_ -match 'email*') {
$Email = ($_ -split ':')[1]
}
if ($_ -match 'FN*') {
$NAME = ($_ -split ':')[1]
$writeobj = $true
}
if ($writeobj) {
$obj | Add-Member -Type NoteProperty -Name Email -Value $Email
$obj | Add-Member -Type NoteProperty -Name Name -Value $NAME
$array += $obj
}
Write-Host $Name, $email
}
$array | Export-Csv -Path C:\scripts\reports\test.csv -NoTypeInformation
I expect this to produce single entries but I get duplicates (and they don't line up right either).
(And yes I checked the XML file for single entries)
Select the unique objects.
$array |
Select-Object -Property * -Unique |
Export-Csv -Path 'C:\scripts\reports\test.csv' -NoType
As a side note, you may want to avoid appending to an array in a loop, as that is bound to perform poorly. Just pipe your ForEach-Object loop directly into Export-Csv.
I figured it out.
I REVERSED the $obj Add-Member variables *that fixed the order) and added another "$writeobj = $true" line to the FN match, and VOILÀ no more dupes.
Is that weird or what?
#https://stackoverflow.com/questions/29999682/powershell-parsing-a-text-file
$input = Get-Content $env:USERPROFILE\Downloads\contacts.xml $array =
#() $input | % {
$writeobj = $false
$obj = New-Object System.Object
If ($_ -match 'email') {
$Email = ($_ -split ':')[1]
$writeobj = $true
}
If ($_ -match 'FN') {
$NAME = ($_ -split ':')[1]
$writeobj = $true # <-- right here
}
If ($writeobj){
$obj | Add-Member -type NoteProperty -name Email -value **$NAME**
$obj | Add-Member -type NoteProperty -name Name -value **$Email**
$array += $obj
}
Write-Host $Name, $email } $array | Export-Csv -path C:\scripts\reports\test.csv -NoTypeInformation

Resources