none
Gestión de la inactividad/actividad de una aplicación. RRS feed

  • Pregunta

  • Hola a todos
    Tengo una pregunta sencilla que no encuentro como resolver y seguro que es muy fácil.
    Quiero controlar la inactividad del sistema para que me realice cosas (dependiendo del tiempo puede cambiar de usuario reiniciando valores, ejecutar un salvapantallas o lanzar un proceso pesado).
    La cuestión es que había pensado hacerlo con un timer, pero me encuentro que de esta forma tengo que ir reiniciándolo en todos los eventos  que se produzcan en la aplicación, capturar los eventos de ratón, y teclado para todos los labels, pictures, textbox, etc,etc y eso lo veo muy engorroso.
    Estoy seguro que hay otra forma de controlarlo pero no la encuentro…. Podríais instruirme?
    Por otro lado también quiero controlar que una vez iniciado un proceso, pueda romperlo cuando un usuario empiece a usar la aplicación, y tampoco veo la forma de hacerlo.
    Un saludo y gracias de antemano.
    sábado, 24 de abril de 2010 8:40

Respuestas

  • Hola NewSpike

    Se me ha ocurrido una idea de como hacer todo esto, a ver que te parece, vamos por pasos:

    Primero, en tu clase donde quieras controlar todo esto importa el namespace InteropServices

    Imports System.Runtime.InteropServices
    
    public Class TuClase
      '...
      '...
    End Class

    Ahora, dentro de tu clase vamos a importar la funcion GetLasInputInfo de codigo no manejado y crear las estructuras y metodos necesarios para usarla, esto nos dá en milisegundos cuanto tiempo hace que no se toca el teclado o el ratón:

      'Control de Estado del pc.
      <DllImport("User32.dll")> _
      Private Shared Function GetLastInputInfo(ByRef lii As LASTINPUTINFO) As Boolean
      End Function
      'Estructura con el tiempo
      Public Structure LASTINPUTINFO
        Public cbSize As UInteger
        Public dwTime As UInteger
      End Structure
      'Función que devuelve el numero de milisegundos sin actividad
      Public Shared Function GetIdle() As UInteger
        Dim lii As New LASTINPUTINFO()
        lii.cbSize = Convert.ToUInt32((Marshal.SizeOf(lii)))
        GetLastInputInfo(lii)
        Return Convert.ToUInt32(Environment.TickCount) - lii.dwTime
      End Function

    Bien, Ahora vamos a crear un timer y un backgroundworker que nos ayudaran a hacer todo lo que necesitamos:

      'Timer que controlara el estado de la app.
      Private WithEvents EstadoApp As New System.Timers.Timer()
      'Proceso en Background.
      Private WithEvents AsyncWorker As New System.ComponentModel.BackgroundWorker

    Y vamos a empezar a trabajar! En tu form load, por ejemplo, inicializamos el timer y el worker:

      Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        'Inicializamos el worker
        AsyncWorker.WorkerSupportsCancellation = True
        'Establecemos las propiedades de nuestro temporizador.
        EstadoApp.Interval = 1000
        EstadoApp.Start()
      End Sub

    Bien, capturamos el evento Elapsed del timer donde comprobamos la actividad, en este caso, yo compruebo que llevemos al menos 1 segundo sin actividad:

      Private Sub EstadoApp_Elapsed(ByVal sender As Object, ByVal e As System.Timers.ElapsedEventArgs) Handles EstadoApp.Elapsed
        Dim IdleTm As Integer = GetIdle()
        If IdleTm > 1000 Then
          ListBox1.Invoke(New AddItemDelegate(AddressOf AddItem), "El PC no se usa por :" + IdleTm.ToString)
          'El pc no se está usando, Ejecutamos una tarea asyncrona usando un backgroundWorker
          'Paramos el Timer de estado, dentro de nuestro worker comprobaremos si seguimos idles.
          EstadoApp.Stop()
          'Iniciamos el Worker.
          AsyncWorker.RunWorkerAsync()
        End If
      End Sub

    Y por último declaramos el evento DoWork y Completed del backgroundworker, donde realizaremos nuestro trabajo:

      Private Sub AsyncWorker_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles AsyncWorker.DoWork
        Dim IdleTm As Integer = GetIdle()
        If IdleTm < 1000 Then
          'Cancelamos la tarea.
          AsyncWorker.CancelAsync()
          Exit Sub
        End If
        'Realizamos nuestro código y vamos comprobando el idle, si es menor a 1 segundo, cancelamos el DoWork y salimos de la sub.
      End Sub
    
      Private Sub AsyncWorker_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles AsyncWorker.RunWorkerCompleted
        'Este método se ejecuta cuando se termina el método DoWork, podemos comprobar el resultado:
        If Not e.Error Is Nothing Then
          'Ocurrio un error.
          Exit Sub
        End If
        If e.Error Is Nothing AndAlso e.Cancelled Then
          'Se cancelo la tarea.
          Exit Sub
        End If
        If e.Error Is Nothing AndAlso e.Cancelled = False Then
          'Acabo la tarea correctamente.
          Exit Sub
        End If
      End Sub

    Y Ya esta, con esto en principio cumplimos todo lo que necesitas!!!

    Es un poco largo, pero es código muy sencillo, falta ponerle control de excepciones y todas esas cosillas, pero eso ya es una tarea a gusto de cada uno.

    Espero que de verdad te sea util, Un gran saludo! 


    MCTS .NET Framework 3.5 Windows Forms Application Development
    Visita mi Blog
    sábado, 24 de abril de 2010 10:41
    Moderador

Todas las respuestas

  • Hola NewSpike

    Se me ha ocurrido una idea de como hacer todo esto, a ver que te parece, vamos por pasos:

    Primero, en tu clase donde quieras controlar todo esto importa el namespace InteropServices

    Imports System.Runtime.InteropServices
    
    public Class TuClase
      '...
      '...
    End Class

    Ahora, dentro de tu clase vamos a importar la funcion GetLasInputInfo de codigo no manejado y crear las estructuras y metodos necesarios para usarla, esto nos dá en milisegundos cuanto tiempo hace que no se toca el teclado o el ratón:

      'Control de Estado del pc.
      <DllImport("User32.dll")> _
      Private Shared Function GetLastInputInfo(ByRef lii As LASTINPUTINFO) As Boolean
      End Function
      'Estructura con el tiempo
      Public Structure LASTINPUTINFO
        Public cbSize As UInteger
        Public dwTime As UInteger
      End Structure
      'Función que devuelve el numero de milisegundos sin actividad
      Public Shared Function GetIdle() As UInteger
        Dim lii As New LASTINPUTINFO()
        lii.cbSize = Convert.ToUInt32((Marshal.SizeOf(lii)))
        GetLastInputInfo(lii)
        Return Convert.ToUInt32(Environment.TickCount) - lii.dwTime
      End Function

    Bien, Ahora vamos a crear un timer y un backgroundworker que nos ayudaran a hacer todo lo que necesitamos:

      'Timer que controlara el estado de la app.
      Private WithEvents EstadoApp As New System.Timers.Timer()
      'Proceso en Background.
      Private WithEvents AsyncWorker As New System.ComponentModel.BackgroundWorker

    Y vamos a empezar a trabajar! En tu form load, por ejemplo, inicializamos el timer y el worker:

      Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        'Inicializamos el worker
        AsyncWorker.WorkerSupportsCancellation = True
        'Establecemos las propiedades de nuestro temporizador.
        EstadoApp.Interval = 1000
        EstadoApp.Start()
      End Sub

    Bien, capturamos el evento Elapsed del timer donde comprobamos la actividad, en este caso, yo compruebo que llevemos al menos 1 segundo sin actividad:

      Private Sub EstadoApp_Elapsed(ByVal sender As Object, ByVal e As System.Timers.ElapsedEventArgs) Handles EstadoApp.Elapsed
        Dim IdleTm As Integer = GetIdle()
        If IdleTm > 1000 Then
          ListBox1.Invoke(New AddItemDelegate(AddressOf AddItem), "El PC no se usa por :" + IdleTm.ToString)
          'El pc no se está usando, Ejecutamos una tarea asyncrona usando un backgroundWorker
          'Paramos el Timer de estado, dentro de nuestro worker comprobaremos si seguimos idles.
          EstadoApp.Stop()
          'Iniciamos el Worker.
          AsyncWorker.RunWorkerAsync()
        End If
      End Sub

    Y por último declaramos el evento DoWork y Completed del backgroundworker, donde realizaremos nuestro trabajo:

      Private Sub AsyncWorker_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles AsyncWorker.DoWork
        Dim IdleTm As Integer = GetIdle()
        If IdleTm < 1000 Then
          'Cancelamos la tarea.
          AsyncWorker.CancelAsync()
          Exit Sub
        End If
        'Realizamos nuestro código y vamos comprobando el idle, si es menor a 1 segundo, cancelamos el DoWork y salimos de la sub.
      End Sub
    
      Private Sub AsyncWorker_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles AsyncWorker.RunWorkerCompleted
        'Este método se ejecuta cuando se termina el método DoWork, podemos comprobar el resultado:
        If Not e.Error Is Nothing Then
          'Ocurrio un error.
          Exit Sub
        End If
        If e.Error Is Nothing AndAlso e.Cancelled Then
          'Se cancelo la tarea.
          Exit Sub
        End If
        If e.Error Is Nothing AndAlso e.Cancelled = False Then
          'Acabo la tarea correctamente.
          Exit Sub
        End If
      End Sub

    Y Ya esta, con esto en principio cumplimos todo lo que necesitas!!!

    Es un poco largo, pero es código muy sencillo, falta ponerle control de excepciones y todas esas cosillas, pero eso ya es una tarea a gusto de cada uno.

    Espero que de verdad te sea util, Un gran saludo! 


    MCTS .NET Framework 3.5 Windows Forms Application Development
    Visita mi Blog
    sábado, 24 de abril de 2010 10:41
    Moderador
  • Madre mia, si que te has trabajado la respuesta, y yo que creía que habría algun tipo de objeto, control, o evento que ya lo manejaría.  :)

    Muchas gracias por tu aportación, en serio no sabes como te lo agradezco.

    Un saludo

    sábado, 24 de abril de 2010 10:58
  • De nada, es un placer poder ayudar!

     

    Si la respuesta te ha sido util, marcala, así otro usuario tendra más sencillo encontrar la solución!


    MCTS .NET Framework 3.5 Windows Forms Application Development
    Visita mi Blog
    sábado, 24 de abril de 2010 16:17
    Moderador