ForEach-Object : Cannot convert 'System.Object[]' - csv

For some reason I have a script that started to give me problems all of a sudden. Maybe a co-worker modified it, I don't know but I need to get it running again.
This is my script that is causing the problem:
$result = ForEach-Object $filter {
Select-String -Pattern $pattern |
Select-Object Path, LineNumber, Line }
$result | Export-Csv "W:\test\search_results\$name.csv" -NoType
This is what $filter contains if I export it to CSV rather than $result:
FullName
\\omega.dce-eir.net\etm\ETMWinHeadPROD\CRA_WEB_UA\cra_htdocs\bt\fq-eng.html
\\omega.dce-eir.net\etm\ETMWinHeadPROD\CRA_WEB_UA\cra_htdocs\bt\ll_fq-eng.html
\\omega.dce-eir.net\etm\ETMWinHeadPROD\CRA_WEB_UA\cra_htdocs\bt\menu-eng.html
I am getting this error when running my code:
ForEach-Object : Cannot convert 'System.Object[]' to the type 'System.Management.Automation.ScriptBlock' required by parameter 'Process'. Specified method is not supported.
At C:\Tools\menu.ps1:41 char:37
+ $result = ForEach-Object <<<< $filter {
+ CategoryInfo : InvalidArgument: (:) [ForEach-Object], ParameterBindingException
+ FullyQualifiedErrorId : CannotConvertArgument,Microsoft.PowerShell.Commands.ForEachObjectCommand
What am I missing in this script? All it needs to do, is a search string on the files listed in the CSV.

$filter is a list of objects, not a scriptblock. You can't use it like that with ForEach-Object. Change your code to this:
$filter | Select-Object -Expand FullName |
ForEach-Object { Select-String -Path $_ -Pattern $pattern } |
Select-Object Path, LineNumber, Line |
Export-Csv "W:\test\search_results\$name.csv" -NoType

Related

PowerShell failing to convert JSON to CSV

I have spent a bit of time researching how to convert Json to a CSV file using powershell but am failing to have it complete properly. Below is the syntax I have created:
$pathToOutputFile = "C:\OrderLinQ\TESTING\IN\CatalogsRetrieved\test.txt"
$pathToJsonFile = "C:\OrderLinQ\TESTING\IN\CatalogsRetrieved\test.json"
Get-Content -Path $pathToJsonFile |
ConvertFrom-Json |
ConvertTo-Csv -NoTypeInformation |
Set-Content $pathToOutputFile
However, when I attempt to execute this, I get an argument exception error:
ConvertFrom-Json : Invalid array passed in, ']' expected. (1): [
At line:1 char:69
+ Get-Content "C:\OrderLinQ\TESTING\IN\CatalogsRetrieved\test.json" | ConvertFrom- ...
+ ~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [ConvertFrom-Json], ArgumentException
+ FullyQualifiedErrorId : System.ArgumentException,Microsoft.PowerShell.Commands.ConvertFromJsonCommand
Any thoughts as to what I'm doing wrong? I've verified my file using JSONLint and it shows verified. Example file can be found at https://api.myjson.com/bins/mo59w. Any help is appreciated!
Try this. I've also attached the output
$pathToOutputFile = "D:\output.csv"
$pathToJsonFile = "D:\test.json"
$json = Get-Content -Path $pathToJsonFile
function ConvertFrom-JsonToCsv {
param(
[Parameter(ValueFromPipeline)]
$json
)
Process {
($json | ConvertFrom-Json) | ConvertTo-Csv -NoTypeInformation
}
}
ConvertFrom-JsonToCsv $json | Set-Content $pathToOutputFile
Output

Exporting Output From a Powershell Script to CSV

I found a PowerShell script that looks to be just what I need, but I am having trouble exporting the output to a CSV. I think it may be the foreach portion that is giving the trouble, was wondering if anyone can pinpoint the cause.
$Groups = Get-ADGroup -Properties * -Filter * -SearchBase "OU=Groups,DC=corp,DC=ourcompany,DC=Com"
foreach ($G in $Groups)
{
Write-Host $G.Name
Write-Host "-------------"
$G.Members
}
Specific error is:
An empty pipe element is not allowed.
At line:6 char:2
+ }|Export-csv -path c:\temp\adusers.csv
+ ~
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : EmptyPipeElement
Give this one a try:
$Groups = Get-ADGroup -Properties * -Filter * -SearchBase "OU=Groups,DC=corp,DC=ourcompany,DC=Com"
$Groups | Select Name, Members | Export-Csv -Path "C:\temp\myfile.csv" -Delimiter ";"
if you want all attributes just use
$Groups | Export-Csv -Path "C:\temp\myfile.csv" -Delimiter ";"
or get your attributes as you like to:
$Groups | Select Name, Members, DistinguishedName, Email | Export-Csv -Path "C:\temp\myfile.csv" -Delimiter ";"

Powershell - Where-Object : A positional parameter cannot be found that accepts argument 'System.Object[]

I want to add the profile pictures of the exchange to our users in Active Directory.
I tried to do this in Powershell, but cause I'm pretty new to Powershell i'm already stucking.
My Script:
$Name = #()
$Photo = #()
Import-Csv C:\temp\adusers.csv |
ForEach-Object {
$Name += $_.DisplayName
}
Import-Csv C:\temp\photolinks.csv |
ForEach-Object {
$Photo += $_.PSChildName
}
$Name | ForEach-Object {
Where $Photo -Like "*$Name*" {
Set-UserPhoto "$Name" -PictureData ([System.IO.File]::ReadAllBytes("F:\1 path\" + $Photo))
}
}
I created a ps script to get all our AD Users before and I created a list of our userphotos with gci before as well. I exported those results in a csv and I now want to import thos data and tell Powershell add for every User in the List adusers a photo with Set-UserPhoto.
The error message I got is the following:
Where-Object : A positional parameter cannot be found that accepts argument 'System.Object[]'.
At C:\Users\user1\Desktop\setuserphoto.ps1:14 char:13
+ Where $Photo -Like "*$Name*" {
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Where-Object], ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.WhereObjectCommand
Can anyone help me here?

How can I combine fields in a .csv based off of a shared value in powershell?

I have two files in identical formats, one containing destination IP addresses and URLs, and one that contains only the destination IP addresses. I am attempting to write a powershell script to add the URL field from the first file to the second file for that row if the destination IP addresses are equal. Here is an example of the two files:
File Containing URLs:
Date;Time;Source;Destination;Port;User;URL
3/7/2016;0:00:07;168.254.25.6;10.0.1.27;80;jsmith;abcnet
File to add URLs to:
Date;Time;Source;Destination;Port;User;URL
3/7/2016;0:00:09;168.254.25.6;10.0.1.27;80;;
Whenever I run the code below, it appears to be caught in an infinite loop because it does not run to completion, but it throws no errors. My data set is thousands of lines long, but it works when I test it with a sample set that is only a few lines long.
$noURLs = Import-Csv C:\Path\to\noURLs.csv
$containsURLs = Import-Csv C:\Path\to\containsURLs.csv | Select-Object Destination, URL
$outputFile = "C:\Path\to\output.csv"
if(Test-Path $outputFile){
Remove-Item $outputFile
}
foreach($line in $noURLs){
$cpDest = $line.Destination
$destURL = $containsURLs | Where-Object {$_.Destination -eq $cpDest} | Select-Object -ExpandProperty URL | Select-Object -Unique
if($destURL -ne $null){
if( $destURL.Count -gt 1) {
$destURL = $destURL -join ';'
}
}
$line.URL = $destURL
}
$noURLs | Export-Csv $outputFile
I forgot to add a -unique switch to my select object, so for every one record in the first csv, it was looping through every single line of the second csv. Fixed code looks like this:
$noURLs = Import-Csv C:\Path\to\noURLs.csv
$containsURLs = Import-Csv C:\Path\to\containsURLs.csv | Select-Object -Unique Destination, URL
$outputFile = "C:\Path\to\output.csv"
if(Test-Path $outputFile){
Remove-Item $outputFile
}
foreach($line in $noURLs){
$cpDest = $line.Destination
$destURL = $containsURLs | Where-Object {$_.Destination -eq $cpDest} | Select-Object -ExpandProperty URL | Select-Object -Unique
if($destURL -ne $null){
if( $destURL.Count -gt 1) {
$destURL = $destURL -join ';'
}
}
$line.URL = $destURL
}
$noURLs | Export-Csv $outputFile -NoTypeInformation

PowerShell: Function doesn't have proper return value

I wrote a powershell script to compare the content of two folders:
$Dir1 ="d:\TEMP\Dir1"
$Dir2 ="d:\TEMP\Dir2"
function Test-Diff($Dir1, $Dir2) {
$fileList1 = Get-ChildItem $Dir1 -Recurse | Where-Object {!$_.PsIsContainer} | Get-Item | Sort-Object -Property Name
$fileList2 = Get-ChildItem $Dir2 -Recurse | Where-Object {!$_.PsIsContainer} | Get-Item | Sort-Object -Property Name
if($fileList1.Count -ne $fileList2.Count) {
Write-Host "Following files are different:"
Compare-Object -ReferenceObject $fileList1 -DifferenceObject $fileList2 -Property Name -PassThru | Format-Table FullName
return $false
}
return $true
}
$i = Test-Diff $Dir1 $Dir2
if($i) {
Write-Output "Test OK"
} else {
Write-Host "Test FAILED" -BackgroundColor Red
}
If I set a break point on Compare-Object, and I run this command in console, I get the list of differences. If I run the whole script, I don't get any output. Why?
I'm working in PowerGUI Script Editor, but I tried the normal ps console too.
EDIT:
The problem is the check on the end of the script.
$i = Test-Diff $Dir1 $Dir2
if($i) {
Write-Output "Test OK"
...
If I call Test-Diff without $i = check, it works!
Test-Diff returns with an array of objects and not with an expected bool value:
[DBG]: PS D:\>> $i | ForEach-Object { $_.GetType() } | Format-Table -Property Name
Name
----
FormatStartData
GroupStartData
FormatEntryData
GroupEndData
FormatEndData
Boolean
If I comment out the line with Compare-Object, the return value is a boolean value, as expected.
The question is: why?
I've found the answer here: http://martinzugec.blogspot.hu/2008/08/returning-values-from-fuctions-in.html
Functions like this:
Function bar {
[System.Collections.ArrayList]$MyVariable = #()
$MyVariable.Add("a")
$MyVariable.Add("b")
Return $MyVariable
}
uses a PowerShell way of returning objects: #(0,1,"a","b") and not #("a","b")
To make this function work as expected, you will need to redirect output to null:
Function bar {
[System.Collections.ArrayList]$MyVariable = #()
$MyVariable.Add("a") | Out-Null
$MyVariable.Add("b") | Out-Null
Return $MyVariable
}
In our case, the function has to be refactored as suggested by Koliat.
An alternative to adding Out-Null after every command but the last is doing this:
$i = (Test-Diff $Dir1 $Dir2 | select -last 1)
PowerShell functions always return the result of all the commands executed in the function as an Object[] (unless you pipe the command to Out-Null or store the result in a variable), but the expression following the return statement is always the last one, and can be extracted with select -last 1.
I have modified the bit of your script, to make it run the way you want it. I'm not exactly sure you would want to compare files only by the .Count property though, but its not within the scope of this question. If that wasn't what you were looking after, please comment and I'll try to edit this answer. Basically from what I understand you wanted to run a condition check after the function, while it can be easily implemented inside the function.
$Dir1 ="C:\Dir1"
$Dir2 ="C:\Users\a.pawlak\Desktop\Dir2"
function Test-Diff($Dir1,$Dir2)
{
$fileList1 = Get-ChildItem $Dir1 -Recurse | Where-Object {!$_.PsIsContainer} | Get-Item | Sort-Object -Property Name
$fileList2 = Get-ChildItem $Dir2 -Recurse | Where-Object {!$_.PsIsContainer} | Get-Item | Sort-Object -Property Name
if ($fileList1.Count -ne $fileList2.Count)
{
Write-Host "Following files are different:"
Compare-Object -ReferenceObject $fileList1 -DifferenceObject $fileList2 -Property FullName -PassThru | Format-Table FullName
Write-Host "Test FAILED" -BackgroundColor Red
}
else
{
return $true
Write-Output "Test OK"
}
}
Test-Diff $Dir1 $Dir2
If there is anything unclear, let me know
AlexP