• EnglishSpanishGermanFrenchPolishChinese (Traditional)


EnglishSpanishGermanFrenchPolishChinese (Traditional)

Operating systems, scripting, PowerShell and security

Operating systems, software development, scripting, PowerShell tips, network and security

Menú principal
  • Categorías
  • Cursos
  • Libro de PowerShell
  • Lo mejor
  • Lo último
  • Proyectos
  • Contactar
Ir al contenido

Automatizar el funcionamiento de una aplicación que simula un piano (pulsar automáticamente las notas del piano)

Contenidos

  • Formulario que simula el piano
  • Detectar la nota «DO» y pulsar automáticamente
  • Detectar todas las notas y pulsar automáticamente una melodía (localizar cada botón de cada nota y pulsarlo automáticamente según indique la melodía)

La explicación detallada de cómo funciona se puede obtener contratando clases en el apartado https://www.jesusninoc.com/cursos/

Formulario que simula el piano

PowerShell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# Crear un piano que suene
# Crear una clase con dos propiedades: nombre y frecuencia de la nota
class Nota
{
    [String]$nombre
    [Int]$frecuencia
}
# Crear un ArrayList para añadir los objetos de la clase Coche
$notas = New-Object System.Collections.ArrayList
[void]$notas.Add([Nota]@{nombre="DO";frecuencia=261})
[void]$notas.Add([Nota]@{nombre="RE";frecuencia=293})
[void]$notas.Add([Nota]@{nombre="MI";frecuencia=329})
[void]$notas.Add([Nota]@{nombre="FA";frecuencia=349})
[void]$notas.Add([Nota]@{nombre="SOL";frecuencia=391})
[void]$notas.Add([Nota]@{nombre="LA";frecuencia=440})
[void]$notas.Add([Nota]@{nombre="SI";frecuencia=493})
 
$buttons_functionbuttoncount = $notas.count
 
$loop = 0
 
#Formulario
$Form = New-Object System.Windows.Forms.Form
$Form.Text="Formulario"
$Form.Size=New-Object System.Drawing.Size(500,500)
$Form.StartPosition="CenterScreen"
 
while($loop -lt $buttons_functionbuttoncount)
    {
    $thisbutton = New-Object System.Windows.Forms.Button
    [string]$thisbuttonname = $notas.nombre[$loop]
    $thisbutton.Text = $thisbuttonname
    $thisbutton.size = New-Object System.Drawing.Size(100,40)
    $thisbutton.Location = New-Object System.Drawing.Size(200,(40*$loop+1))
    $thisbutton.Add_Click({
            Write-Host $this.text
            $posicionnota = $notas.nombre.IndexOf($this.text)
            [System.Console]::Beep($notas[$posicionnota].frecuencia,500)
        })
    $Form.Controls.Add($thisbutton)
    $loop += 1
    }
 
$Form.ShowDialog()

Detectar la nota «DO» y pulsar automáticamente

PowerShell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
$MethodDefinition = @'
        [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern int GetWindowText(IntPtr hWnd, string strText, int maxCount);
 
        [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern int GetWindowTextLength(IntPtr hWnd);
 
        [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
 
        [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern int GetClassName(IntPtr hWnd, string lpClassName, int nMaxCount);
 
        // Delegate to filter which windows to include.  Required by EnumWindows()
        public delegate bool EnumWindowsProc(IntPtr hwnd, System.Collections.ArrayList lParam);
 
        [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, System.Collections.ArrayList lParam);
           
        // These two functions are in C# because I can't figure out how to use the .NET API callback functionality via PowerShell
        public static System.Collections.ArrayList GetWindows()
        {
            System.Collections.ArrayList windowHandles = new System.Collections.ArrayList();
            EnumWindowsProc callBackPtr = GetWindowHandle;
            EnumWindows(callBackPtr, windowHandles);
 
            return windowHandles;
        }
 
        private static bool GetWindowHandle(IntPtr hwnd, System.Collections.ArrayList windowHandles)
        {
            windowHandles.Add(hwnd);
            return true;
        }
'@
 
Add-Type -MemberDefinition $MethodDefinition -Name 'ShowHideWindow' -Namespace 'User32' | Out-Null
 
$hwnds = [User32.ShowHideWindow]::GetWindows()
 
$ultimo = $hwnds | sort
 
#  Quick method to create a string of ~290 characters
[String]$tempString = (0..100)
$stringLength = $tempString.Length
[System.Collections.ArrayList]$Windows = @()
 
# Convertir hex to dec
# [uint32]"0X002A00A8"
 
foreach ($hwnd in 1..5752680) {
    $ClassNameLength = [User32.ShowHideWindow]::GetClassName($hwnd, $tempString, $stringLength)
    $ClassName = $tempString.Substring(0,$ClassNameLength)
    if($ClassName)
    {
        #$hwnd
        #$ClassName
        $WindowTextLength = [User32.ShowHideWindow]::GetWindowText($hWnd, $tempString, $stringLength)
        $WindowText = $tempString.Substring(0,$WindowTextLength)
        #$WindowText
        $Window = New-Object -TypeName psobject -Property @{hwnd = $hwnd; ClassName = $ClassName; WindowText = $WindowText}
        $Windows.Add($Window) | Out-Null
    }
}
 
$idcickdo = $Windows| where {$_.WindowText -eq "DO"}
 
$codigo2='
[DllImport("user32.dll", EntryPoint = "FindWindowEx")]public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
[DllImport("User32.dll")]public static extern int SendMessage(IntPtr hWnd, int uMsg, int wParam, string lParam);
'
 
$acciones = Add-Type -MemberDefinition $codigo2 -Name Acciones -PassThru
 
# Hacer click en el botón
0..($idcick.hwnd.Length -1) | % {$acciones::SendMessage($idcickdo.hwnd[$_], 0x00F5, 0, 0)}

Detectar todas las notas y pulsar automáticamente una melodía (localizar cada botón de cada nota y pulsarlo automáticamente según indique la melodía)

PowerShell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
$MethodDefinition = @'
        [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern int GetWindowText(IntPtr hWnd, string strText, int maxCount);
 
        [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern int GetWindowTextLength(IntPtr hWnd);
 
        [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
 
        [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern int GetClassName(IntPtr hWnd, string lpClassName, int nMaxCount);
 
        // Delegate to filter which windows to include.  Required by EnumWindows()
        public delegate bool EnumWindowsProc(IntPtr hwnd, System.Collections.ArrayList lParam);
 
        [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, System.Collections.ArrayList lParam);
           
        // These two functions are in C# because I can't figure out how to use the .NET API callback functionality via PowerShell
        public static System.Collections.ArrayList GetWindows()
        {
            System.Collections.ArrayList windowHandles = new System.Collections.ArrayList();
            EnumWindowsProc callBackPtr = GetWindowHandle;
            EnumWindows(callBackPtr, windowHandles);
 
            return windowHandles;
        }
 
        private static bool GetWindowHandle(IntPtr hwnd, System.Collections.ArrayList windowHandles)
        {
            windowHandles.Add(hwnd);
            return true;
        }
'@
 
Add-Type -MemberDefinition $MethodDefinition -Name 'ShowHideWindow' -Namespace 'User32' | Out-Null
 
$hwnds = [User32.ShowHideWindow]::GetWindows()
 
$ultimo = $hwnds | sort
 
#  Quick method to create a string of ~290 characters
[String]$tempString = (0..100)
$stringLength = $tempString.Length
[System.Collections.ArrayList]$Windows = @()
 
# Convertir hex to dec
# [uint32]"0X002A00A8"
 
foreach ($hwnd in 1..5752680) {
    $ClassNameLength = [User32.ShowHideWindow]::GetClassName($hwnd, $tempString, $stringLength)
    $ClassName = $tempString.Substring(0,$ClassNameLength)
    if($ClassName)
    {
        #$hwnd
        #$ClassName
        $WindowTextLength = [User32.ShowHideWindow]::GetWindowText($hWnd, $tempString, $stringLength)
        $WindowText = $tempString.Substring(0,$WindowTextLength)
        #$WindowText
        $Window = New-Object -TypeName psobject -Property @{hwnd = $hwnd; ClassName = $ClassName; WindowText = $WindowText}
        $Windows.Add($Window) | Out-Null
    }
}
 
$do = $Windows| where {$_.WindowText -eq "DO"}
$re = $Windows| where {$_.WindowText -eq "RE"}
$mi = $Windows| where {$_.WindowText -eq "MI"}
$fa = $Windows| where {$_.WindowText -eq "FA"}
$sol = $Windows| where {$_.WindowText -eq "SOL"}
$la = $Windows| where {$_.WindowText -eq "LA"}
$si = $Windows| where {$_.WindowText -eq "SI"}
 
$codigo2='
[DllImport("user32.dll", EntryPoint = "FindWindowEx")]public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
[DllImport("User32.dll")]public static extern int SendMessage(IntPtr hWnd, int uMsg, int wParam, string lParam);
'
 
$acciones = Add-Type -MemberDefinition $codigo2 -Name Acciones -PassThru
 
$cancion = "Do Do Do Fa La Do Do Do Fa La Fa Fa Mi Mi Re Re Do Do Do Do Mi Sol Do Do Do Mi Sol do re do"
 
# Hacer click en el botón
foreach($nota in $cancion.split(" "))
{
    $acciones::SendMessage(("$"+($nota) | iex).hwnd, 0x00F5, 0, 0)
}
Publicado el día 3 de febrero de 2021

CATEGORÍAS

Automatización, PowerShell

ETIQUETAS

Add-Type, ArrayList, Beep, Collections, Cursos, Drawing, FindWindowEx, foreach, HTTPS, IndexOf, Jesús Niño, Jesús Niño Camazón, Length, New-Object, Objetos, SendMessage, showdialog, size, Sort, Split, Substring, System.Collections.ArrayList, System.Console, System.Drawing, System.Windows.Forms.Form, user32.dll, Windows, Windows.Forms.Form, Write-Host

MÁS

  • Cómo depurar scripts en ISE de Windows PowerShell
  • Buscar el nombre de una clase de un formulario en PowerShell con Microsoft Spy++
  • Buscar el nombre de una clase de un formulario en PowerShell con Microsoft Spy++ y escribir un mensaje en una caja de texto sin conocer el identificador de ventana en concreto del proceso…
  • 11. Gestión del Directorio Activo (nivel intermedio)
  • Ver mediante una lista de botones en un formulario de PowerShell las categorías de una página en Wordpress
  • Crear un formulario en PowerShell