Updates: Inline function now better applies to both 32 and 64-bit processes, and management of the window handles (IntPtr and associated memory) should now be better.
C# Inline Function
Referenced Assemblies: System.dll; System.Core.dll; System.Management.dll
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
public class VAInline
{
public void main()
{
int PtrSize = Marshal.SizeOf(typeof(IntPtr)); // Obtain memory size for IntPtr
IntPtr hwnd = Marshal.AllocHGlobal(PtrSize * 5); // Allocate unmanaged memory for IntPtr hwnd
try // Attempt the following code...
{
Marshal.WriteIntPtr(hwnd, GetForegroundWindow()); // Get the handle of the foreground window (via external function) and write to unmanaged memory
uint ProcessID; // Initialize unsigned integer
GetWindowThreadProcessId(Marshal.ReadIntPtr(hwnd), out ProcessID); // Call external function for obtaining the process ID associated with the inputted window handle
VA.SetText("~~ActiveProcessID", ProcessID.ToString()); // Send active window's process ID back to VoiceAttack as a text variable
var process = Process.GetProcessById(Convert.ToInt32(ProcessID)); // Get process associated with ProcessID and store in variant
VA.SetText("~~ActiveProcessExePath", process.GetMainModuleFileName()); // Send the active window's executable file path back to VoiceAttack as a text variable
}
catch
{
VA.WriteToLog("Error getting file path", "red");
}
finally
{
Marshal.FreeHGlobal(hwnd); // Free the allocated unmanaged memory associated with hwnd
hwnd = IntPtr.Zero; // Set hwnd to IntPtr.Zero (just for good measure)
}
}
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
public static extern IntPtr GetWindowThreadProcessId(IntPtr hWnd, out uint ProcessId);
}
// Extension class for retrieving a process's executable file path (from Bruno Zell)
internal static class Extensions
{
[DllImport("Kernel32.dll")]
private static extern uint QueryFullProcessImageName([In] IntPtr hProcess, [In] uint dwFlags, [Out] StringBuilder lpExeName, [In, Out] ref uint lpdwSize);
public static string GetMainModuleFileName(this Process process, int buffer = 1024)
{
var fileNameBuilder = new StringBuilder(buffer);
uint bufferLength = (uint)fileNameBuilder.Capacity + 1;
return QueryFullProcessImageName(process.Handle, 0, fileNameBuilder, ref bufferLength) != 0 ? fileNameBuilder.ToString() : null;
}
}
// References:
// https://stackoverflow.com/questions/6569405/how-to-get-active-process-name-in-c
// https://stackoverflow.com/questions/5497064/c-how-to-get-the-full-path-of-running-process
// https://stackoverflow.com/questions/6093449/proper-intptr-use-in-c-sharp