
Modulo per compilare script PowerShell in eseguibili
Rielaborazione del grande script di Ingo Karstein con supporto GUI. L'output e l'input GUI sono attivati con un solo interruttore, vengono generati eseguibili Windows reali. Compila solo script compatibili con PowerShell 5.x. Con interfaccia grafica opzionale Win-PS2EXE.
Versione del modulo.
Trovi la versione basata su script qui (https://github.com/MScholtes/TechNet-Gallery).
Autore: Markus Scholtes
Versione: 1.0.18
Data: 2026-06-06
PS C:\> Install-Module ps2exe
o scarica da qui: https://www.powershellgallery.com/packages/ps2exe/.
Invoke-ps2exe .\source.ps1 .\target.exe
oppure
ps2exe .\source.ps1 .\target.exe
compila "source.ps1" nell'eseguibile target.exe (se ".\target.exe" è omesso, l'output viene scritto in ".\source.exe").
oppure avvia Win-PS2EXE per un'interfaccia grafica con
Win-PS2EXE
ps2exe [-inputFile] '<file_name>' [[-outputFile] '<file_name>']
[-prepareDebug] [-x86|-x64] [-lcid <id>] [-STA|-MTA] [-noConsole] [-conHost] [-UNICODEEncoding]
[-credentialGUI] [-iconFile '<filename>'] [-$embedFiles <hashtable>] [-title '<title>'] [-description '<description>']
[-company '<company>'] [-product '<product>'] [-copyright '<copyright>'] [-trademark '<trademark>']
[-version '<version>'] [-configFile] [-noOutput] [-noError] [-noVisualStyles] [-exitOnCancel]
[-DPIAware] [-requireAdmin] [-supportOS] [-virtualize] [-longPaths]
inputFile = Powershell script that you want to convert to executable (file has to be UTF8 or UTF16 encoded)
outputFile = destination executable file name or folder, defaults to inputFile with extension '.exe'
prepareDebug = create helpful information for debugging
x86 or x64 = compile for 32-bit or 64-bit runtime only
lcid = location ID for the compiled executable. Current user culture if not specified
STA or MTA = 'Single Thread Apartment' or 'Multi Thread Apartment' mode
noConsole = the resulting executable will be a Windows Forms app without a console window
conHost = force start with conhost as console instead of Windows Terminal (disables redirections)
UNICODEEncoding = encode output as UNICODE in console mode
credentialGUI = use GUI for prompting credentials in console mode
iconFile = icon file name for the compiled executable
embedFiles = files to embed given as hash, will be extracted to key of hash, source file names must be unique
(e.g. -embedFiles @{'Targetfilepath'='Sourcefilepath'} )
title = title information (displayed in details tab of Windows Explorer's properties dialog)
description = description information (not displayed, but embedded in executable)
company = company information (not displayed, but embedded in executable)
product = product information (displayed in details tab of Windows Explorer's properties dialog)
copyright = copyright information (displayed in details tab of Windows Explorer's properties dialog)
trademark = trademark information (displayed in details tab of Windows Explorer's properties dialog)
version = version information (displayed in details tab of Windows Explorer's properties dialog)
configFile = write config file (<outputfile>.exe.config)
noOutput = the resulting executable will generate no standard output (includes verbose and information channel)
noError = the resulting executable will generate no error output (includes warning and debug channel)
noVisualStyles = disable visual styles for a generated windows GUI application (only with -noConsole)
exitOnCancel = exits program when Cancel or "X" is selected in a Read-Host input box (only with -noConsole)
DPIAware = if display scaling is activated, GUI controls will be scaled if possible (only with -noConsole)
requireAdmin = if UAC is enabled, compiled executable run only in elevated context (UAC dialog appears if required)
supportOS = use functions of newest Windows versions (execute [Environment]::OSVersion to see the difference)
virtualize = application virtualization is activated (forcing x86 runtime)
longPaths = enable long paths ( > 260 characters) if enabled on OS (works only with Windows 10)
Un eseguibile generato ha i seguenti parametri riservati:
-? [<MODIFIER>] Powershell help text of the script inside the executable. The optional parameter combination
"-? -detailed", "-? -examples" or "-? -full" can be used to get the appropriate help text.
-debug Forces the executable to be debugged. It calls "System.Diagnostics.Debugger.Launch()".
-extract:<FILENAME> Extracts the powerShell script inside the executable and saves it as FILENAME.
The script will not be executed.
-wait At the end of the script execution it writes "Hit any key to exit..." and waits for a key to be pressed.
-end All following options will be passed to the script inside the executable.
All preceding options are used by the executable itself and will not be passed to the script.
PS2EXE può essere utilizzato con PowerShell Core. Per farlo, installa il modulo PS2EXE in PowerShell Core come descritto sopra. Ma poiché .Net Core non viene fornito con un compilatore, viene utilizzato il compilatore di .Net Framework (.Net Framework e PowerShell 5.1 sono inclusi in Windows).
Per questo motivo PS2EXE può compilare solo script compatibili con PowerShell 5.1 e genera binari .Net 4.x, ma può ancora essere utilizzato direttamente su ogni sistema operativo Windows supportato senza dipendenze.
Con il parametro -embedFiles seguito da una tabella hash con percorsi di file, quei file verranno incorporati nell'eseguibile compilato. All'avvio dell'eseguibile, quei file verranno scritti su disco nei percorsi specificati, ad esempio -embedFiles @{'Targetfilepath1'='Sourcefilepath1';'Targetfilepath2'='Sourcefilepath2'}. I nomi dei file sorgente devono essere univoci. Sono consentiti percorsi assoluti e relativi. Per i percorsi di destinazione, un percorso relativo che inizia con '.\' viene interpretato come relativo all'eseguibile, senza il '.\' iniziale come relativo al percorso corrente in fase di esecuzione. Le directory vengono create automaticamente all'avvio se necessario. Nel percorso di destinazione, le variabili d'ambiente nella notazione cmd.exe come %TEMP% o %APPDATA% vengono espanse in fase di esecuzione. Un fallimento nella creazione di uno dei file incorporati fermerà immediatamente l'esecuzione dell'eseguibile compilato.
I comandi di input/output di base hanno dovuto essere riscritti in C# per PS2EXE. Non sono implementati Write-Progress in modalità console (troppo lavoro) e Start-Transcript/Stop-Transcript (nessuna implementazione di riferimento adeguata da parte di Microsoft).
Per impostazione predefinita in PowerShell, gli output dei cmdlet sono formattati riga per riga (come un array di stringhe). Quando il tuo comando genera 10 righe di output e usi l'output GUI, appariranno 10 finestre di messaggio ciascuna in attesa di un OK. Per evitarlo, invia il tuo comando al cmdlet Out-String. Questo convertirà l'output in un array di stringhe con 10 righe, e tutto l'output verrà mostrato in un'unica finestra di messaggio (ad esempio: dir C:\ | Out-String).
PS2EXE può creare file di configurazione con il nome dell'eseguibile generato + ".config". Nella maggior parte dei casi questi file di configurazione non sono necessari, sono un manifest che indica quale versione di .Net Framework dovrebbe essere utilizzata. Poiché di solito utilizzerai l'attuale .Net Framework, prova a eseguire il tuo eseguibile senza il file di configurazione.
Gli script compilati elaborano i parametri come lo script originale. Una restrizione deriva dall'ambiente Windows: per tutti gli eseguibili, tutti i parametri hanno il tipo STRING, se non c'è una conversione implicita per il tuo tipo di parametro, devi convertire esplicitamente nel tuo script. Puoi anche inviare contenuto tramite pipe all'eseguibile con la stessa restrizione (tutti i valori inviati tramite pipe hanno il tipo STRING).
Non memorizzare mai le password nel tuo script compilato! Si può semplicemente decompilare lo script con il parametro -extract. Per esempio
Output.exe -extract:C:\Output.ps1
decompilerà lo script memorizzato in Output.exe. E nota: lo script (intenzionalmente) è memorizzato in testo chiaro nell'eseguibile!
Poiché PS2EXE converte uno script in un eseguibile, le variabili relative allo script non sono più disponibili. La variabile $MyInvocation è impostata su altri valori rispetto a uno script. In particolare la variabile $PSScriptRoot è vuota - puoi usare $ScriptRoot come sostituto.
Puoi ottenere $PSScriptRoot indipendentemente dal fatto che sia compilato o meno con la seguente riga di codice:
if (!$PSScriptRoot) { $PSScriptRoot = $ScriptRoot }
Quando una finestra esterna viene aperta in uno script con modalità -noConsole (ad esempio per Get-Credential o per un comando che necessita di una shell cmd.exe), la finestra successiva viene aperta in background.
Il motivo è che alla chiusura della finestra esterna, Windows cerca di attivare la finestra principale. Poiché lo script compilato non ha finestra, viene attivata la finestra principale dello script compilato, normalmente la finestra di Explorer o PowerShell.
Per aggirare il problema, $Host.UI.RawUI.FlushInputBuffer() apre una finestra invisibile che può essere attivata. La chiamata successiva di $Host.UI.RawUI.FlushInputBuffer() chiude questa finestra (e così via).
L'esempio seguente non aprirà più una finestra in background come farebbe una singola chiamata di "ipconfig | Out-String":
$Host.UI.RawUI.FlushInputBuffer()
ipconfig | Out-String
$Host.UI.RawUI.FlushInputBuffer()