Este programa lo hice en un WinForm y funcionaba bien, pero luego decidí que me iba a ser más útil por consola así que modifiqué el tipo de proyecto a "consola", añadí un módulo, eliminé el formulario, pegué el código modificando el Timer para que funcionase y añadíendo el sub main...
Creo que no me ha faltado nada por añadir o modificar, pero el timer no me funciona, es decir, el sub que asocio al evento Elapsed no funciona
' Lock Tick
Public Sub Lock_Ticks()
Console.WriteLine("test")
'If Running Then Cursor.Position = New Point(Screen_Center_X, Screen_Center_Y)
End Sub
(No escribe ninguna línea.)
En el form uso dos timers, y en cambio el otro timer ("Executable timer") si que me funciona perféctamente...
Este es el test del segundo timer (el que funciona):
(http://img801.imageshack.us/img801/177/captura1s.png)
Y este el del que no funciona (no bloquea el mouse, el evento Elapsed de ese timer no se ejecuta):
(http://img109.imageshack.us/img109/9380/captura2dd.png)
Me he asegurado de que el intervalo del primer timer es correcto, y en fin no sé que puede estar pasando...
Y como ya digo, si todo esto lo paso a un WinForm, vuelve a funcionar de forma correcta, no lo entiendo!.
Este es el proyecto completo, lo pueden probar:
Module Module1
#Region " Vars "
Dim Running As Boolean = False
Dim Errors As Boolean = False
Dim Executable_Name As String = Nothing
Dim Toogle_Key As System.Windows.Forms.Keys = Nothing
Dim WithEvents Toogle_Key_Global As Shortcut = Nothing
Dim Executable_Timer As New System.Timers.Timer
Dim Lock_Timer As New System.Timers.Timer
Dim Lock_Interval As Int32 = 10
Dim Lock_Sleep As Int32 = Get_Milliseconds(3)
Dim Screen_Center_X As Int16 = (Screen.PrimaryScreen.Bounds.Width / 2)
Dim Screen_Center_Y As Int16 = (Screen.PrimaryScreen.Bounds.Height / 2)
#End Region
' Load
Sub main()
Pass_Args()
Sleep()
Lock()
End Sub
' Help
Private Sub Help()
Console.WriteLine( _
"[+] Syntax:" & vbNewLine & _
vbNewLine & _
" MouseLock {Executable Name}" & vbNewLine & _
vbNewLine & _
vbNewLine & _
"[+] Syntax (using optional features):" & vbNewLine & _
vbNewLine & _
" MouseLock {Executable Name} -S {Seconds} -I {Milliseconds} -K {Key}" & vbNewLine & _
vbNewLine & _
vbNewLine & _
"[+] Options:" & vbNewLine & _
vbNewLine & _
" -S (or) -Sleep" & vbNewLine & _
" The time to wait until MouseLock will be activated." & vbNewLine & _
" * Default is ""3000""" & vbNewLine & _
vbNewLine & _
" -I (or) -Interval" & vbNewLine & _
" The time between the mouse locks" & vbNewLine & _
" * Default is ""10"", maybe want to use bigger numbers in slower PC's." & vbNewLine & _
vbNewLine & _
" -K (or) -Key" & vbNewLine & _
" The key for toogle between Enabled/Disabled while MouseLock is running." & vbNewLine & _
" * Valid keys: A-Z, 0-9 (Numpad) and F0-F12." & vbNewLine & _
" * All valid keys can be combined with ALT, CTRL or SHIFT." & vbNewLine & _
vbNewLine & _
vbNewLine & _
"[+] Examples:" & vbNewLine & _
vbNewLine & _
" MouseLock Game.exe" & vbNewLine & _
" MouseLock Game.exe -S 5" & vbNewLine & _
" MouseLock Game.exe -I 250" & vbNewLine & _
" MouseLock Game.exe -K F10" & vbNewLine & _
" MouseLock Game.exe -Sleep 10 -Interval 500 -Key ALT+Z")
End Sub
' Pass arguments
Private Sub Pass_Args()
' Empty?
If My.Application.CommandLineArgs.Count = 0 Then
Errors = True
Help()
End
End If
' Executable Name
If Not My.Application.CommandLineArgs.Item(0).ToLower.EndsWith(".exe") Then
Console.WriteLine("Bad executable name: " & My.Application.CommandLineArgs.Item(0))
Errors = True
Else
Executable_Name = My.Application.CommandLineArgs.Item(0).Substring(0, My.Application.CommandLineArgs.Item(0).Length - 4)
End If
For I As Integer = 0 To My.Application.CommandLineArgs.Count - 1
' Sleep
If My.Application.CommandLineArgs.Item(I).ToLower = "-s" Or My.Application.CommandLineArgs.Item(I).ToLower = "-sleep" Then
Try : Lock_Sleep = Get_Milliseconds(My.Application.CommandLineArgs.Item(I + 1))
Catch
Console.WriteLine("Bad argument for -Sleep")
Errors = True
End Try
End If
' Interval
If My.Application.CommandLineArgs.Item(I).ToLower = "-i" Or My.Application.CommandLineArgs.Item(I).ToLower = "-interval" Then
Try : Lock_Interval = My.Application.CommandLineArgs.Item(I + 1)
Catch
Console.WriteLine("Bad argument for -Interval")
Errors = True
End Try
End If
' Key
If My.Application.CommandLineArgs.Item(I).ToLower = "-k" Or My.Application.CommandLineArgs.Item(I).ToLower = "-key" Then
Try
If My.Application.CommandLineArgs.Item(I + 1).ToLower.StartsWith("alt+") Then
Toogle_Key = [Enum].Parse(GetType(System.Windows.Forms.Keys), My.Application.CommandLineArgs.Item(I + 1).ToLower.Replace("alt+", ""), True)
Toogle_Key_Global = Shortcut.Create(Shortcut.Modifier.Alt, Toogle_Key)
ElseIf My.Application.CommandLineArgs.Item(I + 1).ToLower.StartsWith("ctrl+") Then
Toogle_Key = [Enum].Parse(GetType(System.Windows.Forms.Keys), My.Application.CommandLineArgs.Item(I + 1).ToLower.Replace("ctrl+", ""), True)
Toogle_Key_Global = Shortcut.Create(Shortcut.Modifier.Ctrl, Toogle_Key)
ElseIf My.Application.CommandLineArgs.Item(I + 1).ToLower.StartsWith("shift+") Then
Toogle_Key = [Enum].Parse(GetType(System.Windows.Forms.Keys), My.Application.CommandLineArgs.Item(I + 1).ToLower.Replace("shift+", ""), True)
Toogle_Key_Global = Shortcut.Create(Shortcut.Modifier.Shift, Toogle_Key)
Else
Toogle_Key = [Enum].Parse(GetType(System.Windows.Forms.Keys), My.Application.CommandLineArgs.Item(I + 1), True)
Toogle_Key_Global = Shortcut.Create(Shortcut.Modifier.None, Toogle_Key)
End If
Catch
Console.WriteLine("Bad argument for -Key")
Errors = True
End Try
End If
Next
If Errors Then End
End Sub
' Sleep
Private Sub Sleep()
Console.WriteLine("Sleeping for " & (Lock_Sleep \ 1000) & " seconds before start locking the mouse...")
Dim x As Integer = 0
While Not x = (Lock_Sleep \ 1000)
Threading.Thread.Sleep(1000)
x += 1
End While
End Sub
' Lock
Private Sub Lock()
If Process_Is_Running(Executable_Name) Then
AddHandler Lock_Timer.Elapsed, AddressOf Lock_Ticks
AddHandler Executable_Timer.Elapsed, AddressOf Executable_Tick
Lock_Timer.Interval = Lock_Interval
'Lock_Timer.Interval = 100
Lock_Timer.Start()
Executable_Timer.Start()
Running = True
Else
Terminate()
End If
End Sub
' Lock Tick
Public Sub Lock_Ticks()
Console.WriteLine("test - funciona el lock timer?")
If Running Then Cursor.Position = New Point(Screen_Center_X, Screen_Center_Y)
End Sub
' Executable Tick
Private Sub Executable_Tick()
Console.WriteLine("test - funciona el executable timer?")
If Not Process_Is_Running(Executable_Name) Then Terminate()
End Sub
' Esta parte no es necesaria para testear
' Toogle Key
'Private Sub Toogle_Key_Global_Press(ByVal s As Object, ByVal e As Shortcut.HotKeyEventArgs) Handles Toogle_Key_Global.Press
' Select Case Running
' Case False
' Running = True
' Lock_Timer.Start()
' Case True
' Running = False
' End Select
'End Sub
' Get Milliseconds
Private Function Get_Milliseconds(ByVal Seconds As Int32) As Int32
Dim Time_Span As New TimeSpan(TimeSpan.TicksPerSecond * Seconds)
Return Time_Span.TotalMilliseconds
End Function
' Process Is Running
Public Function Process_Is_Running(ByVal Process_Name As String) As Boolean
Dim myProcess As Process() = Process.GetProcessesByName(Process_Name)
If Not myProcess.Length = 0 Then Return True Else Return False
End Function
' Terminate
Private Sub Terminate()
Console.WriteLine("Application """ & Executable_Name & ".exe"" is not Running.")
Console.WriteLine("MouseLock finished.")
Application.Exit()
End Sub
End Module
Ya lo he solucionado, aunque sigo sin entender el motivo... ¿Parece que los Timers los módulos los trata como subprocesos (Threads)?, parece como si la aplicación finalizaba antes de dejarle al timer hacer su trabajo.
Así que he tenido que usar un:
While Running : Application.DoEvents() : End While
Justo después de iniciar los timers, para que la aplicación no finalize.
Private Sub Lock()
If Process_Is_Running(Executable_Name) Then
AddHandler Lock_Timer.Elapsed, AddressOf Locker
AddHandler Executable_Timer.Elapsed, AddressOf Executable_Tick
Lock_Timer.Interval = Lock_Interval
Lock_Timer.Start()
Executable_Timer.Start()
Running = True
While Running : Application.DoEvents() : End While
Else
Terminate()
End If
End Sub
Por esta razón me funcionaba el timer en una class de un WF y no en un module, porque el module no espera a que el timer tickee...
¿Alguien me aclara esto?
Un saludo!
esque antes no has bloqueado el programa en un loop como ahora entonces sigue y termina. la forma correcta es la segunda, con un bucle while "running" y doevents.
Tienes toda la razón, el fallo era muy obvio pero no me daba cuenta por despiste, es decir, como en la versión gráfica la instancia no termina hasta que se recibe el evento FormClosing, pues los timers hacian su trabajo "en segundo plano", pero en la versión de consola esto era imposible porque la instancia finalizaba justo después de iniciar el timer. más o menos xD.
Saludos.
jajajajaj choni.exe ;-) un aplauso enserio jajajaj
No se me ocurrió nada más placentero que hacer un pequeño "homenaje" a las chonis. :silbar:
Saludos