Untitled
unknown
plain_text
10 months ago
23 kB
14
Indexable
# PackageUEPlugin.ps1 (PowerShell 5.1) - Fixed plugin resolution + fresh prompts each run
# Key fixes:
# 1) Alternative approach: Use -PluginPath with dependency resolution
# 2) No persistent configuration - prompt fresh each time
# 3) Better plugin search paths and validation
# 4) Multiple fallback strategies for plugin building
[CmdletBinding()] param()
$ErrorActionPreference = "Stop"
Add-Type -AssemblyName System.Windows.Forms -ErrorAction SilentlyContinue | Out-Null
function Pick-File($title,$filter="All (*.*)|*.*"){
Write-Host "Attempting to open file dialog: $title" -ForegroundColor Gray
try {
$dlg=New-Object System.Windows.Forms.OpenFileDialog
$dlg.Title=$title
$dlg.Filter=$filter
$dlg.Multiselect=$false
$dlg.CheckFileExists=$true
$dlg.CheckPathExists=$true
Write-Host "Showing file dialog..." -ForegroundColor Gray
$result = $dlg.ShowDialog()
Write-Host "File dialog result: $result" -ForegroundColor Gray
if($result -eq [System.Windows.Forms.DialogResult]::OK){
Write-Host "Selected file: $($dlg.FileName)" -ForegroundColor Green
return $dlg.FileName
} else {
Write-Host "File dialog cancelled or closed" -ForegroundColor Yellow
return $null
}
} catch {
Write-Host "Error with file dialog: $($_.Exception.Message)" -ForegroundColor Red
Write-Host "Falling back to text input..." -ForegroundColor Yellow
$path = Read-Host "Please enter the full path to your .uplugin file"
if(Test-Path $path) {
return $path
} else {
Write-Host "Path does not exist: $path" -ForegroundColor Red
return $null
}
}
}
function Pick-Folder($desc){
Write-Host "Attempting to open folder dialog: $desc" -ForegroundColor Gray
try {
$dlg=New-Object System.Windows.Forms.FolderBrowserDialog
$dlg.Description=$desc
$dlg.ShowNewFolderButton=$true
Write-Host "Showing folder dialog..." -ForegroundColor Gray
$result = $dlg.ShowDialog()
Write-Host "Folder dialog result: $result" -ForegroundColor Gray
if($result -eq [System.Windows.Forms.DialogResult]::OK){
Write-Host "Selected folder: $($dlg.SelectedPath)" -ForegroundColor Green
return $dlg.SelectedPath
} else {
Write-Host "Folder dialog cancelled or closed" -ForegroundColor Yellow
return $null
}
} catch {
Write-Host "Error with folder dialog: $($_.Exception.Message)" -ForegroundColor Red
Write-Host "Falling back to text input..." -ForegroundColor Yellow
$path = Read-Host "Please enter the full path to the folder"
if(Test-Path $path) {
return $path
} else {
Write-Host "Path does not exist: $path" -ForegroundColor Red
return $null
}
}
}
function Ask($prompt,$def=""){
if([string]::IsNullOrWhiteSpace($def)){
$v = Read-Host $prompt
} else {
$v = Read-Host "$prompt [$def]"
if([string]::IsNullOrWhiteSpace($v)){ $v = $def }
}
return $v
}
function Ask-YesNo($prompt, $default=$true){
$suffix = if($default) { "(Y/n)" } else { "(y/N)" }
$v = Read-Host "$prompt $suffix"
if([string]::IsNullOrWhiteSpace($v)){ return $default }
return ($v -match '^(?i)y|yes$')
}
function Ensure-Dir($p){
if(-not(Test-Path -LiteralPath $p)){
New-Item -ItemType Directory -Force -Path $p | Out-Null
}
}
function Read-Json($p){
(Get-Content -Raw -LiteralPath $p) | ConvertFrom-Json
}
function Write-Json($obj,$p){
($obj|ConvertTo-Json -Depth 20) | Out-File -LiteralPath $p -Encoding UTF8
}
function Parse-Platforms($s){
if([string]::IsNullOrWhiteSpace($s)){ return @('Win64') }
return ($s -split '[,\s]+' | Where-Object { $_.Trim() } | ForEach-Object { $_.Trim() })
}
function Find-UE-Installations {
$candidates = @()
# Common Epic Games locations
$epicPaths = @(
"$env:ProgramFiles\Epic Games",
"${env:ProgramFiles(x86)}\Epic Games",
"$env:ProgramW6432\Epic Games"
)
foreach($path in $epicPaths) {
if(Test-Path $path) {
$ueVersions = Get-ChildItem -Path $path -Directory | Where-Object { $_.Name -match '^UE_\d+\.\d+' }
foreach($ue in $ueVersions) {
$runUAT = Join-Path $ue.FullName "Engine\Build\BatchFiles\RunUAT.bat"
if(Test-Path $runUAT) {
$candidates += @{
Path = $ue.FullName
Version = ($ue.Name -replace '^UE_', '')
Display = "$($ue.Name) - $($ue.FullName)"
}
}
}
}
}
return $candidates | Sort-Object Version -Descending
}
function Prompt-UE-Selection {
Write-Host ""
Write-Host "=== Unreal Engine Selection ===" -ForegroundColor Cyan
$installations = Find-UE-Installations
if($installations.Count -gt 0) {
Write-Host "Found UE installations:" -ForegroundColor Yellow
for($i = 0; $i -lt $installations.Count; $i++) {
Write-Host " [$($i+1)] $($installations[$i].Display)" -ForegroundColor Green
}
Write-Host " [0] Browse for different location" -ForegroundColor Gray
do {
$choice = Read-Host "Select UE installation (1-$($installations.Count) or 0 to browse)"
$choiceNum = $choice -as [int]
} while($choiceNum -lt 0 -or $choiceNum -gt $installations.Count)
if($choiceNum -eq 0) {
return Pick-Folder "Select UE root directory (e.g. C:\Program Files\Epic Games\UE_5.5)"
} else {
return $installations[$choiceNum - 1].Path
}
} else {
Write-Host "No UE installations found automatically." -ForegroundColor Yellow
return Pick-Folder "Select UE root directory (e.g. C:\Program Files\Epic Games\UE_5.5)"
}
}
function Find-Plugins-In-Directory($dir, $recursive = $true) {
if(-not (Test-Path $dir)) { return @() }
$plugins = @()
if($recursive) {
$upluginFiles = Get-ChildItem -Path $dir -Filter "*.uplugin" -Recurse -ErrorAction SilentlyContinue
} else {
$upluginFiles = Get-ChildItem -Path $dir -Filter "*.uplugin" -ErrorAction SilentlyContinue
}
$upluginFiles | ForEach-Object {
try {
$json = Read-Json $_.FullName
$plugins += @{
Path = $_.FullName
Name = [IO.Path]::GetFileNameWithoutExtension($_.Name)
FriendlyName = if($json.FriendlyName) { $json.FriendlyName } else { [IO.Path]::GetFileNameWithoutExtension($_.Name) }
Directory = $_.Directory.FullName
Version = if($json.VersionName) { $json.VersionName } elseif($json.Version) { $json.Version.ToString() } else { "1.0.0" }
}
} catch {
Write-Warning "Could not parse plugin: $($_.FullName)"
}
}
return $plugins
}
function Prompt-Plugin-Selection {
Write-Host ""
Write-Host "=== Main Plugin Selection ===" -ForegroundColor Cyan
Write-Host "Select the .uplugin file you want to package..." -ForegroundColor Yellow
$selected = Pick-File "Select the main .uplugin file to package" "Unreal Plugin (*.uplugin)|*.uplugin|All (*.*)|*.*"
if(-not $selected) {
Write-Host "No plugin selected." -ForegroundColor Red
return $null
}
return $selected
}
function Find-Dependencies-OneLevel-Up($mainPluginPath, $depNames) {
Write-Host ""
Write-Host "Looking for dependencies one level up from main plugin..." -ForegroundColor Yellow
# Get the parent directory of the main plugin
$mainPluginDir = Split-Path -Parent $mainPluginPath
$oneLevelUp = Split-Path -Parent $mainPluginDir
Write-Host "Main plugin directory: $mainPluginDir" -ForegroundColor Gray
Write-Host "Searching for dependencies in: $oneLevelUp" -ForegroundColor Gray
$foundDeps = @()
foreach($depName in $depNames) {
Write-Host " Looking for: $depName" -ForegroundColor Cyan
# Look for DepName/DepName.uplugin in the parent directory
$depDir = Join-Path $oneLevelUp $depName
$depUplugin = Join-Path $depDir ($depName + ".uplugin")
if(Test-Path $depUplugin) {
Write-Host " Found: $depUplugin" -ForegroundColor Green
$foundDeps += $depUplugin
} else {
Write-Host " Not found at: $depUplugin" -ForegroundColor Red
# Also check if there's a subdirectory with the dependency
$subDirs = Get-ChildItem -Path $oneLevelUp -Directory -ErrorAction SilentlyContinue | Where-Object { $_.Name -eq $depName }
if($subDirs) {
$subDepUplugin = Join-Path $subDirs[0].FullName ($depName + ".uplugin")
if(Test-Path $subDepUplugin) {
Write-Host " Found in subdirectory: $subDepUplugin" -ForegroundColor Green
$foundDeps += $subDepUplugin
}
}
}
}
return $foundDeps
}
function Copy-PluginFolder($pluginUPluginPath, $destPluginsRoot){
$srcPluginDir = Split-Path -Parent $pluginUPluginPath
$name = [IO.Path]::GetFileNameWithoutExtension($pluginUPluginPath)
$destDir = Join-Path $destPluginsRoot $name
if(Test-Path $destDir){ Remove-Item -Recurse -Force -LiteralPath $destDir }
Write-Host " Copying $name -> $destDir" -ForegroundColor Green
# Use robocopy for reliable copying
$robocopyResult = & robocopy "$srcPluginDir" "$destDir" /E /NFL /NDL /NJH /NJS /NP 2>$null
if($LASTEXITCODE -ge 8){
# Fallback to PowerShell copy
Copy-Item -Path $srcPluginDir -Destination $destDir -Recurse -Force
}
return $destDir
}
function Try-BuildPlugin-Method1($runUAT, $pluginPath, $packageDir, $platforms) {
Write-Host ""
Write-Host "==> Trying Method 1: Direct BuildPlugin (no HostProject)" -ForegroundColor Yellow
$platArg = ($platforms -join '+')
$uatArgs = @(
'BuildPlugin',
('-Plugin="{0}"' -f $pluginPath),
('-Package="{0}"' -f $packageDir),
('-TargetPlatforms={0}' -f $platArg),
'-Rocket', '-NoP4'
)
Write-Host "UAT Command: $($uatArgs -join ' ')" -ForegroundColor Gray
try {
& $runUAT @uatArgs
return $LASTEXITCODE -eq 0
} catch {
Write-Host "Method 1 failed with exception: $($_.Exception.Message)" -ForegroundColor Red
return $false
}
}
function Try-BuildPlugin-Method2($runUAT, $pluginPath, $packageDir, $platforms, $workDir) {
Write-Host ""
Write-Host "==> Trying Method 2: BuildPlugin with minimal HostProject" -ForegroundColor Yellow
# Create minimal host project
$hostProjDir = Join-Path $workDir "HostProject"
$hostProjFile = Join-Path $hostProjDir "HostProject.uproject"
Ensure-Dir $hostProjDir
# Get engine version from plugin or use default
try {
$pluginJson = Read-Json $pluginPath
$engineVer = if($pluginJson.EngineVersion) { $pluginJson.EngineVersion } else { "5.5" }
} catch {
$engineVer = "5.5"
}
# Create simple .uproject
@"
{
"FileVersion": 3,
"EngineAssociation": "$engineVer",
"Category": "",
"Description": "Minimal host project for BuildPlugin"
}
"@ | Out-File -LiteralPath $hostProjFile -Encoding UTF8
$platArg = ($platforms -join '+')
$uatArgs = @(
'BuildPlugin',
('-Plugin="{0}"' -f $pluginPath),
('-Package="{0}"' -f $packageDir),
('-TargetPlatforms={0}' -f $platArg),
('-HostProject="{0}"' -f $hostProjFile),
'-Rocket', '-NoP4'
)
Write-Host "UAT Command: $($uatArgs -join ' ')" -ForegroundColor Gray
try {
& $runUAT @uatArgs
return $LASTEXITCODE -eq 0
} catch {
Write-Host "Method 2 failed with exception: $($_.Exception.Message)" -ForegroundColor Red
return $false
}
}
function Try-BuildPlugin-Method3($runUAT, $pluginPath, $depPluginPaths, $packageDir, $platforms, $workDir) {
Write-Host ""
Write-Host "==> Trying Method 3: BuildPlugin with dependency copying to HostProject" -ForegroundColor Yellow
# Create host project with copied dependencies
$hostProjDir = Join-Path $workDir "HostProjectWithDeps"
$hostProjFile = Join-Path $hostProjDir "HostProject.uproject"
$hostPluginsDir = Join-Path $hostProjDir "Plugins"
if(Test-Path $hostProjDir) { Remove-Item -Recurse -Force $hostProjDir }
Ensure-Dir $hostPluginsDir
# Copy all dependencies to host project
$copiedPaths = @()
foreach($depPath in $depPluginPaths) {
$copied = Copy-PluginFolder -pluginUPluginPath $depPath -destPluginsRoot $hostPluginsDir
$copiedPaths += $copied
}
# Also copy main plugin
$mainCopied = Copy-PluginFolder -pluginUPluginPath $pluginPath -destPluginsRoot $hostPluginsDir
$mainPluginName = [IO.Path]::GetFileNameWithoutExtension($pluginPath)
$copiedMainPlugin = Join-Path $hostPluginsDir "$mainPluginName\$mainPluginName.uplugin"
# Create enhanced .uproject
try {
$pluginJson = Read-Json $pluginPath
$engineVer = if($pluginJson.EngineVersion) { $pluginJson.EngineVersion } else { "5.5" }
} catch {
$engineVer = "5.5"
}
# Build plugin references
$pluginRefs = @()
foreach($depPath in $depPluginPaths) {
$depName = [IO.Path]::GetFileNameWithoutExtension($depPath)
$pluginRefs += @{ "Name" = $depName; "Enabled" = $true }
}
$pluginRefs += @{ "Name" = $mainPluginName; "Enabled" = $true }
$uprojectContent = @{
"FileVersion" = 3
"EngineAssociation" = $engineVer
"Category" = ""
"Description" = "Host project with dependencies for BuildPlugin"
"Plugins" = $pluginRefs
}
Write-Json $uprojectContent $hostProjFile
$platArg = ($platforms -join '+')
$uatArgs = @(
'BuildPlugin',
('-Plugin="{0}"' -f $copiedMainPlugin),
('-Package="{0}"' -f $packageDir),
('-TargetPlatforms={0}' -f $platArg),
('-HostProject="{0}"' -f $hostProjFile),
'-Rocket', '-NoP4'
)
Write-Host "UAT Command: $($uatArgs -join ' ')" -ForegroundColor Gray
try {
& $runUAT @uatArgs
return $LASTEXITCODE -eq 0
} catch {
Write-Host "Method 3 failed with exception: $($_.Exception.Message)" -ForegroundColor Red
return $false
}
}
function Get-PackagedPluginPath($packageDir, $pluginBase){
# Look for the packaged plugin directory
$expectedDir = Join-Path $packageDir $pluginBase
$expectedUplugin = Join-Path $expectedDir ($pluginBase + ".uplugin")
if(Test-Path $expectedUplugin){ return $expectedDir }
# Search recursively
$found = Get-ChildItem -Path $packageDir -Filter ($pluginBase + ".uplugin") -Recurse -ErrorAction SilentlyContinue | Select-Object -First 1
if($found){ return $found.Directory.FullName }
return $null
}
# ==== MAIN EXECUTION ====
Write-Host "=== UE Plugin Builder with Dependency Resolution ===" -ForegroundColor Cyan
# 1. Select UE Installation
$ueRoot = Prompt-UE-Selection
if(-not $ueRoot) { throw "No UE installation selected" }
$runUAT = Join-Path $ueRoot "Engine\Build\BatchFiles\RunUAT.bat"
if(-not (Test-Path $runUAT)) { throw "RunUAT not found at: $runUAT" }
Write-Host ""
Write-Host "Selected UE: $ueRoot" -ForegroundColor Green
# 2. Select Main Plugin
$mainPluginPath = Prompt-Plugin-Selection
if(-not $mainPluginPath) { throw "No plugin selected" }
Write-Host ""
Write-Host "Selected Plugin: $mainPluginPath" -ForegroundColor Green
# 3. Get plugin info
try {
$pluginJson = Read-Json $mainPluginPath
$pluginBase = [IO.Path]::GetFileNameWithoutExtension($mainPluginPath)
$pluginName = if($pluginJson.FriendlyName) { $pluginJson.FriendlyName } else { $pluginBase }
$pluginVer = if($pluginJson.VersionName) { $pluginJson.VersionName } elseif($pluginJson.Version) { $pluginJson.Version.ToString() } else { "1.0.0" }
} catch {
throw "Could not read plugin file: $mainPluginPath"
}
# 4. Get build settings
Write-Host ""
Write-Host "=== Build Configuration ===" -ForegroundColor Cyan
$engineVer = Ask "Engine version" "5.5"
$platformsStr = Ask "Target platforms (comma-separated)" "Win64"
$platforms = Parse-Platforms $platformsStr
# 5. Select output directory
Write-Host ""
$artifactsDir = Pick-Folder "Select output directory for build artifacts"
if(-not $artifactsDir) { throw "No output directory selected" }
Write-Host ""
Write-Host "=== Plugin Information ===" -ForegroundColor Cyan
Write-Host " Name: $pluginName" -ForegroundColor Green
Write-Host " Base Name: $pluginBase" -ForegroundColor Green
Write-Host " Version: $pluginVer" -ForegroundColor Green
Write-Host " Engine: $engineVer" -ForegroundColor Green
Write-Host " Platforms: $($platforms -join ', ')" -ForegroundColor Green
Write-Host " Output: $artifactsDir" -ForegroundColor Green
# 6. Check for dependencies
$depNames = @()
if($pluginJson.Plugins) {
foreach($dep in $pluginJson.Plugins) {
if($dep.Name) { $depNames += $dep.Name }
}
}
$depNames = $depNames | Select-Object -Unique
$depPluginPaths = @()
if($depNames.Count -gt 0) {
Write-Host ""
Write-Host "=== Dependency Resolution ===" -ForegroundColor Cyan
Write-Host "Dependencies required: $($depNames -join ', ')" -ForegroundColor Yellow
# Look for dependencies one level up from the main plugin
$foundDeps = Find-Dependencies-OneLevel-Up -mainPluginPath $mainPluginPath -depNames $depNames
foreach($depName in $depNames) {
$found = $foundDeps | Where-Object { [IO.Path]::GetFileNameWithoutExtension($_) -eq $depName }
if($found) {
Write-Host ""
Write-Host "Found dependency: $depName at $found" -ForegroundColor Green
$useFound = Ask-YesNo "Use this dependency?" $true
if($useFound) {
$depPluginPaths += $found
Write-Host " Added: $found" -ForegroundColor Green
} else {
$manual = Pick-File "Locate $depName.uplugin manually" "Unreal Plugin (*.uplugin)|*.uplugin"
if($manual) {
$depPluginPaths += $manual
Write-Host " Added: $manual" -ForegroundColor Green
} else {
Write-Warning "Dependency $depName not provided - build may fail"
}
}
} else {
Write-Host ""
Write-Host "Could not find dependency: $depName" -ForegroundColor Red
$manual = Pick-File "Locate $depName.uplugin manually" "Unreal Plugin (*.uplugin)|*.uplugin"
if($manual) {
$depPluginPaths += $manual
Write-Host " Added: $manual" -ForegroundColor Green
} else {
Write-Warning "Dependency $depName not provided - build may fail"
}
}
}
} else {
Write-Host ""
Write-Host "No dependencies declared in plugin." -ForegroundColor Green
}
# 7. Create work directory and package directory
$timestamp = Get-Date -Format "yyyyMMdd_HHmmss"
$buildStamp = "${pluginBase}_${pluginVer}_UE${engineVer}_$($platforms -join '+')_${timestamp}"
$workDir = Join-Path $artifactsDir "_Work_$buildStamp"
$packageDir = Join-Path $artifactsDir "Package_$buildStamp"
if(Test-Path $workDir) { Remove-Item -Recurse -Force $workDir }
if(Test-Path $packageDir) { Remove-Item -Recurse -Force $packageDir }
Ensure-Dir $workDir
Ensure-Dir $packageDir
Write-Host ""
Write-Host "=== Starting Build Process ===" -ForegroundColor Cyan
Write-Host "Work directory: $workDir" -ForegroundColor Gray
Write-Host "Package directory: $packageDir" -ForegroundColor Gray
# 8. Try multiple build methods
$buildSuccess = $false
$buildMethod = ""
try {
# Method 1: Direct build (works for plugins without dependencies)
if(-not $buildSuccess -and $depPluginPaths.Count -eq 0) {
if(Try-BuildPlugin-Method1 -runUAT $runUAT -pluginPath $mainPluginPath -packageDir $packageDir -platforms $platforms) {
$buildSuccess = $true
$buildMethod = "Direct BuildPlugin (no dependencies)"
}
}
# Method 2: Minimal host project
if(-not $buildSuccess) {
if(Try-BuildPlugin-Method2 -runUAT $runUAT -pluginPath $mainPluginPath -packageDir $packageDir -platforms $platforms -workDir $workDir) {
$buildSuccess = $true
$buildMethod = "BuildPlugin with minimal HostProject"
}
}
# Method 3: Host project with dependencies
if(-not $buildSuccess -and $depPluginPaths.Count -gt 0) {
if(Try-BuildPlugin-Method3 -runUAT $runUAT -pluginPath $mainPluginPath -depPluginPaths $depPluginPaths -packageDir $packageDir -platforms $platforms -workDir $workDir) {
$buildSuccess = $true
$buildMethod = "BuildPlugin with HostProject and dependencies"
}
}
} finally {
# Cleanup work directory
if(Test-Path $workDir) {
try { Remove-Item -Recurse -Force $workDir } catch { Write-Warning "Could not clean up work directory" }
}
}
if(-not $buildSuccess) {
Write-Host ""
Write-Host "=== BUILD FAILED ===" -ForegroundColor Red
Write-Host "All build methods failed. Check the UAT logs above for details." -ForegroundColor Red
throw "Plugin build failed with all attempted methods"
}
Write-Host ""
Write-Host "=== BUILD SUCCESSFUL ===" -ForegroundColor Green
Write-Host "Method used: $buildMethod" -ForegroundColor Yellow
# 9. Package the result
$packagedDir = Get-PackagedPluginPath -packageDir $packageDir -pluginBase $pluginBase
if(-not $packagedDir) {
throw "Could not locate packaged plugin in: $packageDir"
}
$zipPath = Join-Path $artifactsDir "${buildStamp}.zip"
if(Test-Path $zipPath) { Remove-Item $zipPath -Force }
Write-Host ""
Write-Host "Creating ZIP package..." -ForegroundColor Yellow
Write-Host " Source: $packagedDir" -ForegroundColor Gray
Write-Host " ZIP: $zipPath" -ForegroundColor Gray
Compress-Archive -Path $packagedDir -DestinationPath $zipPath -Force
$hash = (Get-FileHash -Algorithm SHA256 -LiteralPath $zipPath).Hash.ToLower()
Write-Host " SHA256: $hash" -ForegroundColor Gray
# 10. Create manifest
$zipFileName = [IO.Path]::GetFileName($zipPath)
# Create artifacts hashtable with string keys
$artifactsHash = @{}
$artifactsHash[$platforms[0].ToString()] = $zipFileName
# Create sha256 hashtable with string keys
$sha256Hash = @{}
$sha256Hash[$platforms[0].ToString()] = $hash
# Create dependencies array
$depsArray = @()
if($depNames.Count -gt 0) {
$depsArray = $depNames | ForEach-Object {
@{
name = [string]$_
range = $null
}
}
}
# Create manifest with proper string keys
$manifest = [ordered]@{
name = [string]$pluginName
id = [string]$pluginBase
version = [string]$pluginVer
engine = [string]$engineVer
platforms = @([string]$platforms[0])
artifacts = $artifactsHash
url = [string]$zipFileName
sha256 = $sha256Hash
buildMethod = [string]$buildMethod
timestamp = (Get-Date).ToString("o")
}
if($depsArray.Count -gt 0) {
$manifest.dependencies = $depsArray
}
$manifestPath = Join-Path $artifactsDir "${buildStamp}.manifest.json"
Write-Json $manifest $manifestPath
Write-Host ""
Write-Host "=== PACKAGING COMPLETE ===" -ForegroundColor Green
Write-Host "Build Method: $buildMethod" -ForegroundColor Cyan
Write-Host "Package ZIP : $zipPath" -ForegroundColor Cyan
Write-Host "SHA256 : $hash" -ForegroundColor Cyan
Write-Host "Manifest : $manifestPath" -ForegroundColor Cyan
Write-Host "Package Dir : $packageDir" -ForegroundColor Cyan
Write-Host ""
Write-Host "Plugin successfully built and packaged!" -ForegroundColor GreenEditor is loading...
Leave a Comment