Public/New-Ps2exe.ps1

<#
.SYNOPSIS
    Creates an executable (.exe) file from a PowerShell script (.ps1) file.
     
.DESCRIPTION
    The New-Ps2exe function converts a PowerShell script (.ps1) file to an executable (.exe) file
    using the PS2EXE module. If the module is not already installed, the function will attempt
    to install it. The resulting executable will be created in the same directory as the source
    script with the same base name by default.
     
.PARAMETER Path
    Specifies the path to the PowerShell script (.ps1) file to convert. Wildcards are supported.
     
.PARAMETER OutputPath
    Specifies the path where the executable file will be created. If not specified, the executable
    will be created in the same directory as the source script with the same base name.
     
.PARAMETER Force
    Specifies that the executable should be created even if it already exists.
     
.EXAMPLE
    New-Ps2exe -Path "C:\Scripts\MyScript.ps1"
     
    Creates an executable file named "MyScript.exe" in the "C:\Scripts" directory.
     
.EXAMPLE
    New-Ps2exe -Path "C:\Scripts\MyScript.ps1" -OutputPath "C:\Output" -Force
     
    Creates an executable file named "MyScript.exe" in the "C:\Output" directory,
    overwriting it if it already exists.
     
.NOTES
    Name: New-Ps2exe
    Author: AutomateSilent
    Version: 1.0
 
#>

function New-Ps2exe {
    [CmdletBinding(SupportsShouldProcess = $true)]
    param (
        [Parameter(Mandatory = $true, 
                   Position = 0, 
                   ValueFromPipeline = $true,
                   ValueFromPipelineByPropertyName = $true,
                   HelpMessage = "Path to the PowerShell script (.ps1) file to convert")]
        [ValidateNotNullOrEmpty()]
        [ValidatePattern('\.ps1$')]
        [SupportsWildcards()]
        [string[]]
        $Path,
        
        [Parameter(Mandatory = $false,
                   Position = 1,
                   HelpMessage = "Path where the executable file will be created")]
        [string]
        $OutputPath,
        
        [Parameter(Mandatory = $false,
                   HelpMessage = "Create the executable even if it already exists")]
        [switch]
        $Force
    )
    
    begin {
        Write-Verbose "Beginning New-Ps2exe function"
        
        # Check if the PS2EXE module is installed
        $moduleFound = Get-Module -ListAvailable -Name "PS2EXE" -ErrorAction SilentlyContinue
        
        if (-not $moduleFound) {
            Write-Verbose "PS2EXE module not found. Attempting to install..."
            
            try {
                if ($PSCmdlet.ShouldProcess("PS2EXE module", "Install")) {
                    Install-Module -Name "PS2EXE" -Scope CurrentUser -Force -ErrorAction Stop
                    Write-Verbose "PS2EXE module installed successfully"
                }
            }
            catch {
                $errorMessage = "Failed to install PS2EXE module: $_. Please install it manually using 'Install-Module -Name PS2EXE -Scope CurrentUser'."
                Write-Error $errorMessage
                throw $errorMessage
            }
        }
        
        # Import the PS2EXE module
        try {
            if ($PSCmdlet.ShouldProcess("PS2EXE module", "Import")) {
                Import-Module -Name "PS2EXE" -ErrorAction Stop
                Write-Verbose "PS2EXE module imported successfully"
            }
        }
        catch {
            $errorMessage = "Failed to import PS2EXE module: $_. Please ensure it is installed correctly."
            Write-Error $errorMessage
            throw $errorMessage
        }
    }
    
    process {
        foreach ($scriptPath in $Path) {
            Write-Verbose "Processing script: $scriptPath"
            
            try {
                # Resolve the path to ensure it exists and get the full path
                $resolvedPath = Resolve-Path -Path $scriptPath -ErrorAction Stop
                Write-Verbose "Resolved path: $resolvedPath"
                
                # Get the script file information
                $scriptFile = Get-Item -Path $resolvedPath -ErrorAction Stop
                
                # Determine the output path
                $executablePath = if ($PSBoundParameters.ContainsKey('OutputPath')) {
                    # Use the specified output path
                    $outputDirectory = $OutputPath
                    if (-not (Test-Path -Path $outputDirectory -PathType Container)) {
                        # Create the output directory if it doesn't exist
                        if ($PSCmdlet.ShouldProcess($outputDirectory, "Create directory")) {
                            New-Item -Path $outputDirectory -ItemType Directory -Force | Out-Null
                            Write-Verbose "Created output directory: $outputDirectory"
                        }
                    }
                    Join-Path -Path $outputDirectory -ChildPath "$($scriptFile.BaseName).exe"
                }
                else {
                    # Use the same directory as the script
                    Join-Path -Path $scriptFile.Directory -ChildPath "$($scriptFile.BaseName).exe"
                }
                
                Write-Verbose "Output executable path: $executablePath"
                
                # Check if the executable already exists
                if ((Test-Path -Path $executablePath) -and -not $Force) {
                    $errorMessage = "Executable file already exists: $executablePath. Use -Force to overwrite."
                    Write-Error $errorMessage
                    continue
                }
                
                # Build the parameter hashtable for ps2exe
                $ps2exeParams = @{
                    InputFile = $resolvedPath
                    OutputFile = $executablePath
                }
                
                if ($Force) {
                    $ps2exeParams.Force = $true
                }
                
                # Convert the script to an executable
                if ($PSCmdlet.ShouldProcess($scriptPath, "Convert to executable")) {
                    Write-Verbose "Converting script to executable..."
                    
                    # Call ps2exe with the parameters
                    # Note: The actual command might be different depending on the PS2EXE module version
                    try {
                        # Try the most common command name first
                        if (Get-Command -Name "Invoke-PS2EXE" -ErrorAction SilentlyContinue) {
                            Invoke-PS2EXE @ps2exeParams
                        }
                        elseif (Get-Command -Name "ps2exe" -ErrorAction SilentlyContinue) {
                            ps2exe @ps2exeParams
                        }
                        elseif (Get-Command -Name "ConvertTo-Exe" -ErrorAction SilentlyContinue) {
                            ConvertTo-Exe @ps2exeParams
                        }
                        else {
                            throw "Could not find a valid command to convert PS1 to EXE. Please check the PS2EXE module documentation."
                        }
                        
                        # Check if the executable was created successfully
                        if (Test-Path -Path $executablePath) {
                            Write-Output "Successfully created executable: $executablePath"
                        }
                        else {
                            Write-Error "Failed to create executable: $executablePath"
                        }
                    }
                    catch {
                        Write-Error "Error converting script to executable: $_"
                    }
                }
            }
            catch {
                Write-Error "Error processing script $scriptPath`: $_"
            }
        }
    }
    
    end {
        Write-Verbose "Completed New-Ps2exe function"
    }
}