9Sep

Cómo usar un archivo por lotes para hacer que los scripts de PowerShell sean más fáciles de ejecutar

click fraud protection

Por varios motivos, en su mayoría relacionados con la seguridad, los scripts de PowerShell no son tan fáciles de usar y usar como los scripts por lotes. Sin embargo, podemos agrupar un script por lotes con nuestros scripts de PowerShell para solucionar estos problemas. Aquí, le mostraremos algunas de esas áreas problemáticas y cómo crear un script por lotes para evitarlas.

¿Por qué no puedo simplemente copiar mi archivo. PS1 a otra computadora y ejecutarlo?

A menos que el sistema de destino haya sido preconfigurado para permitir la ejecución de secuencias de comandos arbitrarias, con los privilegios necesarios y con la configuración correcta, es probable que se encuentre con algunos problemas cuando intente hacerlo.

  1. PowerShell no está asociado a la extensión de archivo. PS1 de forma predeterminada.
    Lo mencionamos inicialmente en nuestra serie PowerShell Geek School. Windows asocia los archivos. PS1 al Bloc de notas de forma predeterminada, en lugar de enviarlos al intérprete de comandos de PowerShell. Esto es para evitar la ejecución accidental de scripts maliciosos simplemente haciendo doble clic en ellos. Hay formas en que puede cambiar este comportamiento, pero probablemente no sea algo que desee hacer en cada computadora con la que está ejecutando sus secuencias de comandos, especialmente si algunas de esas computadoras no son suyas.
    instagram viewer
  2. PowerShell no permite la ejecución de scripts externos de manera predeterminada.
    La configuración de ExecutionPolicy en PowerShell impide la ejecución de scripts externos de forma predeterminada en todas las versiones de Windows. En algunas versiones de Windows, el valor predeterminado no permite la ejecución de scripts. Le mostramos cómo cambiar esta configuración en Cómo permitir la ejecución de scripts de PowerShell en Windows 7. Sin embargo, esto también es algo que no desea hacer en cualquier computadora.
  3. Algunos scripts de PowerShell no funcionarán sin permisos de administrador.
    Incluso ejecutándose con una cuenta de nivel de administrador, usted todavía necesita pasar por el Control de cuentas de usuario( UAC) para realizar ciertas acciones. No queremos deshabilitar esto, pero sigue siendo bueno cuando podemos hacerlo un poco más fácil de tratar.
  4. Algunos usuarios pueden tener entornos personalizados de PowerShell.
    Probablemente no te toparás con esto a menudo, pero cuando lo haces puede hacer que la ejecución y la resolución de problemas de tus scripts sean un poco frustrantes. Afortunadamente, podemos evitar esto sin hacer cambios permanentes también.

Paso 1: Haga doble clic para ejecutar.

Comencemos abordando el primer problema: asociaciones de archivos. PS1.No puede hacer doble clic para ejecutar archivos. PS1, pero puede ejecutar un archivo. BAT de esa manera. Por lo tanto, escribiremos un archivo por lotes para llamar al script de PowerShell desde la línea de comandos para nosotros.

Así que no tenemos que volver a escribir el archivo por lotes para cada secuencia de comandos, o cada vez que movemos una secuencia de comandos, va a hacer uso de una variable autorreferencial para construir la ruta del archivo para la secuencia de comandos de PowerShell. Para que esto funcione, el archivo por lotes deberá colocarse en la misma carpeta que su secuencia de comandos de PowerShell y tener el mismo nombre de archivo. Entonces, si su secuencia de comandos de PowerShell se llama "MyScript.ps1", querrá nombrar su archivo de proceso por lotes "MyScript.bat" y asegurarse de que esté en la misma carpeta. Luego, ponga estas líneas en el script por lotes:

@ECHO OFF PowerShell.exe -Command "& '% ~ dpn0.ps1'" PAUSE

Si no fuera por las otras restricciones de seguridad implementadas, eso sería realmente todose necesita ejecutar un script de PowerShell desde un archivo por lotes. De hecho, la primera y la última línea son principalmente una cuestión de preferencia; es la segunda línea la que realmente está haciendo el trabajo. Aquí está el desglose:

@ECHO OFF desactiva el eco de comandos. Esto solo evita que sus otros comandos se muestren en la pantalla cuando se ejecuta el archivo por lotes. Esta línea está oculta por el uso del símbolo at( @) enfrente de ella.

PowerShell.exe -Command "&'% ~ Dpn0.ps1' " realmente ejecuta el script de PowerShell. Por supuesto, se puede llamar a PowerShell.exe desde cualquier ventana CMD o archivo por lotes para iniciar PowerShell en una consola simple como siempre. También puede usarlo para ejecutar comandos directamente desde un archivo por lotes, incluyendo el parámetro -Command y los argumentos apropiados. La forma en que esto se utiliza para apuntar a nuestro archivo. PS1 es con la variable especial% ~ dpn0.Ejecutar desde un archivo por lotes,% ~ dpn0 evalúa la letra de la unidad, la ruta de la carpeta y el nombre del archivo( sin extensión) del archivo por lotes. Como el archivo por lotes y el script de PowerShell estarán en la misma carpeta y tendrán el mismo nombre,% ~ dpn0.ps1 se traducirá a la ruta completa del archivo del script de PowerShell.

PAUSE hace una pausa en la ejecución del lote y espera la entrada del usuario. En general, es útil tenerlo al final de los archivos de proceso por lotes, de modo que tenga la oportunidad de revisar cualquier salida de comando antes de que la ventana desaparezca. A medida que avanzamos en las pruebas de cada paso, la utilidad de esto se hará más obvia.

Por lo tanto, el archivo de proceso por lotes básico está configurado. Para fines de demostración, este archivo se guarda como "D: \ Script Lab \ MyScript.bat" y hay un "MyScript.ps1" en la misma carpeta. Veamos qué ocurre cuando hacemos doble clic en MyScript.bat.

Obviamente, el script de PowerShell no se ejecutó, pero eso es de esperar; después de todo, solo hemos abordado el primero de nuestros cuatro problemas. Sin embargo, aquí se muestran algunos bits importantes:

  1. El título de la ventana muestra que el script por lotes inició PowerShell correctamente.
  2. La primera línea de salida muestra que se está utilizando un perfil de PowerShell personalizado. Este es el problema potencial # 4, mencionado anteriormente.
  3. El mensaje de error muestra las restricciones de ExecutionPolicy vigentes. Ese es nuestro problema # 2.
  4. La parte subrayada del mensaje de error( que se realiza de forma nativa mediante el resultado de error de PowerShell) muestra que el script por lotes se estaba dirigiendo correctamente al script de PowerShell deseado( D: \ Script Lab \ MyScript.ps1).Entonces, al menos sabemos que mucho está funcionando correctamente.

El perfil, en este caso, es un script simple de una línea utilizado para esta demostración para generar resultados cada vez que el perfil está activo. Puede personalizar su propio perfil de PowerShell para hacer esto también, si desea probar estos scripts usted mismo. Simplemente agregue la siguiente línea a su script de perfil:

Write-Output '¡El perfil Custom PowerShell en efecto!'

ExecutionPolicy en el sistema de prueba aquí está configurado como RemoteSigned. Esto permite la ejecución de scripts creados localmente( como el script de perfil), al tiempo que bloquea los scripts de fuentes externas a menos que estén firmados por una autoridad de confianza. A modo de demostración, se utilizó el siguiente comando para marcar MyScript.ps1 como procedente de una fuente externa:

Add-Content -Path 'D: \ Script Lab \ MyScript.ps1' -Value "[ZoneTransfer]` nZoneId = 3 "-Transmita 'Zone. Identifier'

que establece el flujo de datos alternativo Zone. Identifier en MyScript.ps1 para que Windows piense que el archivo proviene de Internet. Se puede revertir fácilmente con el siguiente comando:

Clear-Content -Path 'D: \ Script Lab \ MyScript.ps1' -Stream 'Zone. Identifier'

Paso 2: Cómo desplazarse por ExecutionPolicy.

Moverse por la configuración de ExecutionPolicy, desde CMD o un script por lotes, es bastante fácil. Solo modificamos la segunda línea de la secuencia de comandos para agregar un parámetro más al comando PowerShell.exe.

PowerShell.exe -ExecutionPolicy Bypass -Command "& '% ~ dpn0.ps1'"

El parámetro -ExecutionPolicy se puede usar para modificar la ExecutionPolicy que se usa cuando genera una nueva sesión de PowerShell. Esto no persistirá más allá de esa sesión, por lo que podemos ejecutar PowerShell de esta manera siempre que lo necesitemos sin debilitar la postura general de seguridad del sistema. Ahora que lo hemos solucionado, vamos a tener otra oportunidad:

Ahora que el script se ha ejecutado correctamente, podemos ver lo que realmente hace. Nos permite saber que estamos ejecutando el script como un usuario limitado. De hecho, el script está siendo ejecutado por una cuenta con permisos de Administrador, pero el Control de cuentas de usuario se interpone en el camino. Aunque los detalles de cómo el script está verificando el acceso del Administrador están fuera del alcance de este artículo, aquí está el código que se está utilizando para la demostración:

if( ([Security. Principal. WindowsPrincipal] [Security. Principal. WindowsIdentity]: : GetCurrent() ). IsInRole( [Security. Principal. WindowsBuiltInRole] "Administrator")){ Write-Output '¡Ejecutando como administrador!'} Else{ Write-Output 'Running Limited!'} Pausa

También notará que ahora hay dosOperaciones de "Pausa" en el resultado del script: una desde el script de PowerShell y otra desde el archivo por lotes. La razón de esto será más evidente en el siguiente paso.

Paso 3: Obtener acceso de administrador.

Si su secuencia de comandos no ejecuta ningún comando que requiera elevación, y está seguro de que no tendrá que preocuparse de que los perfiles personalizados de cualquiera se interpongan, puede omitir el resto de esto. Sin embargo, si está ejecutando algunos cmdlets de nivel de administrador, necesitará esta pieza.

Desafortunadamente, no hay forma de activar el UAC para la elevación desde un archivo de proceso por lotes o una sesión de CMD.Sin embargo, PowerShell nos permite hacer esto con Start-Process. Cuando se utiliza con "-Verb RunAs" en sus argumentos, Start-Process intentará iniciar una aplicación con permisos de Administrador. Si la sesión de PowerShell no está elevada, esto activará un aviso de UAC.Para usar esto desde el archivo de proceso por lotes para iniciar nuestro script, terminaremos generando dos procesos de PowerShell: uno para iniciar Start-Process y otro, iniciado por Start-Process, para ejecutar el script. La segunda línea del archivo por lotes debe cambiarse a esto:

PowerShell.exe -Command "&{ Start-Process PowerShell.exe -ArgumentList '-ExecutionPolicy Bypass -File" "% ~ dpn0.ps1" "' -VerbRunAs} "

Cuando se ejecuta el archivo por lotes, la primera línea de salida que veremos proviene del script de perfil de PowerShell. Entonces, habrá un aviso de UAC cuando Start-Process intente iniciar MyScript.ps1.

Después de hacer clic en el indicador UAC, se generará una nueva instancia de PowerShell. Debido a que esta es una nueva instancia, por supuesto, volveremos a ver el aviso del script de perfil. Luego, se ejecuta MyScript.ps1 y vemos que, de hecho, estamos en una sesión elevada.

Y ahí está la razón por la que tenemos dos pausas aquí también. Si no fuera por el script de PowerShell, nunca veríamos el resultado del script: la ventana de PowerShell simplemente aparecería y desaparecería tan pronto como el script se ejecute. Y sin la pausa en el archivo por lotes, no podríamos ver si hubo algún error al iniciar PowerShell en primer lugar.

Paso 4: Moverse por los perfiles personalizados de PowerShell.

Vamos a deshacernos de ese desagradable aviso de perfil personalizado ahora, ¿de acuerdo? Aquí, apenas es una molestia, pero si el perfil de PowerShell de un usuario cambia las configuraciones, variables o funciones predeterminadas de formas que quizás no haya previsto con su secuencia de comandos, pueden ser realmente molestas. Es mucho más simple ejecutar su script sin el perfil completo, por lo que no tiene que preocuparse por esto. Para hacer eso, solo tenemos que cambiar la segunda línea del archivo por lotes una vez más:

PowerShell.exe -NoProfile -Command "&{ Start-Process PowerShell.exe -ArgumentList '-NoProfile -ExecutionPolicy Bypass -File" "% ~ dpn0.ps1 "" '-Verb RunAs} "

Al agregar el parámetro -NoProfile a ambas instancias de PowerShell que inicia el script, significa que el script del perfil del usuario se omitirá por completo en ambos pasos y nuestro script de PowerShell se ejecutará enun entorno predeterminado bastante predecible. Aquí puede ver que no hay un aviso de perfil personalizado en ninguno de los shells generados.

Si no necesita derechos de administrador en su secuencia de comandos de PowerShell y se ha saltado el Paso 3, puede prescindir de la segunda instancia de PowerShell y la segunda línea de su archivo por lotes debería verse así:

PowerShell.exe -NoProfile -ExecutionPolicy Bypass -Command "& '% ~ dpn0.ps1'"

El resultado será así:

( Por supuesto, para las secuencias de comandos que no son de administrador, podría hacerlo sin una pausa de final de secuencia de comandos en su secuencia de comandos de PowerShellen este punto también, ya que todo se captura en la misma ventana de la consola y se mantendría allí por la pausa al final del archivo por lotes de todos modos.)

Archivos por lotes completados.

Dependiendo de si necesita o no permisos de administrador para su secuencia de comandos de PowerShell( y realmente no debería solicitarlos si no lo hace), el archivo final de proceso por lotes debería verse como uno de los dos a continuación.

Sin acceso de administrador:

@ECHO OFF PowerShell.exe -NoProfile -ExecutionPolicy Bypass -Command "& '% ~ dpn0.ps1'" PAUSE

Con acceso de administrador:

@ECHO OFF PowerShell.exe -NoProfile -Command "&{Start-Process PowerShell.exe -ArgumentList '-NoProfile -ExecutionPolicy Bypass -File ""% ~ dpn0.ps1 ""' -Verb RunAs} "PAUSE

Recuerde colocar el archivo por lotes en la misma carpeta que el script de PowerShell que deseepara usarlo, y darle el mismo nombre. Entonces, no importa en qué sistema se tomen esos archivos, podrá ejecutar su secuencia de comandos de PowerShell sin tener que perder el tiempo con ninguna de las configuraciones de seguridad del sistema. Sin duda, puede hacer esos cambios de forma manual todas las veces, pero esto le ahorra ese problema y no tendrá que preocuparse por revertir los cambios más adelante.

Referencias:

  • Ejecución de scripts de PowerShell desde un archivo de proceso por lotes - Daniel Schroeder's Programming Blog
  • Comprobación de los permisos de administrador en PowerShell - ¡Hola, Scripting Guy! Blog