Two ways of returning the owner User Name of a running process using PowerShell.
Who is Using RemoteApps?
I manage an environment where RemoteApps are hosted on a server running Windows Server 2008 R2. We recently provisioned a new Remote Desktop Services (RDS) farm using Windows Server 2012 R2. We are getting ready to shut our old RemoteApps server down and want to make sure all of our users have started using the new farm before we decommission.
We don’t want to send out a blanket communication, but instead want to tailor the communication to each application’s user audience. We also don’t want to send it to people that have already stopped using the old RemoteApps server. What we needed was a way to see a snapshot in time of which applications were still being used and by what users.
Process Name and User Name: PowerShell 4.0 and Later
If you have Windows Server 2012 R2 or later, or have upgraded PowerShell on your Windows Server 2008 R2 systems to 4.0, Get-Process can easily return the process owner, even though it isn’t a property of the type returned by Get-Process.
In PowerShell 4.0, the switch -IncludeUserName was added to the Get-Process cmdlet. Run it from an elevated prompt and it will add a column with the process owner’s user name:
PS C:\WINDOWS\system32> Get-Process -Name Calculator -IncludeUserName Handles WS(K) CPU(s) Id UserName ProcessName ------- ----- ------ -- -------- ----------- 457 30772 0.31 10168 SHS1MWS1-AARON\aaron Calculator
Process Name and User Name: Before PowerShell 4.0
If you need to get similar output from a server running a version of PowerShell prior to 4.0, there is another method you can use, leveraging the Get-WmiObject cmdlet. The object type returned by Get-WmiObject includes a method called GetOwner. GetOwner returns another set of properties, one of which is User:
PS C:\WINDOWS\system32> Get-WmiObject -Class Win32_Process -Filter "name='calculator.exe'" | Foreach {$_.GetOwner() | Get-Member} TypeName: System.Management.ManagementBaseObject#\__PARAMETERS Name MemberType Definition ---- ---------- ---------- PSComputerName AliasProperty PSComputerName = __SERVER Domain Property string Domain {get;set;} ReturnValue Property uint32 ReturnValue {get;set;} User Property string User {get;set;} ...
The following one-liner will return the Process Name and the Owner’s Domain and User Name:
PS C:\WINDOWS\system32> Get-WmiObject Win32_Process -Filter "name='calculator.exe'" | Select Name, @{Name="UserName";Expression={$_.GetOwner().Domain+"\"+$_.GetOwner().User}} | Sort-Object UserName, Name Name UserName ---- -------- Calculator.exe SHS1MWS1-AARON\aaron
Only a Snapshot
These methods only give us the processes and owners at the time the command is run. For my purposes, it can be ran at different times of the day to capture a good portion of the users and applications that I need to target with communication to move to our new RemoteApp environment. I will be exploring the event log to determine if I can generate a report of users and applications for a given time period.
Alex Nicastro says
Hello,
I wrote a script that will make sure a user is logged in. We use a SCOM AD account to acknowledge our alerts for whoever is on-call. We needed a way to let us know when the user wasn’t logged in. Being SCOM doesnt provide a way to ack alerts via mobile device. I came up with a script that will ack an alert with the alert id in the subject line. The only down fall the user has to always be logged into the computer so the rule can run. So here it is, dunno if anyone could use it but I wanted to put it out there.. If the user isnt logged on it will send an sms alert via primary/secondary contacts we have set up. Which goes to whoever is on-call vztext.com phone. You should see in the code to change for your Environment..
#Declare variables
$computername =’Enter Computer Name to check here’
$prim=@();
$sec=@();
$explorerInstance=@();
$result=@();
$ctr =@();
$c=@();
$users=@();
#Import Exchange Module for External Contacts
$session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://YourHybridServerHere/PowerShell -Authentication Kerberos -AllowRedirection;
#Import Remote Session to Exchange Server
Import-PSSession $Session -AllowClobber;
#Get Primary On-Call Email Address
$prim = Get-DistributionGroupmember -id “primaryeas”| select primarysmtpaddress;
#Get Secondary On-Call Email Address
$sec = Get-DistributionGroupMember -id “secondaryeas” | select primarysmtpaddress;
#Get the username from explorer.exe processs
$explorerInstance = Get-WmiObject -Class Win32_Process -ComputerName $computername | Where-Object -Property name -EQ -Value ‘explorer.exe’;
ForEach ($Instance in $explorerInstance)
{
$ownerInfo = $Instance.GetOwner()
$result += New-Object -TypeName PSObject -Property @{
Domain = $ownerInfo.Domain;
Username = $ownerInfo.User;
ComputerName = $computername;
} | select Username
}
#Get how many users are logged in
$c = $result.username.count;
#Get Usernames
$users =$result.username;
#Loop through until Scom Account is found if not send out email.
do
{
for ($ctr=0;$ctr -le $c;)
{
if ($users[$ctr] -ne “scom”)
{
++$ctr;
}Elseif ($users[$ctr] -eq “scom”) { break;}
if ($ctr -gt $c){ Send-MailMessage -to $sec.primarysmtpaddress -cc $prim.PrimarySmtpAddress -From “Scom-Alert@teachforamerica.org” -Subject “SCOM ID Not Logged into YOURCOMPUTERNAMEHERE.. Message Sent from PWEXHYD01” -Body “`n The User Domain\Account is not signed into YOURCOMPUTERNAMEHERE.. `n Script Sent From: COMPUTERSENDINGTHISMESSAGE” -SmtpServer “smtp-relay-1.prod.tfanet.org” -Encoding “UTF8” -Priority High;
}
}
}while($ctr -eq $c)
Thanks,
Alex Nicastro
Aaron Rothstein says
Nice script, Alex. Thanks for sharing!