Powershell, paginating output from foreach - powershell

Seems like this should be simple, but powershell is winning another battle with me. Simply wanting to output the name of all the services running on a system, and their executable path, and pipe that into something I can use to search through it like Less.
So far I have:
$services = get-WmiObject -query 'select * from win32_service'
foreach($service in $services){$service.Name $service.Pathname} | less
But thats giving me the "An empty pipe element is not allowed." that I seem to have come up alot. Anyone tell me how to fix this, either by outputting to a file and Ill go through it with vim, or pipe to page/less/etc so I can do quick scan (with my eyes not programically quite yet).

Try doing the following
$services | %{ $_.Pathname } | less
EDIT Add multiple to the path
$services | %{ "{0} {1}" -f $_.Pathname,$_.Name } | less

If you are using PowerShell 2.0, you might like this:
gwmi win32_service | select-object Name,PathName | ogv
ogv (Output-GridView) is a new cmdlet in 2.0.

get-wmiobject win32_service | select-object name, pathname | more
This is also powershell 2.0 and is the close to the comment above.
You were just trying to use a foreach when you didn't need to in this case.
Even with the foreach, you were close to getting an output you could work with.
A comma in your foreach would have generated a output like a list and you could have used the more command instead of less.
$services = get-WmiObject -query 'select * from win32_service'
foreach($service in $services){$service.Name $service.Pathname} | more
Here is another way to write this same statement.
get-WmiObject win32_service | foreach{$.Name, $.Pathname} | more
This is still not the same as my first example, but I wanted to show you how close you were.

Looks like a good reason to use foreach-object:
$services = get-WmiObject -query 'select * from win32_service'
$services|ForEach-Object {$_|Select-Object Name,Pathname}|less
Please excuse me while I oneline it:
get-WmiObject -query 'select * from win32_service' |ForEach-Object {$_|Select-Object Name,Pathname}|less
foreach-object will return an object to the pipeline based on the input object.
I'm assuming less is an alias of your own making since I don't seem to have it.

Related

Get current version number of specified program

I started with this, on a recommendation from a friend
Get-WmiObject win32_product | ft name, version
But then I found this, which gives me pause.
A little research led me to this
wmic product where "Name='Revit 2018'" get name,version
Which works as far as the data gathered. And yes, I am looking for a different program in this example. in any case, once I had good info using WMIC I tried to get the data into a variable so I could get just the version number, but the data formatting is something I have never seen before. I was hoping for a simple solution, like
$object = wmic product where "Name='Revit 2018'" get name,version
$object.version
But only the result is an array with 6 items, and only one seems to be the actual data line, and that's a single line, not two properties. And, I really wonder if an old command line utility is the right answer here. If it really is the best way to do this, is there a trick to converting the raw data to something more, PowerShelly? And if it's not the best way to get this info, what is? Is that scary link real, or is Get-WmiObject win32_product actually safe? And if so, is there a way to filter on a specific name, to speed things up? And indeed, Get-WmiObject doesn't work as I was expecting, as
$object = Get-WmiObject win32_product | ft name, version
foreach ($item in $object) {
Write-Host "$($item.version)"
}
Doesn't work as expected at all.
EDIT: This seems to be working as expected, which is progress.
$version = (Get-WmiObject win32_product -filter:"Name = 'Revit 2018'" | Select-Object -property:*).version
Write-Host "$version!"
I guess the question is really, is this a safe and consistent approach, or is there a better one?
Why not use the registry?
Set-Location HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall
$app = Get-ChildItem | Where-Object { $_.GetValue("DisplayName") -match 'YourSoftware' }
$app.GetValue("DisplayVersion")
Or
Set-Location HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall
$apps = Get-ChildItem
foreach ($app in $apps) {
$app.GetValue("DisplayName","DisplayVersion")
}
Note: You'll also need to check the SysWow64 registry location as well
HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\
Note: Not all items will have a display version in which case you always have the option of looking in the installation directory for the executable itself, which should have a version on it.

Powershell pipeline access to ADComputer object "Info"

I've been trying to work with the following query to get AD info for my servers, but "Info" just comes back as blob of stuff. To me it looks like I should be able extract specific parts, but I've had little success. I've even tried to use regex to get what I need out, but I'm terrible with regex. Any help with how to extract the SN,MAC and IP from "Info" would be much appreciated.
Get-ADComputer -Filter * -Property * -SearchBase $server | select -Property name,info
You could try using '-split':
$comp = Get-ADComputer -Filter * -Property * -SearchBase $server
$info = $comp.info
$SerialNumber = ($info -split 'SN=')[1] #replace with 'VMWare-' if desired
$SerialNumber = ($SerialNumber -split ';')[0]
This works with serial number assuming the output is formatted exactly as you have displayed it in the comments. It does, however, bring in that 'VMware' string included. Use the code in my comment if you would like just the #s.
You can copy that -split code out for the remaining fields you would like to extract.

How to get result of Get-WmiObject into a file

I have a PowerShell-V2 script I am trying to run. Very simply, I pass it an application, and it outputs the result of the win32_process.
e.g.
$filter = "name like '%"+$_Application+"%'"
$result = Get-WmiObject win32_process -Filter "$filter"
However I need to get this into a file.
But when I run:
write-host $result
I just seem to get the "__RELPATH" result, and not the whole thing.
Trying to get it into a file results in the same thing. Is there a way of doing this, without me having to loop through one by one, listing each one in turn?
You can use the Out-File cmdlet:
$result | Out-File 'your_file_path.txt'
Note: You may want to set the encoding within the Out-File cmdlet. E. g. -Encoding utf8

How can I get a plaintext list/array of local users on my system in powershell?

I need to get a plaintext list or array of all the local users on my system so I can loop through them and preform certain actions. By "plaintext" I mean just the user's names. Nothing else. No fancy formatting, no titles, no groups, nothing but the user's names.
I've googled around and tried several solutions, (for e.g. this one powershell - list local users and their groups) but they all have extraneous data that makes looping through the users impossible.
Is there any way I can get just a plain list of users? I wouldn't mind a cmd solution if that's what you have. Note that I have already tried net users, but like I stated earlier, it has this extraneous data.
VBScript:
Dim ADsContainer, User
Set ADsContainer = GetObject("WinNT://.,Computer")
ADsContainer.Filter = Array("User")
For Each User In ADsContainer
WScript.Echo User.Name
Next
Paste the above lines into GetLocalUsers.vbs and run it like this:
cscript //nologo GetLocalUsers.vbs
If you want to use WMI directly in PowerShell, you can use this:
get-wmiobject Win32_UserAccount -filter 'LocalAccount=TRUE' |
select-object -expandproperty Name
You have to write it like this to get it formatted as you requested:
Get-WmiObject -Class Win32_UserAccount | Format-wide -property name -column 1
Prints:
Administrator
Guest
and so on..
After a bit more experimentation, reading, etc, I found a rather simple solution:
$accounts = Get-WmiObject -Class Win32_UserAccount | Select name
Returns:
name
----
Administrator
Guest
John Doe
Other User
Not quite what I want, but if I loop through it like this:
foreach ($i in $accounts) { Write-host $i.name }
It prints:
Administrator
Guest
John Doe
Other User
This is messy, so I shortened it down to one loop:
foreach ($i in Get-WmiObject -Class Win32_UserAccount | Select name) {
# refer to the looped user as $i.name now
}
and per Bill_Stewart's comment, it is a good idea to filter by local account:
foreach ($i in Get-WmiObject -Class Win32_UserAccount -filter 'LocalAccount=true' | Select name) {
# refer to the looped user as $i.name now
}
Still less than optimal, but for now it suits my needs.

WQL query Win32_NtLogEvent on WinRM using group by

I need a query that returns the SourceName, Logfile, EventIdentifier, Type, NumberOfEvents from Win32_NTLogEvent where NumberOfEvents is the number of events that share common SourceName, LogFile and EventIdentifier (I am not sure about Type). I would like to use the query in a PowerShell script using Get-CimInstance.
Other solutions to the same problem that can be used in PowerShell is also much appreciated!
Try following:
$Logs = Get-WmiObject -class Win32_NTLogEvent -filter "(logfile='Application')"
Write-Host $logs
of course, filter you can change. If you prefer other "format" of result you can for example to something like:
$Logs | Format-Table EventCode, EventType, Message -auto
UPDATE:
I just read your question again :) To do grouping just invoke:
$logs | Group-Object Type,LogFile,EventCode