A conversation started on another thread. This is a demo using PowerShellProTools cmdlet Merge-Script to package a ps1 as an executable.
This demo code contains two different configurations. The default configuration will build for .Net core 9.0/powershell core 7.5.0. Copy the contents to a ps1 file and call from either powershell.exe or pwsh.exe.
$Path = $env:TEMP # choose your own path, a folder where the script.ps1, config.psd1, and generated executable will be stored
$scriptfile = Join-Path $Path script.ps1
$configfile = Join-Path $Path package.psd1
$destination = 'google.com'
$psicon = '\path\to\your\icon.file'
$pscoreicon = 'C:\Program Files\PowerShell\7\assets\Powershell_black.ico'
$configexample = 1 # 0 for windows powershell, 1 for ps core
$ErrorActionPreference = 'Stop'
$modulelist = @'
Name,Version
PowershellProTools,2025.2.0
'@ | ConvertFrom-Csv
foreach($module in $modulelist){
Write-Host "Verifying $($module.Name) module is installed" -ForegroundColor Cyan
$installed = Get-Module -ListAvailable -Name $module.Name |
Sort-Object -Property {[version]$_.version} | Select-Object -Last 1
if(-not $installed -or [version]$installed.version -lt [version]$module.Version){
Write-Host "Searching gallery for module $($module.Name)"
$found = Find-Module -Name $module.Name -AllVersions |
Sort-Object -Property {[version]$_.version} | Select-Object -Last 1
Write-Host "Installing $($module.Name) $($found.Version)" -ForegroundColor Cyan
$found | Install-Module -Force -Scope CurrentUser
}
}
$scriptcontents = @'
Import-Module NetTCPIP -Force
Import-Module DnsClient -Force
$host.UI.RawUI.WindowTitle = '{0} pinger v1.0'
Write-Host "Pinger utility running in PS version $($PSVersionTable.PSVersion)" -ForegroundColor Cyan
Write-Host "Testing connection to {0}" -ForegroundColor Cyan
Test-NetCOnnection -ComputerName {0}
Write-Host "Completed connection test to {0}" -ForegroundColor Cyan
Write-Host "Press enter to continue" -ForegroundColor Cyan
Read-Host
'@ -f $destination
$configcontents = @(
# Powershell 5/.net 4.x
@"
@{
Root = '$scriptfile'
OutputPath = '$Path'
Package = @{
Enabled = `$true
Obfuscate = `$false
HideConsoleWindow = `$false
DotNetVersion = 'v4.6.2'
FileVersion = '1.0.4'
FileDescription = 'Utility to ping $destination'
Platform = 'x64'
ProductName = '$destination pinger'
ProductVersion = '2.2'
Copyright = '© 2025 KrzyDoug'
RequireElevation = `$false
#ApplicationIconPath = '$((Get-Command powershell.exe).source)'
PackageType = 'Console'
}
Bundle = @{
Enabled = `$true
Modules = `$true
# IgnoredModules = @()
}
}
"@
# Powershell core/.net core
@"
@{
Root = '$scriptfile'
OutputPath = '$Path'
Package = @{
Enabled = `$true
Obfuscate = `$false
HideConsoleWindow = `$false
DotNetVersion = 'net9.0'
FileVersion = '1.0.4'
FileDescription = 'Utility to ping $destination'
Platform = 'x64'
PowerShellVersion = '7.5.0'
ProductName = '$destination pinger'
ProductVersion = '2.2'
Copyright = '© 2025 KrzyDoug'
RequireElevation = `$false
ApplicationIconPath = '$pscoreicon'
PackageType = 'Console'
}
Bundle = @{
Enabled = `$true
Modules = `$true
# IgnoredModules = @()
}
}
"@
)[$configexample]
try{
Set-Content -LiteralPath $scriptfile -Value $scriptcontents
Write-Host "$scriptfile created successfully" -ForegroundColor Cyan
}
catch{
Write-Warning $_.exception.message
Exit 1
}
try{
Set-Content $configfile -Value $configcontents
Write-Host "$configfile created successfully" -ForegroundColor Cyan
}
catch{
Write-Warning $_.exception.message
Exit 1
}
Write-Host "Packaging $scriptfile as exe file" -ForegroundColor Cyan
Start-Sleep -Seconds (Get-Random (2..4))
try{
$outputfile = Merge-Script -ConfigFile $configfile
Write-Host "Executable package $($outputfile.OutputFileName) created successfully" -ForegroundColor Cyan
}
catch{
Write-Warning $_.exception.message
Exit 1
}
Write-Host "Press enter to continue" -ForegroundColor Cyan
Read-Host
cmd /c "explorer.exe /select,$($outputfile.OutputFileName)"
It will generate a demo executable that just pings google.com.
After you press enter, the directory will open with the exe highlighted.
![]()
It’s a simple network test to google.com.
Notice the size, it’s over 200MB and that’s a sign it’s a .net core package that’s all self contained.
To build against .Net Framework/Powershell 5.1, change the line with $configexample to 0.
$configexample = 1 # 0 for windows powershell, 1 for ps core
Then when you run the script again, it will build the exe against .Net Framework.
![]()
The file size is much smaller, as the system is expected to have .Net Framework 4.6.2 or higher installed.
The basic demo tool is the same


