Lo normal seria crear un script en Python y ejecucarlo en el BATCH
En mi opinión, y sobre todo para alguien cuya única experiencia en programación parece ser
Batch-Script, lo menos "normal" precisamente sería recurrir al uso e instalación de motores de lenguajes de terceros como
Python, pudiendo utilizar en su lugar
Visual Basic Script o
PowerShell simplemente por que ya están integrados por defecto en
Windows y son autosuficientes para esta tarea.
Por supuesto alguien que tenga preferencia por utilizar
Python tendrá una opinión opuesta a lo que acabo de decir. Es comprensible y respetable, de hecho yo también prefiero utilizar cierto lenguaje antes que recurrir a
Batch, y a
VBS,
PS y
Python. Solo digo que cada caso y cada sujeto requieren un enfoque personalizado y
Python a mi no me parece lo más adecuado para este escenario.
un archivo por LOTES...
Batch-Script es una herramienta limitada y obsoleta que carece de funcionalidad alguna para este tipo de automatización multimedia.
Con puro
Batch-Script, es decir sin apoyarte en el uso de otro lenguaje adicional, no puedes hacerlo. Con
Batch puedes iniciar
WMP o cualquier reproductor externo que haya instalado en tu S.O. para reproducir un archivo de audio específico, eso si que puedes hacerlo, pero no puedes controlar la reproducción en búcle (a menos que por defecto ya esté activada en el reproductor externo).
que reproduzca en forma de bucle (continua) un archivo de AUDIO .mp3 que tengo en mi computadora..
es decir el archivo de audio con la SIRENA.. tiene una duracion de 40 segundos.. a mi me gustaria que se reprodujera de manera continua sin que se corte despues de los 40 segundos.. si me explico?
En
PowerShell, reproducir en búcle un archivo de audio es tan sencillo como usar este código:
Add-Type -AssemblyName System.Runtime.WindowsRuntime
$audioFile = "C:\Sirena.mp3"
$MediaPlayer = [Windows.Media.Playback.MediaPlayer, Windows.Media, ContentType = WindowsRuntime]::New()
$MediaPlayer.IsLoopingEnabled = $true
$MediaPlayer.Source = [Windows.Media.Core.MediaSource]::CreateFromUri($audioFile)
$MediaPlayer.Play()
Nota: la reproducción del audio es asíncrona.
si pudiera agregar la opcion para bloquear la PC de manera automatica, es decir cerrar sección o suspenderla para que no puedan utilizarla pero que el archivo de audio o la alarma mas bien siga sonando
En
PowerShell, cerrar la sesión del usuario actual es tan sencillo como esto:
$win32OS = Get-WmiObject Win32_OperatingSystem -ComputerName "." -EnableAllPrivileges
$win32OS.win32shutdown(4)
( Donde ves un número "4" entre paréntesis puedes reemplazarlo por un "0" para reiniciar el PC. O también puedes utilizar el cmdlet "
Restart-Computer" para hacer lo mismo. )
Sin embargo, cerrar la sesión de usuario no es una opción viable, ya que las aplicaciones deben cerrarse si o si (el proceso de
PowerShell.exe debe cerrarse).
Para que fuese viable reproducir la sirena con la sesión cerrada, tendrías que ejecutar estas operaciones mediante un servicio de Windows, no mediante un proceso.
Así que lo sencillo y factible sería salir a la pantalla de bloqueo o lock-screen, de esta forma el archivo de audio (la sirena) seguirá sonando. Y esto es igual de sencillo hacerlo tanto en
Batch-Script como con
PowerShell mediante
rundll32:
Invoke-Command {rundll32.exe user32.dll, LockWorkStation}
Claro que primeramente debes asegurarte de haber especificado una contraseña para tu cuenta de usuario, de lo contrario salir a la pantalla de bloqueo no te aportará ninguna seguridad y por ende no tendría sentido hacerlo.
Si no tienes contraseña especificada para tu cuenta de usuario, una opción alternativa a salir a la pantalla de bloqueo, sería bloquear la entrada del teclado y del ratón durante un tiempo indeterminado llamando a la función "BlockInput" de la API de Windows.
No me apetece escribir código para esto, así que he buscado para ti esta función reutilizable que además de bloquear la entrada del mouse y el teclado, adicionalmente te permite especificar un mensaje en letras grandes para que lo pueda leer el incauto ladrón de guante blanco (o un o
Kupa
):
Function Lock-Screen
{
[CmdletBinding()]
param
(
# number of seconds to lock
[int]
$LockSeconds = 10,
# message shown. Use {0} to insert remaining seconds
# do not use {0} for a static message
[string]
$Title = 'wait for {0} more seconds...',
# dim screen
[Switch]
$DimScreen
)
# when run without administrator privileges, the keyboard will not be blocked!
# get access to API functions that block user input
# blocking of keyboard input requires admin privileges
$code = @'
[DllImport("user32.dll")]
public static extern int ShowCursor(bool bShow);
[DllImport("user32.dll")]
public static extern bool BlockInput(bool fBlockIt);
'@
$userInput = Add-Type -MemberDefinition $code -Name Blocker -Namespace UserInput -PassThru
# get access to UI functionality
Add-Type -AssemblyName PresentationFramework
Add-Type -AssemblyName PresentationCore
# set window opacity
$opacity = 1
if ($DimScreen) { $opacity = 200 }
# create a message label
$label = New-Object -TypeName Windows.Controls.Label
$label.FontSize = 60
$label.FontFamily = 'Consolas'
$label.FontWeight = 'Bold'
$label.Background = 'Transparent'
$label.Foreground = 'Blue'
$label.VerticalAlignment = 'Center'
$label.HorizontalAlignment = 'Center'
# create a window
$window = New-Object -TypeName Windows.Window
$window.WindowStyle = 'None'
$window.AllowsTransparency = $true
$color = [Windows.Media.Color]::FromArgb($opacity, 0,0,0)
$window.Background = [Windows.Media.SolidColorBrush]::new($color)
$window.Opacity = 0.8
$window.Left = $window.Top = 0
$window.WindowState = 'Maximized'
$window.Topmost = $true
$window.Content = $label
# block user input
$null = $userInput::BlockInput($true)
$null = $userInput::ShowCursor($false)
# show window and display message
$null = $window.Dispatcher.Invoke{
$window.Show()
$LockSeconds..1 | ForEach-Object {
$label.Content = ($title -f $_)
$label.Dispatcher.Invoke([Action]{}, 'Background')
Start-Sleep -Seconds 1
}
$window.Close()
}
# unblock user input
$null = $userInput::ShowCursor($true)
$null = $userInput::BlockInput($false)
}
Fuente:
https://community.idera.com/database-tools/powershell/powertips/b/tips/posts/locking-the-screen-with-powershellNota: lo malo de usar esta alternativa es que no puedes bloquear la combinación de teclas CTRL+ALT+DEL. Esta combinación es una característica especial del S.O. y no hay forma viable de anularla, excepto desarrollando un controlador de filtro del teclado, o desarrollar una interfaz gráfica de identificación y autenticación (GINA) y reemplazarla en el S.O. Cosas muy avanzadas que llevarían mucho tiempo y dedicación. Y quizás haya alguna otra técnica más rebuscada que explote alguna vulnerabilidad conocida por los hackers más experimentados...
Pues como ya dije, lo sencillo y factible es salir a la pantalla de bloqueo. Pero bueno, ahí tienes esa alternativa.
Por último, ¿cómo puedes usar todo esto desde un script .bat/.cmd?, pues muy sencillo: copiando el contenido del script de
PowerShell en un nuevo archivo de texto plano, y seguidamente ejecutar
PowerShell.exe para lanzar ese script.
( Aunque lo ideal sería que directamente utilices PowerShell. )
Ejemplos:
Batch-Script para reproducir en búcle un archivo de audio y salir a la pantalla de bloqueo:@ECHO OFF
SET "audioFile=C:\Sirena.mp3"
SET "ps1File=%TEMP%\LockMe.ps1"
(
ECHO:Add-Type -AssemblyName System.Runtime.WindowsRuntime
ECHO+
ECHO:$audioFile = "%audioFile%"
ECHO+
ECHO:$MediaPlayer = [Windows.Media.Playback.MediaPlayer, Windows.Media, ContentType = WindowsRuntime]::New^(^)
ECHO:$MediaPlayer.IsLoopingEnabled = $true
ECHO:$MediaPlayer.Source = [Windows.Media.Core.MediaSource]::CreateFromUri^($audioFile^)
ECHO:$MediaPlayer.Play^(^)
ECHO+
ECHO:Invoke-Command {rundll32.exe user32.dll, LockWorkStation}
)>"%ps1File%"
("PowerShell.exe" -NoExit -Command "if((Get-ExecutionPolicy ) -ne 'AllSigned') { Set-ExecutionPolicy -Scope Process Bypass }; & '%ps1File%'") && (
Exit /B 0
) || (
Exit /B 1
)
Batch-Script para reproducir en búcle un archivo de audio y bloquear la entrada del mouse y el teclado:@ECHO OFF
SET "audioFile=C:\Sirena.mp3"
SET "ps1File=%TEMP%\LockMe.ps1"
(
ECHO:Function Lock-Screen
ECHO:{
ECHO: [CmdletBinding^(^)]
ECHO: param
ECHO: ^(
ECHO: # number of seconds to lock
ECHO: [int]
ECHO: $LockSeconds = 10,
ECHO+
ECHO: # message shown. Use {0} to insert remaining seconds
ECHO: # do not use {0} for a static message
ECHO: [string]
ECHO: $Title = 'wait for {0} more seconds...',
ECHO:
ECHO: # dim screen
ECHO: [Switch]
ECHO: $DimScreen
ECHO: ^)
ECHO+
ECHO: # when run without administrator privileges, the keyboard will not be blocked!
ECHO+
ECHO: # get access to API functions that block user input
ECHO: # blocking of keyboard input requires admin privileges
ECHO: $code = @'
ECHO: [DllImport^("user32.dll"^)]
ECHO: public static extern int ShowCursor^(bool bShow^);
ECHO+
ECHO: [DllImport^("user32.dll"^)]
ECHO: public static extern bool BlockInput^(bool fBlockIt^);
ECHO:'@
ECHO+
ECHO: $userInput = Add-Type -MemberDefinition $code -Name Blocker -Namespace UserInput -PassThru
ECHO+
ECHO: # get access to UI functionality
ECHO: Add-Type -AssemblyName PresentationFramework
ECHO: Add-Type -AssemblyName PresentationCore
ECHO:
ECHO: # set window opacity
ECHO: $opacity = 1
ECHO: if ^($DimScreen^) { $opacity = 200 }
ECHO:
ECHO: # create a message label
ECHO: $label = New-Object -TypeName Windows.Controls.Label
ECHO: $label.FontSize = 60
ECHO: $label.FontFamily = 'Consolas'
ECHO: $label.FontWeight = 'Bold'
ECHO: $label.Background = 'Transparent'
ECHO: $label.Foreground = 'Blue'
ECHO: $label.VerticalAlignment = 'Center'
ECHO: $label.HorizontalAlignment = 'Center'
ECHO:
ECHO:
ECHO: # create a window
ECHO: $window = New-Object -TypeName Windows.Window
ECHO: $window.WindowStyle = 'None'
ECHO: $window.AllowsTransparency = $true
ECHO: $color = [Windows.Media.Color]::FromArgb^($opacity, 0,0,0^)
ECHO: $window.Background = [Windows.Media.SolidColorBrush]::new^($color^)
ECHO: $window.Opacity = 0.8
ECHO: $window.Left = $window.Top = 0
ECHO: $window.WindowState = 'Maximized'
ECHO: $window.Topmost = $true
ECHO: $window.Content = $label
ECHO:
ECHO: # block user input
ECHO: $null = $userInput::BlockInput^($true^)
ECHO: $null = $userInput::ShowCursor^($false^)
ECHO:
ECHO: # show window and display message
ECHO: $null = $window.Dispatcher.Invoke{
ECHO: $window.Show^(^)
ECHO: $LockSeconds..1 ^| ForEach-Object {
ECHO: $label.Content = ^($title -f $_^)
ECHO: $label.Dispatcher.Invoke^([Action]{}, 'Background'^)
ECHO: Start-Sleep -Seconds 1
ECHO: }
ECHO: $window.Close^(^)
ECHO: }
ECHO:
ECHO: # unblock user input
ECHO: $null = $userInput::ShowCursor^($true^)
ECHO: $null = $userInput::BlockInput^($false^)
ECHO:}
ECHO+
ECHO:Add-Type -AssemblyName System.Runtime.WindowsRuntime
ECHO+
ECHO:$audioFile = "%audioFile%"
ECHO+
ECHO:$MediaPlayer = [Windows.Media.Playback.MediaPlayer, Windows.Media, ContentType = WindowsRuntime]::New^(^)
ECHO:$MediaPlayer.IsLoopingEnabled = $true
ECHO:$MediaPlayer.Source = [Windows.Media.Core.MediaSource]::CreateFromUri^($audioFile^)
ECHO:$MediaPlayer.Play^(^)
ECHO+
ECHO:Lock-Screen -LockSeconds 30 -DimScreen -Title 'La pantalla se desbloqueará en {0} segundos.'
)>"%ps1File%"
("PowerShell.exe" -Command "if((Get-ExecutionPolicy ) -ne 'AllSigned') { Set-ExecutionPolicy -Scope Process Bypass }; & '%ps1File%'") && (
Exit /B 0
) || (
Exit /B 1
)
Nota: donde pone "
-LockSeconds 30"
(30 son los segundos de duración del bloqueo) puedes reemplazarlo por "
-LockSeconds [int]::MaxValue", que sería el máximo valor permitido, y así el bloqueo tendría una duración de 2147483647 segundos (68 años).
PD: es necesario tener instalado
Windows 8 o superior:
https://en.wikipedia.org/wiki/Windows_Runtime-Enjuto Mojamuto "rey de los frikis" a su disposición para futuras dudas.