Cómo ejecutar un script de PowerShell desde un archivo por lotes

197

Estoy tratando de ejecutar este script en PowerShell. He guardado el siguiente script como ps.ps1en mi escritorio.

$query = "SELECT * FROM Win32_DeviceChangeEvent WHERE EventType = 2"
Register-WMIEvent -Query $query -Action { invoke-item "C:\Program Files\abc.exe"}

Hice un script por lotes para ejecutar este script de PowerShell

@echo off
Powershell.exe set-executionpolicy remotesigned -File  C:\Users\SE\Desktop\ps.ps1
pause

Pero recibo este error:

Ingrese la descripción de la imagen aquí

Eka
fuente

Respuestas:

267

Necesitas el -ExecutionPolicyparámetro:

Powershell.exe -executionpolicy remotesigned -File  C:\Users\SE\Desktop\ps.ps1

De lo contrario, PowerShell considera los argumentos como una línea para ejecutar y, aunque Set-ExecutionPolicy es un cmdlet, no tiene ningún -Fileparámetro.

Joey
fuente
2
@joey funcionó gracias ... pero después de ejecutar el archivo bat recibí este error "Advertencia: la columna 'comando' no cabe en la pantalla y fue eliminada"
Eka
Eso es una advertencia, no un error. Y más de un tema para otra pregunta.
Joey
@joey, ¿es prudente escribir otra pregunta en la pila. SE para esta advertencia menor?
Eka
2
@Joey Jaja, así que efectivamente puedes anular esta política sin ser administrador. ¿Es eso un problema de seguridad?
Kolob Canyon,
2
@KolobCanyon: Si está en una posición en la que puede ejecutar PowerShell, también puede hacer casi todo lo demás. Tenga en cuenta que la política de ejecución no significa que PowerShell tenga más privilegios de los que tendría de otro modo. En cierto modo, es simplemente una conveniencia para evitar ejecutar accidentalmente cosas que quizás no desee ejecutar. Similar a tener que prefijar comandos en el directorio actual con ./y tener un indicador ejecutable en Unix.
Joey
117

Explico por qué querría llamar a un script de PowerShell desde un archivo por lotes y cómo hacerlo en mi blog aquí .

Esto es básicamente lo que estás buscando:

PowerShell -NoProfile -ExecutionPolicy Bypass -Command "& 'C:\Users\SE\Desktop\ps.ps1'"

Y si necesita ejecutar su script de PowerShell como administrador, use esto:

PowerShell -NoProfile -ExecutionPolicy Bypass -Command "& {Start-Process PowerShell -ArgumentList '-NoProfile -ExecutionPolicy Bypass -File ""C:\Users\SE\Desktop\ps.ps1""' -Verb RunAs}"

Sin embargo, en lugar de codificar la ruta completa al script de PowerShell, recomiendo colocar el archivo por lotes y el archivo de script de PowerShell en el mismo directorio, como lo describe mi publicación de blog.

perro mortal
fuente
Invoke-WebRequest funciona bien cuando escribo la línea de comando en una ventana de cmd, pero devuelve un 404 cada vez que lo ejecuto desde un archivo por lotes. Estoy intentando PowerShell -NoProfile -ExecutionPolicy Bypass -Command "& {Start-Process PowerShell -ArgumentList '-NoProfile -ExecutionPolicy Bypass Invoke-WebRequest https://www.example.com/example.ics -OutFile C:\_my\script.ics' -Verb RunAs}";o powershell -Command "Invoke-WebRequest https://www.example.com/example.ics -OutFile c:\_my\file.ics", o estoy usando la opción -File a lo mismo en un archivo .ps1, o (New-Object Net.WebClient).DownloadFile. ¿Algunas ideas?
Chris
Intente usar -ExecutionPolicy Unrestricted. Supongo que la opción Bypass no le da acceso a la red PowerShell.
deadlydog
1
@Belun La publicación de blog referenciada muestra cómo pasar parámetros al script.
deadlydog
19

Si desea ejecutar desde el directorio actual sin una ruta totalmente calificada, puede usar:

PowerShell -NoProfile -ExecutionPolicy Bypass -Command "& './ps.ps1'"
por ejemplo
fuente
16

Si ejecuta un archivo por lotes que llama a PowerShell como administrador, será mejor que lo ejecute así, ahorrándole todos los problemas:

powershell.exe -ExecutionPolicy Bypass -Command "Path\xxx.ps1"

Es mejor usar Bypass...

Root Loop
fuente
3

Si desea ejecutar algunos scripts, puede usar Set-executionpolicy -ExecutionPolicy Unrestrictedy luego restablecer con Set-executionpolicy -ExecutionPolicy Default.

Tenga en cuenta que la política de ejecución solo se verifica cuando comienza su ejecución (o eso parece) y, por lo tanto, puede ejecutar trabajos en segundo plano y restablecer la política de ejecución de inmediato.

# Check current setting
Get-ExecutionPolicy

# Disable policy
Set-ExecutionPolicy -ExecutionPolicy Unrestricted
# Choose [Y]es

Start-Job { cd c:\working\directory\with\script\ ; ./ping_batch.ps1 example.com | tee ping__example.com.txt }
Start-Job { cd c:\working\directory\with\script\ ; ./ping_batch.ps1 google.com  | tee ping__google.com.txt  }

# Can be run immediately
Set-ExecutionPolicy -ExecutionPolicy Default
# [Y]es
Nux
fuente
2

Otra forma fácil de ejecutar un script ps desde un lote es simplemente incorporarlo entre los caracteres ECHO y Redirection, (> y >>), por ejemplo:

@echo off
set WD=%~dp0
ECHO New-Item -Path . -Name "Test.txt" -ItemType "file" -Value "This is a text string." -Force > "%WD%PSHELLFILE.ps1"
ECHO add-content -path "./Test.txt" -value "`r`nThe End" >> "%WD%PSHELLFILE.ps1"
powershell.exe -ExecutionPolicy Bypass -File "%WD%PSHELLFILE.ps1"
del "%WD%PSHELLFILE.ps1"

La última línea elimina el archivo temporal creado.

Dobbelina
fuente
1

Si su secuencia de comandos de inicio de sesión de PowerShell se está ejecutando después de 5 minutos (como la mía) en un servidor de 2012, hay una configuración de GPO en un servidor: 'Configurar retraso de secuencia de comandos de inicio de sesión' la configuración predeterminada 'no configurado', esto dejará un retraso de 5 minutos antes de ejecutar el script de inicio de sesión.

Neil 11111
fuente
1

Pequeña muestra test.cmd

<# :
  @echo off
    powershell /nologo /noprofile /command ^
         "&{[ScriptBlock]::Create((cat """%~f0""") -join [Char[]]10).Invoke(@(&{$args}%*))}"
  exit /b
#>
Write-Host Hello, $args[0] -fo Green
#You programm...
DimoN
fuente