How to get active process name in C#?
I know that I must use this code:
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
but I don't know how use it.
As mentioned in this answer, you have to use GetWindowThreadProcessId() to get the process id for the window and then you can use the Process:
[DllImport("user32.dll")]
public static extern IntPtr GetWindowThreadProcessId(IntPtr hWnd, out uint ProcessId);
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
string GetActiveProcessFileName()
{
IntPtr hwnd = GetForegroundWindow();
uint pid;
GetWindowThreadProcessId(hwnd, out pid);
Process p = Process.GetProcessById((int)pid);
p.MainModule.FileName.Dump();
}
Be aware that this seems to throw an exception (“A 32 bit processes cannot access modules of a 64 bit process”) when run from a 32-bit application when the active process is 64-bit.
EDIT: As Damien pointed out, this code is prone to race conditions, because the process that had the active window at the time when GetForegroundWindow() was called might not exist anymore when GetWindowThreadProcessId() is called. Even worse situation would be if the same hwnd would be assigned to another window at that time, but I guess this should be really rare.
I would suggest using System.Diagnostics.Process.
var currentProc = System.Diagnostics.Process.GetCurrentProcess();
string name = currentProc.ProcessName;
As an alternative you could use:
string name = currentProc.MainModule.FileName;
Its just need two line of code, you can use linq to get all processes.
var processss = from proc in System.Diagnostics.Process.GetProcesses() orderby proc.ProcessName ascending select proc;
foreach (var item in processss) {
Console.WriteLine(item.ProcessName );
}
Now you have all active process by just on line.
Here's a link describing the exact thing you want to do:
http://www.blackwasp.co.uk/GetActiveProcess.aspx
And another one describing the GetForegroundWindow function, which I copy below.
Note that you may need to reference some extra assemblies, for this code to work.
Look at the MSDN for each function. Example, GetProcessesByName requires System.Diagnostics.
public ApplicationState AppState
{
get
{
Process[] processCollection =
Process.GetProcessesByName(ProcessName);
if(processCollection != null &&
processCollection.Length >= 1 &&
processCollection[0] != null)
{
IntPtr activeWindowHandle = Win32.GetForegroundWindow();
// Optional int ProcessID;
// Optional Win32.GetWindowThreadProcessId(
GetForegroundWindow(),
out ProcessID)
foreach(Process wordProcess in processCollection)
{
//Optional if( ProcessID == wordProcess.Id )
// return ApplicationState.Focused;
if(wordProcess.MainWindowHandle == activeWindowHandle)
{
return ApplicationState.Focused;
}
}
return ApplicationState.Running;
}
return ApplicationState.NotRunning;
}
}
public void GetProcessNames()
{
List<string> windowNames = new List<string>();
foreach (Process window in Process.GetProcesses())
{
if (window.MainWindowHandle != IntPtr.Zero)
{
windowNames.Add(window.MainWindowTitle);
}
// It's that simple
}
}
Related
How do I suspend a whole process (like the Process Explorer does when I click Suspend) in C#.
I'm starting the Process with Process.Start, and on a certain event, I want to suspend the process to be able to do some investigation on a "snapshot" of it.
Here's my suggestion:
[Flags]
public enum ThreadAccess : int
{
TERMINATE = (0x0001),
SUSPEND_RESUME = (0x0002),
GET_CONTEXT = (0x0008),
SET_CONTEXT = (0x0010),
SET_INFORMATION = (0x0020),
QUERY_INFORMATION = (0x0040),
SET_THREAD_TOKEN = (0x0080),
IMPERSONATE = (0x0100),
DIRECT_IMPERSONATION = (0x0200)
}
[DllImport("kernel32.dll")]
static extern IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle, uint dwThreadId);
[DllImport("kernel32.dll")]
static extern uint SuspendThread(IntPtr hThread);
[DllImport("kernel32.dll")]
static extern int ResumeThread(IntPtr hThread);
[DllImport("kernel32", CharSet = CharSet.Auto,SetLastError = true)]
static extern bool CloseHandle(IntPtr handle);
private static void SuspendProcess(int pid)
{
var process = Process.GetProcessById(pid); // throws exception if process does not exist
foreach (ProcessThread pT in process.Threads)
{
IntPtr pOpenThread = OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)pT.Id);
if (pOpenThread == IntPtr.Zero)
{
continue;
}
SuspendThread(pOpenThread);
CloseHandle(pOpenThread);
}
}
public static void ResumeProcess(int pid)
{
var process = Process.GetProcessById(pid);
if (process.ProcessName == string.Empty)
return;
foreach (ProcessThread pT in process.Threads)
{
IntPtr pOpenThread = OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)pT.Id);
if (pOpenThread == IntPtr.Zero)
{
continue;
}
var suspendCount = 0;
do
{
suspendCount = ResumeThread(pOpenThread);
} while (suspendCount > 0);
CloseHandle(pOpenThread);
}
}
Thanks to Magnus
After including the Flags, I modified the code a bit to be an extension method in my project. I could now use
var process = Process.GetProcessById(param.PId);
process.Suspend();
Here is the code for those who might be interested.
public static class ProcessExtension
{
[DllImport("kernel32.dll")]
static extern IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle, uint dwThreadId);
[DllImport("kernel32.dll")]
static extern uint SuspendThread(IntPtr hThread);
[DllImport("kernel32.dll")]
static extern int ResumeThread(IntPtr hThread);
public static void Suspend(this Process process)
{
foreach (ProcessThread thread in process.Threads)
{
var pOpenThread = OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)thread.Id);
if (pOpenThread == IntPtr.Zero)
{
break;
}
SuspendThread(pOpenThread);
}
}
public static void Resume(this Process process)
{
foreach (ProcessThread thread in process.Threads)
{
var pOpenThread = OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)thread.Id);
if (pOpenThread == IntPtr.Zero)
{
break;
}
ResumeThread(pOpenThread);
}
}
}
I have a utility done which I use to generally suspend/kill/list a process. Full source is on Git
So really, what the other answer's are showing is suspending thread's in the process, there is no way to really suspend the process (i.e. in one call)....
A bit of a different solution would be to actually debug the target process which you are starting, see Mike Stall's blog for some advice how to implement this from a managed context.
If you implement a debugger, you will be able to scan memory or what other snap-shotting you would like.
However, I would like to point out, that technically, there is now way to really do this. Even if you do debugbreak a target debuggee process, another process on your system may inject a thread and will be given some ability to execute code regardless of the state of the target process (even let's say if it's hit a breakpoint due to an access violation), if you have all thread's suspended up to a super high suspend count, are currently at a break point in the main process thread and any other such presumed-frozen status, it is still possible for the system to inject another thread into that process and execute some instructions. You could also go through the trouble of modifying or replacing all of the entry point's the kernel usually calls and so on, but you've now entered the viscous arm's race of MALWARE ;)...
In any case, using the managed interfaces for debugging seems' a fair amount easier than p/invoke'ng a lot of native API call's which will do a poor job of emulating what you probably really want to be doing... using debug api's ;)
See this CodeProject article for the win32 basics : http://www.codeproject.com/KB/threads/pausep.aspx. This sample code makes use of the ToolHelp32 library from the SDK, so I would recommend turning this sample code into an unmanaged C++/CLI library with a simple interface like "SuspendProcess(uint processID).
Process.Start will return you a Process object, from which you can get the process id, and then pass this to your new library based on the above.
Dave
[DllImport("ntdll.dll", PreserveSig = false)]
public static extern void NtSuspendProcess(IntPtr processHandle);
static IntPtr handle;
string p = "";
foreach (Process item in Process.GetProcesses())
{
if (item.ProcessName == "GammaVPN")
{
p = item.ProcessName;
handle = item.Handle;
NtSuspendProcess(handle);
}
}
Console.WriteLine(p);
Console.WriteLine("done");
How to get active process name in C#?
I know that I must use this code:
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
but I don't know how use it.
As mentioned in this answer, you have to use GetWindowThreadProcessId() to get the process id for the window and then you can use the Process:
[DllImport("user32.dll")]
public static extern IntPtr GetWindowThreadProcessId(IntPtr hWnd, out uint ProcessId);
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
string GetActiveProcessFileName()
{
IntPtr hwnd = GetForegroundWindow();
uint pid;
GetWindowThreadProcessId(hwnd, out pid);
Process p = Process.GetProcessById((int)pid);
p.MainModule.FileName.Dump();
}
Be aware that this seems to throw an exception (“A 32 bit processes cannot access modules of a 64 bit process”) when run from a 32-bit application when the active process is 64-bit.
EDIT: As Damien pointed out, this code is prone to race conditions, because the process that had the active window at the time when GetForegroundWindow() was called might not exist anymore when GetWindowThreadProcessId() is called. Even worse situation would be if the same hwnd would be assigned to another window at that time, but I guess this should be really rare.
I would suggest using System.Diagnostics.Process.
var currentProc = System.Diagnostics.Process.GetCurrentProcess();
string name = currentProc.ProcessName;
As an alternative you could use:
string name = currentProc.MainModule.FileName;
Its just need two line of code, you can use linq to get all processes.
var processss = from proc in System.Diagnostics.Process.GetProcesses() orderby proc.ProcessName ascending select proc;
foreach (var item in processss) {
Console.WriteLine(item.ProcessName );
}
Now you have all active process by just on line.
Here's a link describing the exact thing you want to do:
http://www.blackwasp.co.uk/GetActiveProcess.aspx
And another one describing the GetForegroundWindow function, which I copy below.
Note that you may need to reference some extra assemblies, for this code to work.
Look at the MSDN for each function. Example, GetProcessesByName requires System.Diagnostics.
public ApplicationState AppState
{
get
{
Process[] processCollection =
Process.GetProcessesByName(ProcessName);
if(processCollection != null &&
processCollection.Length >= 1 &&
processCollection[0] != null)
{
IntPtr activeWindowHandle = Win32.GetForegroundWindow();
// Optional int ProcessID;
// Optional Win32.GetWindowThreadProcessId(
GetForegroundWindow(),
out ProcessID)
foreach(Process wordProcess in processCollection)
{
//Optional if( ProcessID == wordProcess.Id )
// return ApplicationState.Focused;
if(wordProcess.MainWindowHandle == activeWindowHandle)
{
return ApplicationState.Focused;
}
}
return ApplicationState.Running;
}
return ApplicationState.NotRunning;
}
}
public void GetProcessNames()
{
List<string> windowNames = new List<string>();
foreach (Process window in Process.GetProcesses())
{
if (window.MainWindowHandle != IntPtr.Zero)
{
windowNames.Add(window.MainWindowTitle);
}
// It's that simple
}
}
I am working on a WPF application and I need a way to get all the open windows within the application, including the ones that have been opened from another thread. I tried Application.Current.Windows but this does not give me the windows that have been opened from another thread. Is it even possible to access the windows opened by another thread? Shouldn't all the windows be in the same Application Domain?
Thanks.
This should do it. It will return a list of integer pointers to each open window of the given application name:
public delegate bool Win32Callback(IntPtr hwnd, IntPtr lParam);
[DllImport("user32.dll")]
public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
[DllImport("user32.Dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumChildWindows(IntPtr parentHandle, Win32Callback callback, IntPtr lParam);
static void Main(string[] args)
{
Process[] processes = Process.GetProcessesByName("MyApp");
var windows = new List<IntPtr>();
foreach (Process p in processes)
{
IEnumerable<IntPtr> w = GetRootWindowsOfProcess(p.Id);
windows.AddRange(w);
}
}
private static IEnumerable<IntPtr> GetRootWindowsOfProcess(int pid)
{
IEnumerable<IntPtr> rootWindows = GetChildWindows(IntPtr.Zero);
var dsProcRootWindows = new List<IntPtr>();
foreach (IntPtr hWnd in rootWindows)
{
uint lpdwProcessId;
GetWindowThreadProcessId(hWnd, out lpdwProcessId);
if (lpdwProcessId == pid)
dsProcRootWindows.Add(hWnd);
}
return dsProcRootWindows;
}
private static IEnumerable<IntPtr> GetChildWindows(IntPtr parent)
{
var result = new List<IntPtr>();
GCHandle listHandle = GCHandle.Alloc(result);
try
{
var childProc = new Win32Callback(EnumWindow);
EnumChildWindows(parent, childProc, GCHandle.ToIntPtr(listHandle));
}
finally
{
if (listHandle.IsAllocated)
listHandle.Free();
}
return result;
}
private static bool EnumWindow(IntPtr handle, IntPtr pointer)
{
GCHandle gch = GCHandle.FromIntPtr(pointer);
var list = gch.Target as List<IntPtr>;
if (list == null)
{
throw new InvalidCastException("GCHandle Target could not be cast as List<IntPtr>");
}
list.Add(handle);
// You can modify this to check to see if you want to cancel the operation, then return a null here
return true;
}
Now as one of the commenter's mentioned, you shouldn't have multiple threads doing GUI work. One thread should be doing the GUI drawing while other threads do the actual other work.
The Window class checks that the current application's dispatcher is the current thread's dispatcher, if it is then it is added to the Windows collection. It doesn't look like these other windows are exposed in a public collection but there is an internal property on Application, NonAppWindowsInternal that has the windows.
I would always create UI objects on a single UI thread. If you do so, you will have access to all the Window objects via Application.Current.Windows.
I'm unsure of this solution but it is what I found to be the closest to one.
Try getting the proceses:
using System.Diagnostics;
Process[] processlist = Process.GetProcesses();
foreach (Process process in processlist)
{
if (!String.IsNullOrEmpty(process.MainWindowTitle))
{
Console.WriteLine("Process: {0} ID: {1} Window title: {2}", process.ProcessName, process.Id, process.MainWindowTitle);
}
}
If this doesn't help, try using Process.GetProcessesByName("ApplicationName") and see what it returns.
It may also help to look at this solution and the MSDN class page and the available methods in it.
i want to do this... IF notepad is in the foreground it opens the calculator... if another program is open does nothing... the notepad is oepn manualy... "Start, Notepad"... i have this code to "see" if notepad is open... dont know how to continue D: i know i have to use
if (switch == 0)
{
if (SOMETHING == "Notepad")
{
var switch = 1 //so it doesnt enters in a loop
OPEN CALCULATOR //irrelevant, i may use another part of otrher code that is already working
}
}
the "switch" variable is going to be 0 from the beginning of the code, so that is going to work (hope)
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll", SetLastError = true)]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
Process GetActiveProcess()
{
IntPtr hwnd = GetForegroundWindow();
uint pid;
GetWindowThreadProcessId(hwnd, out pid);
Process p = Process.GetProcessById((int)pid);
return p;
}
the problem is that i dont know what to put on "SOMETHING" to use the rest of the code, and Where or How to use the If...
You can do:
Process[] notePadProcesses = Process.GetProcessesByName("notepad.exe");
IntPtr activeWindowHandle = GetForegroundWindow();
if (notePadProcesses != null && notePadProcesses.Length > 0
&& notePadProcesses.Any(p=>p.MainWindowHandle == activeWindowHandle))
{
// notepad is open in the foreground.
switch = 1;
// OPEN Calculator or whatever you need to.
}
else
{
// notepad is either not open, or not open in the foreground.
}
basically we use the C# friendly Process class to find all the open notepad processes.
Then find if it is an active process and go from there.
please be careful using activewindow logic, because many a time, they result in race conditions where by the time you determine a process is active and try to do something, it may no longer be an active process. tread carefully.
How can I programmatically detect if a thread has windows handles on it for a given process?
spy++ gives me this information but I need to do it programmatically.
I need to do this in C#, however the .net diagnostics libs don't give me this information. I imagine spy++ is using some windows api call that I don't know about.
I have access to the code of the system I'm trying to debug. I want to embed some code called by a timer periodically that will detect how many thread contain windows handles and log this info.
thanks
I believe you can use win api functions: EnumWindowsProc to iterate through window handles and GetWindowThreadProcessId to get the thread id and process id associated with given window handle
Please check if an example below would work for you:
this code iterates through processes and threads using System.Diagnostics; for each thread ID I'm calling GetWindowHandlesForThread function (see code below)
foreach (Process procesInfo in Process.GetProcesses())
{
Console.WriteLine("process {0} {1:x}", procesInfo.ProcessName, procesInfo.Id);
foreach (ProcessThread threadInfo in procesInfo.Threads)
{
Console.WriteLine("\tthread {0:x}", threadInfo.Id);
IntPtr[] windows = GetWindowHandlesForThread(threadInfo.Id);
if (windows != null && windows.Length > 0)
foreach (IntPtr hWnd in windows)
Console.WriteLine("\t\twindow {0:x}", hWnd.ToInt32());
}
}
GetWindowHandlesForThread implementation:
private IntPtr[] GetWindowHandlesForThread(int threadHandle)
{
_results.Clear();
EnumWindows(WindowEnum, threadHandle);
return _results.ToArray();
}
private delegate int EnumWindowsProc(IntPtr hwnd, int lParam);
[DllImport("user32.Dll")]
private static extern int EnumWindows(EnumWindowsProc x, int y);
[DllImport("user32.dll")]
public static extern int GetWindowThreadProcessId(IntPtr handle, out int processId);
private List<IntPtr> _results = new List<IntPtr>();
private int WindowEnum(IntPtr hWnd, int lParam)
{
int processID = 0;
int threadID = GetWindowThreadProcessId(hWnd, out processID);
if (threadID == lParam) _results.Add(hWnd);
return 1;
}
result of the code above should dump into console smth like this:
...
process chrome b70
thread b78
window 2d04c8
window 10354
...
thread bf8
thread c04
...