powershell get PID for specific app running for calling user - powershell

We have an ERP application with restrictive licensing, which we access via RemoteApp. We need to only allow one instance per user. So, I've been experimenting with PowerShell to try to do this.
What the script has to do is check and see if "pxxi.exe" is running for the calling user.
My first attempt used WMI. It worked, but it turns out WMI is very very slow.
(gwmi win32_process -Filter "name='pxxi.exe'" | ? {$_.getowner().user
-eq $env:username}).pid
My second attempt used Get-Process. This works great, but unfortunately requires elevated rights.
Get-Process pxxi -IncludeUserName | ? {$_.username -match $env:username}).id
My third attempt focused on the win32 command line program Tasklist.
$result = Invoke-Command { c:\windows\system32\tasklist.exe /fi
"username eq $env:username" /fi "imagename eq pxxi.exe"}
This works! And thanks to EBGreen's code, I can extract just the PID.
($result[3] -split '\s+')[1]
And while that runs really quick as an Administrator, for regular users, Tasklist runs as slow as WMI, above...
So, that puts me back to square one.
Does anyone out there know of a bit of code to quickly check and see if a user XYZ is running a process with name ABC.EXE ?? This needs to work for regular users (but regular users don't need to see other user's processes) and it needs to not take 30+ seconds to run.
I'm not married to powershell. VBScript would be fine. Or any little tool available on the internet.
Thanks!

For the example that you have:
($result[3] -split '\s+')[1]
Be aware that this works for just one result being returned. If you expect more than one instance then you should write a loop to iterate from the 4th item in the array on splitting each item to get that process's PID.

I gave up trying to find a way to do it in Powershell. Either the method was too slow, or required admin.
So I wrote something in C#:
c# - check if program is running for current user

Related

Can I tee unbuffered program output in Powershell?

I'm trying to use Putty's plink.exe as part of a Powershell script, and am having trouble teeing the output.
Some of the commands invoke an interactive response (eg: entering password). Specifically, I'm testing against an Isilon.
Example code:
$command = '&"C:\Program Files\Putty\plink.exe" root#10.0.0.141 -pw "password" -t -batch "isi auth users create testuser --set-password"'
iex $command
Expected result:
I get a prompt password:
I enter the password
I get a prompt confirm:
I enter the password again
Command ends
If I try to tee the output, using iex $command | tee-object -variable result or even just redirect with iex $command *>test.log, the prompt text doesn't show up until after I've responded to it. While still technically functional, if you don't know exactly what prompt to expect, it's useless.
I've tried using Start-Transcript, but that doesn't capture the output at all. I've also tried using plink's -sshlog argument, but that logs way too much, in a less than readable format.
Is there any way to have stdout be unbuffered in the console, and also have it stored in a variable?
To answer some potential questions:
-This is to be run in an environment that doesn't allow modules, so can't use Posh-SSH.
-The Powershell version available isn't new enough to use the built-in openssh functionality.
This is all about redirecting streams.
When you use redirection, all outputs are redirected from the streams, and passed to be written to file. When you execute:
Write-Host "Some Text" *>out.txt
You don't see any output and it is all redirected to the file.
Key Note: Redirection works on a (simplification) line by line basis, as
the redirection works by writing to the file one line at a time.
Similarly, when you use Tee-Object, all outputs are redirected from the stream and down the pipeline. This is passed to the cmdlet Tee-Object. Tee-Object takes the input, and then writes that input to both the variable/file you want and to the screen. This happens After the input has been gathered and processed.
This means that both redirection and the Tee-Object commands work on a line by line basis. This makes sense both redirection and the Tee-Object commands work this way because it is hard to deal with things like deleting characters, moving around and editing text dynamically while trying to edit and maintain an open file at the same time. It is only designed for a one-way once the statement is complete, output.
In this case, when running it interactively, the password: prompt is written to the screen and you can respond.
When redirecting/Teeing the output, the password: text prompt is redirected, and buffered, awaiting your response. This makes sense because the statement has not completed yet. You don't want to send half a statement that could change, or half an object down the pipeline. It is only after you complete the statement (e.g. entering in the password + enter) that the whole statement is passed down the stream/pipeline. Once the whole statement is sent, then it is redirected/output Tee'd and can be displayed.
#Bill_Stewart is correct, in the sense that you should pick either an interactive prompt, or a fully automated solution.
Edit: To add some more information from comments.
If we use Tee-Object it relies on the Pipeline. Pipelines can only pass complete objects down the pipeline (e.g. complete strings inc. New Line). Pipelines have to interact with other commands like ForEach-Object or Select-Object, and they can't handle passing incomplete data to them. That's how the PowerShell console works, and you can't change it.
Similarly, redirection works line by line. The underlying reason why, I will explain why in a moment.
So, if you want to interact with it character by character, then you are dealing with streams. And if you want to deal with streams directly, it's 100 times more complicated because you can't use the convenience of the PowerShell console, you have to directly run of the process manually and handle all the input and output yourself.
To start, you have to manually launch the process. To do this we use the System.Diagnostics.Process class. The Pseudocode looks something like this:
$p = [System.Diagnostics.Process]::New()
$p.StartInfo.RedirectStandardOutput = $true
$p.StartInfo.RedirectStandardError = $true
$p.StartInfo.RedirectStandardInput = $true
$p.StartInfo.UseShellExecute = $false
#$p.StartInfo.CreateNoWindow = $true
$p.StartInfo.FileName = "plink.exe"
$p.StartInfo.Arguments = 'root#10.0.0.141 -pw "password" -t -batch "isi auth users create testuser --set-password"'
$p.EnableRaisingEvents = $true
....
We essentially create the process, specify that we are going to redirect the stdout (StartInfo.RedirectStandardOutput = $true), as well as the stdin to something else for us to handle. How do we know when to read the data? Well, the class has the Process.OutputDataReceived Event. You bind to this event to read in the additional data. But:
The OutputDataReceived event indicates that the associated Process has
written a line, terminating with a newline character, to its
redirected StandardOutput stream.
Remarks
So even the process class revolves around newlines for streaming data. This is why even redirects *> work on a line by line basis. PowerShell, and cmd, etc. all use the Process class as a basis to run processes. They all bind to this same event and methods to do their processing. Hence, why everything revolves around newlines and statement completions.
(big breath) So. You still want to interactively work with things one character at a time? well then you can't use the convenience of events. You will have to fall back to using a Stream Reader and directly binding to the Process.StandardOutput Property. Unfortunately this is where I stop, and say that to accomplish this
is beyond the scope of SO, and will require much more research to accomplish.

How to output specific information from a powershell command?

So I've been playing around with Powershell recently, trying some things with a basic command net user $username. As an example net user administrator produces an output that you can see at the bottom of this page.
My question is: How do I output specific elements of this?
I'm aware of pipes and have been trying to use them but I think I'm missing something as it never comes out right. Lets say, for example, I just want user name, full name, password expires and last logon to be shown as an output. What command do I use after the pipe to get this?
Many thanks!
net.exe is not a PowerShell cmdlet. Therefore getting information out it is processing the output of the executable as a string.
For example, retrieving the user name:
$netoutput = net user administrator
#User name is on the first line, separated by spaces, the actual username is last word
$netoutput[1].Split(" ")[-1]
If you are using Win10 1607 or newer, you could retrieve this information with the Get-LocalUser cmdlet
Get-LocalUser administrator | Select-Object Name,FullName,PasswordExpires,LastLogon

Pipeline semantics aren't propagated into Where-Object

I use the following command to run a pipeline.
.\Find-CalRatioSamples.ps1 data16 `
| ? {-Not (Test-GRIDDataset -JobName DiVertAnalysis -JobVersion 13 -JobSourceDatasetName $_ -Exists -Location UWTeV-linux)}
The first is a custom script of mine, and runs very fast (miliseconds). The second is a custom command, also written by me (see https://github.com/LHCAtlas/AtlasSSH/blob/master/PSAtlasDatasetCommands/TestGRIDDataset.cs). It is very slow.
Actually, it isn't so slow processing each line of input. The setup before the first line of input can be processed is very expensive. That done, however, it goes quite quickly. So all the expensive code gets executed once, and only the fairly fast code needs to be executed for each new pipeline input.
Unfortunately, when I want to do the ? { } construct above, it seems like PowerShell doesn't keep the pipe-line as it did before. It now calls me command a fresh time for each line of input, causing the command to redo all the setup for each line.
Is there something I can change in how I invoke the pipe-line? Or in how I've coded up my cmdlet to prevent this from happening? Or am I stuck because this is just the way Where-Object works?
It is working as designed. You're starting a new (nested) pipeline inside the scriptblock when you call your command.
If your function is doing the expensive code in its Begin block, then you need to directly pipe the first script into your function to get that advantage.
.\Find-CalRatioSamples.ps1 data16 |
Test-GRIDDataset -JobName DiVertAnalysis -JobVersion 13 -Exists -Location UWTeV-linux |
Where-Object { $_ }
But then it seems that you are not returning the objects you want (the original).
One way you might be able to change Test-GRIDDataset is to implement a -PassThru switch, though you aren't actually accepting the full objects from your original script, so I'm unable to tell if this is feasible; but the code you wrote seems to be retrieving... stuff(?) from somewhere based on the name. Perhaps that would be sufficient? When -PassThru is specified, send the objects through the pipeline if they exist (rather than just a boolean of whether or not they do).
Then your code would look like this:
.\Find-CalRatioSamples.ps1 data16 |
Test-GRIDDataset -JobName DiVertAnalysis -JobVersion 13 -Exists -Location UWTeV-linux -PassThru

How to format output in Posh Server (Powershell web server)?

I am currently trying the Powershell web server PoSH (http://poshserver.net/) for some administration reports. But i don't know how to format ouput.
From the start: i start the console with the default shortcut, with admin rights. I type Import-Module PoSHServer, then Start-PoSHServer. The web server starts, then i create a simple index.ps1 file, with just one line of code in the body section: $(command).
For example, i want to use the Get-Service Mpssvc command, but what i obtain is :
System.ServiceProcess.ServiceController
I try Get-Service MpsSvc | Select Name,Status. Output:
#{Name=MpsSvc; Status=Running}
Same thing for cmdlets Get-Process, i have an output with list of processes but it appears like this: System.Diagnostics.Process (AcroRd32) ...
However, some cmlets just like the Get-Date (used in the Posh demonstration web page) works fine and have a "normal" output.
I read the documentation, but there is no example which can help me for that.
How can i write powershell code to obtain a "clean" and console-like output?
I just downloaded and installed Posh-Server yesterday after reading this post.
If you want output to look like console inside a web-page you are probably looking at this from the wrong angle, you need to think string not console. Your code is supposed to be running inside of a here-string, in the example. So I got the hint here that the standard console formatter does not apply, posh-server will use whatever it wants to to turn your returned object into a STRING!. Your code output will get turned into a string using whatever formatter it deems applies unless you explicitly return a string - which the example script does correctly do. So try this on the console
get-process "power*" | out-string -width 80
And then try it in your posh-server script.
You probably really wanted this:
Get-Service MpsSvc | Select Name,Status | out-string -width 120
Hope that helps - I think the lack of examples in this project is a good thing because this is really a very simplistic web-server; lots of conceptual thinking required before you even start :) .

Are there good references for moving from Perl to Powershell?

I hate to say it, but powershell is really annoying me. I just cannot seem to get my mind around it. I have an O'Reilly book on the topic, and I can see how to do some extremely powerful stuff -- it's the easy stuff I can't seem to get right.
Case in point: Iterate across a list of filenames.
In CMD:
for /F %x in ('dir EXPRESSION') do #(
arbitrary-action %x
)
In Perl:
#foo=glob("*");
foreach (#foo)
{
arbitrary-command $_ ;
}
In Powershell:
I'm dumbfounded. I can't seem to get it right.
But I am not sending this post so somebody can tell me the answer. I don't want the answer to this simple question. I want to know how to figure it out, and Google/Bing searches are just not cutting it. The get-help functionality is powershell is nice, but it's still not enough.
I've been programming for 20 years.
I've learned BASIC, Fortran, C, Pascal, Perl, C++, C#, BASH and CMD scripting...And never have I had the trouble I'm having with Powershell.
Are there no references "out there" for migrating from Perl to Powershell? It seems like such a straightforward thing to publish, but I have yet to find one.
Any help would be appreciated. Thanks.
Update:
Okay, so maybe this wasn't the best example to post.
I think I was thrown off by the fact that when I tried gci interactively, I got a directory listing, where what I wanted was an array of strings.
I took a leap of faith and tried:
foreach ($foo in gci "*") {
echo $foo;
}
And yeah, it worked. And yes, I can continue to do searches to piece my way through. I guess I was just hoping to find a guide that makes use of the similarity to languages I already know. I know that Microsoft published a VBScript-to-Powershell guide, so I was hoping for a Perl equivalent.
Thanks again
I've never seen such a guide. I've seen something to help people going from VBScript to PowerShell.
Bruce Payette's PowerShell in Action does have a few pages on PowerShell vs X scripting language, but that won't cut it for a conversion guide.
Now, there was a site out there that had all kinds of constructs in multiple languages, thus providing a task, and then going about solving it in all kinds of languages based on answers from the community... Anyone know what I'm talking about?
I don't know of any good Perl to Powershell comparisons but I can answer your secondary question.
$files = get-childitem "c:\test\" -filter *.dll
foreach ($file in $files) { $file.Name }
There are two different ways you can express a foreach loop in Powershell.
You can pipe an array of objects into foreach and $_ becomes the current object on each iteration.
0,1,2,3 | foreach { $_ }
Alternatively, you can pass a variable to iterate over.
foreach ($num in 0,1,2,3) { $num }
Output in both cases.
0
1
2
3
Like he said himself, he realized the potential to get some very powerful things using powershell...I recently started using it myself and the ease with which things can be done is astounding...just a few lines is all it takes to accomplish things that in python woulda taken me some extra workarounds etc.
I'm curious do you have the powershell cookbook? I thought since I had programming experience that it would be the best way to quickly learn powershell. This turned out to be a poor assumption. Even though the book was really good, I was struggling because I needed a book that was structured more for learning than reference.
The two best free online ebooks I found are:
https://blogs.technet.com/chitpro-de/archive/2007/05/10/english-version-of-windows-powershell-course-book-available-for-download.aspx
http://powershell.com/cs/blogs/ebook/
I'm still looking for a good print book.
I think finding a Perl to PowerShell guide is going to be difficult. It is actually more accurate to compare PowerShell to BASh and the C Shell than Perl. I think what makes learning PowerShell difficult from most of the available books is that they are aimed at system admins, not programmers. I recommend the "PowerShell in Action" for the best coverage of PowerShell as a general purpose programming language.
The other thing you need to do is immediately embrace the core principal of PowerShell -- you are dealing with objects, not text. With BASh and the other Unix shells, it's all about text manipulation and while Perl can do objects, its roots are still very much in the Unix shell and command line utilities (grep, sed, awk, etc.).
Larry Wall stole a lot of great ideas from other languages when he created Perl. PowerShell has done the same, using the POSIX shell as its starting point. You can see a lot of Perl in PowerShell, as well as other languages. I think the best way to learn PowerShell is by having a PowerShell window in front of you while reading "PowerShell in Action" which will help you get into the PowerShell way of thinking about how it does objects. It is easy to interactively enter code snippets in a PowerShell window and examine the properties and methods available within the objects returned by the commands.
BTW -- if you are use to using BASh with the default command line editing features, put the following command in your PowerShell $PROFILE
Set-PSReadlineOption -editmode Emacs
Do this and you'll feel right at home. Now that I can run PowerShell on Linux and the Mac, I'm not sure what I will ever need BASh for again.
Funny... I had the same issues when I started with PowerShell, but after using PowerShell now for a couple of months, I have dumped Perl like ugly Sally after the Prom. There are several great ways of using foreach to loop through an list of objects. Let's look at the following example where I have a number of services that I want to make sure are running on my Windows Server (the processes all have Equal in the name). I can do this with a one liner command as follows:
Get-Service | where-object {$_.displayname -like "Equal*"} | foreach {
if($_.Status -eq "Stopped") {
Write-Host "`nRestarting..."
write-host $_.DisplayName
Start-Service $_.name
}
}
The first part of the command is the get-service command - filtering the services looking for services with the display name with Equal in them. The next part of the one liner really shows the beauty of PowerShell. The get-service command returns a list of objects, which can then be acted upon by piping them into a foreach loop. Note I did not have to declare any variables or an array to hold the objects. The objects are stored in the default $_ variable from which I can pull out object properties like name and status. Foreach returned object (service) I check its status to see if it's status is stopped and if it is it is restarted with the Start-Service command. I could do this a similar action with Perl, but I would have to screen scrape and place the values into an array, then foreach over the array in a similar manner as I did above. The screen scrapping would involve grep with regexp which adds lines of code. Because PowerShell commands produce objects with properties, I can quickly drill down to the properties I am looking for without the screen scraping hassles.