Cannot bind argument to parameter 'FilePath' because it is null - multithreading

(1, 2, 3) | ForEach-Object {
Start-ThreadJob {
$TempIn = New-TemporaryFile
('1', '1', '2', '3') | Out-File $TempIn.FullName -Encoding ascii
}
} | Receive-Job -Wait -AutoRemoveJob
Running the above minimum example triggers the "Open with" prompt (even though nowhere am I telling it to open the temporary file) and the following error for every iteration:
Out-File:
Line |
3 | ('1', '1', '2', '3') | Out-File $TempIn.FullName -Encodi …
| ~~~~~~~~~~~~~~~~~~~~~
| Cannot bind argument to parameter 'FilePath' because it is null.

Related

How to Combining PowerShell Output from multiple server to Single csv

I need to pull the report from below code, now I'm running this in every server separately.
Is it possible to combine the the all output from different server and get it in one csv file or get it to my email directedly.
where to define the servers name ?
how to display the server name in every output ?
how to combine and get in single output ?
Get-ADSyncToolsRunHistory | Where {$_.RunProfileName -match "Delta Import"} | Select-Object -Index 0, 1 | Format-Table StartDate, EndDate, ConnectorName, RunProfileName, Result
Get-ADSyncToolsRunHistory | Where {$_.RunProfileName -match "Delta Synchronization"} | Select-Object -Index 0, 1 | Format-Table StartDate, EndDate, ConnectorName, RunProfileName, Result
Get-ADSyncToolsRunStepHistory | Where {$_.RunProfileName -match "Full Import"} | Select-Object -Index 0, 1 | Format-Table StartDate, EndDate, ConnectorName, RunProfileName, StepResult
Get-ADSyncToolsRunStepHistory | Where {$_.RunProfileName -match "Full Synchronization"} | Select-Object -Index 0, 1 | Format-Table StartDate, EndDate, ConnectorName, RunProfileName, StepResult
you could do this from local, to start with:
in servers.txt file - add your servers hostname line by line like
server1
server2
$servers = Get-Content "c:\temp\servers.txt"
$Report = foreach ($server in $servers){
Invoke-Command -ComputerName $server -ScriptBlock{
Get-ADSyncToolsRunHistory | Where {$_.RunProfileName -match "Delta Import"} | Select-Object #{N='ServerName';E={"$env:COMPUTERNAME"}},StartDate, EndDate, ConnectorName, RunProfileName, Result
}
}
$Report|Export-Csv "c:\temp\DeltaImport.csv" -NoTypeInformation
Before Using Invoke-Command, I suggest you to go through this link once:
https://4sysops.com/archives/use-powershell-invoke-command-to-run-scripts-on-remote-computers/

Export-CSV only gets the "Length"

when I try to export to a CSV list, I only get all number for "Length"
.Count property until the split point is reached, then split the CSV array to a new file with a new name that will be used from this point on. What might be the issue?
$RootFolder = Get-Content "c:\DRIVERS\myfile.txt"
foreach ($arrayOfPaths in $RootFolder){
$csv = $arrayofPaths -replace '^\\\\[^\\]+\\([^\\]+)\\([^\\]+).*', 'C:\output\Company_name_${1}_${2}.csv'
$csvIndex = 1
$maxRows = 1000000
$rowsLeft = $maxRows
Get-ChildItem $arrayOfPaths -Recurse | Where-Object {$_.mode -match "d"} | ForEach-Object {
#$csv = $_.FullName -replace '^\\\\[^\\]+\\([^\\]+)\\([^\\]+).*', 'C:\output\Company_name_${1}_${2}.csv'# <- construct CSV path here
$path = $_.FullName
$thisCSV = Get-Acl $path | Select-Object -Expand Access |
Select-Object #{n='Path';e={$path}}, IdentityReference, AccessControlType,
FileSystemRights |
ConvertTo-Csv
if ($thisCSV.count -lt $rowsLeft) {
$thisCSV | Export-Csv $csv -append -noType
$rowsLeft -= $thisCSV.count
} else {
$thisCSV[0..($rowsLeft - 1)] | Export-Csv $csv -append -noType
$csvIndex++
$csv = $csv -replace '\.csv$', "$csvIndex.csv"
if ($thisCSV.count -gt $rowsLeft) {
$thisCSV[$rowsLeft..($thisCSV.count - 1)] | Export-Csv $csv -append -noType
}
$rowsLeft = $maxRows - ($thisCSV.count - $rowsLeft)
}
}
}
Export-CSV is built to take PSCustomObjects as input, not lines of text.
$thisCSV = Get-Acl $path | Select-Object -Expand Access |
Select-Object #{n='Path';e={$path}}, IdentityReference, AccessControlType,
FileSystemRights |
ConvertTo-Csv
The output of this line will be something like:
#TYPE Selected.System.Security.AccessControl.FileSystemAccessRule
"Path","IdentityReference","AccessControlType","FileSystemRights"
"c:\test","BUILTIN\Administrators","Allow","FullControl"
At least three lines, an array of string. What properties does an array of string have?
PS C:\> 'a','b' | Get-Member -MemberType Property
TypeName: System.String
Name MemberType Definition
---- ---------- ----------
Length Property int Length {get;}
Length. The only property you see in the CSV, because Export-CSV is exporting all the properties, and that's the only property.
Fix: Remove | ConvertTo-CSV from the Get-ACL line, leave your custom objects as custom objects and let the export handle converting them.
(This should also fix the counting, because it's not counting 3+ lines of text while trying to export 1+ line of data every time).

Powershell - Get Last 3 char from AD attribute in PsObject

I got a script which export to csv some AD attributes
I want to have the last 3 characters of the 'initials' attribute in a PsObject but i have an error and i spent Hours on this...
Could you help me ?
The Error:
*Method invocation failed because [Microsoft.ActiveDirectory.Management.ADUser] doesn't contain a method named 'substring'.
At C:\scripts\ExtractDWH\Untitled2.ps1:15 char:26
+ "Test" = $_.substring <<<< ($_.initials.length - 3, 3)
+ CategoryInfo : InvalidOperation: (substring:String) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound*
The Code :
$output = 'c:\scripts\ExtractDWH\consultants_test.csv'
$users = Get-ADUser -Filter * -SearchBase "ou=Rennes,ou=Consultants,ou=Utilisateurs,ou=FedFinance,dc=dfedinterim,dc=fr" - Properties * | ? { ($_.initials -notlike 'IC*') -and ($_.initials -notlike 'IM*') -and ($_.initials -ne $null) }
fileIn | % {
$users | % {
New-Object psobject -Property #{
"ID" = $_.initials
"Last 3 strings ID" = $_.substring($_.initials.length - 3, 3)
"Centre Imputation" = $_.extensionAttribute10
"Date Entrée" = $_.extensionAttribute9
# The line below does not work
"Test" = $_.substring($_.initials.length - 3, 3)
}
}
} | Select-Object ID, 'Centre Imputation', 'Date Entrée', 'Test'
| Export-CSV $output -Delimiter ';' -Encoding "UTF8" -NoTypeInformation `
Thank you !
Change this:
"Last 3 strings ID" = $_.substring($_.initials.length - 3, 3)
To This:
"Last 3 strings ID" = $_.initials.substring($_.initials.length -3, 3)
Avshalom showed you the error. You can also use the following to access the last 3 characters:
"Test" = $_.initials[-3 .. -1] -join ''

Adding data to variable results in a singleline string

I have a PowerShell PSCustomObject $result which I am filtering with multiple Where-Object statements.
$SatServers = $Global:result | Where-Object {$_ -like '*sat?2:00*' -and `
$_.MaintenanceWindow -notmatch 'all.da.servers' -and `
$_.Server -match "^IT"} | % {"{0}" -f $_.Server}
$SatServers += $Global:result | Where-Object {$_ -like '*sat?18:00*' -and `
$_.MaintenanceWindow -notmatch 'all.da.servers' -and `
$_.Server -match "^IT"} | % {"{0}" -f $_.Server}
$SatServers | Out-File d:\path\file.txt
If I output to the console or if I pipe to Out-File it looks great but when I send the output to a variable as seen above, I get output on a single line.
Is there something I'm missing in order to get a variable with a multiple line result? -Thanks!
You need to initialize $SatServers as an array first. You first call makes $SatServers a string-object and when you append (+=) a string to a string it simply adds it to the end of the last string.
String:
$string = "Hello"
$string += "Frode"
$string.GetType() | ft -AutoSize
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True String System.Object
$string
HelloFrode
Array:
$string = #()
$string += "Hello"
$string += "Frode"
$string.GetType() | ft -AutoSize
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array
$string
Hello
Frode
You could also have added a NewLine at the end of the string by doing the following change in your Foreach-Object-scriptblock (but personally I prefer the array-solution).
% { ("{0}" -f $_.Server) + [environment]::NewLine }

How do I get unique values from this array in PowerShell?

Why is the code below returning $null? I'm trying to store just unique values.
$DailyPathsToDelete = #("C:\temp\IMG000483\","C:\temp\IMG000483\")
$DailyPathsToDelete = Select-Object $DailyPathsToDelete -Unique
Short answer:
To get all unique paths, you should pipe $DailyPathsToDelete to Select-Object and set the Unique switch.
$DailyPathsToDelete = $DailyPathsToDelete | Select-Object -Unique
Longer answer:
1. Why it's not working
After running your script $DailyPathsToDelete equals $null because (in the second line of your script) $DailyPathsToDelete is bound to the parameter Property. The parameter InputObject of the Select-Object cmdlet was not speficified, which is why the result of the invocation of Select-Object is $null.
This can be easily verified by tracing your expression:
Trace-Command -psHost -Name ParameterBinding { Select-Object $DailyPathsToDelete -Unique}
gives:
DEBUG: ParameterBinding Information: 0 : BIND NAMED cmd line args [Select-Object]
DEBUG: ParameterBinding Information: 0 : BIND arg [True] to parameter [Unique]
DEBUG: ParameterBinding Information: 0 : COERCE arg to [System.Management.Automation.SwitchParameter]
DEBUG: ParameterBinding Information: 0 : Parameter and arg types the same, no coercion is needed.
DEBUG: ParameterBinding Information: 0 : BIND arg [True] to param [Unique] SUCCESSFUL
DEBUG: ParameterBinding Information: 0 : BIND POSITIONAL cmd line args [Select-Object]
DEBUG: ParameterBinding Information: 0 : BIND arg [System.Object[]] to parameter [Property]
DEBUG: ParameterBinding Information: 0 : BIND arg [System.Object[]] to param [Property] SUCCESSFUL
DEBUG: ParameterBinding Information: 0 : MANDATORY PARAMETER CHECK on cmdlet [Select-Object]
DEBUG: ParameterBinding Information: 0 : CALLING BeginProcessing
DEBUG: ParameterBinding Information: 0 : CALLING EndProcessing
2. How to fix it
Using Select-Object:
$DailyPathsToDelete = $DailyPathsToDelete | Select-Object -Unique
Using Sort-Object:
$DailyPathsToDelete = $DailyPathsToDelete | Sort-Object -Unique
3. How NOT to fix it
I would advise against using Get-Unique in your scenario since Windows local file systems (NTFS, FAT and variants) are case insensitive.
Example:
$DailyPathsToDelete = #("C:\temp\IMG000483\","C:\Temp\IMG000483\")
PS C:\> $DailyPathsToDelete | get-unique
C:\temp\IMG000483\
C:\Temp\IMG000483\
You can try :
$unique = $DailyPathsToDelete | Get-Unique
With Get-Unique, gotcha - Get-Unique is case-sensitive and you also have to sort the list first!
$DailyPathsToDelete = $DailyPathsToDelete | Sort-Object | Get-Unique
With Select-Object
$DailyPathsToDelete = $DailyPathsToDelete | Select-Object -Unique
With Sort-Object
$DailyPathsToDelete = $DailyPathsToDelete | Sort-Object -Unique

Resources