Pipe sc query output to powershell method? - powershell

I'd like to pipe output from sc query to a method in powershell. For example, checking the status of a service and finding the part that says "STOPPED", and performing an action based on that output.
Is there a way to do this right from the output of sc query? Or do I need to output the results to a text file, and then.. I'm not sure, run a for-loop to find the piece I'm looking for to make an if condition true / false.
This is what I have so far:
Function IsStopped {
sc.exe query remoteregistry >> RemoteRegistry.txt
Get-Content -Path C:\RemoteRegistry.txt | Where-Object {$_ -like '*stopped*'} | ForEach-Object {
}
Not sure where to go next?

PowerShell has a cmdlet for examining services. Running Get-Service without parameters gives you all of the running services in the same way sc.exe does (actually while researching this I reminded myself that in PowerShell sc, without .exe, is an alias for Set-Content, so I ended up generating some useless files. This might be another good reason to use Get-Service to avoid confusion with Set-Content).
Running Get-Service | Get-Member gives a list of the properties and methods from the output of the command. Status is the Property of interest, so we run:
Get-Service | Where-Object { $_.Status -eq 'Stopped' }
The output of this command can then be piped into a for each loop as you have suggested, and each service's properties or methods can be accessed using the $_ shorthand:
Get-Service | Where-Object { $_.Status -eq 'Stopped' } | ForEach-Object {
Write-Host "Do something with $($_.ServiceName)"
}
It is possible to restart services in this manner, using $_.Start(), but I would recommend writing some error handling into the process if that's your ultimate aim.'
If you need more information, such as the executable, you might want to look here:
How can I extract "Path to executable" of all services with PowerShell

Related

create a txt file in PowerShell list of all running services

I am trying to create a txt file in PowerShell that provides a list of services that are running. This what I came up with but it keeps on giving me an error message that says its not valid.
Get-Service | Export-txt -path "C:\Windows\Temp\services.txt"
Get-Service | where {$_.Status -eq "Running"} | Export-txt -path "C:\Windows\Temp\services.txt"
There is no commandlet called Export-txt.
One option is to use Out-File. It uses -FilePath as a parameter (or no named flag).
Get-Service | Out-File -FilePath "C:\Windows\Temp\services.txt"
There is no cmdlet by the name of Export-txt. To get a list of cmdlets you can use, you can think logically and apply that to Get-Command. Running Get-Command will get you a list of all available cmdlets you may use in accordance with your Posh version.
Get-Command *out* returns a list of cmdlets you can send out to something. Same logic applies to Get-Command "Export*".
#This gets you all services
Get-Service | Out-File "C:\Windows\Temp\services.txt"
#This gets you only running services
Get-Service | where {$_.Status -eq "Running"} | Out-File "C:\Tmp.txt"
Use Get-Help Out-File to see how the cmdlet is used and what parameters it accepts. It also lists examples you can use.

Differences between two options to run a command

I tried to run the following command in two different ways:
get-service | where-object {$_.Status -eq 'Running'}
In the upper window I loaded the PowerShell and then the command
and in the lower both steps at once.
Generally the second option works fine,
what was the reason for the difference?
The same command in two different ways
When PowerShell is invoked from a command prompt, use a string:
powershell "get-service | where-object {`$_.Status -eq 'Running'}"
(note the backtick in front of the $)
Or use a script block:
powershell { get-service | where-object {$_.Status -eq 'Running'} }
Put the command after powershell in quotes, then it will run

test-connection that supports wildcard? workaround?

trying to see if anyone has a known workaround for using the test-connection cmdlet in powershell to ping wildcard entries in DNS.
I'm trying to clean out our DNS db and exported a list from our BIND server and am in the process of just pinging through the 600+ machines to see if anything responds. I made my own simple script but have also found one that works slightly better on this forum. The script works but the cmdlet help files state that the -computername parameter does not support wildcards and sure enough, when i run the script all CNAME records are reporting down/false when they actually should be responding. The code I'm using is below and is kind of messy but I just needed something quick and it works, but I've included it below for reference:
Get-Content -path C:\Work\testy.txt | ForEach-Object { Test-Connection -ComputerName $_ -Count 1 -AsJob } | Get-Job | Receive-Job -Wait | Select-Object #{Name='ComputerName';Expression={$_.Address}},#{Name='Reachable';Expression={if ($_.StatusCode -eq 0) { $true } else { $false }}} |out-file -FilePath c:\work\TEST.txt
As pointed out by briantist, any non-existing record name will do. You could generate a GUID to substitute the * in your record name:
"subdomain.domain.tld","*.domain.tld" |ForEach-Object {
Test-Connection -ComputerName $($_ -replace '\*',"$([guid]::NewGuid())")
}
Your expression for whether it's "Reachable" or not can be simplified as well:
#{Name='Reachable'; Expression={[bool]($_.StatusCode -eq 0)}}

Filtering output using "Where-Object" in Powershell

I'm trying to get into PowerShell and have encountered my first hurdle.
when I run
Get-Command | Where-Object CommandType -contains Cmdlet
My output gets filtered so that only commands with "CommandType" property value containing "Cmdlet" gets shown, like so:
Same thing can be done with the object "Source":
Get-Command | Where-Object Source -contains appx
Which gets me:
But when i try to run:
Get-Command | Where-Object Name -contains Add
I get nothing.
Why can I filter the output by the objects "CommandType", and "Source but not "Name"? I'm surely missing something here...
Edit: i know i can run:
Get-Command -verb "get"
And get the desired output. But i'm trying to figure out why my "where-object" statement did not work.
Edit 2:
Appearantly if I use the "-match" comparison operator it works...
get-command | where-object Name -match "add"
But isn't "name" properties just strings? -match should be used for Regular expression comparison afaik? I'm so confused right now...
use either the like or the match operator:
Get-Command | Where-Object Name -like Add*
this will match add anywhere in the word
Get-Command | Where-Object Name -match Add
but a better way to do this would be:
Get-Command -verb Add
read more about the contains operator here
-Contains
Description: Containment operator. Tells whether a collection of reference
values includes a single test value. Always returns a Boolean value. Returns TRUE
only when the test value exactly matches at least one of the reference values.
PS C:\> "abc", "def" -Contains "def"
True

PowerShell 3.0 - Setting Affinity to CPU per USER's PROCESS

my first post here. I am working on a script using powerShell, the objective is to set a certain amount of CPU-threads per USER's process, using the forum here, i was able to find most of the answers, and even got my script to run, except, if it sets the affinity, it sets it to EVERY-Process, not just the user i need.
here is the code(with comments):
# GET LIST of all process running
$pList = get-wmiobject win32_process
# loop through created array and get the OWNER of the processes
foreach ($p in $pList) {
#If "myUserName" is found:
if ($p.getowner().User -eq 'myUserName') {
# get process name
$procName = $p.ProcessName
# trim STRING to remove EXE
$procName = $procName.Replace('.exe','')
# use get-process to make array of processes run by "myUserName"
$activeProc = Get-Process -name $procName
# Loop to set affinity for each process
foreach ($i in $activeProc){
$i.ProcessorAffinity=0xFE
}
}
}
when i execute this command, all of the process are set to new Thread Count,
any suggestions how to make it ONLY adjust threads for SPECIFIC user?
Thanks a lot guys!
this is pretty urgent.
By calling get-process -name $procName you are finding all processes that have the same name as one run by the user.
Instead of using the ProcessName, use ProcessId.
In PowerShell version 4.0, you can use the -IncludeUserName parameter on the Get-Process cmdlet. Once you have a list of processes, you can then filter then using the Where-Object cmdlet, which has a default alias of ?.
Get-Process -IncludeUserName | Where-Object -FilterScript { $PSItem.UserName -match 'system' };
Or short-hand might look like this:
gps -inc | ? { $_.UserName -match 'system' };
Note: Using the -IncludeUserName parameter requires privilege elevation.