Splitting an array to different variables - powershell

I have an XML file with multiple same-name fields like this:
<XMLDAT>
<Interpret>Crow Jonathan</Interpret>
<Interpret>Mcnabney Douglas</Interpret>
<Interpret>Haimovitz Matt</Interpret>
<Interpret>Sitkovetski Dmitri</Interpret>
</XMLDAT>
I'm trying to split these into a separate variable for each Interpret so I can be able to export it as a CSV file. Ex.
[xml]$XML = Get-Content -Path C:\TestFile.xml
$Interpret = $XML.XMLDAT.Interpret
$interpret1 = ""
$interpret2 = ""
$interpret3 = ""
$interpret4 = ""
$DATACOLLECTION = #()
$DATA = New-Object PSObject
Add-Member -inputObject $DATA -memberType NoteProperty -name "Interpret1" -value $interpret1
Add-Member -inputObject $DATA -memberType NoteProperty -name "Interpret2" -value $interpret2
Add-Member -inputObject $DATA -memberType NoteProperty -name "Interpret3" -value $interpret3
Add-Member -inputObject $DATA -memberType NoteProperty -name "Interpret4" -value $interpret4
$DATACOLLECTION += $DATA
$DATACOLLECTION | Export-Csv -append -path C:\test.csv -NoTypeInformation
I'm not sure how to proceed into splitting these into their own variables.

PowerShell supports multi-target variable assignments:
[xml]$XML = Get-Content -Path C:\TestFile.xml
$interpret1, $interpret2, $interpret3, $interpret4 = $XML.XMLDAT.Interpret
But you don't really need all those variables :)
You could construct the final object by dynamically adding all the "Interpret" node values to a hashtable and then convert that to an object:
[xml]$XML = Get-Content -Path C:\TestFile.xml
$properties = [ordered]#{}
$XML.XMLDAT.Interpret |ForEach-Object -Begin {$number = 1} -Process {
$properties["Interpret$($number++)"] = "$_"
}
#( [pscustomobject]$properties ) |Export-Csv -Append -Path C:\test.csv -NoTypeInformation

Was able to get desired result using this ForEach loop:
ForEach ($Interprets in $Interpret){
$interpret1 = $Interpret[0]
$interpret2 = $Interpret[1]
$interpret3 = $Interpret[2]
$interpret4 = $Interpret[3]
}

I would just do one column with four rows:
$xml.xmldat.interpret | % { [pscustomobject]#{Interpret = $_} }
Interpret
---------
Crow Jonathan
Mcnabney Douglas
Haimovitz Matt
Sitkovetski Dmitri

Related

Not able to add data to csv file powershell

I am trying to add data to an csv file.
I am creating the csv with header first and then trying to add the rows. but it is returning blank csv file
$props=[ordered]#{
ServerName=''
SystemFolderPath=''
IdenityReference=''
FileSystemRights=''
}
New-Object PsObject -Property $props |
Export-Csv "C:\status_report.csv" -NoTypeInformation
$serverlist = Get-Content -Path "C:\ServerList.txt"
foreach($server in $serverlist)
{
$paths_list = $env:Path -Split ';'
Foreach ($sys_Path in $paths_list)
{
$Permissions = Get-Acl -Path $sys_Path
$Users_Permissions = $Permissions.Access | Where-Object {$_.IdentityReference}
#$Users_Permission
Foreach ($user in $Users_Permissions)
{
$IdenityReference = $user.IdentityReference.Value
$FileSystemRights = $user.FileSystemRights
$NewLine = "{0},{1},{2},{3}" -f $server,$sys_Path,$IdenityReference,$FileSystemRights
$NewLine | Export-Csv -Path "C:\status_report.csv" -Append -NoTypeInformation -Force
}
}
}
Please let me know what I am doing wrong here
The main reason why you're seeing this is because Export-Csv expects an object or object[] through the pipeline and you're passing a formatted string instead. This is specified on MS Docs:
Do not format objects before sending them to the Export-CSV cmdlet. If Export-CSV receives formatted objects the CSV file contains the format properties rather than the object properties.
PS /> 'server01,C:\Windows,Computer\User,FullControl' | ConvertTo-Csv
"Length"
"45"
Instead of appending to a CSV which is quite inefficient, unless there is a specific need for this, what you will want to do is collect the results first and then export them.
I'm not too sure why | Where-Object { $_.IdentityReference } is needed, I left it there but I don't think it's needed.
Regarding $serverlist, if you will run this on remote hosts you would be better of using Invoke-Command since it allows parallel invocations. The outer loop wouldn't be needed in that case:
$serverlist = Get-Content -Path "C:\ServerList.txt"
# Collect results here
$result = Invoke-Command -ComputerName $serverlist -ScriptBlock {
$paths_list = $env:Path -Split [System.IO.Path]::PathSeparator
foreach($sys_Path in $paths_list)
{
$Permissions = (Get-Acl -Path $sys_Path).Access
foreach($acl in $Permissions)
{
if(-not $acl.IdentityReference)
{
continue
}
[pscustomobject]#{
ComputerName = $env:ComputerName
SystemFolderPath = $sys_Path
IdenityReference = $acl.IdentityReference.Value
FileSystemRights = $acl.FileSystemRights
}
}
}
} -HideComputerName
$result | Export-Csv -Path "C:\status_report.csv" -NoTypeInformation
Accept Santiago above but this is what I did with what you wrote.
$props = [ordered]#{
ServerName = ''
SystemFolderPath = ''
IdenityReference = ''
FileSystemRights = ''
}
New-Object PsObject -Property $props |
Export-Csv "C:\status_report.csv" -NoTypeInformation
$serverlist = Get-Content -Path "C:\ServerList.txt"
$result = $serverlist | ForEach-Object {
foreach ($server in $_) {
$paths_list = $null
$paths_list = $env:Path -Split ';'
Foreach ($sys_Path in $paths_list) {
$Permissions = Get-Acl -Path $sys_Path
$Users_Permissions = $Permissions.Access | Where-Object { $_.IdentityReference }
#$Users_Permission
Foreach ($user in $Users_Permissions) {
$IdenityReference = $null
$FileSystemRights = $null
$IdenityReference = $user.IdentityReference.Value
$FileSystemRights = $user.FileSystemRights
[PSCustomObject]#{
Server = $server
Sys_Path = $sys_Path
Referecent = $IdenityReference
Rights = $FileSystemRights
}
$sys_Path = $null
}
}
}
}
$result | Export-Csv -Path "C:\status_report.csv" -NoTypeInformation
Santiago's answer is correct and contains all the required information for you to understand the issue you have here.
I just wanted to provide you with the minimum modifications to be done in your script:
Replace the $props custom object by a function (i.e CreateCustomObject)
function CreateCustomObject($val1, $val2, $val3, $val4) {
$NewObject = New-Object PSObject ;
Add-Member -InputObject $NewObject -MemberType NoteProperty -Name "ServerName" -Value $val1 ;
Add-Member -InputObject $NewObject -MemberType NoteProperty -Name "SystemFolderPath" -Value $val2 ;
Add-Member -InputObject $NewObject -MemberType NoteProperty -Name "IdenityReference" -Value $val3 ;
Add-Member -InputObject $NewObject -MemberType NoteProperty -Name "FileSystemRights" -Value $val4 ;
return $NewObject ;
}
Replace the String Variable $NewLine by an Array
$NewLine = #()
$NewLine += CreateCustomObject $server $sys_Path $IdenityReference $FileSystemRights
Write to CSV only once data is collected (move the command to the end of the script)
So the final script will look something like that:
function CreateCustomObject($val1, $val2, $val3, $val4) {
$NewObject = New-Object PSObject ;
Add-Member -InputObject $NewObject -MemberType NoteProperty -Name "ServerName" -Value $val1 ;
Add-Member -InputObject $NewObject -MemberType NoteProperty -Name "SystemFolderPath" -Value $val2 ;
Add-Member -InputObject $NewObject -MemberType NoteProperty -Name "IdenityReference" -Value $val3 ;
Add-Member -InputObject $NewObject -MemberType NoteProperty -Name "FileSystemRights" -Value $val4 ;
return $NewObject ;
}
$serverlist = Get-Content -Path "C:\Temp\ServerList.txt"
$NewLine = #()
foreach($server in $serverlist) {
$paths_list = $env:Path -Split ';'
Foreach ($sys_Path in $paths_list) {
$Permissions = Get-Acl -Path $sys_Path
$Users_Permissions = $Permissions.Access | Where-Object {$_.IdentityReference}
#$Users_Permission
Foreach ($user in $Users_Permissions) {
$IdenityReference = $user.IdentityReference.Value
$FileSystemRights = $user.FileSystemRights
$NewLine += CreateCustomObject $server $sys_Path $IdenityReference $FileSystemRights
}
}
}
$NewLine | Export-Csv -Path "C:\temp\status_report.csv" -NoTypeInformation -Force

Sharepoint - Export all data to csv with powershell

I am attempting to use a script provided by Thriggle See His Answer Here and am having some issues with it. It works almost flawlessly for what I am doing - EXCEPT - it doesn't export the Created By, Created Date, Modified By, and Modified Date.
Is there a way to add those fields into the script?
Here is his script:
$url = "$url"
$listName = "$list"
$path ="c:\ColumnsOfList.csv"
$web = Get-SPWeb $url
$list = $web.Lists.TryGetList($listName)
$fields = $list.ContentTypes | %{ $_.FieldLinks } | select Name, DisplayName
$items = #() #array to store objects representing list items
$list.items | %{
$item = $_;
$hash = #{}; #hash table to store field name-value pairs
$fields | %{ $hash[$_.DisplayName] = $item[$_.Name] };
$items += new-object psobject -Property $hash }
$items | Export-Csv -Path $path
You could try this one.
Here is my test code.
Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue
#Get the Web
$web = Get-SPWeb -identity "http://sp:12001"
#Get the Target List
$list = $web.Lists["OrderDetails"]
#Array to Hold Result - PSObjects
$ListItemCollection = #()
#Get All List items where Status is "In Progress"
$list.Items | foreach {
$ExportItem = New-Object PSObject
$ExportItem | Add-Member -MemberType NoteProperty -name "Title" -value $_["Title"]
$ExportItem | Add-Member -MemberType NoteProperty -Name "OrderDate" -value $_["OrderDate"]
$ExportItem | Add-Member -MemberType NoteProperty -name "CreatedBy" -value $_["Author"]
$ExportItem | Add-Member -MemberType NoteProperty -name "Created" -value $_["Created"]
#Add the object with property to an Array
$ListItemCollection += $ExportItem
}
#Export the result Array to CSV file
$ListItemCollection | Export-CSV "C:\Lee\ListData.csv" -NoTypeInformation
#Dispose the web Object
$web.Dispose()

Export list/array to CSV in Powershell

done some googling but answers I have found seem to be more complex than what I need. I have a simple script to fetch DNS cache entries, and I'd like to export the results to a CSV in the most "powershell" manner. Code looks like this:
function Get-Dns
{
$domains = #()
$cmdOutput = Invoke-Command -ScriptBlock {ipconfig /displaydns}
ForEach ($line in $($cmdOutput -split "`r`n"))
{
if ($line -like '*Record Name*'){
$domain = $line -split ":"
$domains += $domain[1]
}
}
so I have an array, $domains, which I would like to use Export-CSV to essentially output a one column CSV with one domain per line. Using Export-CSV seems to just output the length of each element rather than the contents itself. Any help is appreciated!
The most PowerShell way:
(ipconfig /displaydns|where{$_-match'Record Name'})|%{$_.split(":")[1].Trim()}>dnscache.txt
"ipconfig /displaydns" is going to give you back a big'ol string array, which is going to be harder to work with. Try the native commandlets for DNS manipulation:
Get-DnsClientCache | Export-Csv -Path .\stuff.csv
If you're using Windows 7 or earlier, try this...
$dns_client_cache = #()
$raw_dns_data = ipconfig /displaydns
for ($element = 3; $element -le $raw_dns_data.length - 3; $element++) {
if ( $raw_dns_data[$element].IndexOf('Record Name') -gt 0 ) {
if ( $dns_entry ) { $dns_client_cache += $dns_entry }
$dns_entry = New-Object -TypeName PSObject
Add-Member -InputObject $dns_entry -MemberType NoteProperty -Name 'RecordName' -Value $raw_dns_data[$element].Split(':')[1].Trim()
} elseif ( $raw_dns_data[$element].IndexOf('Record Type') -gt 0 ) {
Add-Member -InputObject $dns_entry -MemberType NoteProperty -Name 'RecordType' -Value $raw_dns_data[$element].Split(':')[1].Trim()
} elseif ( $raw_dns_data[$element].IndexOf('Time To Live') -gt 0 ) {
Add-Member -InputObject $dns_entry -MemberType NoteProperty -Name 'TimeToLive' -Value $raw_dns_data[$element].Split(':')[1].Trim()
} elseif ( $raw_dns_data[$element].IndexOf('Data Length') -gt 0 ) {
Add-Member -InputObject $dns_entry -MemberType NoteProperty -Name 'DataLength' -Value $raw_dns_data[$element].Split(':')[1].Trim()
} elseif ( $raw_dns_data[$element].IndexOf('Section') -gt 0 ) {
Add-Member -InputObject $dns_entry -MemberType NoteProperty -Name 'Section' -Value $raw_dns_data[$element].Split(':')[1].Trim()
} elseif ( $raw_dns_data[$element].IndexOf('CNAME Record') -gt 0 ) {
Add-Member -InputObject $dns_entry -MemberType NoteProperty -Name 'CNAMERecord' -Value $raw_dns_data[$element].Split(':')[1].Trim()
}
}
$dns_client_cache | Export-Csv -Path .\dns_stuff.csv -Force -NoTypeInformation
Sorry! I know it's messy.
I ended up going with to export multiple value array to csv
$Data | %{$_} | export-csv -nti -Path C:\

Powershell custom append object to csv file

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
}
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
}
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++
}

Sum Columns Using Powershell

I have written the following PowerShell script for getting disk space information for servers in our environment.
$servers = Get-Content E:\POC.txt
$array = #()
foreach($server in $servers){
$sysinfo = Get-WmiObject Win32_Volume -ComputerName $server
for($i = 0;$i -lt $sysinfo.Count; $i++){
$sname = $sysinfo[$i].SystemName
$servername = $server
$label = $sysinfo[$i].Label
if(($label) -and (!($label.Contains("FILLER")))){
write-host "Processing $label from $server"
$name = $sysinfo[$i].Name
$capacity = [math]::round(($sysinfo[$i].Capacity/1GB),2)
$fspace = [math]::round(($sysinfo[$i].FreeSpace/1GB),2)
$sused = [math]::round((($sysinfo[$i].Capacity - $sysinfo[$i].FreeSpace)/1GB),2)
$fspacepercent = [math]::Round((($sysinfo[$i].FreeSpace*100)/$sysinfo[$i].Capacity),2)
$obj = New-Object PSObject
$obj | Add-Member -MemberType NoteProperty -Name "SystemName" -Value $sname
$obj | Add-Member -MemberType NoteProperty -Name "ServerName" -Value $server
$obj | Add-Member -MemberType NoteProperty -Name "Label" -Value $label
$obj | Add-Member -MemberType NoteProperty -Name "Name" -Value $name
$obj | Add-Member -MemberType NoteProperty -Name "Capacity(GB)" -Value $capacity
$obj | Add-Member -MemberType NoteProperty -Name "FreeSpace(GB)" -Value $fspace
$obj | Add-Member -MemberType NoteProperty -Name "Used(GB)" -Value $sused
$obj | Add-Member -MemberType NoteProperty -Name "FreeSpace%" -Value $fspacepercent
$array += $obj
}
}
$array += write-output " "
$totalSize = ($array | Measure-Object 'Capacity(GB)' -Sum).Sum
$array += $totalsize
$array += write-output " "
}
$filename = "E:\VolumeReport.csv"
$array | Export-CSV $filename -NoTypeInformation
One additional requirement here is to get the sum of the columns for Capacity, Size and Freespace for each server. I tried using Measure-Object but no success.
No values are getting outputted here. Just blank. Please look into this and kindly assist.
Let try this on for size shall we.
$servers = Get-Content E:\POC.txt
$propertyOrdered = "SystemName","ServerName","Label","Name","Capacity(GB)","FreeSpace(GB)","Used(GB)","FreeSpace%"
$filename = "C:\temp\VolumeReport.csv"
('"{0}"' -f ($propertyOrdered -join '","')) | Set-Content $filename
foreach($server in $servers){
$sysinfo = Get-WmiObject Win32_Volume -ComputerName $server
$serverDetails = #()
for($i = 0;$i -lt $sysinfo.Count; $i++){
$sname = $sysinfo[$i].SystemName
$servername = $server
$label = $sysinfo[$i].Label
if(($label) -and (!($label.Contains("FILLER")))){
write-host "Processing $label from $server"
$name = $sysinfo[$i].Name
$capacity = [math]::round(($sysinfo[$i].Capacity/1GB),2)
$fspace = [math]::round(($sysinfo[$i].FreeSpace/1GB),2)
$sused = [math]::round((($sysinfo[$i].Capacity - $sysinfo[$i].FreeSpace)/1GB),2)
$fspacepercent = [math]::Round((($sysinfo[$i].FreeSpace*100)/$sysinfo[$i].Capacity),2)
$props = #{
"SystemName" = $sname
"ServerName" = $server
"Label" = $label
"Name" = $name
"Capacity(GB)" = $capacity
"FreeSpace(GB)" = $fspace
"Used(GB)" = $sused
"FreeSpace%" = $fspacepercent
}
# Build this server object.
$serverDetails += New-Object PSObject -Property $props
}
}
# Output current details to file.
$serverDetails | Select $propertyOrdered | ConvertTo-Csv -NoTypeInformation | Select-Object -Skip 1 | Add-Content $filename
#Calculate Totals and append to file.
$totals = '"","","","Totals",{0},{1},{2},""' -f ($serverDetails | Measure-Object -Property "Capacity(GB)" -Sum).Sum,
($serverDetails | Measure-Object -Property "FreeSpace(GB)" -Sum).Sum,
($serverDetails | Measure-Object -Property "Used(GB)" -Sum).Sum
$totals | Add-Content $filename
}
Part of the issue here is that you were mixing object output and static string output which most likely would have been holding you back. I tidied up the object generation in a way that should be 2.0 compliant. Not that what you were going was wrong in anyway but this is a little more pleasing to the eye then all the Add-Members
I removed $array since it did not have a place anymore since the logic here is constantly output data to the output file as supposed to storing it temporarily.
For every $server we build an array of disk information in the variable $serverDetails. Once all the disks have been calculated (using your formulas still) we then create a totals line. You were not really clear on how you wanted your output so I guessed. The above code should net output like the following. (It looks a lot nicer in Excel or in a csv aware reader. )
"SystemName","ServerName","Label","Name","Capacity(GB)","FreeSpace(GB)","Used(GB)","FreeSpace%"
"server01","server01","System Reserved","\\?\Volume{24dbe945-3ea6-11e0-afbd-806e6f6e6963}\","0.1","0.07","0.03","71.85"
"","","","Totals",0.1,0.07,0.03,""
"server02","server02","System Reserved","\\?\Volume{24dbe945-3ea6-11e0-afbd-806e6f6e6963}\","0.1","0.07","0.03","69.27"
"server02","server02","images","I:\","1953.12","152.1","1801.02","7.79"
"server02","server02","Data","E:\","79.76","34.59","45.18","43.36"
"","","","Totals",2032.98,186.76,1846.23,""