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

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

Related

Write a script to get 10 longest words chart and put them in separate file

I need to sort the words in a text file and output them to a file
Function AnalyseTo-Doc{
param ([Parameter(Mandatory=$true)][string]$Pad )
$Lines = Select-String -Path $Pad -Pattern '\b[A-Za-zA-Яа-я]{2,}\b' -AllMatches
$Words = ForEach($Line in $Lines){
ForEach($Match in $Line.Matches){
[PSCustomObject]#{
LineNumber = $Line.LineNumber
Word = $Match.Value
}
}
}
$Words | Group-Object Word | ForEach-Object {
[PSCustomObject]#{
Count= $_.Count
Word = $_.Name
Longest= $_.Lenght
}
}
| Sort-Object -Property Count | Select-Object -Last 10
}
AnalyseTo-Doc 1.txt
#Get-Content 1.txt | Sort-Bubble -Verbose | Write-Host Sorted Array: | Select-Object -Last 10 | Out-File .\dz11-11.txt
it's don't work
Sort by the Longest property (consider renaming it to Length), which is intended to contain the word length, but must be redefined to $_.Group[0].Word.Length:Tip of the hat to Daniel.
$Words | Group-Object Word | ForEach-Object {
[PSCustomObject]#{
Count= $_.Count
Word = $_.Name
Longest = $_.Group[0].Word.Length
}
} |
Sort-Object -Descending -Property Longest |
Select-Object -First 10
Note that, for conceptual clarity, I've used -Descending to sort by longest words first, which then requires -First 10 instead of -Last 10 to get the top 10.
As for what you tried:
Sorting by the Count property sorts by frequency of occurrence instead, i.e. by how often each word appears in the input file, due to use of Group-Object.
Longest= $_.Length (note that your code had a typo there) accesses the length property of each group object, which is an instance of Microsoft.PowerShell.Commands.GroupInfo, not that of the word being grouped by.
(Since such a GroupInfo instance has no type-native .Length property, but PowerShell automatically provides such a property as an intrinsic member, in the interest of unified handling of collections and scalars. Since a group object itself is considered a scalar (single object), .Length returns 1. PowerShell also provides .Count with the same value - unless present type-natively, which is indeed the case here: a GroupInfo object's type-native .Count property returns the count of elements in the group).
The [pscustomobject] instances wrapping the word at hand are stored in the .Group property, and since they're all the same here, .Group[0].Word.Length can be used to return the length of the word at hand.
Function AnalyseTo-Doc{
param ([Parameter(Mandatory=$true)][string]$Pad )
$Lines = Select-String -Path $Pad -Pattern '\b[A-Za-zA-Яа-я]{2,}\b' -AllMatches
$Words = ForEach($Line in $Lines){
ForEach($Match in $Line.Matches){
[PSCustomObject]#{
LineNumber = $Line.LineNumber
Word = $Match.Value
}
}
}
$Words | Group-Object Word | ForEach-Object {
[PSCustomObject]#{
#Count= $_.Count
Word = $_.Name
Longest = $_.Group[0].Word.Length
}
} |
Sort-Object -Descending -Property Longest | Select-Object -First 10 | Out-File .\dz11-11.txt
}
AnalyseTo-Doc 1.txt

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/

Powershell Strings from Objects

Trying to take an object and filter down to a value as a string. And save that string to variable and then use that variable in another command as a value for a flag.
So this command will get the PNPDevice InstanceID
$x = (Get-PnpDevice -PresentOnly -Class 'Net' | Where-Object {$_.FriendlyName -EQ 'Intel(R) Ethernet Connection I217-LM'} | Select-Object -ExpandProperty InstanceId | Format-Table -AutoSize | out-string )
Here I am checking the variable X and its content and type since the next command Disable-PNPDevice and the flag instanceID has to be a string
PS C:\Temp> $x.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True String System.Object
PS C:\Temp> echo $x
PCI\VEN_1234&DEV_543A&SUBSYS_32A39857&REV_04\3&1234839&0&C8
When I try to use $x for -InstanceId i get this error
PS C:\Temp> Disable-PnpDevice -InstanceId $x
Disable-PnpDevice : Invalid query
At line:1 char:1
+ Disable-PnpDevice -InstanceId $x
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (Win32_PnPEntity:ROOT\cimv2\Win32_PnPEntity) [Disable-PnpDevice], CimException
+ FullyQualifiedErrorId : HRESULT 0x80041017,Disable-PnpDevice
However if I manually create the variable with a string it works fine
PS C:\Temp> $y = "PCI\VEN_1234&DEV_543A&SUBSYS_32A39857&REV_04\3&1234839&0&C8"
PS C:\Temp> Disable-PnpDevice -InstanceId $y
PS C:\Temp> $y.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True String System.Object
Thank you.
Omit | Format-Table -AutoSize | out-string from your command, which is not only redundant in your case (the .InstanceId property already is a string), but causes the instance ID string to have a trailing newline, which is likely the cause of your problem.
Generally:
Format-* cmdlets emit output objects whose sole purpose is to provide formatting instructions to PowerShell's for-display output-formatting system. In short: only ever use Format-* cmdlets to format data for display, never for subsequent programmatic processing - see this answer for more information.
As an aside: That Out-String blindly appends a trailing newline to its output string is both unexpected and inconvenient: see GitHub issue #14444.
Note: With a single input object (such as in your case), -NoNewLine can be used to suppress the trailing newline (but Out-String is never needed for an input object that already is a string).
The problem is that with multiple input objects, -NoNewLine also suppresses newlines between their representations; e.g., 'one', 2 | Out-String -NoNewLine yields verbatim one2

Change output results in PowerShell

I want to get all user ID's with a specific token assigned.
It looks like this now when I run my script..
Get-ADUser -Filter * -Properties * | Select-Object vasco-LinkUserToDPToken, displayname
#Output#
vasco-LinkUserToDPToken Displayname
{CN=VES0423061,OU=br... User X
{} User X
{} User X
{CN=0067511310,OU=br... User X
{CN=0067077717,OU=br... User X
Example of a full vasco-LinkUserToDPToken :
{CN=VES0976944,OU=Internal Users,DC=mgm,DC=agf,DC=be}
the thing is I only want to filter VES + it should be shown like this (not containing empty strings or tokens that are not starting with VES):
VES0423061 User X
It looks like your property 'vasco-LinkUserToDPToken' is a multivalued property type (string array) of which you need to extract the DN inside.
You could try:
Get-ADUser -Filter "vasco-LinkUserToDPToken -like 'CN=VES*'" -Properties 'vasco-LinkUserToDPToken', DisplayName |
Select-Object #{Name = 'vasco-LinkUserToDPToken'; Expression = {
($_.'vasco-LinkUserToDPToken' | Where-Object {$_ -match '^CN=VES.*'}) -replace '.*(VES[^,]+).*', '$1'}
}, DisplayName
P.S. It is always a bad idea to use -Properties * is what you are after is just two properties. Using * forces to pull down ALL properties which is a waste of time
If the -Filter doesn't work on this custom property, you can always use a Where-Object clause afterwards like:
Get-ADUser -Filter * -Properties 'vasco-LinkUserToDPToken', DisplayName |
Where-Object { $_.'vasco-LinkUserToDPToken' -like 'CN=VES*' } |
Select-Object #{Name = 'vasco-LinkUserToDPToken'; Expression = {
($_.'vasco-LinkUserToDPToken' | Where-Object {$_ -match '^CN=VES.*'}) -replace '.*(VES[^,]+).*', '$1'}
}, DisplayName

Powershell : Remove Info from Get-WinEvent Returned Results

Running the following
Get-WinEvent -ComputerName $env:ComputerName -LogName Application | Where {$_.ID -eq 63} | Select-Object -Unique
Results are as follows
ProviderName: Outlook
TimeCreated Id LevelDisplayName Message
----------- -- ---------------- -------
10/17/2014 10:09:04 AM 63 Information The Exchange web service request GetAppManifests succeeded.
How can I remove or strip out the following
ProviderName: Outlook
TimeCreated Id LevelDisplayName Message
----------- -- ---------------- -------
So that I am just left with
10/17/2014 10:09:04 AM 63 Information The Exchange web service request GetAppManifests succeeded.
Pipe your output to Format-Table:
Get-WinEvent -ComputerName $env:ComputerName -LogName Application `
| Where {$_.ID -eq 63} | Select-Object -Unique `
| Format-Table -HideTableHeaders
And if you want to convert the output to string, you can further pipe to Out-String.

Resources