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

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

    Per diversi motivi, per lo più legati alla sicurezza, gli script PowerShell 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 fare questo.

    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 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. Ti abbiamo mostrato come modificare questa impostazione in Come consentire l'esecuzione di script PowerShell su Windows 7. Tuttavia, questo è anche qualcosa che non vuoi fare su un qualsiasi computer.
    3. Alcuni script PowerShell non funzioneranno senza le autorizzazioni di amministratore.
      Anche con un account di livello 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 dobbiamo riscrivere il file batch per ogni script, o ogni volta che spostiamo uno script, useremo 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 assegnare un nome al file batch "MyScript.bat" e assicurarti che si trovi nella stessa cartella. Quindi, inserisci queste righe nello script batch:

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

    Se non fosse per le altre restrizioni di sicurezza, sarebbe davvero sufficiente 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 ripartizione:

    @TO SPENTO 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. Naturalmente PowerShell.exe può 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.

    PAUSA 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 esaminiamo ogni fase, l'utilità di questa operazione 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 affrontato solo il primo dei nostri quattro problemi. Tuttavia, ci sono alcuni bit importanti dimostrati qui:

    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 funziona 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. Aggiungi semplicemente la seguente riga allo script del tuo 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 una fonte esterna:

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

    Questo 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: Spostarsi in ExecutionPolicy.

    Spostarsi attorno all'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 la ExecutionPolicy utilizzata 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, facciamo un altro tentativo:

    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 negli scopi 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!' altro Write-Output 'Running Limited!' Pausa

    Noterai anche che ora ci sono due operazioni di "Pausa" nell'output dello script: uno dallo script PowerShell e uno dal file batch. La ragione di ciò sarà più evidente nel prossimo passo.

    Passaggio 3: accesso all'amministratore.

    Se il tuo script non esegue alcun comando che richiede elevazione, e sei abbastanza sicuro che non dovrai preoccuparti del fatto che i profili personalizzati di qualcuno possano intralciarti, puoi saltare il resto. Se stai eseguendo 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" "' -Verb RunAs" "

    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 dello script 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 lo script verrà eseguito. 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, vero? 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 lanciate dallo script, lo script del profilo dell'utente verrà completamente bypassato in entrambi i passaggi e il nostro script PowerShell verrà eseguito in un ambiente predefinito abbastanza prevedibile. Qui puoi vedere che non c'è 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 assomigliare a questa:

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

    L'output sarà quindi simile a questo:

    (Naturalmente, per gli script non-Administrator, si può fare a meno di una pausa di fine script nello script PowerShell anche in questo momento poiché tutto viene catturato nella stessa finestra della console e verrà trattenuto dalla pausa alla fine di il file batch comunque.)

    File batch completati.

    A seconda che tu abbia bisogno o meno delle autorizzazioni di amministratore per il tuo script PowerShell (e davvero 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'" PAUSA

    Con accesso 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 per il quale si desidera utilizzarlo e assegnargli 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 le 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: il Blog di programmazione di Daniel Schroeder
    • Verifica delle autorizzazioni di amministratore in PowerShell - Hey, Scripting Guy! blog