I am trying to end a powershell window I spawned from a task running as SYSTEM. I don't have the ID of the process since I am launching it through psexec to be able to set the session id. The task and the target powershell process are in different sessions.
I thought it would be simple just to set a window title and then query on the window title but I am running to issues since processes running under the system don't seem to see the window title. For example when I run get-process powershell | format-table -property Name, MainWindowTitle as a user I get:
Name MainWindowTitle
---- ---------------
powershell Administrator: C:\Windows\System32\cmd.exe
powershell My Title
powershell
By when I run the same command under the system account I get:
Name MainWindowTitle
---- ---------------
powershell
powershell
powershell
I am not sure what is going on here. Is there a way to get the MainWindowTitle from the SYSTEM account? If not, is there something else I could query for that would return my powershell window and leave any other powershell processes running?
I am on Window 7 x64
Name Value
---- -----
CLRVersion 2.0.50727.5477
BuildVersion 6.1.7601.17514
PSVersion 2.0
WSManStackVersion 2.0
PSCompatibleVersions {1.0, 2.0}
SerializationVersion 1.1.0.1
PSRemotingProtocolVersion 2.1
If there is something unique about the command line of the process you'd like to kill, maybe you could use something like:
Get-CimInstance Win32_Process -Filter "Name='powershell.exe'" |
Where-Object { $_.CommandLine -match $commandLineToMatch } |
ForEach-Object { Stop-Process -WhatIf -Id $_.ProcessId }
I added -WhatIf for testing purposes.
You need to call the GetOwner() method on the Win32_Process object to get the user that started the process.
Get-WmiObject -Class Win32_Process -Filter "Name='powershell.exe'" | ForEach-Object {
if ($_.GetOwner().User -match 'system') {
$_.Terminate()
}
}
Related
I am running a python script using "python script.py arg1 arg2 ...". I wanted to use powershell to check memory consumption of this script (process). The below command can't catch the python process. Looks like it isn't a win32_process?
Get-WmiObject win32_process -Filter "name like '%python'"
In this blog by Raymond Chen, it is dealing with win32_process class. Looks like my python process is not win32_process, because the above command doesn't catch it.
You can use the win32_process wmi class for python, and the name has the .exe on the end, slightly different from get-process:
Get-WmiObject win32_process -Filter "name = 'python.exe'" | select name,commandline
name commandline
---- -----------
python.exe "C:\Program Files\emacs\bin\python.exe"
Or
Get-WmiObject win32_process | ? name -eq python.exe | select name,commandline
name commandline
---- -----------
python.exe "C:\Program Files\emacs\bin\python.exe"
Or in powershell 7, get-process has the commandline property:
get-process python | select name,commandline
Name CommandLine
---- -----------
python "C:\Program Files\emacs\bin\python.exe"
It seems like the command history of PowerShell is stored separately from PowerShell ISE.
But I have one question is that where is the commands history of PowerShell ISE stored at and how do I view them?
As for the location of history files; they are located here:
Get-ChildItem -Path "$env:USERPROFILE\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadLine" |
Format-Table -AutoSize
# Results
<#
Directory: C:\Users\YourUserName\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadLine
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 17-May-21 02:23 258925 ConsoleHost_history.txt
-a---- 11-May-21 01:20 120222 Visual Studio Code Host_history.txt
-a---- 27-Jun-20 18:58 0 Windows PowerShell ISE Host_history.txt
#>
As noted, in the ISE, you can just leverage the Start-Transcript cmdlet to capture all you do, but again, it is not an out-of-box/console/ISE immediate lookup of previous commands to execute like PSReadLine. Yet, you can do that, sort of, with some creativity. Yet, that's just a kludge.
A note about using Start-Transcript. It will default to your "$env:USERPROFILE\Documents" folder.
So, I'd recommend you set to go to a specific folder. Also, though the files can be small, there will be tons of them over time, thus, you need to manage that.
They of course can just be opened in the ISE directly:
psEdit -filenames ((Get-ChildItem -Path "$env:USERPROFILE\Documents" | Sort-Object -Property LastWriteTime -Descending)[0]).FullName
Yet, since you are already in the ISE, you can just type and run all commands from the editor pane, and as needed, select anyone and just run it again.
Yet if you are just using the ISE console, and thinking it is the same as the PowerShell consolehost, then that's wrong. It's really an output window with some console skills. Back in the early ISE days, there were 3 panes. Editor, output window and true console.
The true console got removed in later ISE versions. Why, who knows? VSCode almost got us back there.
If you want to do the console stuff, then use the PowerShell console, or shell to the PowerShell console using runspaces to stay in the ISE.
For the runspaces thing, here is an example to run PowerShell Core (v6+), while still in the ISE.
Using PowerShell 7 in the Windows PowerShell ISE
https://old.ironmansoftware.com/using-powershell-core-6-and-7-in-the-windows-powershell-ise
$psISE.CurrentPowerShellTab.AddOnsMenu.Submenus.Clear()
$psISE.CurrentPowerShellTab.AddOnsMenu.Submenus.Add("Switch to PowerShell 7", {
function New-OutOfProcRunspace {
param($ProcessId)
$ci = New-Object -TypeName System.Management.Automation.Runspaces.NamedPipeConnectionInfo -ArgumentList #($ProcessId)
$tt = [System.Management.Automation.Runspaces.TypeTable]::LoadDefaultTypeFiles()
$Runspace = [System.Management.Automation.Runspaces.RunspaceFactory]::CreateRunspace($ci, $Host, $tt)
$Runspace.Open()
$Runspace
}
$PowerShell = Start-Process PWSH -ArgumentList #("-NoExit") -PassThru -WindowStyle Hidden
$Runspace = New-OutOfProcRunspace -ProcessId $PowerShell.Id
$Host.PushRunspace($Runspace)
}, "ALT+F5") | Out-Null
$psISE.CurrentPowerShellTab.AddOnsMenu.Submenus.Add("Switch to Windows PowerShell", {
$Host.PopRunspace()
$Child = Get-CimInstance -ClassName win32_process | where {$_.ParentProcessId -eq $Pid}
$Child | ForEach-Object { Stop-Process -Id $_.ProcessId }
}, "ALT+F6") | Out-Null
So, with a bit of tweaking, you can do the same for Windows PowerShell 5 to get the raw console
But again,m avoid all the hoops, and use VSCode, if you are allowed. Yet on your servers, we all know ISE is still a thing. ;-}
I am restricted to PowerShell version 2, I have crafted a command that lists out all of the accounts in the disabled state:
Get-WmiObject Win32_UserAccount | where{$_.Disabled -eq "True"} | select Name, Disabled
This works well, however, it also lists DC user accounts, I am only trying to query local users.
Is there any way to query only local user accounts in the disabled state?
Get-WmiObject -Class Win32_UserAccount -Filter "LocalAccount=True and Disabled=True" | Select-Object Name, Disabled
Old school Windows Tools still work, even from PowerShell regardless of version.
wmic useraccount get Name,Disabled
or
Start-Process powershell -ArgumentList '-NoExit', '-NoProfile', '-Command &{ "wmic useraccount get Name,Disabled" }'
# Results
<#
Disabled Name
TRUE Administrator
...
#>
Update for proof relative to your comment...
...it seems to give me an Invalid GET Expression error message on
PowerShell version 2
...
C:\>powershell -version 2.0 -nologo -noprofile
PS C:\> (Get-WmiObject -Class Win32_OperatingSystem).Caption
Microsoft Windows 10 Pro
PS C:\> $PSVersionTable
Name Value
---- -----
CLRVersion 2.0.50727.9151
BuildVersion 6.1.7600.16385
PSVersion 2.0
WSManStackVersion 2.0
PSCompatibleVersions {1.0, 2.0}
SerializationVersion 1.1.0.1
PSRemotingProtocolVersion 2.1
PS C:\> wmic useraccount get Name
Name
Administrator
...
PS C:\> wmic useraccount get Disabled
Disabled
TRUE
..
PS C:\> wmic useraccount get "Name,Disabled"
Disabled Name
TRUE Administrator
...
I have 4-5 process (like java.exe, javaw.exe etc) having username "OWNER"(suppose). Below is the script that filters the java.exe process and kills it if it belongs to "OWNER". I need your help to modify this so that any process related to "OWNER" would be killed if found.
Just do it with Get-Process:
get-process -IncludeUserName | where username -like $username | stop-process
Basically your whole script can be replaced with this line
Get-Process with -IncludeUsername switch is only available in WMF 5.0.
WMI is the option here.
You could probably terminate the process just by checking the owner equals to the corresponding user.
Get-WmiObject -Class Win32_Process | Where-Object -FilterScript {
$_.GetOwner.User -eq "$Owner" } | Invoke-WmiMethod -Name Terminate
Edit: The above code is a one liner, you could save the out put of Get-WmiObject in a variable and for foreach through the collection to print the process id and call the terminate() method instead of using Invoke-WmiMethod.
Note:This code is not tested
I'm trying to call a .PS1 using a batch file to produce a csv file with just the User Name and Other Telephone number details. I have the script to produce the csv file.
Get-ADUser -Filter * -Properties otherTelephone |
select name, #{L='otherTelephone'; E={$_.otherTelephone[0]}} | sort-object otherTelephone | select-object -last 1000 |
Export-Csv C:\Test.csv -NoTypeInformation
and I have the batch file to elevate the PowerShell
powershell -noprofile -command "&{ start-process powershell -ArgumentList '-noprofile -file C:\Test.ps1' -verb RunAs}"
The problem is when I try to import the system modules by adding
powershell.exe -ImportSystemModules
to the front of the powershell script, the CSV only returns the header information e.g. name and otherTelephone. The script works if I import the modules manually i.e right click import system modules, but not when I try to load modules before running the script.
Basically I need to run the PS script as admin, import the system modules and have the code output my data.
Any help as to where I am going wrong is appreciated.
powershell.exe -ImportSystemModules Get-ADUser -Filter * -Properties otherTelephone |
select name, #{L='otherTelephone'; E={$_.otherTelephone[0]}} | sort-object otherTelephone | select-object -last 10 |
Export-Csv C:\Test.csv -NoTypeInformation
If you need to load the modules inside your script use the following code:
Get-Module -ListAvailable | Where-Object {$_.Path -like "$PSHOME*"} | Import-Module
The -ImportSystemModules switch is a flag for powershell.exe. If you call powershell.exe -ImportSystemModules inside of your script it will start another powershell instance and load the modules inside of it.
You could also add the -ImportSystemModules to your powershell call inside the batch file. That should work too
Regards