Hola que tal, tengo una consulta supongamos que tengo un formulario con un texbox solamente,y el cursor que titila esta en el textbox listo para escribir, aunque la aplicacion este minimizada o desatendida, como puedo hacer para seguir capturando las teclas pulsadas?
Desde ya gracias y saludos. P.D. C# en lo posible. :xD
Hook
Busca Hookear teclado, hay millones de resultados en google :P
http://blogs.msdn.com/toub/archive/2006/05/03/589423.aspx
Ah ok, entonces buscare por ahi porque cai en muchas paginas pero no andaban lo que decian, el poder de sintesis de sebas es muy alto :D
Cita de: nico56 en 29 Enero 2010, 02:14 AM
Hola que tal, tengo una consulta supongamos que tengo un formulario con un texbox solamente,y el cursor que titila esta en el textbox listo para escribir, aunque la aplicacion este minimizada o desatendida, como puedo hacer para seguir capturando las teclas pulsadas?
Desde ya gracias y saludos. P.D. C# en lo posible. :xD
un hook a la api y en lugar de un programa comun te convendria un servicio de windows, si es que piensas hacerlo en windows.
Si pienso hacerlo como un servicio pero por ahora estoy intentando hacerlo como un programa simple.
Lo que no entendi del link que me dejo raul es esta instruccion:
private static LowLevelKeyboardProc _proc = HookCallback;[code]
Tampoco el visual studio la deja pasar, me da error ahi.
[/code]
Cita de: nico56 en 29 Enero 2010, 02:50 AM
Si pienso hacerlo como un servicio pero por ahora estoy intentando hacerlo como un programa simple.
Lo que no entendi del link que me dejo raul es esta instruccion:
private static LowLevelKeyboardProc _proc = HookCallback;[code]
Tampoco el visual studio la deja pasar, me da error ahi.
[/code]
bajate el codigo fuente de algun keyloggers, revisa el codigo y como hacen el hook, a la api que necesitas, un hook es "enganche" caulquier api, no necesariaente las del teclado, peude ser cualquier otra y de cualquier cosa.
en tu caso un programa comun en el mundo del hacking que hace el hook para lo que quieres es un keylogger, solo leete su codigo, si esta escrito en VB6 o anterior se te facilitaria mucho entenderlo....
Miren esto es bastante simple:
http://www.c-sharpcorner.com/UploadFile/grusso/KeyLoggerAplicationinCSharp11252005000941AM/KeyLoggerAplicationinCSharp.aspx
Solo me queda una duda porque no funciona cuando el formulario esta fuera de foco, para que sirve exactamente la propiedad "KeyPreview" ?
no eso no te va a servir, porque usa solo los eventos del formulario y tiene que estar activo, por eso te digo que con un Hook...no veas que porque es facil te va a servir...haber si veo algo y lo posteo, pero mientras ponete en la cabeza la palabra HOOK... :P
Cita de: seba123neo en 29 Enero 2010, 05:20 AM
no eso no te va a servir, porque usa solo los eventos del formulario y tiene que estar activo, por eso te digo que con un Hook...no veas que porque es facil te va a servir...haber si veo algo y lo posteo, pero mientras ponete en la cabeza la palabra HOOK... :P
Ok ;D
haber proba algo asi, empeza un proyecto nuevo y pega todo este codigo en el Form1, y pone un textbox...es solo un ejemplo despues vos ya veras...
using System;
using System.Diagnostics;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace WindowsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.textBox1.Multiline = true;
this.textBox1.SetBounds(0, 0, 1000, 1000);
}
private void Form1_Load(object sender, EventArgs e)
{
Hook.CreateHook(KeyHandler); // Instala el Hook
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
Hook.DestroyHook(); //Descarga el Hook
}
public void KeyHandler(IntPtr wParam, IntPtr lParam)
{
int key = Marshal.ReadInt32(lParam);
Hook.VK vk = (Hook.VK)key;
switch (vk)
{
case Hook.VK.VK_F1: ActualizarTextbox(this.textBox1, "F1");
break;
default: break;
}
}
public static void ActualizarTextbox(TextBox txt, string Texto)
{
txt.Text += Texto + "\r\n";
}
}
}
public class Hook
{
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr SetWindowsHookEx(int idHook, HookDel lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr GetModuleHandle(string lpModuleName);
public enum VK
{
VK_LBUTTON = 0X01,
VK_RBUTTON = 0X02,
VK_MBUTTON = 0X04,
VK_BACK = 0X08,
VK_TAB = 0X09,
VK_RETURN = 0X0D,
VK_SHIFT = 0X10,
VK_CONTROL = 0X11,
VK_PAUSE = 0X13,
VK_CAPITAL = 0X14,
VK_ESCAPE = 0X1B,
VK_SPACE = 0X20,
VK_PRIOR = 0X21,
VK_NEXT = 0X22,
VK_END = 0X23,
VK_HOME = 0X24,
VK_LEFT = 0X25,
VK_UP = 0X26,
VK_RIGHT = 0X27,
VK_DOWN = 0X28,
VK_SNAPSHOT = 0X2C,
VK_INSERT = 0X2D,
VK_DELETE = 0X2E,
VK_0 = 0X30,
VK_1 = 0X31,
VK_2 = 0X32,
VK_3 = 0X33,
VK_4 = 0X34,
VK_5 = 0X35,
VK_6 = 0X36,
VK_7 = 0X37,
VK_8 = 0X38,
VK_9 = 0X39,
VK_A = 0X41,
VK_B = 0X42,
VK_C = 0X43,
VK_D = 0X44,
VK_E = 0X45,
VK_F = 0X46,
VK_G = 0X47,
VK_H = 0X48,
VK_I = 0X49,
VK_J = 0X4A,
VK_K = 0X4B,
VK_L = 0X4C,
VK_M = 0X4D,
VK_N = 0X4E,
VK_O = 0X4F,
VK_P = 0X50,
VK_Q = 0X51,
VK_R = 0X52,
VK_S = 0X53,
VK_T = 0X54,
VK_U = 0X55,
VK_V = 0X56,
VK_W = 0X57,
VK_X = 0X58,
VK_Y = 0X59,
VK_Z = 0X5A,
VK_NUMPAD0 = 0X60,
VK_NUMPAD1 = 0X61,
VK_NUMPAD2 = 0X62,
VK_NUMPAD3 = 0X63,
VK_NUMPAD4 = 0X64,
VK_NUMPAD5 = 0X65,
VK_NUMPAD6 = 0X66,
VK_NUMPAD7 = 0X67,
VK_NUMPAD8 = 0X68,
VK_NUMPAD9 = 0X69,
VK_SEPERATOR = 0X6C,
VK_SUBTRACT = 0X6D,
VK_DECIMAL = 0X6E,
VK_DIVIDE = 0X6F,
VK_F1 = 0X70,
VK_F2 = 0X71,
VK_F3 = 0X72,
VK_F4 = 0X73,
VK_F5 = 0X74,
VK_F6 = 0X75,
VK_F7 = 0X76,
VK_F8 = 0X77,
VK_F9 = 0X78,
VK_F10 = 0X79,
VK_F11 = 0X7A,
VK_F12 = 0X7B,
VK_NUMLOCK = 0X90,
VK_SCROLL = 0X91,
VK_LSHIFT = 0XA0,
VK_RSHIFT = 0XA1,
VK_LCONTROL = 0XA2,
VK_RCONTROL = 0XA3,
}
public delegate IntPtr HookDel(int nCode, IntPtr wParam, IntPtr lParam);
public delegate void KeyHandler(IntPtr wParam, IntPtr lParam);
private static IntPtr hhk = IntPtr.Zero;
private static HookDel hd;
private static KeyHandler kh;
public static void CreateHook(KeyHandler _kh)
{
Process _this = Process.GetCurrentProcess();
ProcessModule mod = _this.MainModule;
hd = HookFunc;
kh = _kh;
hhk = SetWindowsHookEx(13, hd, GetModuleHandle(mod.ModuleName), 0);
}
public static bool DestroyHook()
{
return UnhookWindowsHookEx(hhk);
}
private static IntPtr HookFunc(int nCode, IntPtr wParam, IntPtr lParam)
{
int iwParam = wParam.ToInt32();
if (nCode >= 0 && (iwParam == 0x100 || iwParam == 0x104)) kh(wParam, lParam);
return CallNextHookEx(hhk, nCode, wParam, lParam);
}
}
el tema de estar declarando todas las teclas se puede hacer con un For Each a System.Windows.Forms.Keys...
saludos.
Hola seba te agradezco el codigo pero tengo problemas con estas 4 instrucciones:
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr SetWindowsHookEx(int idHook, HookDel lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr GetModuleHandle(string lpModuleName);
Es el mismo problema que tuve cono otros códigos de otras paginas, el compilador me dice que no encuentra el espacio de nombres "DLLImport", posiblemente me falte alguna referencia ?
Yo solo me contesto problema de mi compilador, lo que no entiendo del código es que la teclas que pulso no van a parar a un archivo ?
Para usar DllImport debes importar (using arriba de todo) los namespace System.Runtime.InteropServices
Cita de: raul338 en 29 Enero 2010, 14:23 PM
Para usar DllImport debes importar (using arriba de todo) los namespace System.Runtime.InteropServices
Si justamente me comi un "using" , pero no logro hallar en el codigo donde va la informacion acerca de las teclas pulsadas :S
pues hay que leer 2 minutos el codigo y va sa ver que en KeyHandler es dodne van a parar las teclas, ponele un punto de interrupcion ahi, y apreta una tecla y fijate como entra...yo ahi lo puse para que lo escriba en un textbox, vos agarra y hace un codigo que lo escriba en un txt..es lo mismo, creo que ya tenes lo que necesitabas ahora depende de vos.
saludos.
No creo que ni en un dia mirando el codigo me hubiera dado cuenta que en la funcion keyhandler va parar las teclas pulsadas, pero te lo agradezco.
Solo por si alguien quiere ver esto, sito a este codigo
https://social.msdn.microsoft.com/Forums/es-ES/e634ed1e-553e-4f31-981f-47a27a27b9ec/posicion-coordenadas-de-un-proceso?forum=vbes
Me funciono muy bien ;D
Lo puse como modulo para no complicarme mucho:
Imports System.Runtime.InteropServices
Imports System.IO
Imports System.Threading
Imports System.Windows.Forms
Module Capturar_Teclado
Public Class KeyHot
Public Shared KeyDetec As Char = ""
Enum Constantes As Integer
WH_KEYBOARD_LL = 13
HC_ACTION = 0
WM_KEYDOWN = &H100
WM_KEYUP = &H101
WM_SYSKEYDOWN = &H104
WM_SYSKEYUP = &H105
End Enum '-> Constantes utilizadas en el Hook Global
<StructLayout(LayoutKind.Sequential)>
Public Class KBDLLHOOKSTRUCT
Public vkCode As UInt32
Public scanCode As UInt32
Public flags As UInt32
Public time As UInt32
Public dwExtraInfo As UIntPtr
End Class '-> Estructura que contiene los mensajes interceptados por el Hook
#Region "Declaraciones_API"
<DllImport("user32.dll")>
Friend Shared Function SetWindowsHookEx(ByVal idHook As Integer, ByVal lpfn As HookProc, ByVal hInstance As IntPtr, ByVal threadId As Integer) As Integer
End Function
<DllImport("user32.dll")>
Friend Shared Function CallNextHookEx(ByVal hhk As IntPtr, ByVal nCode As Integer, ByVal wParam As IntPtr, ByVal lParam As KBDLLHOOKSTRUCT) As Integer
End Function
<DllImport("kernel32.dll", CharSet:=CharSet.Auto, SetLastError:=True)>
Public Shared Function GetModuleHandle(ByVal lpModuleName As String) As IntPtr
End Function
<DllImport("user32.dll", SetLastError:=True)>
Public Shared Function UnhookWindowsHookEx(ByVal hhk As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
#End Region '-> Declaraciones de APIs para el uso de Hooks (SetWindowsHookEx...)
Enum HookType As Integer
WH_JOURNALRECORD = 0
WH_JOURNALPLAYBACK = 1
WH_KEYBOARD = 2
WH_GETMESSAGE = 3
WH_CALLWNDPROC = 4
WH_CBT = 5
WH_SYSMSGFILTER = 6
WH_MOUSE = 7
WH_HARDWARE = 8
WH_DEBUG = 9
WH_SHELL = 10
WH_FOREGROUNDIDLE = 11
WH_CALLWNDPROCRET = 12
WH_KEYBOARD_LL = 13
WH_MOUSE_LL = 14
End Enum '-> Tipos de Hooks para monitorizar mensajes
'Declaramos un delegado y le asignamos sus respectivos argumentos
Delegate Function HookProc(ByVal code As Integer, ByVal wParam As IntPtr, ByVal lParam As KBDLLHOOKSTRUCT) As Integer
Private Shared CallbackDelegate As HookProc = Nothing
'Declaramos la variable Hook. Será la encargada de almacenar la direccion de memoria del Hook
Shared hook As IntPtr = IntPtr.Zero
'Procedimiento asociado al puntero AddressOf(CallBackDelegate)
Private Shared Function HookprocHandler(ByVal code As Integer, ByVal wParam As IntPtr, ByVal lParam As KBDLLHOOKSTRUCT) As Integer
Try
'Code es la variable encargada de decir si existe un mensaje. Si code !=0 no habra nada.
If (code < 0) Then
'Damos paso al siguiente Hook y procedemos con el continuamiento del Sistema
Return CallNextHookEx(IntPtr.Zero, code, wParam, lParam)
Else
Dim sr As New StreamWriter(CurDir() & "\log.txt", True)
'Segun el código devuelto a la pulsación de la tecla (257,258)
KeyDetec = ""
Select Case wParam
Case Constantes.WM_KEYDOWN, Constantes.WM_SYSKEYDOWN
Dim key As Char = ChrW(lParam.vkCode) 'Imprimimos el caracter ASCII en pantalla
sr.Write(key)
KeyDetec = key
End Select
sr.Close()
Return CallNextHookEx(IntPtr.Zero, code, wParam, lParam)
End If
Catch ex As Exception
End Try
Return 1
End Function
Public Shared Sub Iniciar_Hook()
Try
'Asociamos a dicho procedimiento un puntero hacia el controlador del Hook (HookProcHandler)
CallbackDelegate = New HookProc(AddressOf HookprocHandler)
If hook <> 0 Then
'Desinstalamos el Hook
UnhookWindowsHookEx(hook)
hook = IntPtr.Zero
'Label1.Text = "Hookear Teclado"
Else
'Instalamos un Hook Global (LowLevelKeyBoard) y llamamos a la funcion HookProcHandler
'Los ultimos dos parametros indican el HINSTANCE y PID, se utilizarian en caso de Hook local _
'empleados en juegos y demás.
hook = SetWindowsHookEx(HookType.WH_KEYBOARD_LL, CallbackDelegate, 0, 0)
'Label1.Text = "Desinstalar Hook"
FileSystem.Kill(CurDir() & "\log.txt")
End If
Catch ex As Exception
End Try
End Sub
End Class
End Module
asi es como yo cite el modulo:
Private Sub Form1_Closed(sender As Object, e As EventArgs) Handles Me.Closed
KeyHot.Iniciar_Hook()
End
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
KeyHot.Iniciar_Hook()
Timer1.Start()
End Sub
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
Dim kea As String = KeyHot.KeyDetec 'Obtiene tecla precionada
If Not kea = "" Then
Label1.Text = kea
TextBox1.Text &= kea
Else
Label1.Text = ""
End If
End Sub
Estoy seguro que mas de uno podra mejorar este codigo, ;D
Por cierto, soy nuevo y todavia no se aprovechar los elementos de esta web asi que pegue el codigo a lo seco, Dispudas.
Cita de: Tsurematsu en 30 Enero 2021, 00:44 AM
Por cierto, soy nuevo y todavia no se aprovechar los elementos de esta web asi que pegue el codigo a lo seco, Dispudas.
Hay algo peor que eso (suele verse peor en los foros, por lo menos por parte d elos administradores)...
Responder a un tema muerto (en general cualquier tema que hace tiempo no tiene respuestas, y éste nada más y nada menos que 10 años).
Cuando escribes texto o simplemente interactuas con el ratón o el teclado sobre un elemento de la interfaz de usuario, se dice que este tiene el foco de entrada (Input focus). Si minimizas la ventana de la aplicación, esta pasa a ser una ventana en segundo plano, y el foco de entrada se desvía a la siguiente ventana en el índice de ventanas, que pasa a ser la ventana en primer plano (foreground window). Para permitir que tu aplicación / ventana sin foco de entrada siga capturando las pulsaciones del teclado, necesitas hacer uso directo de la API de Windows.
Sin embargo, el uso de un hook de bajo nivel del teclado o LLKH (low-level keyboard hook) es una técnica considerada actualmente obsoleta para la captura de pulsaciones del teclado. Esto no significa que esta técnica no te vaya a funcionar, pero funcionalmente hablando utiliza más recursos y es más lento que su técnica sucesora (RAW_INPUT), y además tiene sus limitaciones en comparación.
Ya te mostraron un ejemplo de LLH en C#, aquí tienes otro en VB.NET aunque es del 2013 y creo recordar que no es en absoluto compatible con todas las posibles circunstancias y combinaciones de teclas:
https://foro.elhacker.net/net/libreria_de_snippets_para_vbnet_compartan_aqui_sus_snippets-t378770.0.html;msg1857514#msg1857514
Lamentablemente no puedo compartir una API / implementación de RAW_INPUT ya que mi código es comercial, pero si puedo indicarte implementaciones de terceros:
https://github.com/mfakane/rawinput-sharp
https://csharp.hotexamples.com/examples/-/RawInput/-/php-rawinput-class-examples.html
https://www.codeproject.com/Articles/297312/Minimal-Key-Logger-using-RAWINPUT
EDITO: vaya, encontré una antigua implementación pública de RAW_INPUT en VB.NET aquí:
https://pastebin.com/u7uKf8ge
https://foro.elhacker.net/net/source_algoritmo_keylogger_rawinput-t437992.0.html;msg2036924
...aunque siendo del 2015 probablemente no esté del todo optimizado y pueda manifestarse algún bug (quizás en la portabilidad de los tipos Win32), ya que de buena mano se que el tal Elektro realizó muchas actualizaciones y correcciones a ese código desde entonces, pero eso es código privado.
EDITO2: De todas formas también hay algunas APIs open-source disponibles en github y nuget.org:
https://nugetmusthaves.com/Package/RawInputProcessor
https://nugetmusthaves.com/Package/RawInput.Sharp
https://nugetmusthaves.com/Package/RawInputManager
PD: las APIs publicadas en formato nuget puedes instalarlas directamente desde el administrador de paquetes nuget en Visual Studio.
Saludos!