9Sep

Come utilizzare un file batch per rendere gli script di PowerShell più facili da eseguire

Per diversi motivi, per lo più gli script PowerShell relativi alla sicurezza non sono altrettanto facilmente trasferibili e utilizzabili come possono essere gli script batch. Tuttavia, possiamo raggruppare uno script batch con i nostri script PowerShell per ovviare a questi problemi. Qui, ti mostreremo alcune di quelle aree problematiche e come creare uno script batch per aggirarle.

Perché non posso semplicemente copiare il mio file. PS1 su un altro computer ed eseguirlo?

A meno che il sistema di destinazione non sia stato preconfigurato per consentire l'esecuzione di script arbitrari, con i privilegi richiesti e utilizzando le giuste impostazioni, è probabile che si verifichino dei problemi quando si tenta di farlo.

  1. PowerShell non è associato all'estensione del file. PS1 per impostazione predefinita.
    L'abbiamo portato inizialmente nella nostra serie PowerShell Geek School. Windows associa i file. PS1 al Blocco note per impostazione predefinita, anziché inviarli all'interprete dei comandi di PowerShell. Questo serve a prevenire l'esecuzione accidentale di script dannosi semplicemente facendo doppio clic su di essi. Ci sono modi in cui puoi cambiare questo comportamento, ma probabilmente non è qualcosa che vuoi fare su ogni computer su cui stai portando i tuoi script - specialmente se alcuni di quei computer non sono i tuoi.
  2. PowerShell non consente l'esecuzione di script esterni per impostazione predefinita.
    L'impostazione ExecutionPolicy in PowerShell impedisce l'esecuzione di script esterni per impostazione predefinita in tutte le versioni di Windows. In alcune versioni di Windows, l'impostazione predefinita non consente affatto l'esecuzione di script. Vi abbiamo mostrato come modificare questa impostazione in Come consentire l'esecuzione di script PowerShell su Windows 7. Tuttavia, questo è anche qualcosa che non si vuole fare su un qualsiasi computer.
  3. Alcuni script PowerShell non funzionano senza autorizzazioni di amministratore.
    Anche con un account a livello di amministratore, è comunque necessario passare attraverso il Controllo dell'account utente( UAC) per eseguire determinate azioni. Non vogliamo disabilitare questo, ma è ancora bello quando possiamo renderlo un po 'più facile da gestire.
  4. Alcuni utenti potrebbero avere ambienti PowerShell personalizzati.
    Probabilmente non ci si imbatterà spesso in questo, ma quando lo fai può rendere l'esecuzione e la risoluzione dei problemi degli script un po 'frustranti. Fortunatamente, possiamo aggirare questo senza apportare modifiche permanenti pure.

Passaggio 1: fare doppio clic per eseguire.

Iniziamo affrontando il primo problema: le associazioni di file. PS1.Non è possibile fare doppio clic per eseguire i file. PS1, ma è possibile eseguire un file. BAT in questo modo. Quindi, scriveremo un file batch per chiamare lo script PowerShell dalla riga di comando per noi.

Quindi non è necessario riscrivere il file batch per ogni script, o ogni volta che spostiamo uno script, verrà utilizzata una variabile autoreferenziale per creare il percorso del file per lo script PowerShell. Per fare in modo che funzioni, il file batch dovrà essere collocato nella stessa cartella dello script PowerShell e avere lo stesso nome file. Quindi, se lo script PowerShell si chiama "MyScript.ps1", ti consigliamo di dare un nome al file batch "MyScript.bat" e assicurarti che sia nella stessa cartella. Quindi, inserisci queste righe nello script batch:

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

Se non fosse per le altre restrizioni di sicurezza in atto, sarebbe davvero tuttoserve per eseguire uno script PowerShell da un file batch. In effetti, la prima e l'ultima riga sono principalmente solo una questione di preferenza - è la seconda linea che sta davvero facendo il lavoro. Ecco la descrizione:

@ECHO OFF disattiva il comando echoing. Ciò mantiene solo gli altri comandi da mostrare sullo schermo quando viene eseguito il file batch. Questa linea è nascosta dall'uso del simbolo a( @) davanti ad esso.

PowerShell.exe -Command "&'% ~ Dpn0.ps1' " esegue effettivamente lo script PowerShell. PowerShell.exe può ovviamente essere chiamato da qualsiasi finestra CMD o file batch per avviare PowerShell su una console nuda come al solito. Puoi anche usarlo per eseguire comandi direttamente da un file batch, includendo il parametro -Command e gli argomenti appropriati. Il modo in cui questo viene utilizzato per indirizzare il nostro file. PS1 è con la variabile% ~ dpn0 speciale. Eseguito da un file batch,% ~ dpn0 valuta la lettera dell'unità, il percorso della cartella e il nome del file( senza estensione) del file batch. Poiché il file batch e lo script PowerShell si troveranno nella stessa cartella e avranno lo stesso nome,% ~ dpn0.ps1 verrà convertito nel percorso file completo dello script PowerShell.

PAUSE interrompe l'esecuzione del batch e attende l'input dell'utente. Generalmente è utile avere alla fine dei file batch, in modo da avere la possibilità di rivedere qualsiasi output di comando prima che la finestra scompaia. Mentre testiamo ogni fase, l'utilità di ciò diventerà più ovvia.

Quindi, il file batch di base è impostato. A scopo dimostrativo, questo file viene salvato come "D: \ Script Lab \ MyScript.bat" e c'è un "MyScript.ps1" nella stessa cartella. Vediamo cosa succede quando facciamo doppio clic su MyScript.bat.

Ovviamente lo script di PowerShell non è stato eseguito, ma c'è da aspettarselo, dopotutto abbiamo solo affrontato il primo dei nostri quattro problemi. Tuttavia, qui sono mostrati alcuni bit importanti:

  1. Il titolo della finestra mostra che lo script batch ha lanciato correttamente PowerShell.
  2. La prima riga di output mostra che è in uso un profilo PowerShell personalizzato. Questo è il potenziale problema n. 4, elencato sopra.
  3. Il messaggio di errore mostra le restrizioni ExecutionPolicy in vigore. Questo è il nostro problema # 2.
  4. La parte sottolineata del messaggio di errore( che viene eseguita in modo nativo dall'output degli errori di PowerShell) mostra che lo script batch stava indirizzando correttamente lo script PowerShell desiderato( D: \ Script Lab \ MyScript.ps1).Quindi sappiamo almeno che molto sta funzionando correttamente.

Il profilo, in questo caso, è un semplice script a riga singola utilizzato per questa dimostrazione per generare output ogni volta che il profilo è attivo. Puoi anche personalizzare il tuo profilo PowerShell per fare questo, se vuoi testare questi script tu stesso. Basta aggiungere la seguente riga allo script del profilo:

Write-Output "Profilo PowerShell personalizzato in vigore!"

La ExecutionPolicy sul sistema di test qui è impostata su RemoteSigned. Ciò consente l'esecuzione di script creati localmente( come lo script del profilo), mentre blocchi gli script da fonti esterne a meno che non siano firmati da un'autorità attendibile. A scopo dimostrativo, è stato utilizzato il seguente comando per contrassegnare MyScript.ps1 come proveniente da un'origine esterna:

Aggiungi contenuto -Path 'D: \ Script Lab \ MyScript.ps1' -Valore "[ZoneTransfer]` nZoneId = 3 "-Stream 'Zone. Identifier'

che imposta il flusso di dati alternativo Zone. Identifier su MyScript.ps1 in modo che Windows pensi che il file provenga da Internet. Può essere facilmente invertito con il seguente comando:

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

Passaggio 2: Spostamento di ExecutionPolicy.

Andare in giro per l'impostazione ExecutionPolicy, da CMD o da uno script batch, è in realtà piuttosto semplice. Modifichiamo semplicemente la seconda riga dello script per aggiungere un altro parametro al comando PowerShell.exe.

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

Il parametro -ExecutionPolicy può essere utilizzato per modificare ExecutionPolicy utilizzato quando si genera una nuova sessione di PowerShell. Ciò non persisterà oltre quella sessione, quindi possiamo eseguire PowerShell in questo modo ogni volta che è necessario senza indebolire la postura di sicurezza generale del sistema. Ora che l'abbiamo risolto, diamo un altro risultato:

Ora che lo script è stato eseguito correttamente, possiamo vedere cosa effettivamente fa. Ci fa sapere che stiamo eseguendo la sceneggiatura come utente limitato. Lo script è infatti gestito da un account con autorizzazioni di amministratore, ma il controllo dell'account utente sta intralciando. Sebbene i dettagli su come lo script sta verificando l'accesso come amministratore non rientrano nell'ambito di questo articolo, ecco il codice che viene utilizzato per la dimostrazione:

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

Noterai che ora ci sono due"Sospendi" operazioni nell'output dello script, uno dallo script PowerShell e uno dal file batch. Il motivo per questo sarà più evidente nel passaggio successivo.

Passaggio 3: ottenere l'accesso come amministratore.

Se il tuo script non esegue alcun comando che richiede elevazione, e sei abbastanza sicuro che non dovrai preoccuparti che i profili personalizzati di chiunque si intromettano, puoi saltare il resto di questo. Se stai utilizzando alcuni cmdlet a livello di amministratore, avrai bisogno di questo pezzo.

Sfortunatamente, non c'è modo di attivare UAC per l'elevazione da un file batch o da una sessione CMD.Tuttavia, PowerShell ci consente di farlo con Start-Process. Se utilizzato con "-Verb RunAs" nei suoi argomenti, Start-Process tenterà di avviare un'applicazione con le autorizzazioni di amministratore. Se la sessione di PowerShell non è già elevata, verrà attivato un prompt UAC.Per utilizzare questo dal file batch per l'avvio del nostro script, finiremo per generare due processi PowerShell: uno per avviare Start-Process e un altro, avviato da Start-Process, per eseguire lo script. La seconda riga del file batch deve essere modificata in questo modo:

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

Quando viene eseguito il file batch, la prima riga di output che vedremo proviene dallo script del profilo di PowerShell. Quindi, verrà visualizzato un prompt UAC quando Start-Process tenta di avviare MyScript.ps1.

Dopo aver fatto clic sul prompt UAC, verrà generata una nuova istanza di PowerShell. Perché questa è una nuova istanza, ovviamente, vedremo di nuovo la notifica del profilo. Quindi, MyScript.ps1 viene eseguito e vediamo che siamo davvero in una sessione elevata.

E c'è anche il motivo per cui abbiamo due pause qui. Se non fosse per quello nello script di PowerShell, non vedremmo mai l'output dello script: la finestra di PowerShell si aprirà e scomparirà non appena viene eseguito lo script. E senza la pausa nel file batch, non saremmo in grado di vedere se c'erano degli errori che lanciavano PowerShell in primo luogo.

Passaggio 4: spostamento dei profili PowerShell personalizzati.

Liberiamoci da quel brutto avviso sul profilo personalizzato ora, giusto? Qui, non è nemmeno una seccatura, ma se il profilo PowerShell di un utente cambia le impostazioni, le variabili o le funzioni predefinite in modi che potresti non aver previsto con il tuo script, possono essere davvero fastidiosi.È molto più semplice eseguire il tuo script senza il profilo in modo da non doverti preoccupare di questo. Per fare ciò, abbiamo solo bisogno di cambiare la seconda riga del file batch ancora una volta:

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

Aggiungendo il parametro -NoProfile a entrambe le istanze di PowerShell avviate dallo script, lo script del profilo dell'utente verrà completamente bypassato in entrambi i passaggi e verrà eseguito lo script PowerShell inun ambiente predefinito abbastanza prevedibile. Qui puoi vedere che non vi è alcun avviso di profilo personalizzato in nessuna delle shell generate.

Se non hai bisogno dei diritti di amministratore nello script PowerShell e hai saltato il passaggio 3, puoi fare a meno della seconda istanza di PowerShell e la seconda riga del file batch dovrebbe apparire così:

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

L'output sarà quindi simile a questo:

( Ovviamente, per gli script non-Administrator, è possibile eseguire una pausa di fine script nello script PowerShellanche a questo punto poiché tutto viene catturato nella stessa finestra della console e verrà comunque trattenuto dalla pausa alla fine del file batch.)

File batch completati.

A seconda che siano necessarie o meno le autorizzazioni di amministratore per lo script PowerShell( e in realtà non dovresti richiederle se non lo fai) il file batch finale dovrebbe apparire come uno dei due seguenti.

Senza accesso amministratore:

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

con accesso di amministratore:

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

Ricordarsi di inserire il file batch nella stessa cartella dello script PowerShell che si desideraper usarlo e dargli lo stesso nome. Quindi, indipendentemente dal sistema in cui vengono portati i file, sarete in grado di eseguire il vostro script PowerShell senza dover perdere tempo con nessuna delle impostazioni di sicurezza del sistema.È possibile eseguire tali modifiche manualmente ogni volta, ma questo ti evita i problemi e non dovrai preoccuparti di ripristinare le modifiche in un secondo momento. Riferimenti

:

  • Esecuzione di script PowerShell da un file batch - Blog di programmazione di Daniel Schroeder
  • Controllo delle autorizzazioni di amministratore in PowerShell - Hey, Scripting Guy! Blog