Past only select fields to out-gridview - powershell

How can I past only a selection of fields from an object to show in out-gridview, but still keep the whole object as a result.
For example, I retrieve an object that gives me:
$listcreds = get-listofcredentials
Id : 03c0e0c0-0951-4698-9ba9-a70508b5467f
IsLocalProtect : True
Name : vsphere.local\Administrator
CurrentUser : False
UserName : vsphere.local\Administrator
UserNameAtNotation : Administrator#vsphere.local
UserNameSlashNotation : vsphere.local\Administrator
UserNameOnly : Administrator
DomainName : vsphere.local
EncryptedPassword : Veeam.Backup.Common.CCodedPassword
In the gridview I want to only see Name and ID. After the user selects the row desired, I would like to have the result as the same type of object again.
When I use select-object,
$selectedcred = $listofcredentials | select-object Name, Id | out-gridview -passthru
I get the result back but I would now have to search the original object again to get the other properties of that row.
What better way to do this?

You need to find the full object again in the list with Where-Object
This answer assumes the Id property is unique for every item in $listcreds
$listcreds = get-listofcredentials
$selectedcred = $listofcredentials | select-object Name, Id | out-gridview -passthru
$selectedcred = $listcreds | Where-Object {$_.Id -eq $selectedcred.Id}
I don't think there's a better solution here. If performance is a concern, you can convert the Where-Object into a foreach as below:
$listcreds = get-listofcredentials
$selectedcred = $listofcredentials | select-object Name, Id | out-gridview -passthru
foreach ($cred in $listcreds) {
if ($cred.Id -eq $selectedcred.Id) {
$selectedcred = $cred
break
}
}
However, the performance difference may be negligible or even negative.

Related

How to access properties of Get-Child Registry output

Using the below code, I get Name & LastLogon populated, but not ProfilePath.
Add-RegKeyMember is https://gallery.technet.microsoft.com/scriptcenter/Get-Last-Write-Time-and-06dcf3fb .
I have tried to access ProfileImagePath with $Profile.Properties.ProfileImagePath, $Profile.Name.ProfileImagePath, and others, but they all return blank (could be null). How on earth is this seemingly object making these properties available?
$Profiles = get-childitem "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList" | Add-RegKeyMember
foreach($Profile in $Profiles)
{
$ThisProfileInfo = #{Name=$Profile.Name;
LastLogon=$Profile.LastWriteTime;
ProfilePath=$Profile.ProfileImagePath}
$Profile
}
Name Property
---- --------
S-1-5-18 Flags : 12
ProfileImagePath : C:\WINDOWS\system32\config\systemprofile
RefCount : 1
Sid : {1, 1, 0, 0...}
State : 0
This is because [Microsoft.Win32.RegistryKey] object returns properties as string array. You should simply retrieve the value ProfileImagePath from the object itself :
ProfilePath=$Profile.GetValue("ProfileImagePath")
Please see the below adjustments to your script.
You can pull the sub values of property by using the method GetValue.
I have also adjusted how you are storing each iteration and outputting the value post the foreach loop as the example above will just output each $profile as it was before the loop.
I have not tested with Add-RegKeyMember and therefore I am unable to confirm if this will pull the LastWriteTime property, but I can confirm that this will pull the profileimagepath property.
$Profiles = get-childitem "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList" | Add-RegKeyMember
$ProfileData = #()
foreach($Profile in $Profiles){
$ThisProfileInfo = $null
$ThisProfileInfo = #{Name=$Profile.Name;
LastLogon=$Profile.GetValue("LastWriteTime");
ProfilePath=$Profile.GetValue("ProfileImagePath")}
$ProfileData += $ThisProfileInfo
}
$ProfileData

Grouping objects on the property in PowerShell

I would like the Application and ShortcutName columns to be grouped into one column, while keeping the Version and Architecture columns as they are :
$object | Select-Object -Property Application, Version, Architecture, ShortcutName |
Sort-Object -Property #{expression="Architecture";Descending=$true},Application |
Out-GridView
How can I do that ?
In PowerShell you group objects by properties with Group-Object. What you want is not grouping in that sense, but defining a new custom property.
You create custom properties a hashtable with the Name and Expression keys.
Something like this will probably do the trick.
$Expression = {
if ($_.Application) {
$_.Application
}
else {
$_.Shortcut
}
}
$object |
Select-Object -Property #{ Name = 'Application'; Expression = $Expression }, Version, Architecture |
Sort-Object -Property #{expression="Architecture";Descending=$true},Application |
Out-GridView
The expression checks whether the Application property is filled. If so, it will use the existing application name, otherwise it will take the Shortcut property as application name.

How to iterate over the properties of an object

I am trying to write a PowerShell script that iterates through the objects properties and outputs only the ones that have a value of True.
My starting data is this:
UserId : 00546000000m3vCAAQ
UserPermissionsOfflineUser : True
UserPermissionsMobileUser : False
UserPermissionsSupportUser : True
UserPermissionsWebUser : False
I would like the output to consist of the UserID and only the licenses that are true like the following:
UserId : 00546000000m3vCAAQ
UserPermissionsOfflineUser : True
UserPermissionsSupportUser : True
I think I need two loops, one to iterate over each user and then another loop to iterate over the user's properties and just parse out all the false values.
foreach ($_ in $resultset)
{
$_ |
Select-Object -Property #{ N = 'UserId'; E = { $_.Id } }
#This is where I am getting stuck on the second loop.
#$_.psobject.properties | % { $_.Value }
}
Use Where-Object to find the properties with a value of $true, then use Select-Object to select those along with the UserID property:
$resultSet |ForEach-Object {
$trueProperties = $_.psobject.Properties |Where-Object {$_.Value -eq $true} |Select -ExpandProperty Name
$_ |Select -Property #('Id';$trueProperties)
}
Be aware that selectively picking out properties based on their value like this may cause you pain later on with Export-* or Format-* cmdlets
The |Select-Object -ExpandProperty Name part grabs the values of the Name property of the properties that made it through our Where-Object filter, so at this point $trueProperties contain 2 strings: "UserPermissionsOfflineUser" and "UserPermissionsSupportUser".
The expression #('Id';$trueProperties) simply concatenates the strings to the "Id" string, so the last Select-Object statement is basically the same as saying:
$_ |Select Id,UserPermissionsOfflineUser,UserPermissionsSupportUser

How to get the value of a particular propery from the result of a powershell command

I have a variable $ results which has the value :
SESSIONNAME USERNAME ID STATE TYPE DEVICE
rdp-tcp#1 account17 7 Active rdpwd
I want to get the value of ID alone and use it in a different query.
I tried the following ways :
1.$idValue = #($result | %{ $_.ID }) - but it was not getting the value.
2.$result |Select -ExpandProperty ID - I was getting the error 'Select-Object : Property "ID" cannot be found.'
How to get the value of the property ID alone from the result?
The output of the qwinsta/query commands are strings, not objects, so there isn't a property ID to print. You need to transform the strings into objects if you want the fields as properties:
query session | ? { $_ -match '^[ >](\S+) +(\S*?) +(\d+) +(\S+)' } |
select #{n='Service';e={$matches[1]}},
#{n='Username';e={$matches[2]}},
#{n='ID';e={$matches[3]}},
#{n='Status';e={$matches[4]}} | % {
$_.ID
}
Or, if you're just interested in the ID, you could do a regular expression replacement like this:
$account = 'account17'
$pattern = '^[ >]\S+ +\S*? +(\d+) +\S+.*'
(query session $account | select -Skip 1) -replace $pattern, '$1'
This is the format to refer to a single property properly. I don't see your command to create your RDP $result, so I'll example get-process, encapsulate it with () and tack an ().ID to the end. Works with any property, not just.ID
(get-process | where {$_.Name -eq "Powershell"}|select ID).ID
# or
$MYID = (get-process | where {$_.Name -eq "Powershell"}|select ID).ID
$MYID
Another option is -split:
One solution, using V4:
($result).ForEach({($_ -split '\s+')[2]}) -match '\d'

How do I add a column of incrementing values to cmdlet output?

Suppose I call Get-Service and want to assign a new column ID with the cmdlet output that prints incrementing integers so that:
ID Status Name DisplayName
-- ------ ---- -----------
0 Running AdobeARMservice Adobe Acrobat Update Service
1 Stopped AeLookupSvc Application Experience
2 Stopped ALG Application Layer Gateway Service
I'm trying to use Select-Object right now to add this column, but I don't quite understand how to iterate a variable in this sort of expression. Here's what I've got:
Get-Service |
Select-Object #{ Name = "ID" ; Expression= { } }, Status, Name, DisplayName |
Format-Table -Autosize
Is there a way to iterate integers within Expression= { }, or am I going about this problem the wrong way?
You can do it this way, though you will need to maintain some counter variable outside of the main expression.
$counter = 0
Get-Service |
Select-Object #{ Name = "ID" ; Expression= {$global:counter; $global:counter++} }, Status, Name, DisplayName |
Format-Table -Autosize
Another option, which is perhaps cleaner
Get-Service `
|% {$counter = -1} {$counter++; $_ | Add-Member -Name ID -Value $counter -MemberType NoteProperty -PassThru} `
| Format-Table ID
I asked the same question a different way and got the following answer
$x = 10
Get-Service |
Select-Object #{ Name = "ID" ; Expression={ (([ref]$x).Value++) }}, Status, Name, DisplayName | Format-Table -Autosize
It wasn't at all clear to me that the expression is being invoked within Select-Object's scope, not the pipe's. The [ref] qualifier bumps the increment's result up to the pipe's scope achieving the same result as explicitly specifying the variable as global.