Author Topic: Help getting active window's executable file path  (Read 7846 times)

Exergist

  • Global Moderator
  • Sr. Member
  • *****
  • Posts: 405
  • Ride the lightning
Help getting active window's executable file path
« on: March 15, 2017, 02:37:58 PM »
Thanks to the VoiceAttack help document and the interwebs I found a way to use a VoiceAttack VB.net inline function to obtain the filepath for the active window's executable file. The code is as such:

Referenced Assemblies: System.dll;System.Core.dll;System.Data.dll;System.Data.DataSetExtensions.dll;System.Deployment.dll;System.Drawing.dll;System.Net.Http.dll;System.Windows.Forms.dll;System.Xml.dll;System.Xml.Linq.dll
Code: [Select]
'Adapted from code by jay20aiii ==> http://www.vbforums.com/showthread.php?668460-Get-path-of-active-window
Imports Microsoft.VisualBasic
Imports System
Imports System.Collections
Imports System.Collections.Generic
Imports System.Data
Imports System.Drawing
Imports System.Diagnostics
Imports System.Windows.Forms
Imports System.Linq
Imports System.Xml.Linq
Imports System.Threading.Tasks

Public Class VAInline

Private Declare Function GetWindowThreadProcessId Lib "user32.dll" (ByVal hWnd As IntPtr, ByRef lpdwProcessId As UInt32) As UInt32
Private Declare Function GetForegroundWindow Lib "user32.dll" Alias "GetForegroundWindow" () As IntPtr

    Public Sub Main()

            'Get the ForeGround Window
            Dim hWnd As IntPtr = GetForegroundWindow()
            Dim ProcessID As UInt32 = Nothing
            'Get the Window's Process using it's ID (obtained using the GetWindowThreadProcessId API)
            GetWindowThreadProcessId(hWnd, ProcessID)
            Dim Proc As Process = Process.GetProcessById(ProcessID)
               
            'Send the filename back to VoiceAttack and store in a text variable
            VA.SetText("application path", Proc.MainModule.FileName)

    End Sub

End Class

This seems to work great for getting the executable filepath for 32 bit applications. However it doesn't work for 64 bit applications.

I have nearly zero knowledge about VB.net (and C#), and I was hoping that the community might help me figure out how to get the executable filepath for a 64 bit application through VoiceAttack.

Thanks!

Exergist

  • Global Moderator
  • Sr. Member
  • *****
  • Posts: 405
  • Ride the lightning
Re: Help getting active window's executable file path
« Reply #1 on: May 22, 2017, 12:46:39 PM »
After doing some more research I believe I found a way to obtain the file path for the active window's executable that works for both 32 and 64-bit applications. I've tested it alongside the earlier code I posted and the new code has no problems generating the active application's executable path. Sources are provided below. The outputs are VA text variables "active window process ID" and "active window executable path." Here is the VB.net inline function code:

Code: [Select]
Referenced Assemblies: System.dll;System.Core.dll;System.Data.dll;System.Data.DataSetExtensions.dll;System.Deployment.dll;System.Drawing.dll;System.Net.Http.dll;System.Windows.Forms.dll;System.Xml.dll;System.Xml.Linq.dll;System.Management.dll

'Leveraged Resources:
'https://stackoverflow.com/questions/5497064/c-how-to-get-the-full-path-of-running-process
'http://www.vbforums.com/showthread.php?668460-Get-path-of-active-window
'http://converter.telerik.com/

Imports Microsoft.VisualBasic
Imports System
Imports System.Collections
Imports System.Collections.Generic
Imports System.Data
Imports System.Drawing
Imports System.Diagnostics
Imports System.Windows.Forms
Imports System.Linq
Imports System.Xml.Linq
Imports System.Threading.Tasks
Imports System.Management

Public Class VAInline

    Private Declare Function GetForegroundWindow Lib "user32.dll" Alias "GetForegroundWindow" () As IntPtr
    Private Declare Function GetWindowThreadProcessId Lib "user32.dll" (ByVal hWnd As IntPtr, ByRef lpdwProcessId As UInt32) As UInt32

    Public Sub Main()

        'Get the ForeGround Window
        Dim hWnd As IntPtr = GetForegroundWindow()
        Dim ProcessID As UInt32 = Nothing
        'Get the Window's process ID (obtained using the GetWindowThreadProcessId API)
        GetWindowThreadProcessId(hWnd, ProcessID)

        'Send Window's Process ID back to VoiceAttack as a text variable
        VA.SetText("active window process ID", ProcessID)

        'Get the executable path for the Window using the Window's Process ID
        Dim MethodResult As String = ""
        Dim Query As String = "SELECT ExecutablePath FROM Win32_Process WHERE ProcessId = " + ProcessID.ToString()
        Try
            Using mos As New ManagementObjectSearcher(Query)
                Using moc As ManagementObjectCollection = mos.[Get]()
                    Dim ExecutablePath As String = (From mo In moc.Cast(Of ManagementObject)() Select mo("ExecutablePath")).First().ToString()
                    MethodResult = ExecutablePath
                End Using
            End Using
        Catch
            MessageBox.Show("catch")
         End Try

        'Send Window's executable path back to VoiceAttack as a text variable
        VA.SetText("active window executable path", MethodResult)

    End Sub

End Class

Hopefully others will have use for this as I did!  :)



Update: since posting the above content I've grown more accustomed with C# as opposed to VB.net, so below you will find a C# inline function that has the same functionality as the VB.net inline function shown above (though the C# code is slimmer).

Referenced Assemblies = System.dll;System.Core.dll;System.Management.dll
Code: [Select]
// Referenced Assemblies = System.dll;System.Core.dll;System.Management.dll

using System;
using System.Linq;
using System.Management;
using System.Runtime.InteropServices;

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

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

    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
    }

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

// 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: January 22, 2018, 10:06:12 AM by Exergist »