Ir al contenido



Foto

Botón del Pánico o como desaferentar el PC


  • Por favor identifícate para responder
10 respuestas en este tema

#1 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.876 mensajes
  • LocationMadrid - España

Escrito 01 septiembre 2016 - 11:03

¿Nunca se os ha ocurrido apagarle a alguien el monitor por código de forma que no pueda encenderlo?, a mi sí y no voy a decir porqué  *-)

 

Apagar el monitor es fácil con SC_MONITORPOWER pero en cuanto se toca el teclado o el ratón, se enciende. Para darle consistencia al apagado he escrito un thread que repite el apagado cada 100 ms y listo. Pero al hacer eso el usuario cambiaría cosas inconscientemente en las aplicaciones en primer plano al tratar de activar el monitor aporreando el teclado o interactuando desesperadamente con el ratón. Para solucionar este inconveniente bloqueo el teclado y el ratón.

 

¡Ni monitor, ni teclado ni ratón! Que no cunda el pánico, que las combinaciones de teclas en un hook al teclado nos abren la puerta:

    ALT - F10: Cierra el programa devolviéndonos el control.

    ALT - F11: Nos devuelve el control sin cerrar el programa.

    ALT - F12: Apaga el monitor y bloquea el teclado + ratón.

 

La aplicación no tiene interface gráfico y queda como sigue:


delphi
  1. program MonitorPower;
  2.  
  3. uses
  4. Windows, Messages;
  5.  
  6. var
  7. idThTurnOffMonitor: DWORD = 0;
  8. WHookKeyboard: HHOOK = 0;
  9. WHookMouse: HHOOK = 0;
  10.  
  11. function ThTurnOffMonitor(): DWORD; stdcall
  12. var
  13. msg: TMsg;
  14. i: DWORD;
  15. begin
  16. // Monitor off
  17. repeat PeekMessage(msg,0,0,0, PM_REMOVE);
  18. Sleep(100);
  19. SendNotifyMessage(GetForegroundWindow(), WM_SYSCOMMAND, SC_MONITORPOWER, 2);
  20. DispatchMessage(msg);
  21. until (msg.Message = WM_QUIT);
  22.  
  23. // Monitor on
  24. SendNotifyMessage(GetForegroundWindow(), WM_SYSCOMMAND, SC_MONITORPOWER, -1);
  25. for i:= 0 to 4 do
  26. begin
  27. mouse_event(MOUSEEVENTF_MOVE, 0, 10, 0, 0);
  28. Sleep(40);
  29. mouse_event(MOUSEEVENTF_MOVE, 0, DWORD(-10), 0, 0);
  30. end;
  31. Result:= 0;
  32. end;
  33.  
  34. procedure CmdEnableMonitor(Enable: BOOL);
  35. begin
  36. if not Enable and (idThTurnOffMonitor = 0) then
  37. // Turn off monitor
  38. CloseHandle(CreateThread(nil, 0, @ThTurnOffMonitor, nil, 0, idThTurnOffMonitor));
  39. if Enable then
  40. begin
  41. // Turn on monitor
  42. PostThreadMessage(idThTurnOffMonitor, WM_QUIT, 0, 0);
  43. idThTurnOffMonitor:= 0;
  44. end;
  45. end;
  46.  
  47. function KeyboardHook(Code, wParam, lParam: Integer): Integer; stdcall;
  48. begin
  49. if (Code = HC_ACTION) and LongBool(PDWORD(lParam + 8)^ and $20{LLKHF_ALTDOWN}) then
  50. begin
  51. if PDWORD(lParam)^ = VK_F11 then // ALT + F11: Monitor Off
  52. CmdEnableMonitor(true);
  53. if PDWORD(lParam)^ = VK_F12 then // ALT + F12: Monitor On
  54. CmdEnableMonitor(false);
  55. if PDWORD(lParam)^ = VK_F10 then // ALT + F10: Quit
  56. PostThreadMessage(GetCurrentThreadId, WM_QUIT, 0, 0);
  57. end;
  58. Result:= -1;
  59. if idThTurnOffMonitor = 0 then
  60. Result:= CallNextHookEx(WHookKeyboard, Code, wParam, lParam);
  61. end;
  62.  
  63. function MouseHook(Code, wParam, lParam: Integer): Integer; stdcall;
  64. begin
  65. Result:= -1;
  66. if (Code <> HC_ACTION) or (idThTurnOffMonitor = 0) then
  67. Result:= CallNextHookEx(WHookMouse, Code, wParam, lParam);
  68. end;
  69.  
  70. var
  71. msg: TMsg;
  72. begin
  73. idThTurnOffMonitor:= 0;
  74. WHookKeyboard:= SetWindowsHookEx(13{WH_KEYBOARD_LL}, @KeyboardHook, HInstance, 0);
  75. WHookMouse:= SetWindowsHookEx(14{WH_MOUSE_LL}, @KeyboardHook, HInstance, 0);
  76.  
  77. // Bucle de mensajes:
  78. repeat GetMessage(msg, 0, 0, 0);
  79. DispatchMessage(msg);
  80. until (msg.Message = WM_QUIT);
  81.  
  82. CmdEnableMonitor(true);
  83. UnhookWindowsHookEx(WHookKeyboard);
  84. UnhookWindowsHookEx(WHookMouse);
  85. end.

El código puede tener su utilidad como botón del pánico, una broma no demasiado pesada o... la imaginación es libre.

 

 

 

Saludos.


  • 2

#2 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.011 mensajes
  • LocationMéxico

Escrito 01 septiembre 2016 - 11:32

El código puede tener su utilidad como botón del pánico, una broma no demasiado pesada o... la imaginación es libre.

 

 

 

Saludos.

 

 

:dlaug:  :dmad:

 

Saludos  *-)  *-)  *-)

 


  • 0

#3 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.876 mensajes
  • LocationMadrid - España

Escrito 02 septiembre 2016 - 06:49

El mismo código en C/C++


cpp
  1. //---------------------------------------------------------------------------
  2.  
  3. #include <windows.h>
  4. #pragma hdrstop
  5.  
  6. //---------------------------------------------------------------------------
  7.  
  8. #pragma argsused
  9.  
  10.  
  11. DWORD idThTurnOffMonitor = 0;
  12. HHOOK WHookKeyboard = 0;
  13. HHOOK WHookMouse = 0;
  14.  
  15. DWORD WINAPI ThTurnOffMonitor(LPVOID lpParameter)
  16. {
  17. MSG msg;
  18. DWORD i;
  19.  
  20. // Monitor off
  21. do {
  22. PeekMessage(&msg,0,0,0, PM_REMOVE);
  23. Sleep(100);
  24. SendNotifyMessage(GetForegroundWindow(), WM_SYSCOMMAND, SC_MONITORPOWER, (LPARAM) 2);
  25. DispatchMessage(&msg);
  26. } while(msg.message != WM_QUIT);
  27.  
  28. // Monitor on
  29. SendNotifyMessage(GetForegroundWindow(), WM_SYSCOMMAND, SC_MONITORPOWER, -1);
  30. for(i= 0; i<4; i++){
  31. mouse_event(MOUSEEVENTF_MOVE, 0, 10, 0, 0);
  32. Sleep(40);
  33. mouse_event(MOUSEEVENTF_MOVE, 0, DWORD(-10), 0, 0);
  34. }
  35. return 0;
  36. }
  37.  
  38. void CmdEnableMonitor(BOOL Enable)
  39. {
  40. if(!Enable && !idThTurnOffMonitor)
  41. // Turn off monitor
  42. CloseHandle(CreateThread(NULL, 0, ThTurnOffMonitor, NULL, 0, &idThTurnOffMonitor));
  43. if(Enable){
  44. // Turn on monitor
  45. PostThreadMessage(idThTurnOffMonitor, WM_QUIT, 0, 0);
  46. idThTurnOffMonitor = 0;
  47. }
  48. }
  49.  
  50. LRESULT CALLBACK KeyboardHook(int nCode, WPARAM wParam, LPARAM lParam)
  51. {
  52. if(nCode == HC_ACTION && (*PDWORD(lParam + 8) & LLKHF_ALTDOWN)){
  53. if(*PDWORD(lParam) == VK_F11) // ALT + F11: Monitor Off
  54. CmdEnableMonitor(true);
  55. if(*PDWORD(lParam) == VK_F12) // ALT + F12: Monitor On
  56. CmdEnableMonitor(false);
  57. if(*PDWORD(lParam) == VK_F10) // ALT + F10: Quit
  58. PostThreadMessage(GetCurrentThreadId(), WM_QUIT, 0, 0);
  59. }
  60.  
  61. if(idThTurnOffMonitor)
  62. return -1;
  63.  
  64. return CallNextHookEx(WHookKeyboard, nCode, wParam, lParam);
  65. }
  66.  
  67. LRESULT WINAPI MouseEvent(int nCode, WPARAM wParam, LPARAM lParam)
  68. {
  69. if(nCode == HC_ACTION && idThTurnOffMonitor)
  70. return -1;
  71. return CallNextHookEx(WHookMouse, nCode, wParam, lParam);
  72. }
  73.  
  74. WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
  75. {
  76. MSG msg;
  77.  
  78. idThTurnOffMonitor = 0;
  79. WHookKeyboard = SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC)KeyboardHook, hInstance, 0);
  80. WHookMouse = SetWindowsHookEx(WH_MOUSE_LL, (HOOKPROC)KeyboardHook, hInstance, 0);
  81.  
  82. // Bucle de mensajes:
  83. do{
  84. GetMessage(&msg, 0, 0, 0);
  85. DispatchMessage(&msg);
  86. }while(msg.message != WM_QUIT);
  87.  
  88. CmdEnableMonitor(true);
  89. UnhookWindowsHookEx(WHookKeyboard);
  90. UnhookWindowsHookEx(WHookMouse);
  91.  
  92. return 0;
  93. }
  94. //---------------------------------------------------------------------------

Saludos.


  • 2

#4 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.269 mensajes
  • LocationArgentina

Escrito 02 septiembre 2016 - 07:49

Interesante amigo...

Mi duda es ¿Esto es para hacerlo en local, sobre la propia máquina, no es cierto?

¿Se puede hacerlo remotamente?

 

Se que hay formas de hacer que a ciertas horas se apaguen y prendas equipos de forma totalmente remota aunque no las he explorado.

 

Saludos,


  • 0

#5 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.876 mensajes
  • LocationMadrid - España

Escrito 02 septiembre 2016 - 10:49

Interesante amigo...

Mi duda es ¿Esto es para hacerlo en local, sobre la propia máquina, no es cierto?

¿Se puede hacerlo remotamente?

 

Se que hay formas de hacer que a ciertas horas se apaguen y prendas equipos de forma totalmente remota aunque no las he explorado.

 

Saludos,

 

Efectivamente es para hacerlo en local, pero nada impide hacerlo en red, de hecho estoy haciendo unas pruebas y publicaré la desaferentación en red, con lo que el PC quedaría inutilizado para el usuario pero trabajando, quedando liberado por el "administrador" desde la red,

 

 

Saludos.


  • 0

#6 genriquez

genriquez

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 520 mensajes
  • LocationCali, Colombia

Escrito 02 septiembre 2016 - 10:52

DataSnap tiene una funcionalidad interesante de CallBacks,  lo único que hay que garantizar es la conexión del cliente hacia el servidor, y luego se pueden enviar mensajes hacia ese cliente,  sería una buena forma de enviar el mensaje de apagado, 


  • 0

#7 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.011 mensajes
  • LocationMéxico

Escrito 02 septiembre 2016 - 11:19

Interesante amigo...

Mi duda es ¿Esto es para hacerlo en local, sobre la propia máquina, no es cierto?

¿Se puede hacerlo remotamente?

 

Se que hay formas de hacer que a ciertas horas se apaguen y prendas equipos de forma totalmente remota aunque no las he explorado.

 

Saludos,

 

 

Pues si, porque lo que quieres es que no se metan en tu maquina en algún  descuido,

 

Oops, eso lo pensé o lo dije!!!! :D :D :D 

 

Saludos


  • 0

#8 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.876 mensajes
  • LocationMadrid - España

Escrito 02 septiembre 2016 - 01:52

DataSnap tiene una funcionalidad interesante de CallBacks,  lo único que hay que garantizar es la conexión del cliente hacia el servidor, y luego se pueden enviar mensajes hacia ese cliente,  sería una buena forma de enviar el mensaje de apagado, 

 

Para eso Windows tiene el comando de consola shutdown que funciona también en red.

 

 

Saludos.


  • 0

#9 sir.dev.a.lot

sir.dev.a.lot

    Advanced Member

  • Miembros
  • PipPipPip
  • 545 mensajes
  • Location127.0.0.1

Escrito 02 septiembre 2016 - 02:17

¿Nunca se os ha ocurrido apagarle a alguien el monitor por código de forma que no pueda encenderlo?, a mi sí y no voy a decir porqué  *-)

 

Apagar el monitor es fácil con SC_MONITORPOWER pero en cuanto se toca el teclado o el ratón, se enciende. Para darle consistencia al apagado he escrito un thread que repite el apagado cada 100 ms y listo. Pero al hacer eso el usuario cambiaría cosas inconscientemente en las aplicaciones en primer plano al tratar de activar el monitor aporreando el teclado o interactuando desesperadamente con el ratón. Para solucionar este inconveniente bloqueo el teclado y el ratón.

 

¡Ni monitor, ni teclado ni ratón! Que no cunda el pánico, que las combinaciones de teclas en un hook al teclado nos abren la puerta:

    ALT - F10: Cierra el programa devolviéndonos el control.

    ALT - F11: Nos devuelve el control sin cerrar el programa.

    ALT - F12: Apaga el monitor y bloquea el teclado + ratón.

 

La aplicación no tiene interface gráfico y queda como sigue:


delphi
  1. program MonitorPower;
  2.  
  3. uses
  4. Windows, Messages;
  5.  
  6. var
  7. idThTurnOffMonitor: DWORD = 0;
  8. WHookKeyboard: HHOOK = 0;
  9. WHookMouse: HHOOK = 0;
  10.  
  11. function ThTurnOffMonitor(): DWORD; stdcall
  12. var
  13. msg: TMsg;
  14. i: DWORD;
  15. begin
  16. // Monitor off
  17. repeat PeekMessage(msg,0,0,0, PM_REMOVE);
  18. Sleep(100);
  19. SendNotifyMessage(GetForegroundWindow(), WM_SYSCOMMAND, SC_MONITORPOWER, 2);
  20. DispatchMessage(msg);
  21. until (msg.Message = WM_QUIT);
  22.  
  23. // Monitor on
  24. SendNotifyMessage(GetForegroundWindow(), WM_SYSCOMMAND, SC_MONITORPOWER, -1);
  25. for i:= 0 to 4 do
  26. begin
  27. mouse_event(MOUSEEVENTF_MOVE, 0, 10, 0, 0);
  28. Sleep(40);
  29. mouse_event(MOUSEEVENTF_MOVE, 0, DWORD(-10), 0, 0);
  30. end;
  31. Result:= 0;
  32. end;
  33.  
  34. procedure CmdEnableMonitor(Enable: BOOL);
  35. begin
  36. if not Enable and (idThTurnOffMonitor = 0) then
  37. // Turn off monitor
  38. CloseHandle(CreateThread(nil, 0, @ThTurnOffMonitor, nil, 0, idThTurnOffMonitor));
  39. if Enable then
  40. begin
  41. // Turn on monitor
  42. PostThreadMessage(idThTurnOffMonitor, WM_QUIT, 0, 0);
  43. idThTurnOffMonitor:= 0;
  44. end;
  45. end;
  46.  
  47. function KeyboardHook(Code, wParam, lParam: Integer): Integer; stdcall;
  48. begin
  49. if (Code = HC_ACTION) and LongBool(PDWORD(lParam + 8)^ and $20{LLKHF_ALTDOWN}) then
  50. begin
  51. if PDWORD(lParam)^ = VK_F11 then // ALT + F11: Monitor Off
  52. CmdEnableMonitor(true);
  53. if PDWORD(lParam)^ = VK_F12 then // ALT + F11: Monitor On
  54. CmdEnableMonitor(false);
  55. if PDWORD(lParam)^ = VK_F10 then // ALT + F10: Quit
  56. PostThreadMessage(GetCurrentThreadId, WM_QUIT, 0, 0);
  57. end;
  58. Result:= -1;
  59. if idThTurnOffMonitor = 0 then
  60. Result:= CallNextHookEx(WHookKeyboard, Code, wParam, lParam);
  61. end;
  62.  
  63. function MouseHook(Code, wParam, lParam: Integer): Integer; stdcall;
  64. begin
  65. Result:= -1;
  66. if (Code <> HC_ACTION) or (idThTurnOffMonitor = 0) then
  67. Result:= CallNextHookEx(WHookMouse, Code, wParam, lParam);
  68. end;
  69.  
  70. var
  71. msg: TMsg;
  72. begin
  73. idThTurnOffMonitor:= 0;
  74. WHookKeyboard:= SetWindowsHookEx(13{WH_KEYBOARD_LL}, @KeyboardHook, HInstance, 0);
  75. WHookMouse:= SetWindowsHookEx(14{WH_MOUSE_LL}, @KeyboardHook, HInstance, 0);
  76.  
  77. // Bucle de mensajes:
  78. repeat GetMessage(msg, 0, 0, 0);
  79. DispatchMessage(msg);
  80. until (msg.Message = WM_QUIT);
  81.  
  82. CmdEnableMonitor(true);
  83. UnhookWindowsHookEx(WHookKeyboard);
  84. UnhookWindowsHookEx(WHookMouse);
  85. end.

El código puede tener su utilidad como botón del pánico, una broma no demasiado pesada o... la imaginación es libre.

 

 

 

Saludos.

 

Estaba leyendo y vi esto en el comentario

 

if PDWORD(lParam)^ = VK_F12 then // ALT + F11: Monitor On

 

tambien esta en C++

 

Saludos!


  • 1

#10 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.876 mensajes
  • LocationMadrid - España

Escrito 02 septiembre 2016 - 02:45

Estaba leyendo y vi esto en el comentario

 

if PDWORD(lParam)^ = VK_F12 then // ALT + F11: Monitor On

 

tambien esta en C++

 

Saludos!

 

Muy cierto, es el efecto de mi vagancia a la hora de escribir y usar el corta-pega :

 

Menos mal que el código está correcto pues no recuperaríamos el control sin matar el programa  :p :D :D :D

 

Ya he editado esos comentarios (y)

 

 

 

Saludos


  • 0

#11 genriquez

genriquez

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 520 mensajes
  • LocationCali, Colombia

Escrito 08 septiembre 2016 - 08:02

Para eso Windows tiene el comando de consola shutdown que funciona también en red.

 

 

Saludos.

 

El CallBacks funciona sobre internet, aún sobre routers.  es bien interesante.


  • 0