Script que deje apretado tecla Shift

Iniciado por vampirolicano, 18 Julio 2017, 15:09 PM

0 Miembros y 1 Visitante están viendo este tema.

vampirolicano

Hola que tal a todos. queria saber si podrian ayudarme para hacer un script de teclado. He investigado y leido en el foro y lorgre hacer que se precione la tecla shift pero no logro que quede apretada.

Necesito que la tecla Shift quede presionada (es para un juego que manteniendo presionado esa tecla hace una accion)


Set objshell = createobject("wscript.shell")
Set bloc = objshell.exec("notepad")
Wscript.sleep 2000
Objshell.appactivate bloc.processid
Wscript.sleep 200
Objshell.sendkeys "+"




MCKSys Argentina

Hola!

El objeto WshShell no provee una forma de mandar ventos KeyUp y KeyDown. Lo mejor que puedes hacer para obtener lo que quieres, es hacer que la tecla se repita las veces necesarias. Esto lo puedes lograr colocando SendKeys en un loop o poniendo un numero despues de la tecla entre llaves:


Código (vb) [Seleccionar]

Set objshell = createobject("wscript.shell")
Set bloc = objshell.exec("notepad")
Wscript.sleep 2000
Objshell.appactivate bloc.processid
Wscript.sleep 200
Objshell.sendkeys "{+ 40}"


Lo anterior debería apretar shift 40 veces.

Source: https://stackoverflow.com/questions/42422088/permanently-press-key-via-vbs-keep-key-pressed

Saludos!
MCKSys Argentina

"Si piensas que algo está bien sólo porque todo el mundo lo cree, no estás pensando."


Eleкtro

#2
El método SendKeys() es muy limitado, igual que el lenguaje VBS, donde ni tan siquiera se puede llamar a la API de Windows sin recurrir a la instalación de componentes de terceros.

Tengamos presente que Windows no es solo Batch y VBS, hay otros lenguajes soportados de forma nativa y son mucho más potentes/completos, como JS, y PowerShell.

En este último lenguaje podemos simplificar muchas tareas, pero para intentar demostrar el potencial de este lenguaje yo he optado por compilar una clase escrita en otro lenguaje adicional, VB.NET (aunque también podría haber sido C#, F# o VC++), con una clase donde he implementado los métodos necesarios y los P/Invokes para hacer lo que pides (ejecutar el notepad y activar el foco de ventana, y luego mantener pulsada una tecla). No es necesario conocer el lenguaje VB.NET, tan solo debes fijarte en las 3 últimas lineas al final de este código:

Script.ps1
Código (vbnet,101,102,103) [Seleccionar]
$vbCode = @'
Imports Microsoft.VisualBasic
Imports System
Imports System.ComponentModel
Imports System.Diagnostics
Imports System.Runtime.InteropServices
Imports System.Threading
Imports System.Windows.Forms

Namespace Elektro

   Public NotInheritable Class NativeMethods

       Friend Const KEYEVENTF_KEYUP As UInteger = 2UI

       <DllImport("User32.dll", CharSet:=CharSet.Auto, SetLastError:=True)>
       Friend Shared Sub keybd_event(ByVal vkey As Byte,
                                     ByVal scanCode As Byte,
                                     ByVal flags As UInteger,
                                     ByVal extraInfo As UInteger)
       End Sub

       <DllImport("User32.dll", SetLastError:=True)>
       Friend Shared Function GetForegroundWindow() As IntPtr
       End Function

       <DllImport("User32.dll", SetLastError:=True)>
       Friend Shared Function SetForegroundWindow(ByVal hwnd As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
       End Function

   End Class

   Public NotInheritable Class ProcessTools

       ''' <summary>
       ''' Runs and activates Notepad process.
       ''' </summary>
       Public Shared Sub RunNotepad()

           Using p As New Process() With {
                   .StartInfo = New ProcessStartInfo("notepad.exe") With {
                       .UseShellExecute = True
                   }
               }

               p.Start()
               p.WaitForInputIdle(Timeout.Infinite)

               Dim hwnd As IntPtr = IntPtr.Zero
               Do While (hwnd = IntPtr.Zero)
                   hwnd = p.MainWindowHandle
               Loop
               Debug.WriteLine("Window Handle: " & hwnd.ToInt32())

               Do Until (NativeMethods.GetForegroundWindow() = hwnd)
                   Dim result As Boolean = NativeMethods.SetForegroundWindow(hwnd)
               Loop
               '' Alternativa administrada:
               ' Interaction.AppActivate(p.Id)

           End Using

       End Sub

   End Class

   Public NotInheritable Class KeyboardTools

       ' Press and holds the specified key.
       Public Shared Sub PressKey(ByVal key As Keys)
           NativeMethods.keybd_event(CByte(key), 0, 0UI, 0UI)
       End Sub

       ' Releases a previous hold key.
       Public Shared Sub ReleaseKey(ByVal key As Keys)
           NativeMethods.keybd_event(CByte(key), 0, NativeMethods.KEYEVENTF_KEYUP, 0UI)
       End Sub

   End Class

End Namespace
'@
$vbType = Add-Type -TypeDefinition $vbCode `
                  -CodeDomProvider (New-Object Microsoft.VisualBasic.VBCodeProvider) `
                  -PassThru `
                  -ReferencedAssemblies "Microsoft.VisualBasic.dll", `
                                        "System.dll", `
                                        "System.ComponentModel.dll", `
                                        "System.Runtime.InteropServices.dll", `
                                        "System.Threading.dll", `
                                        "System.Windows.Forms.dll" `
| where { $_.IsPublic }

# # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# End of VB.NET CodeDom Provider Compiler Services Sample
# # # # # # # # # # # # # # # # # # # # # # # # # # # # #

Add-Type -AssemblyName "System.Windows.Forms"
$Keys = [System.Windows.Forms.Keys]

[Elektro.ProcessTools]::RunNotepad()
[Elektro.KeyboardTools]::PressKey($Keys::ShiftKey)
# [Elektro.KeyboardTools]::ReleaseKey($Keys::ShiftKey)


El modo de empleo es muy sencillo, abstraido de cualquier complejidad. Con el método Elektro.ProcessTools.RunNotepad() se ejecuta una nueva instancia del proceso Notepad.exe (o el hijack correspondiente que haya definido en el sistema) y se activa el foco de ventana. Con el método Elektro.KeyboardTools.PressKey(Keys) se simula una pulsación del teclado de la tecla que deseemos (la tecla se mantendrá pulsada), y con el método Elektro.KeyboardTools.ReleaseKey(Keys) liberamos la tecla que previamente habiamos pulsado.

Espero que te sirva de ayuda.

PD: Nótese que el miembro keybd_event de la API de Windows está considerado obsoleto, esto en realidad debería reemplazarse por la utilización de la infraestructura SENDINPUT, sin embargo la implementación de los miembros necesarios habría extendido el código de ejemplo en varios cientos de lineas, así que simplemente lo he preferido hacer así como una decisión de diseño y simplificación; esto es tan solo un ejemplo ordinario y funcional, no una solución optimizada.

Saludos