Ir al contenido


Foto

Monitorizando el Shell sólo con la API


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

#1 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4.107 mensajes
  • LocationMadrid - España

Escrito 02 junio 2010 - 04:50

A raíz de este hilo, en el que se preguntaba cómo podía nuestra aplicación enterarse de la creación de un nuevo archivo, me acordé de que esta utilidad la había implementado mas ampliamente en el hilo Treeview como explorer con checkboxes que alguno seguisteis.

Aunque egostar me aconsejó no traducir el código desde el C al delphi, por la razón de que delphi tiene un componente que abarca esas utilidades, lo he hecho por un motivo. La implementación que realizo es sencilla y se basa sólo en la API de Windows, con lo que su utilidad se hará patente en aquellos programas en que por los motivos que sean, queramos utilizar API pura sin librerías de clase alguna.

La filosofía es sencilla. Debemos dar a una ventana de nuestra aplicación de la capacidad de recibir y responder a los mensajes que se envían al Shell y sus extensiones al producirse cambios. Esas notificaciones se envían mediante la API SHChangeNotify. Los mensajes que a los que debemos responder los encontramos también aquí. Con esa misma API, podemos notificar al Shell de los cambios que nos parezcan oportunos.

El código que nos habilita para recibir los mensajes está en una unit:

delphi
  1. unit ShellMonitor;
  2.  
  3. interface
  4.  
  5. uses
  6.   Windows, Messages, Shlobj;
  7.  
  8. function StartNotification(hWnd: THandle; Msg: integer): DWORD;
  9. procedure EndNotification(NotifyRegister: DWORD);
  10.  
  11. implementation
  12.  
  13. type
  14.  
  15. PCIDLIST_ABSOLUTE = ^ITEMIDLIST;
  16.  
  17. SHChangeNotifyEntry = record
  18.   pidl:      PCIDLIST_ABSOLUTE;
  19.   fRecursive: boolean;
  20. end;
  21. PSHChangeNotifyEntry = ^SHChangeNotifyEntry;
  22.  
  23. const
  24.   SHCNRF_INTERRUPT_LEVEL    = $0001;
  25.   SHCNRF_SHELL_LEVEL        = $0002;
  26.  
  27. function SHChangeNotifyRegister(hwnd: THandle; fSources, fEvents, wMsg, cEntries: integer; pshcne: PSHChangeNotifyEntry): ULONG; stdcall; external 'shell32.dll' name 'SHChangeNotifyRegister';
  28. function SHChangeNotifyDeregister(ulID: integer): boolean; stdcall; external 'shell32.dll' name 'SHChangeNotifyDeregister';
  29.  
  30. function StartNotification(hWnd: THandle; Msg: integer): DWORD;
  31. var
  32.     shCNE: SHChangeNotifyEntry;
  33.     Events: DWORD;
  34. begin
  35.     shCNE.pidl := nil;
  36.     shCNE.fRecursive := TRUE;
  37.  
  38.     // Eventos que se van a registrar
  39.     Events := SHCNE_MEDIAINSERTED or SHCNE_MEDIAREMOVED or SHCNE_DRIVEADD or
  40.               SHCNE_DRIVEREMOVED or SHCNE_UPDATEDIR or SHCNE_UPDATEITEM or
  41.               SHCNE_RENAMEFOLDER or SHCNE_RENAMEITEM or SHCNE_MKDIR or
  42.               SHCNE_RMDIR or SHCNE_CREATE or SHCNE_DELETE;
  43.  
  44.     Result := SHChangeNotifyRegister(hWnd, SHCNRF_INTERRUPT_LEVEL or SHCNRF_SHELL_LEVEL, Events, Msg, 1, @shCNE);
  45. end;
  46.  
  47. procedure EndNotification(NotifyRegister: DWORD);
  48. begin
  49.     if (NotifyRegister <> 0) then
  50.       SHChangeNotifyDeregister(NotifyRegister);
  51.  
  52. end;
  53.  
  54. end.

StartNotification habilita a la ventana dada por hWnd a la recepción del mensaje Msg, que será el que el Sistema nos enviará al producirse alguno de los eventos que hemos registrado. EndNotification deshabilita la recepción.

Ahora voy a poner un ejemplo hecho con la VCL tradicional para mostrar cómo localizar y responder a los eventos deseados. Esto podría trasladarse a un programa sin VCL. Muestro la función de respuesta al mensaje:

delphi
  1. procedure TForm1.WMShellChanged(var Msg: TMessage);
  2. var
  3.   i: integer;
  4.   ppidl: PPITEMIDLIST;
  5.   Path: array [0..MAX_PATH] of CHAR;
  6. begin
  7.   ppidl:= PPITEMIDLIST(Msg.WParam);
  8.   SHGetPathFromIDList(ppidl^, Path);
  9.   if Path[0] = #0 then exit;
  10.   case Msg.LParam and $7FFFFFF of
  11.     SHCNE_UPDATEDIR:
  12.       Memo1.Lines.Add('Contenido de la carpeta cambiado: ' + String(Path));
  13.     SHCNE_MKDIR:
  14.       Memo1.Lines.Add('Carpeta creada: ' + String(Path));
  15.     SHCNE_RMDIR:
  16.       Memo1.Lines.Add('Carpeta borrada: ' + String(Path));
  17.     SHCNE_CREATE:
  18.       Memo1.Lines.Add('Archivo nuevo: ' + String(Path));
  19.     SHCNE_DELETE:
  20.       Memo1.Lines.Add('Archivo borrado: ' + String(Path));
  21.     SHCNE_RENAMEFOLDER:
  22.     begin
  23.       i:=1;
  24.       lstrcpy(Path, ' a ');
  25.       SHGetPathFromIDList(PAPITEMIDLIST(ppidl)[i], Path + lstrlen(Path));
  26.       Memo1.Lines.Add('Carpata renombrada: ' + String(Path));
  27.     end;
  28.     SHCNE_RENAMEITEM:
  29.     begin
  30.       i:=1;
  31.       lstrcat(Path, ' a ');
  32.       SHGetPathFromIDList(PAPITEMIDLIST(ppidl)[i], Path + lstrlen(Path));
  33.       Memo1.Lines.Add('Archivo renombrado: ' + String(Path));
  34.     end;
  35.     SHCNE_DRIVEADD:
  36.       Memo1.Lines.Add('Disco insertado: ' + String(Path));
  37.     SHCNE_DRIVEREMOVED:
  38.       Memo1.Lines.Add('Disco retirado: ' + String(Path));
  39.     SHCNE_UPDATEITEM:
  40.       // La desconexión del cable de red viene por aquí.
  41.       Memo1.Lines.Add(Path);
  42.   end;
  43. end;

Subo un archivo con la unit ShellMonitor y una aplicación de ejemplo.

PD: Vuelvo a subir el archivo por problemas en las descargas.
Espero que sea de utilidad.

Saludos.

Archivos adjuntos


  • 1

#2 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.446 mensajes
  • LocationMéxico

Escrito 02 junio 2010 - 04:58

Amigo escafandra, mis respetos, es usted un duro, llegando a casa lo descargaré. (y)

Salud OS
  • 0

#3 Wilson

Wilson

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.137 mensajes

Escrito 03 junio 2010 - 06:34

Gracias maestro Escafandra, como siempre muy buen código.
  • 0

#4 enecumene

enecumene

    Webmaster

  • Administrador
  • 7.419 mensajes
  • LocationRepública Dominicana

Escrito 04 junio 2010 - 08:41

:o  :|  :lipsrsealed:
  • 0

#5 poliburro

poliburro

    Advanced Member

  • Administrador
  • 4.945 mensajes
  • LocationMéxico

Escrito 04 junio 2010 - 09:12

Amigo escafandra, como siempre sus aportaciones son impresionantes, Gracias por compartir.
  • 0

#6 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4.107 mensajes
  • LocationMadrid - España

Escrito 16 septiembre 2010 - 06:54

Vista la necesidad de presentar este truco en C++ aquí está el código:


cpp
  1. //---------------------------------------------------------------------------
  2. #define NO_WIN32_LEAN_AND_MEAN
  3.  
  4. #include <vcl.h>
  5. #pragma hdrstop
  6. #include <shlobj.h>
  7. #include <shellapi.h>
  8. #include <stdio.h>
  9. #include "Unit1.h"
  10. //---------------------------------------------------------------------------
  11. #pragma package(smart_init)
  12. #pragma resource "*.dfm"
  13.  
  14. TForm1 *Form1;
  15.  
  16. #define WM_USER_SHELLCHANGED WM_USER + 100
  17.  
  18. #define  SHCNRF_INTERRUPT_LEVEL    0x0001
  19. #define  SHCNRF_SHELL_LEVEL        0x0002
  20. #define  SHCNRF_RECURSIVE_INTERRUPT 0x1000
  21. #define  SHCNRF_NEW_DELIVERY        0x8000  // Messages received use shared memory. Call SHChangeNotification_Lock to access the actual data
  22.  
  23.  
  24. typedef struct _SHChangeNotifyEntry
  25. {
  26.     LPCITEMIDLIST pidl;
  27.     BOOL  fRecursive;
  28. } SHChangeNotifyEntry;
  29.  
  30. typedef ULONG(WINAPI *PSHChangeNotifyRegister)(HWND hwnd, int fSources, LONG fEvents, UINT wMsg,
  31.                                     int cEntries, const SHChangeNotifyEntry *pshcne);
  32.  
  33. typedef BOOL (WINAPI *PSHChangeNotifyDeregister)(ULONG ulID);
  34.  
  35.  
  36. ULONG m_ulSHChangeNotifyRegister;
  37.  
  38. //---------------------------------------------------------------------------
  39. __fastcall TForm1::TForm1(TComponent* Owner)
  40.         : TForm(Owner)
  41. {
  42. }
  43. //---------------------------------------------------------------------------
  44.  
  45. // SHChangeNotify
  46. void __fastcall TForm1::WndProc(Messages::TMessage &Message)
  47. {
  48.   if (Message.Msg == WM_USER_SHELLCHANGED){
  49.     //  ppidl[0] =  the previous PIDL or name of the folder.
  50.     //  ppidl[0] =  the new PIDL or name of the folder.
  51.     LPITEMIDLIST *ppidl = (LPITEMIDLIST*)Message.WParam;
  52.     char Path[MAX_PATH];
  53.  
  54.     switch(Message.LParam & 0x7FFFFFF)
  55.     {
  56.       case SHCNE_UPDATEDIR:
  57.         SHGetPathFromIDList(ppidl[0], Path);
  58.         if(*Path)
  59.             Memo1->Lines->Add("Contenido de la carpeta cambiado: " + String(Path));
  60.       break;
  61.       case SHCNE_MKDIR:
  62.         SHGetPathFromIDList(ppidl[0], Path);
  63.         if(*Path)
  64.             Memo1->Lines->Add("Carpeta creada: " + String(Path));
  65.       break;
  66.       case SHCNE_RMDIR:
  67.         SHGetPathFromIDList(ppidl[0], Path);
  68.         if(*Path)
  69.             Memo1->Lines->Add("Carpeta borrada: " + String(Path));
  70.       break;
  71.       case SHCNE_CREATE:
  72.         SHGetPathFromIDList(ppidl[0], Path);
  73.         if(*Path)
  74.             Memo1->Lines->Add("Archivo nuevo: " + String(Path));
  75.       break;
  76.       case SHCNE_DELETE:
  77.         SHGetPathFromIDList(ppidl[0], Path);
  78.         if(*Path)
  79.             Memo1->Lines->Add("Archivo borrado: " + String(Path));
  80.       break;
  81.       case SHCNE_RENAMEFOLDER:
  82.         SHGetPathFromIDList(ppidl[0], Path);
  83.         strcat(Path, " a ");
  84.         SHGetPathFromIDList(ppidl[1], Path + strlen(Path));
  85.         if(*Path)
  86.           Memo1->Lines->Add("Carpata renombrada: " + String(Path));
  87.       break;
  88.       case SHCNE_RENAMEITEM:
  89.         SHGetPathFromIDList(ppidl[0], Path);
  90.         strcat(Path, " a ");
  91.         SHGetPathFromIDList(ppidl[1], Path + strlen(Path));
  92.         if(*Path)
  93.           Memo1->Lines->Add("Archivo renombrado: " + String(Path));
  94.       break;
  95.       case SHCNE_DRIVEADD:
  96.         SHGetPathFromIDList(ppidl[0], Path);
  97.         if(*Path)
  98.           Memo1->Lines->Add("Disco insertado: " + String(Path));
  99.       break;
  100.       case SHCNE_DRIVEREMOVED:
  101.         SHGetPathFromIDList(ppidl[0], Path);
  102.         if(*Path)
  103.           Memo1->Lines->Add("Disco retirado: " + String(Path));
  104.       case SHCNE_UPDATEITEM:
  105.         // La desconexión del cable de red viene por aquí.
  106.         SHGetPathFromIDList(ppidl[0], Path);
  107.         if(*Path)
  108.           Memo1->Lines->Add("SHCNE_UPDATEITEM " + String(Path));
  109.  
  110.       }
  111.  
  112.   }
  113.  
  114.   TForm::WndProc(Message);
  115. }
  116.  
  117. void __fastcall TForm1::StartNotification()
  118. {
  119.     PSHChangeNotifyRegister SHChangeNotifyRegister =
  120.           (PSHChangeNotifyRegister)GetProcAddress(GetModuleHandle("shell32.dll"), "SHChangeNotifyRegister");
  121.  
  122.     LPITEMIDLIST ppidl1, ppidl2;
  123.     SHChangeNotifyEntry shCNE;
  124.     DWORD Atributes;
  125.  
  126.     shCNE.pidl = 0;
  127.     shCNE.fRecursive = TRUE;
  128.  
  129.  
  130.     // Eventos que se van a registrar
  131.     LONG Events = SHCNE_MEDIAINSERTED | SHCNE_MEDIAREMOVED | SHCNE_DRIVEADD |
  132.                   SHCNE_DRIVEREMOVED | SHCNE_UPDATEDIR | SHCNE_UPDATEITEM |
  133.                   SHCNE_RENAMEFOLDER | SHCNE_RENAMEITEM | SHCNE_MKDIR | SHCNE_RMDIR |
  134.                   SHCNE_CREATE |SHCNE_DELETE;
  135.  
  136.     m_ulSHChangeNotifyRegister = SHChangeNotifyRegister(Handle, SHCNRF_INTERRUPT_LEVEL | SHCNRF_SHELL_LEVEL, Events, WM_USER_SHELLCHANGED, 1, &shCNE);
  137. }
  138. //---------------------------------------------------------------------------
  139.  
  140. void __fastcall TForm1::FormDestroy(TObject *Sender)
  141. {
  142.     PSHChangeNotifyDeregister SHChangeNotifyDeregister =
  143.       (PSHChangeNotifyDeregister)GetProcAddress(GetModuleHandle("shell32.dll"), "SHChangeNotifyDeregister");
  144.  
  145.     if(m_ulSHChangeNotifyRegister)
  146.       SHChangeNotifyDeregister(m_ulSHChangeNotifyRegister);
  147.  
  148. }
  149. //---------------------------------------------------------------------------
  150.  
  151. void __fastcall TForm1::FormCreate(TObject *Sender)
  152. {
  153.   StartNotification();
  154. }



Saludos.
  • 0

#7 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.446 mensajes
  • LocationMéxico

Escrito 15 febrero 2012 - 02:52

Hola

Sólo para agradecer a escafandra por éste código, me ha resultado genial para una aplicación que estoy creando ahora mismo :)

Saludos
  • 0

#8 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.446 mensajes
  • LocationMéxico

Escrito 16 febrero 2012 - 10:35

Hola

Trabajando con el código, veo que monitorea la actividad de todo el disco, no he podido encontrar donde se configura que el monitoreo sea solamente en un directorio en particular, lo que hago es validar que el evento se está produciendo en el directorio que quiero monitorear.



delphi
  1.   //Verificamos que el evento ser haya producido en el directorio que deseamos
  2.   Ruta := ExtractFilePath( String(Path) );
  3.   if Ruta <> DirMonitoreo then exit;



¿ Hay alguna otra forma ?

Saludos
  • 0

#9 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4.107 mensajes
  • LocationMadrid - España

Escrito 16 febrero 2012 - 12:53

Sólo para agradecer a escafandra por éste código, me ha resultado genial para una aplicación que estoy creando ahora mismo :)

Gracias a ti por usarlo.

Trabajando con el código, veo que monitorea la actividad de todo el disco, no he podido encontrar donde se configura que el monitoreo sea solamente en un directorio en particular, lo que hago es validar que el evento se está produciendo en el directorio que quiero monitorear...

...¿ Hay alguna otra forma ?



En realidad no monitorea la actividad de todo el disco, sino de todo el Shell. Puedes registrar los mensajes que quieres recibir, en el ejemplo registro muchos para explicar el significado de cada uno, pero tu debes registrar sólo los que te interesen.

El enfoque del evento lo haces bien, si no corresponde con la carpeta deseada, abortas... También puedes fijarte en los archivos, depende de la necesidad que tengas que cubrir.


Saludos.
  • 0

#10 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.446 mensajes
  • LocationMéxico

Escrito 16 febrero 2012 - 01:06

En realidad no monitorea la actividad de todo el disco, sino de todo el Shell. Puedes registrar los mensajes que quieres recibir, en el ejemplo registro muchos para explicar el significado de cada uno, pero tu debes registrar sólo los que te interesen.

El enfoque del evento lo haces bien, si no corresponde con la carpeta deseada, abortas... También puedes fijarte en los archivos, depende de la necesidad que tengas que cubrir.

Saludos.


En realidad no me interesa el archivo, es un directorio para almacenar archivos específicos y que está parametrizado en el programa que los genera.

Y si, lo conceptualicé mal se monitorea el shell :). Y me di cuenta porque una vez que obtengo ese archivo lo muevo a otro directorio y lo envió dos veces :s.

Bueno, además como sólo me interesa los nuevos archivos hice esto:


delphi
  1.   Events := SHCNE_CREATE;
  2.   Result := SHChangeNotifyRegister(hWnd, SHCNRF_INTERRUPT_LEVEL or SHCNRF_SHELL_LEVEL, Events, Msg, 1, @shCNE);

Pero pensando en la posibilidad de que el programa lo cierren..... cosa mas frecuente de lo que uno cree :D :D :D debo idear un proceso alterno, pero bueno eso ya es menos complejo, con un Findfirst lo puedo resolver, pero... (como siempre hay un pero jejeje) necesito "parar" la lectura del shell cuando haga eso.

Ya veré la mejor forma :)

Gracias amigo.
  • 0

#11 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4.107 mensajes
  • LocationMadrid - España

Escrito 16 febrero 2012 - 02:28

Pero pensando en la posibilidad de que el programa lo cierren..... cosa mas frecuente de lo que uno cree :D :D :D debo idear un proceso alterno...

Pues dependiendo de la naturaleza del programa puedes diseñarlo como servicio, o ejecutarlo como otro usuario (administrador, por ejemplo) así es mas difícil cerrarlo desde un taskmanager, anular éste o también puedes usar el truco que publiqué en platino ProcessProtector.
 

...pero bueno eso ya es menos complejo, con un Findfirst lo puedo resolver, pero... (como siempre hay un pero jejeje) necesito "parar" la lectura del shell cuando haga eso.

En el mismo ejemplo tienes la respuesta:


delphi
  1. procedure EndNotification(NotifyRegister: DWORD);
  2. begin
  3.     if (NotifyRegister <> 0) then
  4.       SHChangeNotifyDeregister(NotifyRegister);
  5.  
  6. end;


Saludos.
  • 0

#12 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.446 mensajes
  • LocationMéxico

Escrito 16 febrero 2012 - 02:38

Pues dependiendo de la naturaleza del programa puedes diseñarlo como servicio, o ejecutarlo como otro usuario (administrador, por ejemplo) así es mas difícil cerrarlo desde un taskmanager, anular éste o también puedes usar el truco que publiqué en platino ProcessProtector.


Si, eso no me preocupa, solo que debo tomarlo en cuenta :)
 

En el mismo ejemplo tienes la respuesta:


Si, ya lo había visto, pero me refería a la logística de como y cuando :)

Saludos


  • 0

#13 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4.107 mensajes
  • LocationMadrid - España

Escrito 16 febrero 2012 - 03:00

...me refería a la logística de como y cuando :)


En ese caso, tu mejor que nadie, te darás cuenta del detalle... Quizás en cada arranque nuevo del programa...


Saludos.
  • 0

#14 luk2009

luk2009

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.040 mensajes
  • LocationSanto Domingo

Escrito 19 septiembre 2015 - 08:21

Hola Como estan

 

Probando el codigo de escafandra he visto que si los cambios los realiza un programa, estos no se detectan por este metodo.

Me explico, tengo un programa que graba las llamadas telefonicas y que segun la fecha, crea un archivo de audio con esa llamada. La idea es monitorear esas carpetas y cuando se genere un nuevo archivo de audio, tomar la ruta completa del archivo para guardarlo en una base de datos firebird. 

 

Si cambio algo, de forma manual en esos directorios, los cambios son detectados, pero cuando el programa crea un archivo nuevo, no pasa nada.

 

Que se puede hacer en estos casos?


  • 0

#15 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4.107 mensajes
  • LocationMadrid - España

Escrito 19 septiembre 2015 - 08:55

Probando el codigo de escafandra he visto que si los cambios los realiza un programa, estos no se detectan por este metodo.


No se como lo estás usando. Como me ha llamado la atención tu comentario he abierto la aplicación ShellMonitor publicada como adjunto en este tema, he dado al botón start y he compilado un programa que estoy escribiendo. Resultado: todos los archivos creados han aparecido el el monitor. Luego he puesto mi keylogger en marcha y el resultado es que ha aparecido en el monitor el archivo donde graba lo capturado. Ninguno de los casos ha sido a mano...

Lo que te puede ocurrir es que no detecte cambios en un archivo no nuevo, el monitor de la shell no lo detecta, a no ser que M$ haya cambiado algo en los nuevos S.O. eso ya se discutió aquí.

No se puede monitorizar un archivo concreto pero si detectará un cambio ocurrido en la carpeta, con esa información se puede recorrer y verificar las fechas...

 

 

Saludos.


  • 0

#16 luk2009

luk2009

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.040 mensajes
  • LocationSanto Domingo

Escrito 19 septiembre 2015 - 09:09

Gracias Esca por responder tan rapido

 

Estoy usando windows 7 y he bajado el archivo de este hilo y sin hacer ningun cambio, no me detecta esos cambios.

 

El programa lo que hace es crear un archivo de audio  nuevo, por cada llamada que se genera y le da el nombre segun la fecha, la hora y el telefono al cual se llamó.

 

C:\U2_V3.11\usb-record\2015\09\19\2015-09-19_01-17-10_000_8095487273

 

te reitero si hago cualquier cambio de forma manual en este directorio o copio el nombre o lo que sea, lo detecta inmediatamente, pero cuando se crea el archivo, no detecta nada.


  • 0

#17 luk2009

luk2009

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.040 mensajes
  • LocationSanto Domingo

Escrito 19 septiembre 2015 - 09:38

https://www.youtube....h?v=289CyRPn3QE

 

ese es el programa que utilizo para grabar las llamadas y como ves crea un archivo nuevo por cada llamada


  • 0

#18 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4.107 mensajes
  • LocationMadrid - España

Escrito 19 septiembre 2015 - 09:55

Creo que ya se lo que pasa. ¿Que usuario ejecuta esa app?. El Monitor solo puede capturar el shell del usuario que lo ejecuta, no de otro, pues no se mandan notificaciones.

Prueba con programas ejecutados por el mismo usuario que el monitor y me cuentas.

 

Saludos.


  • 0

#19 luk2009

luk2009

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.040 mensajes
  • LocationSanto Domingo

Escrito 19 septiembre 2015 - 10:19

pues los ejecute los dos como administrador y nada.

 

por si acaso abri el shellmonitor primero y luego el usbrecorder y nada.

 

estuve probando con otro programa que encontre en la red http://www.ajpdsoft....article&sid=427 y tampoco detecta nada.


  • 0

#20 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4.107 mensajes
  • LocationMadrid - España

Escrito 19 septiembre 2015 - 11:15

Ejecuta el monitor y el notepad como usuario normal. Guarda el archivo del notepad a ver que pasa.

 

Se subo el monitor por si acaso...

 

 

Saludos.

Archivos adjuntos


  • 0




IP.Board spam blocked by CleanTalk.