How do I queue processes on C#? [duplicate] - c#

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");

Related

Evaluate if drive is in use

I'd like to evaluate wether a drive is in use (if I'm not mistaken this means that some read/write stuff is happening with the drive) using C#. I wouldn't mind for a solution using bash scripts or similiar either, as I could use them in a C# application. I already found a question regarding bash scripts here, but couldn't solve my problem with the answers given.
I considered to use the DriveInfo class already, however it didn't seem to have anything useful for me. I wondered wether I could use the IsReady property from DriveInfo, because I guessed that it wouldn't be ready while it is read/written, but this attempt seems rather botchy to me.
However I still tried it:
private static bool IsDriveInUse ()
{
var drive = DriveInfo.GetDrives ().FirstOrDefault(info => info.Name.StartsWith(DRIVE_LETTER.ToString()));
return drive != null && !drive.IsReady;
}
But it didn't work (it returned false while I played music from my drive).
An optimal solution for me would be a function that tells me wether the drive was in use in a specific span of time (let's stick to the name IsDriveInUse). That means that if the time was for example 60 seconds, IsDriveInUse should return true if 5 seconds before the function call content from the drive was read and false if there was no read/write action in the passed 60 seconds.
EDIT To specify what exactly I mean by in use, I'll try to explain what I'm trying to do. I am writing a tool, which automatically spins down my hard drive, when it's been idle or when I press a keyboard shortcut. I managed to spin it down programmatically (even though either the windows integrated tool nor other tools I found were able to do that, but that's another problem). However, it now spins down the hard drive every minute, regardless of wether it's currently in use or not. That means, if I play music from my hard drive, it's still spinned down, just to spin up directly after it, which doesn't decrease noise development.
I hope this clarified the matter.
EDIT I now tried using the FSCTL_LOCK_VOLUME control code (I couldn't find a value for IOCTL_DISK_PERFORMANCE), but it still returned false for IsDriveInUse() while I was playing music. Furthermore it caused windows to directly spin the drive up again as I spinned it down (probably because the releasing made Windows think that something was using the drive). This is what I tried:
public class DriveManager
{
public const int FSCTL_LOCK_VOLUME = 0x00090018;
public const int FSCTL_UNLOCK_VOLUME = 0x0009001c;
[DllImport ("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CreateFile (
string lpFileName, uint dwDesiredAccess, uint dwShareMode, IntPtr lpSecurityAttributes,
uint dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile);
[return: MarshalAs (UnmanagedType.Bool)]
[DllImport ("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool DeviceIoControl (
[In] SafeFileHandle hDevice,
[In] int dwIoControlCode, [In] IntPtr lpInBuffer,
[In] int nInBufferSize, [Out] IntPtr lpOutBuffer,
[In] int nOutBufferSize, out int lpBytesReturned,
[In] IntPtr lpOverlapped);
public static SafeFileHandle CreateFileR (string device)
{
string str = device.EndsWith (#"\") ? device.Substring (0, device.Length - 1) : device;
return new SafeFileHandle (
CreateFile (#"\\.\" + str, WinntConst.GENERIC_READ, WinntConst.FILE_SHARE_READ, IntPtr.Zero,
WinntConst.OPEN_EXISTING, WinntConst.FILE_ATTRIBUTE_NORMAL, IntPtr.Zero), true);
}
internal class WinntConst
{
// Fields
internal static uint FILE_ATTRIBUTE_NORMAL = 0x80;
internal static uint FILE_SHARE_READ = 1;
internal static uint GENERIC_READ = 0x80000000;
internal static uint OPEN_EXISTING = 3;
}
public static bool IsDriveInUse (string deviceName)
{
var handle = CreateFileR (deviceName);
var buffer = Marshal.AllocHGlobal (sizeof (int));
try
{
return
DeviceIoControl (handle,
FSCTL_LOCK_VOLUME,
IntPtr.Zero,
0,
buffer,
sizeof(int),
out var bytesReturned,
IntPtr.Zero
);
}
finally
{
var sessionId = Marshal.ReadInt32 (buffer);
Marshal.FreeHGlobal (buffer);
handle.Close ();
}
}
And the implementation:
private static bool IsDriveInUse () => DriveManager.IsDriveInUse ($#"{DRIVE_LETTER}:\");
Maybe it helps to see the part in which I'm spinning the disc down as well (I used Smartmontools for this):
internal static class Program
{
private const string PROGRAM_PATH = #"External\smartctl.exe";
private const string ARGUMENTS_SHUTDOWN = #"-s standby,now {0}:";
private const char DRIVE_LETTER = 'd';
public static void Main (string [] args)
{
InitializeHotKey ();
Console.WriteLine ("Hotkey registered!");
while (true)
{
Thread.Sleep (60000);
if (!IsDriveInUse ())
ShutDownDrive (true);
}
}
private static bool IsDriveInUse () => DriveManager.IsDriveInUse ($#"{DRIVE_LETTER}:\");
private static void InitializeHotKey ()
{
HotKeyManager.RegisterHotKey (Keys.D, KeyModifiers.Alt | KeyModifiers.Control);
HotKeyManager.HotKeyPressed += HotKeyPressed;
}
private static void HotKeyPressed (object sender, HotKeyEventArgs hotKeyEventArgs) => ShutDownDrive (true);
private static void ShutDownDrive (bool withDialog = false)
{
Process process;
(process = new Process
{
StartInfo = new ProcessStartInfo
{
WindowStyle = ProcessWindowStyle.Hidden,
FileName = PROGRAM_PATH,
Arguments = string.Format (ARGUMENTS_SHUTDOWN, DRIVE_LETTER)
}
}).Start ();
process.WaitForExit ();
process.Close ();
if (withDialog)
Console.WriteLine ("Drive shut down!");
}
}
Perhaps you could use the Windows Performance Counter relevant to your drive ?
"Disk Read/sec" seems quite relevant for what youhave in mind.
In .Net, the counters are available via System.Diagnostics.PerformanceCounter
see there :
https://msdn.microsoft.com/en-us/library/system.diagnostics.performancecounter(v=vs.110).aspx

C# RegisterHotKey - Want to know which process invoked it [duplicate]

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
}
}

Get ALL open windows

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.

Starting process and storing handle to window

Would someone mind helping me out with a problem I've been stuck on for a bit? I'm using C# and trying to start a couple processes, and later move those windows to separate monitors.
So far this was the main idea:
Process p1 = Process.Start(#"1.pptx");
Process p2 = Process.Start(#"2.pptx");
SetWindowPos(p1.MainWindowHandle, -1,
0,
0,
100,
100,
SWP_SHOWWINDOW);
SetWindowPos(p2.MainWindowHandle, -1,
200,
200,
100,
100,
SWP_SHOWWINDOW);
But after trying a bunch of different things, I haven't been able to get it to work. Could anyone give me some pointers?
As a side note which is confusing me, if I print those to process IDs (p1, p2), and then run this code:
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);
}
}
those process IDs don't exist. I know there must be something simple I'm missing...?
UPDATE: The reason for the problem above is that for some reason the MainWindowTitle didn't have a value, so it wasn't printing the pid.
When you use Process.Start to open a document this is handled by the shell. The shell looks in the file association registry and takes whatever steps are needed to open the document.
This may involve creating a new process but equally may not. Office applications will typically reuse already open processes to open new documents. That's what is happening here.
And when this does happen, when no new process is started, the shell returns 0 for the new process handle. That's reflected back to the .net Process object. It explains why you have no main window handle.
So fundamentally your basic approach is flawed. Using Process.Start will not yield window handles for these documents. You'll have to find another way to locate these windows. For instance EnumWindows or a CBT hook. Or perhaps COM automation is the right solution.
As an aside it seems that you did not check for errors when you called SetWindowPos. That would have helped you work this out more quickly. Always check return values when calling Win32 functions.
For those who are still looking for an answer, this is what I did to get it working.
First, use EnumWindows to get a handle to each open window before starting any new process. Then start your process, then check all windows again making sure they're visible and have window text. If you have only 1 new process, chances are that's your new window. If not, I've tried it 3 times before failing. So far, the code has worked great.
Here is the code for helper functions/Win32 API calls.
public delegate bool EnumedWindow(IntPtr handleWindow, ArrayList handles);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumWindows(EnumedWindow lpEnumFunc, ArrayList lParam);
public static ArrayList GetWindows()
{
ArrayList windowHandles = new ArrayList();
EnumedWindow callBackPtr = GetWindowHandle;
EnumWindows(callBackPtr, windowHandles);
return windowHandles;
}
private static bool GetWindowHandle(IntPtr windowHandle, ArrayList windowHandles)
{
windowHandles.Add(windowHandle);
return true;
}
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool IsWindowVisible(IntPtr hWnd);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
const int SWP_SHOWWINDOW = 0x0040;
[DllImport("user32.dll", EntryPoint = "SetWindowPos", SetLastError = true)]
public static extern Boolean SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int Y, int cx, int cy, int wFlags);
My main logic then went something like this (adjust as necessary):
List<IntPtr> alreadyOpenWindows = new List<IntPtr>();
foreach (IntPtr ip in GetWindows())
{
alreadyOpenWindows.Add(ip);
}
Process.Start("your command here");
System.Threading.Thread.Sleep(1000);
foreach (IntPtr ip in GetWindows())
{
// To consider it a new window, it must be visible, it must not have been open previously, and it must have window text length > 0
if (IsWindowVisible(ip) && alreadyOpenWindows.Contains(ip) == false)
{
StringBuilder windowText = new StringBuilder();
windowText.Length = 256;
GetWindowText(ip, windowText, windowText.Length);
if (windowText.Length > 0)
{
numNewWindows++;
handle = ip;
// break if your confident there will only be one new window opened
}
}
}
// Check numNewWindows if you'd like
if (handle != IntPtr.Zero)
{
SetWindowPos(handle, -1,
this.GetScreen().WorkingArea.X,
this.GetScreen().WorkingArea.Y,
this.GetScreen().WorkingArea.Width,
this.GetScreen().WorkingArea.Height,
SWP_SHOWWINDOW);
}

How to Get Active Process Name in C#?

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
}
}

Categories