Click here to Skip to main content
15,894,362 members
Articles / Desktop Programming / Win32

Mirror keys for multiboxing MMORPG games like WOW/LOTRO

Rate me:
Please Sign up or sign in to vote.
5.00/5 (1 vote)
7 Mar 2013CPOL5 min read 20.7K   800   3  
Raw input 64-bit .NET classes.
Public Class Processes
    Private Shared SecondPollTimeToDetectProcessClosingsAndOpenings As Integer = 5
    Private WithEvents bwCheckProcesses As System.ComponentModel.BackgroundWorker = New System.ComponentModel.BackgroundWorker
    Public WithEvents ObjectCreated As New SystemEvent(SystemEvents.EVENT_OBJECT_CREATE)
    Public WithEvents ObjectDestroyed As New SystemEvent(SystemEvents.EVENT_OBJECT_DESTROY)
    Public Event ProcessClosedEvent(ByVal processId As Integer)
    Public Event ProcessOpenedEvent(ByVal processId As Integer)
    Public Event ProcessListChangedNames(ByVal names() As String)
    Public Event ProcessListChangedTitles(ByVal titles() As String)
    Private ProcessList As New System.Collections.SortedList
    'Private fIdentity As Byte() = (New Guid).ToByteArray
    Private ProcessNames As New System.Collections.ArrayList
    Private ProcessTitles As New System.Collections.ArrayList
    Private ProcessListAll As New System.Collections.Hashtable
    Private ProcessNamesAll As New System.Collections.ArrayList
    Private ProcessTitlesAll As New System.Collections.ArrayList
    Private ProcessNamesPrev As String = ""
    Private ProcessTitlesPrev As String = ""
    Private LastChecked As DateTime = New DateTime(0)
    Private LastCheckDenied As Boolean = False
    Private LastCheckedHwnd As String = "0000000000000000"
    Private LastCheckedHwndAttempted As String = "8888888888888888"

    Public Sub OnObjectCreated(ByVal hWinEventHook As IntPtr, ByVal eventType As UInteger, ByVal hwnd As IntPtr, ByVal idObject As Integer, ByVal idChild As Integer, ByVal dwEventThread As UInteger, ByVal dwmsEventTime As UInteger) Handles ObjectCreated.SystemEvent
        'ProcessListAll.Clear()
        'Dim mProcesses() As System.Diagnostics.Process = System.Diagnostics.Process.GetProcesses
        'For x As Integer = 0 To mProcesses.Length - 1
        '    If Not ProcessListAll.Contains(mProcesses(x).MainWindowHandle) Then
        '        ProcessListAll.Add(mProcesses(x).MainWindowHandle, Nothing)
        '    End If
        'Next
        'If ProcessListAll.Contains(hwnd) Then
        '    CheckProcesses()
        'End If
        If idChild <> 0 Then
            'Debug.WriteLine(hWinEventHook.ToString("X8") & Chr(9) & eventType.ToString("X8") & Chr(9) & hwnd.ToString("X8") & Chr(9) & idObject.ToString("X8") & Chr(9) & idChild.ToString("X8") & Chr(9) & dwEventThread.ToString("X8") & Chr(9) & dwmsEventTime.ToString("X8"))
            CheckProcesses(hwnd.ToString("X16"))
        End If
    End Sub

    Public Sub OnObjectDestroyed(ByVal hWinEventHook As IntPtr, ByVal eventType As UInteger, ByVal hwnd As IntPtr, ByVal idObject As Integer, ByVal idChild As Integer, ByVal dwEventThread As UInteger, ByVal dwmsEventTime As UInteger) Handles ObjectDestroyed.SystemEvent
        If ProcessListAll.Contains(hwnd) Then
            CheckProcesses()
        End If
    End Sub

    Private Sub CheckProcesses(Optional ByVal Hwnd As String = "FFFFFFFFFFFFFFFF")
        Dim last As New TimeSpan(Now.Ticks - LastChecked.Ticks)
        If last.TotalSeconds < SecondPollTimeToDetectProcessClosingsAndOpenings Then
            LastCheckDenied = True
            LastCheckedHwndAttempted = Hwnd
        Else
            LastChecked = Now()
            LastCheckDenied = False
            If LastCheckedHwndAttempted <> LastCheckedHwnd Then
                'Debug.WriteLine("checking... " & LastCheckedHwndAttempted & Chr(9) & LastCheckedHwnd)
                LastCheckedHwnd = Hwnd
                LastCheckedHwndAttempted = Hwnd
                Try
                    ProcessListAll.Clear()
                    Dim mProcesses() As System.Diagnostics.Process = System.Diagnostics.Process.GetProcesses
                    For x As Integer = 0 To mProcesses.Length - 1
                        If (mProcesses(x).MainWindowHandle <> IntPtr.Zero) AndAlso (Not ProcessListAll.Contains(mProcesses(x).MainWindowHandle)) Then
                            ProcessListAll.Add(mProcesses(x).MainWindowHandle, Nothing)
                        End If
                        Dim thisName As String = CStr(mProcesses(x).ProcessName.Trim)
                        If (Not thisName Is Nothing) AndAlso (thisName.Length > 0) AndAlso (Not ProcessNamesAll.Contains(thisName)) Then
                            ProcessNamesAll.Add(thisName)
                        End If
                        ProcessNamesAll.Sort()
                        Dim thisTitle As String = CStr(mProcesses(x).MainWindowTitle.Trim)
                        If (Not thisTitle Is Nothing) AndAlso (thisTitle.Length > 0) AndAlso (Not ProcessTitlesAll.Contains(thisTitle)) Then
                            ProcessTitlesAll.Add(thisTitle)
                        End If
                        ProcessTitlesAll.Sort()
                    Next
                Catch ex As Exception
                    Debug.WriteLine(ex.ToString)
                End Try
                Try
                    Dim newProcessList As System.Collections.SortedList = New System.Collections.SortedList
                    Dim mProcesses(ProcessNames.Count - 1)() As System.Diagnostics.Process
                    For x As Integer = 0 To ProcessNames.Count - 1
                        Dim thisName As String = CStr(ProcessNames.Item(x))
                        mProcesses(x) = System.Diagnostics.Process.GetProcessesByName(thisName)
                        For i = 0 To mProcesses(x).Length - 1
                            If ProcessTitles.Contains(mProcesses(x)(i).MainWindowTitle) Then
                                newProcessList.Add(mProcesses(x)(i).Id, mProcesses(x)(i))
                            End If
                        Next
                    Next
                    For Each processId As Integer In newProcessList.Keys
                        If Not ProcessList.ContainsKey(processId) Then
                            ProcessList.Add(processId, newProcessList(processId))
                            OnProcessChange(1, processId)
                        End If
                    Next
                    Dim k(ProcessList.Count - 1) As Integer
                    ProcessList.Keys.CopyTo(k, 0)
                    For i = 0 To k.Length - 1
                        If Not newProcessList.ContainsKey(k(i)) Then
                            ProcessList.Item(k(i)) = Nothing
                            ProcessList.Remove(k(i))
                            OnProcessChange(0, k(i))
                        End If
                    Next
                Catch ex As Exception
                    Debug.WriteLine(ex.ToString)
                End Try
                ProcessNamesAll.Sort()
                ProcessTitlesAll.Sort()
                Dim names As String = Microsoft.VisualBasic.Join(ProcessNamesAll.ToArray, ",")
                Dim titles As String = Microsoft.VisualBasic.Join(ProcessTitlesAll.ToArray, ",")
                If ProcessNamesPrev <> names Then
                    ProcessNamesPrev = names
                    OnProcessChange(2, names)
                End If
                If ProcessTitlesPrev <> titles Then
                    ProcessTitlesPrev = titles
                    OnProcessChange(3, titles)
                End If
            End If
        End If
    End Sub

    Public Sub OnProcessChange(ByVal progress As Integer, ByVal e As Object)
        If Progress = 0 Then
            If ((Not ProcessClosedEventEvent Is Nothing) AndAlso (ProcessClosedEventEvent.GetInvocationList.Length > 0)) Then
                RaiseEvent ProcessClosedEvent(CInt(e))
            End If
        ElseIf progress = 1 Then
            If ((Not ProcessOpenedEventEvent Is Nothing) AndAlso (ProcessOpenedEventEvent.GetInvocationList.Length > 0)) Then
                RaiseEvent ProcessOpenedEvent(CInt(e))
            End If
        ElseIf progress = 2 Then
            If ((Not ProcessListChangedNamesEvent Is Nothing) AndAlso (ProcessListChangedNamesEvent.GetInvocationList.Length > 0)) Then
                RaiseEvent ProcessListChangedNames(CStr(e).Split(","c))
            End If
        ElseIf progress = 3 Then
            If ((Not ProcessListChangedTitlesEvent Is Nothing) AndAlso (ProcessListChangedTitlesEvent.GetInvocationList.Length > 0)) Then
                RaiseEvent ProcessListChangedTitles(CStr(e).Split(","c))
            End If
        End If
    End Sub


    Private Sub CheckProcesses(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bwCheckProcesses.DoWork
        While True
            If bwCheckProcesses.CancellationPending = True Then
                e.Cancel = True
                Exit While
            Else

            End If
            System.Threading.Thread.Sleep(SecondPollTimeToDetectProcessClosingsAndOpenings * 1000)
        End While
    End Sub

    'Public Sub OnProcessChange(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles bwCheckProcesses.ProgressChanged
    '    If e.ProgressPercentage = 0 Then
    '        If ((Not ProcessClosedEventEvent Is Nothing) AndAlso (ProcessClosedEventEvent.GetInvocationList.Length > 0)) Then
    '            RaiseEvent ProcessClosedEvent(CInt(e.UserState))
    '        End If
    '    ElseIf e.ProgressPercentage = 1 Then
    '        If ((Not ProcessOpenedEventEvent Is Nothing) AndAlso (ProcessOpenedEventEvent.GetInvocationList.Length > 0)) Then
    '            RaiseEvent ProcessOpenedEvent(CInt(e.UserState))
    '        End If
    '    ElseIf e.ProgressPercentage = 2 Then
    '        If ((Not ProcessListChangedNamesEvent Is Nothing) AndAlso (ProcessListChangedNamesEvent.GetInvocationList.Length > 0)) Then
    '            RaiseEvent ProcessListChangedNames(CStr(e.UserState).Split(","c))
    '        End If
    '    ElseIf e.ProgressPercentage = 3 Then
    '        If ((Not ProcessListChangedTitlesEvent Is Nothing) AndAlso (ProcessListChangedTitlesEvent.GetInvocationList.Length > 0)) Then
    '            RaiseEvent ProcessListChangedTitles(CStr(e.UserState).Split(","c))
    '        End If
    '    End If
    'End Sub

    Public Sub New(Optional ByVal Names As System.Collections.ArrayList = Nothing, Optional ByVal Titles As System.Collections.ArrayList = Nothing)
        If Not Names Is Nothing Then ProcessNames = Names
        If Not Titles Is Nothing Then ProcessTitles = Titles
        bwCheckProcesses.WorkerReportsProgress = True
        bwCheckProcesses.WorkerSupportsCancellation = True
        bwCheckProcesses.RunWorkerAsync()
    End Sub

    Public Sub AddProcessName(ByVal name As String)
        If Not ProcessNames.Contains(name) Then
            ProcessNames.Add(name)
        End If
    End Sub

    Public Sub RemoveProcessName(ByVal name As String)
        If ProcessNames.Contains(name) Then
            ProcessNames.Remove(name)
        End If
    End Sub

    Public Sub AddProcessTitle(ByVal title As String)
        If Not ProcessTitles.Contains(title) Then
            ProcessTitles.Add(title)
        End If
    End Sub

    Public Sub RemoveProcessTitle(ByVal title As String)
        If ProcessTitles.Contains(title) Then
            ProcessTitles.Remove(title)
        End If
    End Sub

    Default Public ReadOnly Property process(ByVal index As Integer) As Process
        Get
            Dim result As Process = Nothing
            If index >= 0 AndAlso index < ProcessList.Count Then
                Try
                    result = DirectCast(ProcessList.GetByIndex(index), Process)
                Catch ex As Exception
                    Debug.WriteLine(ex.ToString)
                End Try
            End If
            Return result
        End Get
    End Property

    Public ReadOnly Property length() As Integer
        Get
            Return ProcessList.Count
        End Get
    End Property

End Class

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions