Author Topic: Get Active Window's Executable Path (obsolete)  (Read 9282 times)

Exergist

  • Global Moderator
  • Sr. Member
  • *****
  • Posts: 405
  • Ride the lightning
Get Active Window's Executable Path (obsolete)
« on: March 29, 2018, 12:03:59 PM »
Sometimes you may want to access or make modifications to files or folders inside the root directory of a given game or application while it is running. The below C# inline function provides you the file path to the active window's executable, which can then be manipulated to find whatever files you need to modify or other tasks you'd like to perform. For demonstration purposes I've placed the function inside a small loop so that you can see the path retrieval in action across multiple window selections.

Cheers!  :)

VoiceAttack Actions
Code: [Select]
Start Loop : Repeat 5 Times
Inline C# Function: Retrieve active window's executable file path, wait until execution finishes
Write '[Blue] {TXT:~~ActiveProcessID} = {TXT:~~ActiveProcessExePath}' to log
Pause 1 second
End Loop

C# Inline Function
Referenced Assemblies: System.dll; System.Core.dll; System.Management.dll
Code: [Select]
using System;
using System.Linq;
using System.Management;
using System.Runtime.InteropServices;

public class VAInline
{
public void main()
{
IntPtr hwnd = GetForegroundWindow(); // Initialize integer pointer, retrieve the active window's handle, and store it within the pointer
uint ProcessID; // Initialize unsigned integer
GetWindowThreadProcessId(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
string myPath = GetProcessPath((int)ProcessID); // Obtain active window's executable file path and store it in string variable
VA.SetText("~~ActiveProcessExePath", myPath); // Send the active window's executable file path back to VoiceAttack as a text variable
hwnd = IntPtr.Zero; // Set hwnd to IntPtr.Zero (just for good measure)
}

// Function for retrieving executable file path associated with inputted process ID
public string GetProcessPath(int processId)
{
string MethodResult = "";
try
{
string Query = "SELECT ExecutablePath FROM Win32_Process WHERE ProcessId = " + processId;
using (ManagementObjectSearcher mos = new ManagementObjectSearcher(Query))
{
using (ManagementObjectCollection moc = mos.Get())
{
string ExecutablePath = (from mo in moc.Cast<ManagementObject>() select mo["ExecutablePath"]).First().ToString();
MethodResult = ExecutablePath;
}
}
}
catch //(Exception ex)
{
VA.WriteToLog("Error encountered within inline function during executable file path retrieval.");
}
return MethodResult;
}

[DllImport("user32.dll")]
public static extern IntPtr GetWindowThreadProcessId(IntPtr hWnd, out uint ProcessId);

[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
}

// 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
« Last Edit: May 20, 2019, 10:05:21 AM by Exergist »

Exergist

  • Global Moderator
  • Sr. Member
  • *****
  • Posts: 405
  • Ride the lightning
Re: Get Active Window's Executable Path
« Reply #1 on: December 08, 2018, 09:18:32 PM »
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

Code: [Select]
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
« Last Edit: January 30, 2019, 07:10:49 PM by Exergist »

Korfio

  • Guest
Re: Get Active Window's Executable Path
« Reply #2 on: January 23, 2019, 05:00:39 PM »
change
VA.SetText("~~ActiveProcessExePath", process.GetMainModuleFileName)

to
VA.SetText("~~ActiveProcessExePath", process.GetMainModuleFileName().ToString())

Pfeil

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 4782
  • RTFM
Re: Get Active Window's Executable Path
« Reply #3 on: January 23, 2019, 06:07:38 PM »
It needs to be
Code: [Select]
VA.SetText("~~ActiveProcessExePath", process.GetMainModuleFileName());to compile, yes, but is there a reason for using ToString() on this method, which already returns a string?

Exergist

  • Global Moderator
  • Sr. Member
  • *****
  • Posts: 405
  • Ride the lightning
Re: Get Active Window's Executable Path
« Reply #4 on: January 30, 2019, 07:11:14 PM »
Fixed. Not sure how that one got through  :o

Exergist

  • Global Moderator
  • Sr. Member
  • *****
  • Posts: 405
  • Ride the lightning
Re: Get Active Window's Executable Path
« Reply #5 on: May 20, 2019, 08:32:19 AM »
Thanks to advances in VoiceAttack functionality the {ACTIVEWINDOWPROCESSID} and {ACTIVEWINDOWPATH} tokens effectively obsolete the functionality I posted.

So if you want to duplicate the original loop example in a much simpler manner (no inline function required) all you have to do is this:

Code: [Select]
Start Loop : Repeat 5 Times
Write [Blue] '{ACTIVEWINDOWPROCESSID} = {ACTIVEWINDOWPATH}' to log
Pause 1 second
End Loop