
Modul zum Kompilieren von PowerShell-Skripten in ausführbare Dateien
Überarbeitung des großartigen Skripts von Ingo Karstein mit GUI-Unterstützung. Die GUI-Ausgabe und -Eingabe wird mit einem Schalter aktiviert, es werden echte Windows-Executables erzeugt. Kompiliert nur Powershell 5.x-kompatible Skripte. Mit optionaler grafischer Oberfläche Win-PS2EXE.
Modulversion.
Die skriptbasierte Version finden Sie hier (https://github.com/MScholtes/TechNet-Gallery).
Autor: Markus Scholtes Version: 1.0.18 Datum: 2026-06-06
PS C:\> Install-Module ps2exe
oder von hier herunterladen: https://www.powershellgallery.com/packages/ps2exe/.
Invoke-ps2exe .\source.ps1 .\target.exe
oder
ps2exe .\source.ps1 .\target.exe
kompiliert „source.ps1“ in die ausführbare Datei target.exe (wenn „.\target.exe“ weggelassen wird, wird die Ausgabe nach „.\source.exe“ geschrieben).
oder starten Sie Win-PS2EXE für eine grafische Oberfläche mit
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)
Ein erzeugtes Executable hat die folgenden reservierten Parameter:
-? [<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 kann mit Powershell Core verwendet werden. Installieren Sie dazu einfach das Modul PS2EXE in Powershell Core wie oben beschrieben. Da .Net Core jedoch keinen Compiler mitliefert, wird der Compiler von .Net Framework verwendet (.Net Framework und Powershell 5.1 sind in Windows enthalten).
Aus diesem Grund kann PS2EXE nur Powershell 5.1-kompatible Skripte kompilieren und erzeugt .Net 4.x-Binärdateien, kann aber dennoch direkt auf jedem unterstützten Windows-Betriebssystem ohne Abhängigkeiten verwendet werden.
Mit dem Parameter -embedFiles gefolgt von einer Hashtabelle mit Pfaden zu Dateien werden diese Dateien in das kompilierte Executable eingebettet. Beim Start des Executables werden diese Dateien auf die Festplatte an die angegebenen Pfade geschrieben, z.B. -embedFiles @{'Targetfilepath1'='Sourcefilepath1';'Targetfilepath2'='Sourcefilepath2'}. Quelldateinamen müssen eindeutig sein. Absolute und relative Pfade sind erlaubt. Für Zielpfade wird ein relativer Pfad, der mit '.\' beginnt, als relativ zum Executable interpretiert, ohne das führende '.\' als relativ zum aktuellen Pfad zur Laufzeit. Verzeichnisse werden beim Start automatisch erstellt, falls erforderlich. Im Zielpfad werden Umgebungsvariablen in cmd.exe-Notation wie %TEMP% oder %APPDATA% zur Laufzeit expandiert. Ein Fehler beim Erstellen einer der eingebetteten Dateien stoppt die Ausführung des kompilierten Executables sofort.
Die grundlegenden Ein-/Ausgabebefehle mussten für PS2EXE in C# neu geschrieben werden. Nicht implementiert sind Write-Progress im Konsolenmodus (zu viel Aufwand) und Start-Transcript/Stop-Transcript (keine ordnungsgemäße Referenzimplementierung von Microsoft).
Standardmäßig werden in Powershell Ausgaben von Cmdlets zeilenweise formatiert (als Array von Zeichenfolgen). Wenn Ihr Befehl 10 Ausgabezeilen erzeugt und Sie die GUI-Ausgabe verwenden, erscheinen 10 Meldungsfelder, die jeweils auf ein OK warten. Um dies zu verhindern, leiten Sie Ihren Befehl an das Cmdlet Out-String weiter. Dadurch wird die Ausgabe in ein Zeichenfolgenarray mit 10 Zeilen konvertiert, die gesamte Ausgabe wird in einem Meldungsfeld angezeigt (z.B.: dir C:\ | Out-String).
PS2EXE kann Konfigurationsdateien mit dem Namen des erzeugten Executables + ".config" erstellen. In den meisten Fällen sind diese Konfigurationsdateien nicht erforderlich; es handelt sich um ein Manifest, das angibt, welche .Net Framework-Version verwendet werden soll. Da Sie in der Regel das aktuelle .Net Framework verwenden, versuchen Sie, Ihr Executable ohne die Konfigurationsdatei auszuführen.
Kompilierte Skripte verarbeiten Parameter wie das Originalskript. Eine Einschränkung ergibt sich aus der Windows-Umgebung: Für alle Executables haben alle Parameter den Typ STRING. Wenn es keine implizite Konvertierung für Ihren Parametertyp gibt, müssen Sie in Ihrem Skript explizit konvertieren. Sie können dem Executable sogar Inhalte über die Pipeline übergeben, mit der gleichen Einschränkung (alle über die Pipeline übergebenen Werte haben den Typ STRING).
Speichern Sie niemals Passwörter in Ihrem kompilierten Skript! Man kann das Skript einfach mit dem Parameter -extract dekompilieren. Zum Beispiel
Output.exe -extract:C:\Output.ps1
dekompiliert das in Output.exe gespeicherte Skript. Und beachten Sie: Das Skript wird (absichtlich) im Klartext in der ausführbaren Datei gespeichert!
Da PS2EXE ein Skript in ein Executable umwandelt, sind skriptbezogene Variablen nicht mehr verfügbar. Die Variable $MyInvocation wird auf andere Werte gesetzt als in einem Skript.
Insbesondere die Variable $PSScriptRoot ist leer – Sie können $ScriptRoot als Ersatz verwenden.
Sie können $PSScriptRoot unabhängig davon, ob kompiliert oder nicht kompiliert, mit der folgenden Codezeile erhalten:
if (!$PSScriptRoot) { $PSScriptRoot = $ScriptRoot }
Wenn im -noConsole-Modus ein externes Fenster in einem Skript geöffnet wird (z.B. für Get-Credential oder für einen Befehl, der eine cmd.exe-Shell benötigt), wird das nächste Fenster im Hintergrund geöffnet.
Der Grund dafür ist, dass Windows beim Schließen des externen Fensters versucht, das übergeordnete Fenster zu aktivieren. Da das kompilierte Skript kein Fenster hat, wird stattdessen das übergeordnete Fenster des kompilierten Skripts aktiviert, normalerweise das Fenster des Explorers oder von Powershell.
Um dies zu umgehen, öffnet $Host.UI.RawUI.FlushInputBuffer() ein unsichtbares Fenster, das aktiviert werden kann. Der folgende Aufruf von $Host.UI.RawUI.FlushInputBuffer() schließt dieses Fenster (usw.).
Das folgende Beispiel öffnet kein Fenster mehr im Hintergrund, wie es ein einzelner Aufruf von "ipconfig | Out-String" tun würde:
$Host.UI.RawUI.FlushInputBuffer()
ipconfig | Out-String
$Host.UI.RawUI.FlushInputBuffer()