List process for current user - powershell

As an administrator I can get a users processes by running this
Get-Process -IncludeUserName | Where UserName -match test
But as a non-administrator I can't use -IncludeUserName becuase "The 'IncludeUserName' parameter requires elevated user rights".
So if I'm logged on as the user test, how do I list only his processes and not everything that's running?

This is faster, one line, doesn't require admin.
Get-Process | ? {$_.SI -eq (Get-Process -PID $PID).SessionId}

You can do that through WMI. Here is an excerpt of an article you can find here.
$View = #(
#{l='Handles';e={$_.HandleCount}},
#{l='NPM(K)';e={ (Get-Process -Id $_.ProcessId).NonpagedSystemMemorySize/1KB -as [int]}},
#{l='PM(K)';e={ $_.PrivatePageCount/1KB -as [int]}},
#{l='WS(K)';e={ $_.WorkingSetSize/1KB -as [int]}},
#{l='VM(M)';e={ $_.VirtualSize/1mB -as [int]}},
#{l='CPU(s)';e={ (Get-Process -Id $_.ProcessId).CPU -as [int]}},
#{l='Id';e={ $_.ProcessId}},
'UserName'
#{l='ProcessName';e={ $_.ProcessName}}
)
Get-WmiObject Win32_Process | % { $_ |
Add-Member -MemberType ScriptProperty -Name UserName -Value {
'{0}\{1}' -f $this.GetOwner().Domain,$this.GetOwner().User
} -Force -PassThru
} | ? UserName -match $env:USERNAME | ft $View -AutoSize

Get-Process alone will not give you this information, you'll need WMI:
$owners = #{}
gwmi win32_process |% {$owners[$_.handle] = $_.getowner().user}
$ps = get-process | select processname,Id,#{l="Owner";e={$owners[$_.id.tostring()]}}
foreach($p in $ps) {
if($p.Owner -eq $env:USERNAME) {
$p
}
}

Thanks for your code. Based on this, I created a modified version to allow users to kill (a subset of) their own processes:
#Script to allow users to kill (a subset of) their own processes
#Based on : https://stackoverflow.com/questions/35195221/list-process-for-current-user
#Previously we used Task Nanny created by Michel Stevelmans which is a lot faster, but it did not show a process that was causing issues for our users.
$UserProcesses = #()
$Owners = #{}
Get-WmiObject win32_process | Foreach{$owners[$_.handle] = $_.getowner().user}
$Processes = Get-Process | select processname,Description,Id,#{l="Owner";e={$owners[$_.id.tostring()]}}
Foreach($Process in $Processes)
{
IF($process.Owner -eq $env:USERNAME)
{
$UserProcesses += $Process
}
}
$UserProcessesToExclude = #(
'concentr', #Citrix Connection Center
'conhost', #Console Window Host
'dwm', #Desktop Windows Manager
'explorer', #Explorer
'Receiver', #Citrix Receiver Application
'rundll32', #Windows host process (Rundll32)
'ssonsvr', #Citrix Receiver
'taskhost' #Host Process for Windows Tasks
'wfcrun32' #Citrix Connection Manager
'wfshell' #Citrix wfshell shell
)
$UserProcesses | Where{$_.ProcessName -notin $UserProcessesToExclude} | Out-GridView -Title 'Task killer - Select the process(es) you want to kill. Hold CTRL to select multiple processes.' -PassThru | Foreach{Stop-Process -id $_.Id}

Related

How to check Veeam Backup Jobs Status in ALL servers

I have script that checks every 24 hours locally on server the status of all backup jobs along more details.
I want that script to check all my servers, lets say: "SRV1", "SRV2", "SRV3"
How can i manage that?
Here's the script:
$date = (Get-Date).AddHours(-24)
$sessions = Get-VBRComputerBackupJobSession
foreach ($PBackup_job in (Get-VBRComputerBackupJob | Select Name)) {
$PBackup_job_name = $PBackup_job.Name
write "------------ Physical Server Backup Job Name : $PBackup_job_name ------------"
$sessions | where {$_.CreationTime -ge $date} | sort CreationTime | Select CreationTime, endtime, result, state | Format-Table
}
Although I cannot test this myself, I think you could do that using Invoke-Command like below:
$servers = "SRV1", "SRV2", "SRV3"
# set the credentials for admin access on the servers
$cred = Get-Credential 'Please enter your admin credentials'
$result = Invoke-Command -ComputerName $servers -Credential $cred -ScriptBlock {
$date = (Get-Date).AddHours(-24).Date
$sessions = Get-VBRComputerBackupJobSession
foreach ($PBackup_job in (Get-VBRComputerBackupJob)) {
$sessions | Where-Object {$_.CreationTime -ge $date} |
Sort-Object CreationTime |
Select-Object #{Name = 'Server'; Expression = {$env:COMPUTERNAME}},
#{Name = 'BackupJobName'; Expression = {$PBackup_job.Name}},
CreationTime, endtime, result, state
}
}
# remove the extra properties PowerShell added and save to CSV
$result = $result | Select-Object * -ExcludeProperty PS*, RunSpaceId
# output on screen
$result | Format-Table -AutoSize
# write to file
$result | Export-Csv -Path 'X:\Somewhere\BackupJobs.csv' -NoTypeInformation

Task scheduler running power shell script - Username error?

So I have a powershell script that when a user logs into a PC it emails details of the login to me, for example username,IP,location etc. It runs from task scheduler and has a trigger on login.
The script runs fine through powershell my issue I am having that no matter who logs in it always runs the script on my account in task scheduler hence always inputting my name as the Username even tough a different user may be logged in. I've tried calling the username multiple ways but always shows my name as It runs off my account.
For calling the username I have used :
$username = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
$env:UserName
$env:UserDomain
All return the user of who is running the scheduled task.
Any help to get it to print the true user who has logged in would be much appreciated.
Thanks.
It may be because your scheduled task is executing with your credentials. There's no way around this, sadly. That said you can kind of side-step the behaviour by getting the user account associated with the explorer.exe process:
$username = Get-WmiObject Win32_Process -Filter "Name='explorer.exe'" | ForEach-Object { $_.GetOwner() } | Select-Object -Unique -Expand User
This should work fine, as long as you aren't ever in a situation where multiple users could be logged into a machine at the same time (fast user switching, terminal services etc.)
EDIT: To get what you're after, you might need something more like this
$op = #()
$owners = Get-WmiObject Win32_Process -Filter "Name='explorer.exe'" | ForEach-Object { $_.GetOwner() } | Select-Object -Unique -Expand User
foreach($owner in $owners)
{
$wmiprocs = get-wmiobject win32_process -filter "Name='explorer.exe'" | where { $_.getowner().user -eq $owner } | select-object processid
$procs = $wmiprocs | % { get-process -id $_.processid | select-object starttime }
$obj = new-object object
$obj | add-member -type noteproperty -name Username $owner
$obj | add-member -type noteproperty -name Logon ($procs | sort -descending)[0].starttime
$op += $obj
}
$op | ft -auto
Note that your PowerShell instance will need to be running as Admin to query the processes of other users.

How to check if an application is installed on multiple server - powershell

$comps = get-content C:\xyz\test.txt
foreach($comp in $comps)
{
$result = Get-WmiObject -Class Win32_Product -Computer $comp | sort-object Name | select Name | where { $_.Name -match “abc”}
$result | out-file -Append out.txt
}
There is a application abc , im looking to know whether this is installed in multiple servers.
Check this "Hey Scripting Guy" link. This link describes how to query for installed applications via the registry.
From the link:
Win32_Product: The Good, the Bad, and the Ugly
[Good] The Win32_Product WMI class represents products as they are installed >by Windows Installer.
If you choose to query Win32_Product class by using Get-WmiObject, you’ll find >yourself [Bad] waiting for your query (or application) to return [Ugly] a >consistency check of packages that are installed as it attempts to verify and >repair installs. (For more information, see Event log message indicates that >the Windows Installer reconfigured all installed applications).
...
Based on above link you can query your installed products via:
Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* | Select-Object DisplayName, DisplayVersion, Publisher, InstallDate | Format-Table –AutoSize
Additionally you can use Test-Path to check if a requested registry entry exists. Example:
if (test-path HKLM:\Software\abc) { write-host "Found" } else { Write-Host "Not found" }
To check for installed software on multiple servers:
$servers = Get-Content C:\xyz\servers.txt
$results = #()
foreach ($server in $servers) {
$session = New-PSSession -ComputerName $server -Credential (Get-Credential)
$results += Invoke-Command -Session $session -ScriptBlock {
test-path HKLM:\Software\abc
}
}
$results.GetType() # Dump type
$results | gm # Dump properties
$results | Format-Table
Hope that helps.

powershell wait for command to finish before proceeding

In powershell I am trying to do the following:
$name = "computername"
#get installed programs
Write-Host "****APPLICATIONS"
gwmi win32_Product -ComputerName $name | select name
#gets services
write-host "****SERVICES"
Get-Service -ComputerName $name | ft
the expected output would be
****APPLICATIONS
name
of
app
****SERVICES
running services here
more services here
the actual result is
****APPLICATIONS
****SERVICES
name
of
app
running services here
more services here
I have attempted to do start-job then wait-job , but running gwmi as a job seems to output nothing to the console and sending the output to a separate file defeats the purpose of other parts of the script
I also attempted to use start-sleep and it still finishes both write-host commands before proceeding
Try this:
$name = "computername"
Write-Host "`n****APPLICATIONS`n"
gwmi win32_Product -ComputerName $name | % {$_.name}
write-host "`n****SERVICES"
Get-Service -ComputerName $name | ft
If you want the results alphabetical:
$name = "computername"
Write-Host "`n****APPLICATIONS`n"
$apps = gwmi win32_Product -ComputerName $name | % {$_.name}
$apps | sort
write-host "`n****SERVICES"
Get-Service -ComputerName $name | ft
Param(
$ComputerName = 'AT805061'
)
# Get installed programs
Write-Host "`n****APPLICATIONS`n"
Get-WmiObject win32_Product -ComputerName $ComputerName | Select-Object -ExpandProperty Name | Sort-Object
# Get services
Write-Host "`n****SERVICES`n"
Get-Service -ComputerName $ComputerName | Where-Object -Property Status -eq -Value Running | Select-Object -ExpandProperty Name | Sort-Object

Powershell - filtering WMIObject show two scripts result

im new beginner of powershell, now i have two script, one is get remote server's IPs, another one is get remote server's specific service start time, i need to show remote server's IP and specific service start time, can someone guide me how to merge these two script.
below is my two script.
$servers = gc -path D:\Ted\Computers.txt
$Job = get-wmiobject win32_networkadapterconfiguration -computer $servers -filter "IPEnabled='True'" -asjob
$results = $job | receive-job
$results
get-job | wait-job
receive-job job* | select IPAddress
and another one for get service start time is
$servers = gc -path D:\Ted\Computers.txt
$check = get-wmiobject win32_process -computer $servers -Filter "Name='aspnet_state.exe'" -asjob
$results = $check | receive-job
$results
get-job | wait-job
receive-job job* | Select-Object name, processId, #{Name="StartTime"; Expression={ $_.ConvertToDateTime( $_.CreationDate )}}
at last i need know one thing, If I use asjob to this script, that means it is multi-threaded execution?
sorry for my poor english, thank you for your kindly help.
There is probably a cleaner way to do this, but here is my take on your problem. It looks as if you need some way to correlate each computer to the output of the two WMI queries. If it is a requirement to run this in parallel using jobs, it will take a bit more work, but here is a serial version.
Get-Content -Path D:\Ted\Computers.txt | ForEach-Object {
$ip = Get-WmiObject Win32_NetworkAdapterConfiguration -Computer $_ -Filter "IPEnabled='True'" | Select-Object IPAddress
$process = Get-WmiObject Win32_Process -Computer $_ -Filter "Name='aspnet_state.exe'" | Select-Object Name, ProcessId, #{ Name="StartTime"; Expression = { $_.ConvertToDateTime($_.CreationDate) } }
#{
Computer = $_
Ip = $ip
Name = $process.Name
ProcessId = $process.ProcessId
StartTime = $process.StartTime
}
}
A parallel version would be something along the lines of this:
# A collection that stores all the jobs
$AllJobs = #()
# A collection that stores jobs correlated with the computer
$ComputerJobs = Get-Content -Path D:\Ted\Computers.txt | ForEach-Object {
$ipJob = Get-WmiObject Win32_NetworkAdapterConfiguration -Computer $_ -Filter "IPEnabled='True'" -AsJob
$AllJobs += $ipJob
$processJob = Get-WmiObject Win32_Process -Computer $_ -Filter "Name='aspnet_state.exe'"
$AllJobs += $processJob
#{
Computer = $_
IpJob = $ipJob
ProcessJob = $processJob
}
}
# Wait for everything to complete
Wait-Job -Job $AllJobs
# Iterate the correlated collection and expand the results
$ComputerJobs | ForEach-Object {
$ip = Receive-Job -Job $_.IpJob | Select-Object IPAddress
$process = Receive-Job -Job $_.ProcessJob | Select-Object Name, ProcessId, #{ Name="StartTime"; Expression = { $_.ConvertToDateTime($_.CreationDate) } }
#{
Computer = $_.Computer
Ip = $ip
Name = $process.Name
ProcessId = $process.ProcessId
StartTime = $process.StartTime
}
}