Foro de elhacker.net

Programación => .NET (C#, VB.NET, ASP) => Mensaje iniciado por: TrashAmbishion en 5 Septiembre 2016, 06:04 am



Título: Wait For Application To Load
Publicado por: TrashAmbishion en 5 Septiembre 2016, 06:04 am
Hola,

Quería saber sobre el funcionamiento de este Snippet publicado por Elektro para esperar a que una aplicación termine de cargar..

Código
  1.  
  2. Timer_CheckCPU.Tag = "photoshop"          'Nombre del proceso a chequear
  3. Timer_CheckCPU.Enabled = True
  4. While Not Timer_CheckCPU.Tag = ""
  5.         Application.DoEvents()
  6. End While
  7.  
  8.  
  9. #Region " Wait For Application To Load "
  10.  
  11.    Private Declare Function ReadProcessMemory Lib "kernel32" (ByVal hProcess As Integer, ByVal lpBaseAddress As Integer, ByVal lpBuffer As Integer, ByVal nSize As Integer, ByRef lpNumberOfBytesWritten As Integer) As Integer
  12.    Private WithEvents Timer_CheckCPU As New Timer
  13.  
  14.    Dim Memory_Value_Changed As Boolean
  15.    Dim CPU_Changed As Boolean
  16.    Dim CPU_Time As Boolean
  17.    Dim Running_Time As Boolean
  18.    Private _desiredTime_ms As Integer = 1500
  19.  
  20.    Private Sub Timer_CheckCPU_Tick(sender As Object, ev As EventArgs) Handles Timer_CheckCPU.Tick
  21.        Timer_CheckCPU.Enabled = False
  22.        Dim pProcess() As Process = Process.GetProcessesByName(Timer_CheckCPU.Tag)
  23.        Dim hprocess As Process = pProcess(0)
  24.        If hprocess Is Nothing Then
  25.            Running = False
  26.            Timer_CheckCPU.Enabled = True
  27.            Return
  28.        End If
  29.        Running = True
  30.        Memory = hprocess.PrivateMemorySize64
  31.        CPUTotal = hprocess.TotalProcessorTime.TotalMilliseconds
  32.  
  33.        If AllConditionsGood() Then
  34.            If Not (_countdown.IsRunning) Then
  35.                _countdown.Reset()
  36.                _countdown.Start()
  37.            End If
  38.            Dim _elapsed As Long = _countdown.ElapsedMilliseconds
  39.            If _elapsed >= _desiredTime_ms Then
  40.                Timer_CheckCPU.Tag = ""
  41.                Return
  42.            End If
  43.        Else
  44.            _countdown.Reset()
  45.        End If
  46.        Timer_CheckCPU.Enabled = True
  47.    End Sub
  48.  
  49.    Private Function AllConditionsGood() As Boolean
  50.        If CPU_Time Then Return False
  51.        If Memory_Value_Changed Then Return False
  52.        If Running_Time Then Return False
  53.        Return True
  54.    End Function
  55.  
  56.    Private _countdown As New Stopwatch
  57.  
  58.    Private _Running As Boolean = False
  59.    Public WriteOnly Property Running() As Boolean
  60.        Set(ByVal value As Boolean)
  61.            _Running = value
  62.            If value Then
  63.                Running_Time = False
  64.            Else
  65.                Running_Time = True
  66.            End If
  67.        End Set
  68.    End Property
  69.  
  70.    Private _CPUTotal As Double
  71.    Public WriteOnly Property CPUTotal() As Double
  72.        Set(ByVal value As Double)
  73.            CPU = value - _CPUTotal 'used cputime since last check
  74.            _CPUTotal = value
  75.        End Set
  76.    End Property
  77.  
  78.    Private _CPU As Double
  79.    Public WriteOnly Property CPU() As Double
  80.        Set(ByVal value As Double)
  81.            If value = 0 Then
  82.                CPU_Time = False
  83.            Else
  84.                CPU_Time = True
  85.            End If
  86.            _CPU = value
  87.        End Set
  88.    End Property
  89.  
  90.    Private _Memory As Long
  91.    Public WriteOnly Property Memory() As Long
  92.        Set(ByVal value As Long)
  93.            MemoryDiff = Math.Abs(value - _Memory)
  94.            _Memory = value
  95.        End Set
  96.    End Property
  97.  
  98.    Private _MemoryDiff As Long
  99.    Public WriteOnly Property MemoryDiff() As Long
  100.        Set(ByVal value As Long)
  101.            If value = _MemoryDiff Then
  102.                Memory_Value_Changed = False
  103.            Else
  104.                Memory_Value_Changed = True
  105.            End If
  106.            _MemoryDiff = value
  107.        End Set
  108.    End Property
  109.  
  110. #End Region

Necesito verificar los modulos de ese proceso una vez que termine de cargar.. pero no me funciona me devuelve menos modulos de los esperados..

Gracias de antemano


Título: Re: Wait For Application To Load
Publicado por: TrashAmbishion en 5 Septiembre 2016, 20:28 pm
Resolví una posible variante del Snippet

http://stackoverflow.com/questions/15906479/execute-a-application-and-wait-for-it-to-be-loaded

Después reviso a mas profundidad pero hice una prueba rápida y funcionó, lo que me parece es que el programa mucho antes de que caer en un estado de tranquilidad ya hizo la carga todos los módulos que en mi caso con 100...

Salu2


Título: Re: Wait For Application To Load
Publicado por: Eleкtro en 5 Septiembre 2016, 22:45 pm
Ese código es muy antiguo y es una guarrada (todo hay que decirlo), yo no lo escribí: http://stackoverflow.com/a/15906638/1248295 (http://stackoverflow.com/a/15906638/1248295)

El algoritmo de ese código se basa en la comparación de ciertos parámetros de consumo del proceso para determinar si el proceso está "inactivo". Cada 1500 milisegundos, mediante un Timer, comprueba si ha habido un incremento en el tamaño de alojamiento de memoria privada del proceso, y el tiempo de ejecución en modo kernel.

Cuando inicias un proceso se disparan muchos parámetros, entre ellos los que ya he mencionado, y cuando la interfáz de usuario del proceso se ha cargado completamente, los valores de esos parámetros dejan de incrementar (o al menos deberían, los bugs y/o fugas de memoria serían una excepción, jeje), y en ese preciso momento podemos concluir (aunque no en todos los casos) que la interfaz de usuario se ha cargado por completo, por que no está gastando más recursos.

No existe una ciencia ni botón mágico con el que poder determinar cuando la interfaz de usuario de un proceso externo se ha cargado completamente, de hecho hay interfaces de usuario llenas de animaciones que siempre están generando recursos (como por ejemplo el cliente de Battle.net de Blizzard) y eso es un problema muy grande para hacer nuestros cálculos.

En .NET podemos hacer uso del método Process.WaitforInputIdle() pero esto es una metología engañosa, puesto que solo sirve para esperar a que la cola de mensajes de la aplicación entre en un estado Idle, es decir, cuando esté lista para recibir mensajes de entrada, el problema es que muchas aplicaciones (como or ejemplo Steam) entran en ese estado mientras está cargando la UI ...mucho antes, durante la etapa de startup.



Bueno, despues de todo este rollo que he soltado para explicar varios aspectos, vamos a lo que te interesa, el código:

En el código fuente de mi API gratuita ElektroKit puedes encontrar una refactorización que le hice a esa guarrada de código que publiqué en su día, estoy seguro que te será mucho más sencilla de entender:

(http://i.imgur.com/aH0EmiQ.png)

Cita de: https://github.com/ElektroStudios/ElektroKit/blob/master/Solution/Elektro.Processes/Tools/ProcessUtil.vb
Código
  1. Public Shared Sub WaitUntilLoaded(ByVal p As Process,
  2.                                  Optional ByVal timeOut As Integer = 1500)
  3.  
  4.    Dim cpuChanged As Boolean = True
  5.    Dim memChanged As Boolean = True
  6.  
  7.    Dim oldCpu As Double, newCpu As Double
  8.    Dim oldMem As Long, newMem As Long
  9.  
  10.    While ((cpuChanged OrElse memChanged) = True)
  11.  
  12.        Do Until (p.TotalProcessorTime.TotalMilliseconds <> 0.0R)
  13.            Thread.Sleep(10)
  14.        Loop
  15.  
  16.        If (p Is Nothing) OrElse (p.HasExited) Then
  17.            Exit While
  18.  
  19.        Else
  20.            newMem = p.PrivateMemorySize64
  21.            memChanged = (newMem <> oldMem)
  22.            oldMem = newMem
  23.  
  24.            newCpu = p.TotalProcessorTime.TotalMilliseconds
  25.            cpuChanged = (newCpu <> oldCpu)
  26.            oldCpu = newCpu
  27.  
  28.            Thread.Sleep(timeOut)
  29.  
  30.        End If
  31.  
  32.    End While
  33.  
  34. End Sub

De hecho, cualquier sippet mio que encuentres en el foro probablemente con el paso del tiempo lo haya mejorado e integrado en ElektroKit, solo tienes que buscar por el nombre de la función, o preguntarme.



Hoy me he tomado un rato para volver a refactorizar el código, no me convencia demasiado la manera de usarlo, así que he decidido convertirlo en extensiones de método, y he implementado una lógica basada en WMI, ¿por qué?, por que aparte de servirnos para analizar mayor cantidad de parámetros como por ejemplo la cantidad de operaciones de transferencia de lectura/escritura del proceso, además nos sirve para evitar conflictos al intentar leer los parámetros de un exe de 64-bits desde un exe de 32 Bits ...en caso de que lo necesitemos.

En fin, aquí tienes el código (le he eliminado la documentación Xml no-esencial para que no ocupe demasiado espacio):

Código
  1. Public Module ProcessExtensions
  2.  
  3.    ''' ----------------------------------------------------------------------------------------------------
  4.    ''' <summary>
  5.    ''' Causes the <see cref="Process"/> component to wait indefinitely
  6.    ''' until the user interface has been fully loaded then entered in IDLE state.
  7.    ''' <para></para>
  8.    ''' This applies only to processes with a user interface and, therefore, a message loop.
  9.    ''' </summary>
  10.    ''' ----------------------------------------------------------------------------------------------------
  11.    <DebuggerStepThrough>
  12.    <Extension>
  13.    Public Sub WaitForIdle(ByVal sender As Process)
  14.  
  15.        ProcessExtensions.WaitForIdle(sender, checkInterval:=1500)
  16.  
  17.    End Sub
  18.  
  19.    ''' ----------------------------------------------------------------------------------------------------
  20.    ''' <summary>
  21.    ''' Causes the <see cref="Process"/> component to wait for the specified amount of time, in milliseconds,
  22.    ''' until the user interface has been fully loaded then entered in IDLE state.
  23.    ''' <para></para>
  24.    ''' This applies only to processes with a user interface and, therefore, a message loop.
  25.    ''' </summary>
  26.    ''' ----------------------------------------------------------------------------------------------------
  27.    ''' <param name="checkInterval">
  28.    ''' The interval, in milliseconds, to check the parameters that determines
  29.    ''' whether the user-interface has been loaded and the preocess entered in IDLE state.
  30.    ''' <para></para>
  31.    ''' It is recommended to experiment with a value between <c>1000</c> and <c>2000</c> ms,
  32.    ''' smaller values could give unexpected results.
  33.    ''' </param>
  34.    ''' ----------------------------------------------------------------------------------------------------
  35.    <DebuggerStepThrough>
  36.    <Extension>
  37.    Public Sub WaitForIdle(ByVal sender As Process, ByVal checkInterval As Integer)
  38.  
  39.        If (checkInterval < 0) Then
  40.            Throw New ArgumentOutOfRangeException(paramName:="checkInterval")
  41.            Exit Sub
  42.        End If
  43.  
  44.        ' Total time of the process running in kernel mode, in milliseconds.
  45.        ' This is the same as Process.TotalProcessorTime
  46.        Dim oldCpuTime As ULong, newCpuTime As ULong
  47.        Dim cpuTimeChanged As Boolean = True
  48.  
  49.        ' Current number of pages allocated that are only accessible to the process.
  50.        ' This is the same as Process.PrivateMemorySize64
  51.        Dim oldMemSize As ULong, newMemSize As ULong
  52.        Dim memSizeChanged As Boolean = True
  53.  
  54.        ' Total amount of active threads in the process.
  55.        ' This is the same as Process.ThreadCount
  56.        Dim oldThreadCount As UInteger, newThreadCount As UInteger
  57.        Dim threadCountChanged As Boolean = True
  58.  
  59.        ' Total amount of open handles owned by the process.
  60.        ' This is the same as Process.HandleCount
  61.        Dim oldHandleCount As UInteger, newHandleCount As UInteger
  62.        Dim handleCountChanged As Boolean = True
  63.  
  64.        ' Total amount of data transferred by the process in I/O read operations.
  65.        Dim oldReadDataCount As ULong, newReadDataCount As ULong
  66.        Dim readDataChanged As Boolean = True
  67.  
  68.        ' Total amount of data transferred by the process in I/O write operations.
  69.        Dim oldWriteRateCount As ULong, newWriteDataCount As ULong
  70.        Dim writeDataChanged As Boolean = True
  71.  
  72.        ' WMI settings for process query.
  73.        Dim scope As New ManagementScope("root\CIMV2")
  74.        Dim query As New SelectQuery(String.Format("SELECT * FROM Win32_Process Where ProcessId = '{0}'", sender.Id))
  75.        Dim options As New EnumerationOptions With {.ReturnImmediately = True, .DirectRead = False}
  76.  
  77.        Do
  78.            If (sender Is Nothing) OrElse (sender.HasExited) Then
  79.                Throw New InvalidOperationException(message:="The process is not running.")
  80.                Exit Sub
  81.  
  82.            Else
  83.                sender.Refresh()
  84.                sender.WaitForInputIdle(Timeout.Infinite)
  85.  
  86.                Using wmi As New ManagementObjectSearcher(scope, query, options)
  87.  
  88.                    Using obj As ManagementObject = wmi.Get().Cast(Of ManagementObject).SingleOrDefault()
  89.  
  90.                        If (obj IsNot Nothing) Then
  91.  
  92.                            newCpuTime = CULng(obj.Properties("KernelModeTime").Value)
  93.                            cpuTimeChanged = (newCpuTime <> oldCpuTime)
  94.                            oldCpuTime = newCpuTime
  95.  
  96.                            newMemSize = CULng(obj.Properties("PrivatePageCount").Value)
  97.                            memSizeChanged = (newMemSize <> oldMemSize)
  98.                            oldMemSize = newMemSize
  99.  
  100.                            newThreadCount = CUInt(obj.Properties("ThreadCount").Value)
  101.                            threadCountChanged = (newThreadCount <> oldThreadCount)
  102.                            oldThreadCount = newThreadCount
  103.  
  104.                            newHandleCount = CUInt(obj.Properties("HandleCount").Value)
  105.                            handleCountChanged = (newHandleCount <> oldHandleCount)
  106.                            oldHandleCount = newHandleCount
  107.  
  108.                            newReadDataCount = CULng(obj.Properties("ReadTransferCount").Value)
  109.                            readDataChanged = (newReadDataCount <> oldReadDataCount)
  110.                            oldReadDataCount = newReadDataCount
  111.  
  112.                            newWriteDataCount = CULng(obj.Properties("WriteTransferCount").Value)
  113.                            writeDataChanged = (newWriteDataCount <> oldWriteRateCount)
  114.                            oldWriteRateCount = newWriteDataCount
  115.  
  116. #If DEBUG Then
  117.                            Debug.WriteLine("CPU.Time........:{0}(ms)
  118.                                             Memomy.Size.....:{1}(bytes)
  119.                                             Thread.Count....:{2}
  120.                                             Handle.Count....:{3}
  121.                                             Read..Data.Count:{4}
  122.                                             Write.Data.Count:{5}
  123.                                            ".Replace(" "c, ""),
  124.                                            newCpuTime, newMemSize,
  125.                                            newThreadCount, newHandleCount,
  126.                                            newReadDataCount, newWriteDataCount)
  127. #End If
  128.  
  129.                        Else
  130.                            Continue Do
  131.  
  132.                        End If
  133.  
  134.                    End Using
  135.  
  136.                End Using
  137.  
  138.                If (cpuTimeChanged Or memSizeChanged Or
  139.                    threadCountChanged Or handleCountChanged Or
  140.                    readDataChanged Or writeDataChanged) = True Then
  141.  
  142.                    Thread.Sleep(TimeSpan.FromMilliseconds(checkInterval))
  143.                    Continue Do
  144.  
  145.                End If
  146.  
  147.            End If
  148.  
  149.        Loop Until (cpuTimeChanged Or memSizeChanged Or
  150.                    threadCountChanged Or handleCountChanged Or
  151.                    readDataChanged Or writeDataChanged) = False
  152.  
  153.    End Sub
  154.  
  155.    ''' ----------------------------------------------------------------------------------------------------
  156.    ''' <summary>
  157.    ''' Aynchronouslly causes the <see cref="Process"/> component to wait indefinitely  
  158.    ''' until the user interface has been fully loaded then entered in IDLE state.
  159.    ''' <para></para>
  160.    ''' This applies only to processes with a user interface and, therefore, a message loop.
  161.    ''' </summary>
  162.    ''' ----------------------------------------------------------------------------------------------------
  163.    ''' <param name="callback">
  164.    ''' A <see cref="Action"/> delegate which will be invoked inmmediately
  165.    ''' after the process is fully loaded and entered in IDLE state.
  166.    ''' <para></para>
  167.    ''' When <see cref="WaitForIdleAsync"/> method is called from a UI thread,
  168.    ''' <paramref name="callback"/> is invoked on the same UI thread.
  169.    ''' </param>
  170.    ''' ----------------------------------------------------------------------------------------------------
  171.    <DebuggerStepThrough>
  172.    <Extension>
  173.    Public Sub WaitForIdleAsync(ByVal sender As Process,
  174.                                ByVal callback As Action)
  175.  
  176.        ProcessExtensions.WaitForIdleAsync(sender, callback, checkInterval:=1500)
  177.  
  178.    End Sub
  179.  
  180.    ''' ----------------------------------------------------------------------------------------------------
  181.    ''' <summary>
  182.    ''' Aynchronouslly causes the <see cref="Process"/> component to wait for the specified amount of time, in milliseconds,
  183.    ''' until the user interface has been fully loaded then entered in IDLE state.
  184.    ''' <para></para>
  185.    ''' This applies only to processes with a user interface and, therefore, a message loop.
  186.    ''' </summary>
  187.    ''' ----------------------------------------------------------------------------------------------------
  188.    ''' <param name="callback">
  189.    ''' A <see cref="Action"/> delegate that will be invoked inmmediately
  190.    ''' after the process is fully loaded and entered in IDLE state.
  191.    ''' <para></para>
  192.    ''' When <see cref="WaitForIdleAsync"/> method is called from a UI thread,
  193.    ''' <paramref name="callback"/> is invoked on the same UI thread.
  194.    ''' </param>
  195.    '''
  196.    ''' <param name="checkInterval">
  197.    ''' The interval, in milliseconds, to check the parameters that determines
  198.    ''' whether the user-interface has been loaded and the preocess entered in IDLE state.
  199.    ''' <para></para>
  200.    ''' It is recommended to experiment with a value between <c>1000</c> and <c>2000</c> ms,
  201.    ''' smaller values could give unexpected results.
  202.    ''' </param>
  203.    ''' ----------------------------------------------------------------------------------------------------
  204.    <DebuggerStepThrough>
  205.    <Extension>
  206.    Public Sub WaitForIdleAsync(ByVal sender As Process,
  207.                                ByVal callback As Action,
  208.                                ByVal checkInterval As Integer)
  209.  
  210.        Dim tScheduler As TaskScheduler
  211.  
  212.        ' If the current thread is a UI thread then run the callback synchronouslly on the UI thread...
  213.        If (Application.MessageLoop) Then
  214.            tScheduler = TaskScheduler.FromCurrentSynchronizationContext()
  215.  
  216.        Else
  217.            tScheduler = TaskScheduler.Default
  218.  
  219.        End If
  220.  
  221.        Task.Factory.StartNew(Sub() ProcessExtensions.WaitForIdle(sender, checkInterval)).
  222.                     ContinueWith(Sub(t) callback.Invoke(), CancellationToken.None, TaskContinuationOptions.None, tScheduler)
  223.  
  224.    End Sub
  225.  
  226. End Module
  227.  

Ejemplos de uso sincrónico:
Código
  1. Using p As New Process
  2.     p.StartInfo.FileName = "C:\Program Files\Photoshop\Photoshop.exe"
  3.     p.Start()
  4.     p.WaitForIdle(checkInterval:=1500)
  5. End Using
  6.  
  7. MsgBox("Process's UI has been fully loaded.")

Ejemplos de uso asincrónico:
Código
  1. Using p As New Process
  2.     p.StartInfo.FileName = "C:\Program Files\Photoshop\Photoshop.exe"
  3.     p.Start()
  4.     p.WaitForIdleAsync(p, AddressOf WaitForIdleAsync_CallBack, checkInterval:=1500)
  5. End Using
  6.  
  7. Private Sub WaitForIdleAsync_CallBack()
  8.     MsgBox("Process's UI has been fully loaded.")
  9. End Sub



lo que me parece es que el programa mucho antes de que caer en un estado de tranquilidad ya hizo la carga todos los módulos que en mi caso con 100...

Como ya te dije no existe una ciencia con la que predecir la carga completa de la UI, yo te recomiendo usar un valor de entre 1000 a 2000 ms para el parámetro "checkInterval" de los códigos de arriba (en el código que tú pusiste de Stackoverflow también), si usas un valor como 100 ms no es nada bueno, creeme, si el PC está haciendo muchas tareas e intentas iniciar un proceso entonces la información del proceso (me refiero al objeto Process, y la información de WMI), tardará mucho más que 100 ms en actualizarse, y esto quiere decir que los valores que obtendrás en la siguiente iteración serán idénticos así que la comprobación de valores te podría dar un falso positivo, y te lo daría. En otras palabras, cuanto mayor sea el intervalo de ms que especifiques, más seguro será la comprobación.

Un saludo


Título: Re: Wait For Application To Load
Publicado por: TrashAmbishion en 6 Septiembre 2016, 21:08 pm
Muchas gracias lo revisaré...

Salu2

Pd: Ya estoy a punto de poner a prueba el proyecto y quería saber (para cubrir dudas) que como obligatoriamente para poder jugar el juego tiene que ser a traves de mi programa tendría cierta ventaja como por ejemplo bloquear el proceso del juego para que nada mas que mi programa acceda a el, estuve mirando "mutex" pero creo que no tiene nada que ver, y lo otro es iniciarlo de forma que no se pudiera listar en los procesos como un rootkit, pero que la GUI si se mantuviera o cualquier otro invento

No obstante

El injector que estoy mirando, trae una función para oculta la DLL que injecta.. pero esa DLL requiere otra DLL que si se carga y ahi pita mi programa, pero pasa que hay programas que sirven para hacer capturas del juego o grabar incluso hasta el IDM a veces mete una DLL en las del juego..

Estaba pensado hacer una lista de las DLL que carga en un sistema virgen

y entonces de ahi ir partiendo revisar las que esten de mas, hacerle unload si hay algo sospechoso..

que crees ?

Salu2


Título: Re: Wait For Application To Load
Publicado por: Eleкtro en 7 Septiembre 2016, 09:50 am
quería saber (para cubrir dudas) que como obligatoriamente para poder jugar el juego tiene que ser a traves de mi programa tendría cierta ventaja como por ejemplo bloquear el proceso del juego para que nada mas que mi programa acceda a el, estuve mirando "mutex" pero creo que no tiene nada que ver, y lo otro es iniciarlo de forma que no se pudiera listar en los procesos como un rootkit, pero que la GUI si se mantuviera o cualquier otro invento

Bueno, en mi opinión no está del todo claro lo que dices, si tu programa debería ser el único que pudiera INICIAR el executable, o por otro lado el único que pudiera ACCEDER a él, o ambas cosas.



Si te refieres a imposibilitar que el usuario pueda iniciar el exe del juego:
Puedes hacer un API hooking a la función CreateProcessW/CreateProcessA para interceptar las lalmadas a dicha función y anular la llamada en caso de que el parámetro lpApplicationName corresponda con el exe del juego. En .NET puedes implementar técnicas de API Hooking de forma relativamente sencilla con la librería Deviare: http://www.nektra.com/products/deviare-api-hook-windows/ (http://www.nektra.com/products/deviare-api-hook-windows/).

Un ejemplo de implementación que escribí:
  • http://foro.elhacker.net/net/api_para_impedir_la_ejecucion_de_ejecutables-t451335.0.html;msg2067510#msg2067510

Otra opción para llevar a cabo lo mismo sería monitorizar la ejecución de nuevos procesos mediante WMI, lo que practicamente no costaría nada de esfuerzo implementarlo, sin embargo, WMI necesita un mínimo de tiempo para actualizarse y detectar nuevos procesos en la lista de procesos interna del sistema, dicho de otra forma: es una metodología mucho menos sensible que el API hooking.

En mi API gratuita ElektroKit tienes un ejemplo de implementación:
(http://i.imgur.com/2vH8dpZ.png)
  • https://github.com/ElektroStudios/ElektroKit/blob/master/Solution/Elektro.Processes/Types/ProcessWatcher.vb

Pero como ya he explicado WMI es lento, así que sería mejor usar un Timer (de verdad, da muchos mejores resultados que WMI):
(http://i.imgur.com/JQcgCLS.png)
  • https://github.com/ElektroStudios/ElektroKit/blob/master/Solution/Elektro.Processes/Types/ProcessMonitor.vb

Notas adicionales:
 - Si quieres imposibilitar más de una instancia del executable entonces puedes usar un MUTEX o semáforo, no te va a servir para otra cosa en este propósito.
 - Si, puedes ocultar el nombre del exe del juego en el administrador de tareas, puedes hacerlo mediante la metodología tradicional y casi obsoleta de la Win32 API (FindWindow + EnumChildWindows + etc) o también mediante el framework de Windows UI Automation de la librería de classes de .NET Framework, pero no te aconsejo ocultar el nombre del proceso de ninguna forma, puesto que se requiere mucho trabajo para cada versión de Windows necesitarás hacer cambios en los nombres de las classes y etc, te llevaría bastante tiempo solo en investigar los nombres haciéndole un Spy al taskmanager, vaya. No se si existe otra forma para ocultarlo.



Si te refieres a impedir que el usuario pueda utilizar la ventana del proceso:

Mediante la API RAWINPUT puedes registrar un dispositivo de teclado y/o mouse virtual y solo lo usuarias tú, pero requiere mucho trabajo, mucho p/invoking:
  • https://msdn.microsoft.com/en-us/library/windows/desktop/ms645536%28v=vs.85%29.aspx
( En mi API ElektroKit en el namespace Elektro.Interop.Win32 tienes muchas definiciones de RAWINPUT si las llegases a necesitar... )

Cabe mencionar que puedes utilizar la función Win32 BlockInput para imposibilitar el uso del teclado y el mouse, pero lamentablemente esto afectaría de forma global al usuario, no solo a la ventana del juego.

Se me ocurre que podrías registrar un mensaje de ventana, e intentar bloquear la cola de mensajes de la ventana del juego para que solo acepte tu mensaje, supongo que esto es lo que harán los bots más sofisticados (como los Buddy bots de los juegos de Blizzard) pero solo es una hipótesis o una conjetura, realmente no estoy nada seguro de como se implementaría esta técnica.



que crees ?
La inyección de código en video juegos y en general estas cosas para juegos no es lo mio, te podrían orientar mejor en el foro de ingenieria inversa, supongo.

Saludos


Título: Re: Wait For Application To Load
Publicado por: FJDA en 7 Septiembre 2016, 13:43 pm
una forma sencillita sería esta


Código
  1. Public Class Form1
  2.  
  3.    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
  4.        'Process.Start("C:\Program Files\Adobe\Adobe Photoshop CS5 (64 Bit)\Photoshop.exe")
  5.        Process.Start("C:\Program Files (x86)\Adobe\Adobe Photoshop CS5\Photoshop.exe")
  6.  
  7.        'Subprocesoo
  8.        Task.Factory.StartNew(Sub()
  9.                                  Do
  10.                                      'Espera a obtener el handle de la ventana principal de Photoshop
  11.                                      Dim pcs As Process() = Process.GetProcessesByName("Photoshop")
  12.                                      For Each proceso As Process In pcs
  13.                                          If proceso.MainWindowHandle <> IntPtr.Zero Then
  14.                                              Exit Do
  15.                                          End If
  16.                                      Next
  17.                                  Loop
  18.                              End Sub).ContinueWith(Sub()
  19.                                                        System.Threading.Thread.Sleep(1500) 'Espera un segundo y medio
  20.                                                        AppActivate(Process.GetCurrentProcess.Id) 'Activa esta ventana
  21.                                                        MessageBox.Show("Photoshop se ha iniciado") 'Muestra un mensaje
  22.                                                    End Sub)
  23.  
  24.    End Sub
  25.  
  26. End Class
  27.  

__________________________________________________________

y se puede usar HasExited de forma análoga para saber si la aplicación se ha cerrado. Devuelve True.