Cómo utilizar un archivo por lotes para hacer scripts de PowerShell más fácil de ejecutar

Encabezamiento
Por varias razones, sobre todo, scripts de PowerShell de seguridad relacionados no son tan fáciles de transportar y que pueden utilizarse como secuencias de comandos por lotes pueden ser. Sin embargo, podemos agrupar un script por lotes con nuestros scripts de PowerShell para evitar estos problemas. Aquí, le mostraremos algunas de esas áreas problemáticas, y cómo construir una secuencia de comandos por lotes para moverse por ellos.

¿Por qué no puedo simplemente copiar mi archivo .ps1 a otro equipo y ejecutarlo?

A menos que el sistema de destino ha sido pre-configurado para permitir el funcionamiento de scripts arbitrarios con los privilegios necesarios, y el uso de la configuración correcta, lo más probable es que va a encontrarse con algunos problemas al intentar hacer esto.
  1. PowerShell no está asociado a la extensión de archivo .ps1 por defecto.Lo comentamos inicialmente en nuestro PowerShell Geek escuela serie. Windows asocia archivos .ps1 al Bloc de notas por defecto, en lugar de enviarlos a la intérprete de comandos de PowerShell. Esto es para evitar la ejecución accidental de scripts maliciosos haciendo doble clic en ellos. Hay maneras que usted puede cambiar este comportamiento, pero probablemente no es algo que quieres hacer en cada equipo que llevas sus scripts en torno a - especialmente si algunas de esas computadoras no son el suyo propio.
  2. PowerShell no permite la ejecución de scripts externo por defecto.La puesta en PowerShell ExecutionPolicy impide la ejecución de scripts externos por defecto en todas las versiones de Windows. En algunas versiones de Windows, por defecto no permite la ejecución de scripts en absoluto. Te 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 quieres hacer en cualquier ordenador.
  3. Algunos scripts de PowerShell no funcionarán sin permisos de administrador.Incluso se ejecuta con una cuenta de nivel de administrador, usted todavía tiene que pasar por el Control de cuentas de usuario (UAC) para llevar a cabo ciertas acciones. No queremos desactivar esta , pero es todavía muy bien cuando podemos hacerlo un poco más fácil de tratar.
  4. Algunos usuarios podrían configurar entornos PowerShell.
    Es probable que no se ejecutará en esto a menudo, pero cuando lo hace puede hacer correr y solución de problemas de sus guiones un poco frustrante. Afortunadamente, podemos evitar esto sin hacer cambios permanentes también.

Paso 1: Haga doble clic para ejecutar.

Vamos a empezar por abordar el primer problema - .ps1 asociaciones de archivos. Usted no puede hacer doble clic para ejecutar archivos .ps1, pero se puede ejecutar un archivo .bat de esa manera. Por lo tanto, vamos a escribir 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 avanzamos un script alrededor, que va a hacer uso de una variable de referencia a sí misma para construir la ruta del archivo de la secuencia de comandos PowerShell. Para que esto funcione, necesitará el archivo por lotes para ser colocados en la misma carpeta que el script de PowerShell y tienen el mismo nombre de archivo. Así que si su script de PowerShell se llama "MyScript.ps1", usted querrá un nombre a su archivo por lotes "MyScript.bat" y asegurarse de que está en la misma carpeta. Luego, poner estas líneas en el archivo por lotes:
ECHO OFF
PowerShell.exe -Command "&"% ~ dpn0.ps1 '"
PAUSA
Si no fuera por el resto de restricciones de seguridad en el lugar, que sería realmente todo lo que necesita para ejecutar un script de PowerShell desde un archivo por lotes. De hecho, las primeras y últimas líneas son principalmente sólo una cuestión de preferencia - es la segunda línea que realmente está haciendo el trabajo. Aquí está el desglose:
ECHO OFF apaga comando eco. Esto sólo mantiene sus otros comandos de mostrar en pantalla cuando el archivo por lotes se ejecuta. Esta línea está oculto por sí mismo el uso de la al (@) símbolo en frente de ella.
PowerShell.exe -Command "&"% ~ dpn0.ps1 '" en realidad ejecuta el script de PowerShell.PowerShell.exe supuesto, se puede llamar desde cualquier ventana o archivo por lotes CMD lanzar PowerShell a una consola desnuda como de costumbre. También puede utilizarlo para ejecutar comandos directamente desde un archivo por lotes, incluyendo el parámetro -Command y argumentos adecuados. La forma en que se utiliza para orientar nuestro archivo .ps1 es con el% ~ dpn0 variable especial. Ejecutar desde un archivo por lotes,% ~ dpn0 evalúa a la letra de la unidad, ruta de la carpeta y el nombre de archivo (sin extensión) del archivo por lotes. Dado que el archivo por lotes y script de PowerShell estarán en la misma carpeta y tienen el mismo nombre,% ~ dpn0.ps1 se traducen en la ruta de acceso completa de la secuencia de comandos PowerShell.
PAUSA simplemente se detiene la ejecución por lotes y espera a la entrada del usuario. Esto es generalmente útil tener al final de sus archivos por lotes, para que tenga la oportunidad de revisar cualquier salida del comando antes de que desaparezca la ventana. A medida que avanzamos a través de pruebas de cada paso, la utilidad de esto se hará más evidente.
Por lo tanto, el archivo por lotes básico está configurado. Para fines de demostración, este archivo se guarda como "D: \ script Lab \ MyScript.bat" y hay una "MyScript.ps1" en la misma carpeta. Vamos a ver lo que sucede cuando hacemos doble clic MyScript.bat.
ExecutionPolicy
Obviamente, el script de PowerShell no se ha ejecutado, pero eso es de esperar - sólo hemos abordado el primero de nuestros cuatro problemas, después de todo. Sin embargo, hay algunos bits importantes demostrado aquí:
  1. El título de la ventana muestra que la escritura de la hornada lanzó con éxito PowerShell.
  2. La primera línea del resultado muestra que un perfil personalizado PowerShell está en uso.Esto es posible problema # 4, que aparece arriba.
  3. El mensaje de error demuestra restricciones ExecutionPolicy vigente. Ese es nuestro problema # 2.
  4. La parte subrayada del mensaje de error (que se realiza de forma nativa por salida de error de PowerShell) muestra la secuencia de comandos por lotes estaba apuntando correctamente el script de PowerShell previsto (D: \ script Lab \ MyScript.ps1). Así que al menos sabemos que gran parte está trabajando correctamente.
El perfil, en este caso, es un simple script de una línea utilizada para esta demostración para generar la salida cada vez que el perfil está activo. Puedes personalizar tu propio perfil de PowerShell para hacer esto también, si usted desea probar estos scripts ti mismo. Sólo tienes que añadir la siguiente línea a su script perfil:
Write-Output 'perfil personalizado PowerShell en efecto!'
El ExecutionPolicy en el sistema de prueba aquí se establece en RemoteSigned. Esto permite la ejecución de scripts creados localmente (como el guión perfil), mientras que el bloqueo de scripts de fuentes externas a menos que estén firmados por una autoridad de confianza. Para fines de demostración, el siguiente comando se utiliza para la bandera MyScript.ps1 como de una fuente externa:
Add-contenido -Path 'D: \ script Lab \ MyScript.ps1' -Value "[ZoneTransfer]` nZoneId = 3 "'Zone.Identifier' -stream
Que establece la secuencia de datos alternativa Zone.Identifier en MyScript.ps1 para que Windows va a pensar el archivo provenía de Internet . Puede ser fácilmente revertido con el siguiente comando:
Clear-Content -Path 'D: \ script Lab \ MyScript.ps1' 'Zone.Identifier' -stream

Paso 2: Cómo desplazarse ExecutionPolicy.

Moverse por la configuración ExecutionPolicy, desde CMD o un script por lotes, en realidad es bastante fácil. Acabamos de modificar la segunda línea de la secuencia de comandos para agregar un parámetro más para el comando PowerShell.exe.
PowerShell.exe -ExecutionPolicy Bypass -Command "&"% ~ dpn0.ps1 '"
El parámetro -ExecutionPolicy se puede utilizar para modificar el ExecutionPolicy que se utiliza cuando generar una nueva sesión de PowerShell. Esto no va a persistir más allá de ese período de sesiones, por lo que puede ejecutar PowerShell como esto siempre que necesitemos sin debilitar la postura de seguridad general del sistema. Ahora que hemos arreglado eso, vamos a tener otra oportunidad en que:
LimitedUser
Ahora que el guión ha ejecutado correctamente, podemos ver lo que realmente hace. Está haciéndonos saber que estamos ejecutando el script como usuario limitado. El guión está, de hecho, siendo dirigido por una cuenta con permisos de administrador, pero el Control de cuentas de usuario se está en el camino. Aunque los detalles de cómo el guión es la comprobación de acceso de administrador están más allá del alcance de este artículo, aquí está el código que está siendo utilizado para la demostración:
si "Administrador"))
{Write-Output 'Correr como administrador!'}
más
{Write-Output 'Running limitado!'}
Pausa
También te darás cuenta que ahora hay dos operaciones de "pausa" en la salida de la escritura - uno de la secuencia de comandos PowerShell, y uno desde el archivo por lotes. La razón de esto será más evidente en la siguiente etapa.

Paso 3: Obtener acceso de administrador.

Si la secuencia de comandos no se ejecuta ningún comando que requieren elevación, y ya está bastante seguro de que no tendrá que preocuparse acerca de los perfiles personalizados de nadie conseguir en el camino, puede saltarse el resto de esta. Si está ejecutando algunos cmdlets de nivel de administrador sin embargo, usted necesita esta pieza.
Desafortunadamente, no hay manera de activar el UAC para la elevación desde dentro de un archivo por lotes o una sesión de CMD. Sin embargo, PowerShell no nos permiten 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á elevado, esto desencadenará un mensaje de UAC. Para utilizar esto desde el archivo por lotes para el lanzamiento de nuestro script, vamos a terminar generando dos procesos PowerShell - una para disparar Puesta en proceso y otro, puesto en marcha por Start-Process, para ejecutar el script. La segunda línea del archivo por lotes se debe cambiar a la siguiente:
PowerShell.exe -Command "& {Inicio Proceso PowerShell.exe -ArgumentList '-ExecutionPolicy Bypass -File" "% ~ dpn0.ps1" "' -Verb RunAs}"
Al ejecutar el archivo por lotes, la primera línea de salida que veremos es del guión perfil PowerShell. Luego, habrá un mensaje de UAC cuando Start-Process intenta lanzar MyScript.ps1.
UAC
Después de hacer clic a través de la UAC, una nueva instancia PowerShell se generan. Debido a que esta es una nueva instancia, por supuesto, vamos a ver de nuevo la notificación de la escritura de perfil. Entonces, MyScript.ps1 corre y vemos que estamos de hecho en una sesión elevada.
Administración
Y ahí está la razón por la que tenemos dos pausas, también. Si no fuera por la de la secuencia de comandos PowerShell, nunca veríamos la salida de la secuencia de comandos - la ventana de PowerShell gustaría simplemente aparecer y desaparecer tan pronto como la secuencia de comandos se realiza en ejecución. Y sin la pausa en el archivo por lotes, no seríamos capaces de ver si había cualquier error de lanzamiento de PowerShell en el primer lugar.

Paso 4: Cómo desplazarse perfiles personalizados de PowerShell.

Vamos a deshacerse de ese desagradable aviso perfil personalizado ahora, ¿de acuerdo? Aquí, es casi ni una molestia, pero si el perfil PowerShell de un usuario cambia la configuración predeterminada, variables o funciones de un modo que no puede haber anticipado con su escritura, que puede ser realmente molesto. Es mucho más fácil de ejecutar la secuencia de comandos sin el perfil completo de modo que usted no tiene que preocuparse por esto. Para ello, sólo tenemos que cambiar la segunda línea del archivo por lotes una vez más:
PowerShell.exe -NoProfile -Command "& {Inicio Proceso PowerShell.exe -ArgumentList '-NoProfile -ExecutionPolicy Bypass -File" "% ~ dpn0.ps1" "' -Verb RunAs}"
Añadiendo el parámetro -NoProfile a ambas instancias de PowerShell que se lanzan por el guión significa que la escritura de perfil del usuario será completamente anulada en ambas etapas y nuestro script de PowerShell se ejecutará en un entorno por defecto bastante predecible. Aquí, se puede ver que no hay aviso perfil personalizado en cualquiera de las conchas engendrado.
NoProfileAdmin
Si usted no necesita derechos de administrador en su secuencia de comandos PowerShell, y te has saltado el paso 3, se puede prescindir de la segunda instancia PowerShell y la segunda línea de su archivo por lotes debe tener este aspecto:
PowerShell.exe -NoProfile -ExecutionPolicy Bypass -Command "&"% ~ dpn0.ps1 '"
La salida será entonces el siguiente aspecto:
NoProfileLimited
(Por supuesto, para los scripts no-administrador, se puede hacer sin una pausa al final de la secuencia de comandos en el script de PowerShell en este punto demasiado ya que todo es capturado en la misma ventana de la consola y se mantuvo allí por la pausa al final de el lote archivo de todos modos.)

Archivos por lotes completos.

Dependiendo de si o no necesita permisos de administrador para su script de PowerShell (y que realmente no debería estar solicitando que si no lo hace) el archivo de lote final debe ser similar a uno de los dos más adelante.
Sin acceso Admin:
ECHO OFF
PowerShell.exe -NoProfile -ExecutionPolicy Bypass -Command "&"% ~ dpn0.ps1 '"
PAUSA
Con acceso Admin:
ECHO OFF
PowerShell.exe -NoProfile -Command "& {Inicio Proceso PowerShell.exe -ArgumentList '-NoProfile -ExecutionPolicy Bypass -File" "% ~ dpn0.ps1" "' -Verb RunAs}"
PAUSA
Recuerde poner el archivo por lotes en la misma carpeta que el script de PowerShell que desea utilizar para, y darle el mismo nombre. Entonces, no importa qué sistema se toma los archivos a, podrás ejecutar la secuencia de comandos PowerShell sin tener que ensuciar alrededor con cualquiera de las opciones de seguridad del sistema. Por supuesto que podría hacer esos cambios de forma manual cada vez, pero esto le ahorra ese problema y usted no tendrá que preocuparse de revertir los cambios más adelante.

Referencias:
  • Ejecución de scripts de PowerShell de un archivo por lotes - Programación Blog de ​​Daniel Schroeder
  • Comprobación de los permisos de administrador en PowerShell - Hey, chicos del scripting!Blog