I am using an application that kills the process iexplore (Internet Explorer) on a terminal server. The issue I am encountering is that I kill all processes of Internet Explorer on the terminal server, not just the one of the current user.
So if I log on as User1 and kill IE, it will be killed for User2, User3 and so on ... I only want User1's Internet Explorer to be killed. I use the following code to kill my process:
Private Sub ClearProcesses(ByVal ProcessName As String)
Dim myProcesses = Process.GetProcessesByName(ProcessName)
For Each Proc As Process In myProcesses
Try
Proc.Kill()
Catch ex As Exception
MsgBox(ex.Message, MsgBoxStyle.Critical, "ClearProcess")
End Try
Next
End Sub
Is there a way to only kill the process for User1?
You can use WMI to get the owner of a Process, and verify that the process is owned by the current user.
Using a Function like so:
Public Function GetProcessOwner(processId As Integer) As String
Dim query As String = "Select * From Win32_Process Where ProcessID = " + processId
Dim searcher As New ManagementObjectSearcher(query)
Dim processList As ManagementObjectCollection = searcher.[Get]()
For Each obj As ManagementObject In processList
Dim argList As String() = New String() {String.Empty, String.Empty}
Dim returnVal As Integer = Convert.ToInt32(obj.InvokeMethod("GetOwner", argList))
If returnVal = 0 Then
' argList(0) == User
' argList(1) == DOMAIN
Return argList(0)
End If
Next
Return "NO OWNER"
End Function
You should be able to do something like:
Private Sub ClearProcesses(ByVal ProcessName As String)
Dim myProcesses = Process.GetProcessesByName(ProcessName).Where(Function(p) GetProcessOwner(p.Id) = currentUser)
' Your current code...
Related
I am creating a windows service that will write all the start time and exit time for specific process that I wanted to monitor. The problem is when I am trying to monitor the process to wait for exit, I have no idea on how to wait multiple process to exit. Below are my code for writing the start time of the process.
Try
Using regkey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64).OpenSubKey("SOFTWARE\MonitoringApplication\Login", RegistryKeyPermissionCheck.Default)
childrenID = regkey.GetValue("Login User").ToString
End Using
If childrenID.Equals("admin") Then
Else
Dim connection As New SqlConnection("Server=DESKTOP-FTJ3EOA\SQLEXPRESS;Initial Catalog=MonitorDB;User ID = admin; Password = admin")
Dim command As New SqlCommand("SELECT App.ApplicationName FROM App INNER JOIN ChildrenApplication ON App.ApplicationID = ChildrenApplication.ApplicationID WHERE ChildrenID = #a", connection)
command.Parameters.Add("#a", SqlDbType.VarChar).Value = childrenID
Dim adapter As New SqlDataAdapter(command)
Dim table As New DataTable()
adapter.Fill(table)
Using sw As StreamWriter = New StreamWriter(AppDomain.CurrentDomain.BaseDirectory + "\MonitoringApplication.txt", True)
For Each row As DataRow In table.Rows
p = Process.GetProcessesByName(row.Item(0))
Using myprocess = New Process
If p.Count > 0 Then
myprocess.StartInfo.FileName = row.Item(0)
myprocess.EnableRaisingEvents = True
sw.WriteLine(row.Item(0) + "running")
End If
End Using
Next row
End Using
Const SLEEP_AMOUNT As Integer = 100
Do While Not eventHandled
elapsedTime += SLEEP_AMOUNT
If elapsedTime > 30000 Then
Exit Do
End If
Thread.Sleep(SLEEP_AMOUNT)
Loop
End If
Catch ex As Exception
Using sw As StreamWriter = New StreamWriter(AppDomain.CurrentDomain.BaseDirectory + "\MonitoringApplication.txt", True)
sw.WriteLine(ex)
End Using
End Try
Private Sub myProcess_Exited(ByVal sender As Object, ByVal e As System.EventArgs) Handles myProcess.Exited
eventHandled = True
Using sw As StreamWriter = New StreamWriter(AppDomain.CurrentDomain.BaseDirectory + "\MonitoringApplication.txt", True)
sw.WriteLine("Exited")
End Using
End Sub
Is there any ways to monitor multiple process to exit? Thanks in advance.
You're now using Process.GetProcessesByName() to retrieve an array of running processes, if any.
You can use the returned array of processes and subscribe to the Exited event of each one to log the exit time of any of the processes in the array.
Setting EnableRaisingEvent is necessary to raise the Exited event, but you also need to subscribe to event, using AddHandler along with the address of a method or a Lambda:
AddHandler [Process].Exited, AddressOf [Handler]
' or
AddHandler [Process].Exited, Sub() [Lambda]
This method accepts a process name and the path to a file where to store the name of the process and its exit time when the Exited event is raised.
If your current loop:
For Each row As DataRow In table.Rows
'(...)
Next
You can insert a call to this method:
For Each row As DataRow In table.Rows
SubscribeProcExit(row.Item(0), Path.Combine(Application.StartupPath, "MonitoringApplication.txt"))
Next
If the log file doesn't exit, it will be created and a new line is added each time one of the Processes exits, logging the Process.ProcessName and Process.ExitTime.
Note that row.Item(0) must contain the friendly name of the Process. For example, notepad.exe must be referenced as just "notepad".
Private Sub SubscribeProcExit(processName As String, fileName As String)
Dim processes As Process() = Process.GetProcessesByName(processName)
If processes.Length = 0 Then Return
For Each p As Process In processes
p.EnableRaisingEvents = True
AddHandler p.Exited,
Sub()
Using sw As StreamWriter = File.AppendText(fileName)
sw.WriteLine($"Process: {p?.ProcessName}, Exit Time: {p?.ExitTime}")
p?.Dispose()
End Using
End Sub
Next
End Sub
I'm trying to start manage-bde.exe as a new process in VB.net but when it tries to start the proc, Bitlocker crashes. Could anyone please tell me what I'm doing wrong here? This code was converted from C# where it works all day long....
Code:
Private Sub btnLock_Click(sender As Object, e As EventArgs) Handles btnLock.Click
Dim drvSelected As String = cmbDriveSelect.SelectedValue.ToString()
Dim sysDirWithBDE As String = Environment.SystemDirectory + "\manage-bde.exe"
Dim lockStatus As String = String.Empty
' This is the code for the base process
Dim myProcess As New Process()
' Start a new instance of this program
Dim myProcessStartInfo As New ProcessStartInfo(sysDirWithBDE, " -lock " + drvSelected.Remove(2))
'Set Use Shell to false so as to redirect process run info to application
myProcessStartInfo.UseShellExecute = False
myProcessStartInfo.RedirectStandardOutput = True
myProcess.StartInfo = myProcessStartInfo
Try
myProcess.Start()
lblDriveLockMsg.Show()
Catch err As Exception
lblDriveLockMsg.Text = err.Message
End Try
'Read the standard output of the process.
lockStatus = myProcess.StandardOutput.ReadToEnd()
If lockStatus.Contains("code 0x80070057") Then
lblDriveLockMsg.Text = "Drive selected is not Bit Locker encrypted"
ElseIf lockStatus.Contains("code 0x80070005") Then
lblDriveLockMsg.Text = "Drive selected is in use by an application on your machine, force dismounting might result in data loss, please check and close any applications using the drive"
Else
lblDriveLockMsg.Text = lockStatus
End If
myProcess.WaitForExit()
myProcess.Close()
End Sub
I have the following Function intended to identify the username of the user who started a specific process:
Private Function GetProcessAssociatedUserID(ByVal processName As String) As String
Dim user(1) As String
Try
Dim query As New SelectQuery(processName)
Dim searcher As New System.Management.ManagementObjectSearcher(query)
For Each process As ManagementObject In searcher.Get()
process.InvokeMethod("GetOwner", CType(user, Object()))
Next
Catch ex As Exception
End Try
Return user(0)
End Function
However somewhere in the ForEach initiation i'm getting this "ManagementException was Caught: Invalid class" exception thrown into my catch block. I've been in through debug but still cant work out what is. Any help would be much appreciated.
You can try it accomplishing this way
Private Function GetProcessAssociatedUserID(ByVal processName As String) As String
Dim query = "Select * from Win32_Process Where Name = """ + processName + """"
Dim searcher = New ManagementObjectSearcher(query)
Dim processList = searcher.Get()
For Each mObj As ManagementObject In processList
Dim argList As String() = {String.Empty, String.Empty}
Dim returnVal = Convert.ToInt32(mObj.InvokeMethod("GetOwner", argList))
If returnVal = 0 Then
Return argList(1) + "\\" + argList(0)
End If
Next
Return ""
End Function
This snippet works with .NET Framework 3.5 and above. For more details you may refer using-managementobjectsearcher-in-systemmanagement-is-getting-compiling-errors
I'm making a program that looks for processes and can see which user is using them. I've got the scanning code, but not the username code. The username has to be a string. For example: I have 2 people running some processes and the processes will show in the listview. The first column is for processes and the second is for the username. I want it to be like:
(process here) (username here)
(process here) (username here)....
You get the point I think and there's much more processes than that running on the computer. The question is: How do you get the username for someone using the process?
Edit: The code. This is my code.
For Each pr As Process In Process.GetProcesses
Dim lvi As ListViewItem = ListView1.Items.Add(CStr(pr.ProcessName))
'Now I need something to put for the username
Next
This is the other one that is most common.
Public Function GetProcessOwner(processId As Integer) As String
Dim query As String = "Select * From Win32_Process Where ProcessID = " + processId
Dim searcher As New ManagementObjectSearcher(query)
Dim processList As ManagementObjectCollection = searcher.[Get]()
For Each obj As ManagementObject In processList
Dim argList As String() = New String() {String.Empty, String.Empty}
Dim returnVal As Integer = Convert.ToInt32(obj.InvokeMethod("GetOwner", argList))
If returnVal = 0 Then
' argList(0) == User
' argList(1) == DOMAIN
Return argList(0)
End If
Next
Return "NO OWNER"
End Function
This code is taken from here, where you can find more information if you need it. Basically, on a console app this will print the process name and the user to the screen:
Public Shared Sub Main()
Dim selectQuery As SelectQuery = New SelectQuery("Win32_Process")
Dim searcher As ManagementObjectSearcher = New
ManagementObjectSearcher(selectQuery)
For Each proc As ManagementObject In searcher.Get
Console.WriteLine(proc("Name").ToString)
Dim s(1) As String
proc.InvokeMethod("GetOwner", CType(s, Object()))
Console.WriteLine(("User: " & (s(1) + ("\\" + s(0)))))
Next
Console.ReadLine()
End Sub
This could be implemented as a function, like:
Public Function GetUserName(ByVal ProcessName As String)
Dim selectQuery As SelectQuery = New SelectQuery("Win32_Process")
Dim searcher As ManagementObjectSearcher = New ManagementObjectSearcher(selectQuery)
Dim y As System.Management.ManagementObjectCollection
y = searcher.Get
For Each proc As ManagementObject In y
Dim s(1) As String
proc.InvokeMethod("GetOwner", CType(s, Object()))
Dim n As String = proc("Name").ToString()
If n = ProcessName & ".exe" Then
Return ("User: " & s(1) & "\\" & s(0))
End If
Next
End Function
Just for reference, proc.InvokeMethod("GetOwner", CType(s, Object())) will return an array like this:
Index 0: Owner/user name
Index 1: Domain
And in our case, will store it in s(1).
Hope this helps :)
Notes:
If the function returns something like User: \\ then the process is probably a special windows process. To see which processes will act like this (for windows users):
Right click on the task bar
Select Start Task Manager
In the Processes tab, in the User Name column, some processes will have a blank cell instead of a user name.
Edit:
The VB.NET function has been edited and should now work, although I have no idea why the console program still worked. At any rate I've left it alone, if it still works why change it?
I am trying to get a list of processes running on remote machine and the username running them. So far I've got:
Dim ps As System.Diagnostics.Process
For Each ps In System.Diagnostics.Process.GetProcesses("myserver")
ListBox1.Items.Add(ps.ProcessName)
Next
How to get permissions for using System.Diagnostics.Process.GetProcess(string)? - this might be a better way to do it. It is in C# I can translate it if you want.
''' using System.Management;
' don't forget! in VS you may have to add a new reference to this DLL
Dim op As New ConnectionOptions()
op.Username = "REMOTE_USER"
op.Password = "REMOTE_PASSWORD"
Dim sc As New ManagementScope("\\REMOTE_COMPUTER_NAME\root\cimv2", op)
Dim query As New ObjectQuery("Select * from Win32_Process")
Dim searcher As New ManagementObjectSearcher(sc, query)
Dim result As ManagementObjectCollection = searcher.[Get]()
For Each obj As ManagementObject In result
If obj("Caption") IsNot Nothing Then
Console.Write(obj("Caption").ToString() & vbTab)
End If
If obj("CommandLine") IsNot Nothing Then
Console.WriteLine(obj("CommandLine").ToString())
End If
Next
Public Function GetProcessOwner(processId As Integer) As String
Dim query As String = "Select * From Win32_Process Where ProcessID = " & processId
Dim searcher As New ManagementObjectSearcher(query)
Dim processList As ManagementObjectCollection = searcher.[Get]()
For Each obj As ManagementObject In processList
Dim argList As String() = New String() {String.Empty, String.Empty}
Dim returnVal As Integer = Convert.ToInt32(obj.InvokeMethod("GetOwner", argList))
If returnVal = 0 Then
' return DOMAIN\user
Return argList(1) & "\" & argList(0)
End If
Next
Return "NO OWNER"
End Function