自 Aegis Authenticator 匯出明文 json 轉入 PowertoysRunTOTP by KawaiiZapic

這篇文章將介紹如何將 Aegis Authenticator 中的明文 JSON 資料匯出並轉換為 PowertoysRunTOTP 所需的格式,幫助你將雙因素驗證(2FA)帳號從 Aegis 匯入到 PowerToys Run TOTP 擴充套件中。

警告:請勿將明文 JSON 文件長時間保留在電腦中。建議將其存放在加密的存儲空間中,如 pCloud Crypto,或者使用 7zip 壓縮並設置安全密碼來保護文件。

步驟 1:匯出 Aegis Authenticator 明文 JSON

首先,從 Aegis Authenticator 中匯出你的 2FA 帳號資料。確保匯出的文件是明文 JSON 格式,並保存到一個安全的位置,例如 C:\path\to\aegis_export.json

步驟 2:編寫 PowerShell 腳本

編寫一個 PowerShell 腳本來轉換 Aegis 匯出的 JSON 文件為 PowertoysRunTOTP 所需的格式。以下是完整的腳本,你可以用記事本複製貼上,並儲存為 .ps1 檔案例如 convert_aegis_to_powertoysrun.ps1

$inputFilePath = "P:\Crypto Folder\aegis.json"
$outputFilePath = "$env:LOCALAPPDATA\Microsoft\PowerToys\PowerToys Run\Settings\Plugins\Community.PowerToys.Run.Plugin.TOTP\OTPList.json_new"
try {
    # Read the Aegis JSON file and ensure it uses UTF-8 encoding
    $jsonContent = Get-Content -Raw -Path $inputFilePath -Encoding UTF8

    # Check if the JSON file is empty
    if ($jsonContent -eq $null -or $jsonContent.Trim() -eq "") {
        throw "The Aegis JSON file is empty or contains no content"
    }

    try {
        # Parse the JSON file
        $aegisData = $jsonContent | ConvertFrom-Json
    } catch {
        throw "JSON parsing error: $_"
    }

    # Prepare the JSON structure for PowerToysRunTOTP
    $powerToysRunTOTP = @{
        Version = 2
        Entries = @()
    }

    # Check the structure of the Aegis JSON file
    if ($aegisData.db.entries -ne $null) {
        # Iterate over Aegis entries and extract necessary data
        foreach ($entry in $aegisData.db.entries) {
            $newEntry = @{
                Name = "$($entry.issuer): $($entry.name)"
                Key = $entry.info.secret
                IsEncrypted = $false
            }
            $powerToysRunTOTP.Entries += $newEntry
        }
    } else {
        throw "Entries in the Aegis JSON file are empty or not found"
    }

    # Write the converted data to the PowerToysRunTOTP JSON file
    $powerToysRunTOTP | ConvertTo-Json -Depth 3 | Set-Content -Path $outputFilePath -Encoding UTF8

    Write-Host "Aegis JSON conversion successful and saved to $outputFilePath"
} catch {
    Write-Host "An error occurred during the conversion process: $_"
}

步驟 3:執行 PowerShell 腳本

方法一:在 Windows 10 或更高版本上右鍵執行

  1. 確保 PowerToys 已關閉。這樣可以避免 PowertoysRun OTP 擴充套件在執行過程中覆蓋使用者編輯的文件。
  2. 打開檔案總管,找到你保存的 PowerShell 腳本文件,例如 convert_aegis_to_powertoysrun.ps1
  3. 右鍵點擊該文件,選擇「以 PowerShell 執行」。
  4. 如果看到 Windows 安全警告,請選擇「更多資訊」然後點擊「仍要執行」。

方法二:使用 PowerShell 命令執行

  1. 確保 PowerToys 已關閉。這樣可以避免 PowertoysRun OTP 擴充套件在執行過程中覆蓋使用者編輯的文件。
  2. 按下 Win + X 鍵,選擇「Windows PowerShell(管理員)」或「Windows 終端機(管理員)」。
  3. 在 PowerShell 視窗中,輸入以下命令,不要按下 Enter (-File 後面有帶一個空格):
    PowerShell -ExecutionPolicy Bypass -File 
  4. 打開檔案總管,找到你保存的 PowerShell 腳本文件。
  5. 將該文件拖曳到 PowerShell 視窗中。這樣會自動填入文件的完整路徑。
  6. 確認命令如下所示,然後按下 Enter 鍵執行:
    PowerShell -ExecutionPolicy Bypass -File  "C:\path\to\convert_aegis_to_powertoysrun.ps1"

步驟 4:驗證匯入結果

  1. 打開 PowerToys,這將自動啟動 TOTP 擴充套件。
  2. PowertoysRun TOTP 擴充套件啟動後,會自動加密 OTPList.json 文件中的資料。
  3. 打開 PowerToys Run 並檢查是否成功匯入了你的 2FA 帳號。如果一切順利,你應該可以看到你匯入的帳號並使用它們進行身份驗證。

總結

通過以上步驟,我們成功地將 Aegis Authenticator 匯出的明文 JSON 文件轉換並匯入到 PowertoysRunTOTP 中。這種方法可以幫助你輕鬆地管理你的 2FA 帳號,並在不同的裝置之間進行遷移。
如果你覺得文章對你有幫助,歡迎在下方留言、按下笑臉或分享給其他人知道。

若有相關的建議也歡迎留言!

Windows 11 PowerShell 腳本雙擊執行方法

這篇文章將介紹如何在 Windows 11 上讓 PowerShell 腳本(.ps1 檔案)雙擊執行。以下是操作過程:

1. 下載並解壓縮 SetUserFTA 工具:https://kolbi.cz/SetUserFTA.zip

2. 以管理員身份打開 CMD,執行以下指令(使用 Windows PowerShell):

ftype Microsoft.PowerShellScript.1="C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -NoLogo -ExecutionPolicy Bypass -f "%1"

3. 使用 SetUserFTA 工具,給予參數執行:

SetUserFTA.exe .ps1 Microsoft.PowerShellScript.1

若選擇使用 PowerShell 7,將第二步驟指令替換為:

ftype Microsoft.PowerShellScript.1="C:\Program Files\PowerShell\7\pwsh.exe" -NoLogo -ExecutionPolicy Bypass -f "%1"

完成上述操作後,即可在 Windows 11 上雙擊 .ps1 檔案進行執行。

參考資料:
https://www.elevenforum.com/t/run-ps1-files-double-click-on-windows-11.2433/

【ChatGPT 出張嘴寫程式】全程紀錄:GIF 動圖尺寸縮放 (搭配 Magick)

現在不用當上架構或主管,出一張嘴就能寫程式了
不過還是要知道一些術語,不然和 AI 也有可能會花不少溝通成本。
前後大約對話了快要一小時,可能都會有人吐槽,這樣還不如自己寫比較快www
但是出一張嘴就是爽啦 結果還不是要打字

給程式小白

這是什麼? 這是幫你改變 GIF 動圖大小的軟體~很適合拿來做 Discord 的 Emoji 或 Source 遊戲噴漆前置作業。

比起網路上抓不知名的軟體,這個程式安全一百倍,不用怕中毒! (除非你不相信 ImageMagick)

只想要一個可以在 Windows 執行的 Gif 動畫尺寸調整軟體的人,只要這樣做:

  1. 下載安裝 https://imagemagick.org/archive/binaries/ImageMagick-7.1.1-7-Q16-HDRI-x64-dll.exe
  2. 勾選 Add to system path
  3. 打開記事本,複製完整程式碼,儲存為 gif_resizer.ps1
  4. gif_resizer.ps1 點滑鼠右鍵,點選 以 Powershell 執行
  5. 開始使用!

有遇到問題的人,不需要註冊或登入帳號,直接在下方留言。

完整程式碼

Add-Type -AssemblyName System.Windows.Forms
Add-Type -TypeDefinition @"
using System;
using System.Windows.Forms;

public class FileDropLabel : Label
{
    public FileDropLabel()
    {
        AllowDrop = true;
        DragEnter += (s, e) =>
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop)) e.Effect = DragDropEffects.Copy;
        };
    }
}
"@ -ReferencedAssemblies @('System.Windows.Forms.dll', 'System.Drawing.dll')

$global:originalWidth = [ref]0
$global:originalHeight = [ref]0
$global:inputImagePath = New-Object System.Management.Automation.PSReference("")

function UpdateAspectRatio {
    if ($checkboxMaintainAspectRatio.Checked -and $global:originalWidth.Value -gt 0 -and $global:originalHeight.Value -gt 0) {
        if ($textboxWidth.Focused) {
            if ([int32]::TryParse($textboxWidth.Text, [ref]$null)) {
                $height = [int]($textboxWidth.Text) * $global:originalHeight.Value / $global:originalWidth.Value
                $textboxHeight.Text = [string]$height
            }
        } elseif ($textboxHeight.Focused) {
            if ([int32]::TryParse($textboxHeight.Text, [ref]$null)) {
                $width = [int]($textboxHeight.Text) * $global:originalWidth.Value / $global:originalHeight.Value
                $textboxWidth.Text = [string]$width
            }
        }
    }
}

$mainForm = New-Object System.Windows.Forms.Form
$mainForm.Text = 'Image Resizer'
$mainForm.Width = 400
$mainForm.Height = 250

$labelDropImage = New-Object FileDropLabel
$labelDropImage.Text = 'Drag and drop an image here'
$labelDropImage.Size = New-Object System.Drawing.Size(350, 50)
$labelDropImage.Location = New-Object System.Drawing.Point(20, 20)
$labelDropImage.BackColor = [System.Drawing.SystemColors]::ControlLight
$labelDropImage.TextAlign = [System.Drawing.ContentAlignment]::MiddleCenter
$labelDropImage.BorderStyle = [System.Windows.Forms.BorderStyle]::FixedSingle
$labelDropImage.Add_DragDrop({
    $files = $_.Data.GetData([Windows.Forms.DataFormats]::FileDrop)
    if ($files.Count -eq 1 -and [System.IO.File]::Exists($files[0])) {
        $imageExtensions = @('.jpg', '.jpeg', '.png', '.bmp', '.gif')
        $fileExtension = [System.IO.Path]::GetExtension($files[0]).ToLower()
        if ($imageExtensions -contains $fileExtension) {
            $originalImage = [System.Drawing.Image]::FromFile($files[0])
            $global:originalWidth.Value = $originalImage.Width
            $global:originalHeight.Value = $originalImage.Height
            $textboxWidth.Text = $global:originalWidth.Value
            $textboxHeight.Text = $global:originalHeight.Value
            $global:inputImagePath.Value = $files[0].ToString()
            $labelDropImage.Text = $global:inputImagePath.Value
        } else {
            [System.Windows.Forms.MessageBox]::Show('Unsupported image format.', 'Error', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
        }
    }
})

$mainForm.Controls.Add($labelDropImage)

$labelWidth = New-Object System.Windows.Forms.Label
$labelWidth.Text = 'Width:'
$labelWidth.Location = New-Object System.Drawing.Point(20, 80)
$labelWidth.Size = New-Object System.Drawing.Size(50, 20)
$mainForm.Controls.Add($labelWidth)

$textboxWidth = New-Object System.Windows.Forms.TextBox
$textboxWidth.Location = New-Object System.Drawing.Point(80, 80)
$textboxWidth.Size = New-Object System.Drawing.Size(50, 20)
# $textboxWidth.Add_Leave({ UpdateAspectRatio })
$textboxWidth.Add_TextChanged({ UpdateAspectRatio })
$mainForm.Controls.Add($textboxWidth)

$labelHeight = New-Object System.Windows.Forms.Label
$labelHeight.Text = 'Height:'
$labelHeight.Location = New-Object System.Drawing.Point(150, 80)
$labelHeight.Size = New-Object System.Drawing.Size(50, 20) 

$mainForm.Controls.Add($labelHeight)

$textboxHeight = New-Object System.Windows.Forms.TextBox
$textboxHeight.Location = New-Object System.Drawing.Point(210, 80)
$textboxHeight.Size = New-Object System.Drawing.Size(50, 20)
# $textboxHeight.Add_Leave({ UpdateAspectRatio })
$textboxHeight.Add_TextChanged({ UpdateAspectRatio })
$mainForm.Controls.Add($textboxHeight)

$checkboxMaintainAspectRatio = New-Object System.Windows.Forms.CheckBox
$checkboxMaintainAspectRatio.Text = 'Maintain Aspect Ratio'
$checkboxMaintainAspectRatio.Location = New-Object System.Drawing.Point(20, 110)
$checkboxMaintainAspectRatio.Checked = $true
$mainForm.Controls.Add($checkboxMaintainAspectRatio)

$buttonResize = New-Object System.Windows.Forms.Button
$buttonResize.Text = 'Resize Image'
$buttonResize.Location = New-Object System.Drawing.Point(20, 140)
$buttonResize.Size = New-Object System.Drawing.Size(100, 30)
$buttonResize.Add_Click({
    if (-not [string]::IsNullOrEmpty($global:inputImagePath)) {
        $outputImagePath = [System.IO.Path]::ChangeExtension($global:inputImagePath.Value, '_resized' + [System.IO.Path]::GetExtension($global:inputImagePath.Value))

        $resizeCommand = "magick `"$($global:inputImagePath.Value)`" -resize $($textboxWidth.Text)`x$($textboxHeight.Text) `"$($outputImagePath)`""
        try {
            $resizeResult = Invoke-Expression -Command $resizeCommand
            [System.Windows.Forms.MessageBox]::Show("Image resized and saved as `n$outputImagePath", 'Success', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Information)
        } catch {
            $errorMessage = $_.Exception.Message
            [System.Windows.Forms.MessageBox]::Show("Error occurred during resizing: `n$errorMessage", 'Error', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
        }
    } else {
        [System.Windows.Forms.MessageBox]::Show('Please drag and drop an image to be resized.', 'Error', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
    }
})

$mainForm.Controls.Add($buttonResize)

$mainForm.Add_Closing({
    $mainForm.Dispose()
})
[void][System.Windows.Forms.Application]::EnableVisualStyles()
[void][System.Windows.Forms.Application]::Run($mainForm)

完整對話

Hollen9

我想要你幫我做一個 powershell 的 gui 程式,不用和我解釋原理,我只要程式碼,做出來的程式介面要英文,程式的註解也用英文寫;但是你和我的回答必須全程使用台灣繁體中文。

拖曳圖片到 gui,圖片尺寸按照使用者需求縮放,使用者可勾選是否保留長寬比,若保留,長或寬的欄位其中一邊會自動調整成對應原比例的直。

我希望可以支援所有主流圖片格式,不過最主要是要能夠保留 gif 動畫的前提下,縮放後並儲存到來源文件夾。

GPT4

好的,請查看以下的 PowerShell GUI 程式碼。這個程式將根據您的要求製作一個圖片縮放工具,並支援保留 GIF 動畫。注意,需要安裝 ImageMagick 來處理圖像縮放和保留動畫。

請先安裝 ImageMagick,並將其添加到您的系統環境變量中。

Add-Type -AssemblyName System.Windows.Forms
Add-Type -TypeDefinition @"
using System;
using System.Windows.Forms;

public class FileDropLabel : Label
{
    public FileDropLabel()
    {
        AllowDrop = true;
        DragEnter += (s, e) =>
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop)) e.Effect = DragDropEffects.Copy;
        };
    }
}
"@

function UpdateAspectRatio {
    if ($checkboxMaintainAspectRatio.Checked) {
        if ($textboxWidth.Focused) {
            $height = [int]($textboxWidth.Text) * $originalHeight / $originalWidth
            $textboxHeight.Text = [math]::Round($height)
        } elseif ($textboxHeight.Focused) {
            $width = [int]($textboxHeight.Text) * $originalWidth / $originalHeight
            $textboxWidth.Text = [math]::Round($width)
        }
    }
}

$mainForm = New-Object System.Windows.Forms.Form
$mainForm.Text = 'Image Resizer'
$mainForm.Width = 400
$mainForm.Height = 250

$labelDropImage = New-Object FileDropLabel
$labelDropImage.Text = 'Drag and drop an image here'
$labelDropImage.Size = New-Object System.Drawing.Size(350, 50)
$labelDropImage.Location = New-Object System.Drawing.Point(20, 20)
$labelDropImage.BackColor = [System.Drawing.SystemColors]::ControlLight
$labelDropImage.TextAlign = [System.Drawing.ContentAlignment]::MiddleCenter
$labelDropImage.BorderStyle = [System.Windows.Forms.BorderStyle]::FixedSingle
$labelDropImage.Add_DragDrop({
    $files = $_.Data.GetData([Windows.Forms.DataFormats]::FileDrop)
    if ($files.Count -eq 1 -and [System.IO.File]::Exists($files[0])) {
        $imageExtensions = @('.jpg', '.jpeg', '.png', '.bmp', '.gif')
        $fileExtension = [System.IO.Path]::GetExtension($files[0]).ToLower()
        if ($imageExtensions -contains $fileExtension) {
            $originalImage = [System.Drawing.Image]::FromFile($files[0])
            $originalWidth = $originalImage.Width
            $originalHeight = $originalImage.Height
            $textboxWidth.Text = $originalWidth
            $textboxHeight.Text = $originalHeight
            $inputImagePath = $files[0]
            $labelDropImage.Text = $inputImagePath
        } else {
            [System.Windows.Forms.MessageBox]::Show('Unsupported image format.', 'Error', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
        }
    }
})
$mainForm.Controls.Add($labelDropImage)

$labelWidth = New-Object System.Windows.Forms.Label
$labelWidth.Text = 'Width:'
$labelWidth.Location = New-Object System.Drawing.Point(20, 80)
$mainForm.Controls.Add($labelWidth)

$text

Hollen9

請繼續,從
‵‵‵
$mainForm.Controls.Add($labelDropImage)

$labelWidth = New-Object System.Windows.Forms.Label
$labelWidth.Text = 'Width:'
$labelWidth.Location = New-Object System.Drawing.Point(20, 80)
$mainForm.Controls.Add($labelWidth)
‵‵‵
接續

GPT4

好的,請參考以下程式碼:

$textboxWidth = New-Object System.Windows.Forms.TextBox
$textboxWidth.Location = New-Object System.Drawing.Point(80, 80)
$textboxWidth.Size = New-Object System.Drawing.Size(50, 20)
$textboxWidth.Add_Leave({ UpdateAspectRatio })
$mainForm.Controls.Add($textboxWidth)

$labelHeight = New-Object System.Windows.Forms.Label
$labelHeight.Text = 'Height:'
$labelHeight.Location = New-Object System.Drawing.Point(150, 80)
$mainForm.Controls.Add($labelHeight)

$textboxHeight = New-Object System.Windows.Forms.TextBox
$textboxHeight.Location = New-Object System.Drawing.Point(210, 80)
$textboxHeight.Size = New-Object System.Drawing.Size(50, 20)
$textboxHeight.Add_Leave({ UpdateAspectRatio })
$mainForm.Controls.Add($textboxHeight)

$checkboxMaintainAspectRatio = New-Object System.Windows.Forms.CheckBox
$checkboxMaintainAspectRatio.Text = 'Maintain Aspect Ratio'
$checkboxMaintainAspectRatio.Location = New-Object System.Drawing.Point(20, 110)
$checkboxMaintainAspectRatio.Checked = $true
$mainForm.Controls.Add($checkboxMaintainAspectRatio)

$buttonResize = New-Object System.Windows.Forms.Button
$buttonResize.Text = 'Resize Image'
$buttonResize.Location = New-Object System.Drawing.Point(20, 140)
$buttonResize.Size = New-Object System.Drawing.Size(100, 30)
$buttonResize.Add_Click({
    if (-not [string]::IsNullOrEmpty($inputImagePath)) {
        $outputImagePath = [System.IO.Path]::ChangeExtension($inputImagePath, '_resized' + [System.IO.Path]::GetExtension($inputImagePath))
        $resizeCommand = "magick `"$inputImagePath`" -resize $textboxWidth.Text`x$textboxHeight.Text `"$outputImagePath`""
        try {
            $resizeResult = Invoke-Expression -Command $resizeCommand
            [System.Windows.Forms.MessageBox]::Show("Image resized and saved as `n$outputImagePath", 'Success', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Information)
        } catch {
            [System.Windows.Forms.MessageBox]::Show('Error occurred during resizing.', 'Error', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
        }
    } else {
        [System.Windows.Forms.MessageBox]::Show('Please drag and drop an image to be resized.', 'Error', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
    }
})
$mainForm.Controls.Add($buttonResize)

$mainForm.Add_Closing({
    $mainForm.Dispose()
})
[void][System.Windows.Forms.Application]::Run($mainForm)

這段程式碼將繼續創建圖形界面,包括寬度、高度的標籤和文本框,保持長寬比的複選框以及用於執行縮放操作的按鈕。當用戶拖曳圖像到界面並點擊“Resize Image”按鈕時,將使用 ImageMagick 對圖像進行縮放,並將結果保存到源文件夾中。

Hollen9

程式執行我可以看到視窗 GUI,但是 powershell 的 console 有報錯:

PS C:\Users\Hollen9> . 'c:\Program Files (Portable)\SomePowershell\ImageResize - DEV.ps1'
Add-Type : c:\Users\Hollen9\AppData\Local\Temp\gsrfdomm.0.cs(2) : The type or namespace name 'Forms' does not exist in the namespace 'System.Windows' (are you missing an assembly reference?)
c:\Users\Hollen9\AppData\Local\Temp\gsrfdomm.0.cs(1) : using System;
c:\Users\Hollen9\AppData\Local\Temp\gsrfdomm.0.cs(2) : >>> using System.Windows.Forms;
c:\Users\Hollen9\AppData\Local\Temp\gsrfdomm.0.cs(3) :
At C:\Program Files (Portable)\SomePowershell\ImageResize - DEV.ps1:2 char:1
+ Add-Type -TypeDefinition @"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidData: (Microsoft.Power...peCompilerError:AddTypeCompilerError) [Add-Type], Exception
    + FullyQualifiedErrorId : SOURCE_CODE_ERROR,Microsoft.PowerShell.Commands.AddTypeCommand

Add-Type : c:\Users\Hollen9\AppData\Local\Temp\gsrfdomm.0.cs(4) : The type or namespace name 'Label' could not be found (are you missing a using directive or an assembly reference?)
c:\Users\Hollen9\AppData\Local\Temp\gsrfdomm.0.cs(3) :
c:\Users\Hollen9\AppData\Local\Temp\gsrfdomm.0.cs(4) : >>> public class FileDropLabel : Label
c:\Users\Hollen9\AppData\Local\Temp\gsrfdomm.0.cs(5) : {
At C:\Program Files (Portable)\SomePowershell\ImageResize - DEV.ps1:2 char:1
+ Add-Type -TypeDefinition @"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidData: (Microsoft.Power...peCompilerError:AddTypeCompilerError) [Add-Type], Exception
    + FullyQualifiedErrorId : SOURCE_CODE_ERROR,Microsoft.PowerShell.Commands.AddTypeCommand

Add-Type : Cannot add type. Compilation errors occurred.
At C:\Program Files (Portable)\SomePowershell\ImageResize - DEV.ps1:2 char:1
+ Add-Type -TypeDefinition @"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidData: (:) [Add-Type], InvalidOperationException
    + FullyQualifiedErrorId : COMPILER_ERRORS,Microsoft.PowerShell.Commands.AddTypeCommand

New-Object : Cannot find type [FileDropLabel]: verify that the assembly containing this type is loaded.
At C:\Program Files (Portable)\SomePowershell\ImageResize - DEV.ps1:36 char:19
+ $labelDropImage = New-Object FileDropLabel
+                   ~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidType: (:) [New-Object], PSArgumentException
    + FullyQualifiedErrorId : TypeNotFound,Microsoft.PowerShell.Commands.NewObjectCommand

The property 'Text' cannot be found on this object. Verify that the property exists and can be set.
At C:\Program Files (Portable)\SomePowershell\ImageResize - DEV.ps1:37 char:1
+ $labelDropImage.Text = 'Drag and drop an image here'
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : PropertyNotFound

The property 'Size' cannot be found on this object. Verify that the property exists and can be set.
At C:\Program Files (Portable)\SomePowershell\ImageResize - DEV.ps1:38 char:1
+ $labelDropImage.Size = New-Object System.Drawing.Size(350, 50)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : PropertyNotFound

The property 'Location' cannot be found on this object. Verify that the property exists and can be set.
At C:\Program Files (Portable)\SomePowershell\ImageResize - DEV.ps1:39 char:1
+ $labelDropImage.Location = New-Object System.Drawing.Point(20, 20)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : PropertyNotFound

The property 'BackColor' cannot be found on this object. Verify that the property exists and can be set.
At C:\Program Files (Portable)\SomePowershell\ImageResize - DEV.ps1:40 char:1
+ $labelDropImage.BackColor = [System.Drawing.SystemColors]::ControlLig ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : PropertyNotFound

The property 'TextAlign' cannot be found on this object. Verify that the property exists and can be set.
At C:\Program Files (Portable)\SomePowershell\ImageResize - DEV.ps1:41 char:1
+ $labelDropImage.TextAlign = [System.Drawing.ContentAlignment]::Middle ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : PropertyNotFound

The property 'BorderStyle' cannot be found on this object. Verify that the property exists and can be set.
At C:\Program Files (Portable)\SomePowershell\ImageResize - DEV.ps1:42 char:1
+ $labelDropImage.BorderStyle = [System.Windows.Forms.BorderStyle]::Fix ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : PropertyNotFound

You cannot call a method on a null-valued expression.
At C:\Program Files (Portable)\SomePowershell\ImageResize - DEV.ps1:43 char:1
+ $labelDropImage.Add_DragDrop({
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

GPT4

抱歉之前的回答中出現了問題。請使用以下修正後的程式碼:

Add-Type -AssemblyName System.Windows.Forms
Add-Type -TypeDefinition @"
using System;
using System.Windows.Forms;

public class FileDropLabel : Label
{
    public FileDropLabel()
    {
        AllowDrop = true;
        DragEnter += (s, e) =>
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop)) e.Effect = DragDropEffects.Copy;
        };
    }
}
"@ -ReferencedAssemblies @('System.Windows.Forms.dll', 'System.Drawing.dll')

# 省略與上一段程式碼相同的部分...

[void][System.Windows.Forms.Application]::EnableVisualStyles()
[void][System.Windows.Forms.Application]::Run($mainForm)

這個修正將在 Add-Type 指令中添加了參數 -ReferencedAssemblies 以引用所需的組件,並在最後一行添加了 [void][System.Windows.Forms.Application]::EnableVisualStyles() 以應用主題樣式。請確保在 PowerShell 中以管理員身份運行此程式,以避免出現權限問題。

Hollen9

Weight 和 Height 的 Label 寬度太寬了,把右側的 Textbox 蓋住了

GPT4

抱歉造成困擾,請將 $labelWidth$labelHeightSize 屬性進行調整,以避免覆蓋相鄰的控件。請參考以下修改後的程式碼:

$labelWidth = New-Object System.Windows.Forms.Label
$labelWidth.Text = 'Width:'
$labelWidth.Location = New-Object System.Drawing.Point(20, 80)
$labelWidth.Size = New-Object System.Drawing.Size(50, 20)  # 修改後的 Size 屬性
$mainForm.Controls.Add($labelWidth)

$labelHeight = New-Object System.Windows.Forms.Label
$labelHeight.Text = 'Height:'
$labelHeight.Location = New-Object System.Drawing.Point(150, 80)
$labelHeight.Size = New-Object System.Drawing.Size(50, 20)  # 修改後的 Size 屬性
$mainForm.Controls.Add($labelHeight)

# 省略與上一段程式碼相同的部分...

這樣應該能避免覆蓋問題。請確保根據需要調整其他控件的位置和大小。

Hollen9

我發現當我還沒拖曳圖片進去時,去修改尺寸會出現以下錯誤:

Attempted to divide by zero.
At C:\Program Files (Portable)\SomePowershell\ImageResize - DEV.ps1:25 char:13
+             $width = [int]($textboxHeight.Text) * $originalWidth / $o ...
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], RuntimeException
    + FullyQualifiedErrorId : RuntimeException

程式還是可以繼續執行就是了

GPT4

抱歉造成困擾。這是因為在拖曳圖片之前, $originalWidth$originalHeight 的值為零。要解決這個問題,可以在 UpdateAspectRatio 函數開頭添加一個條件,檢查 $originalWidth$originalHeight 是否大於零。請參考以下修改後的程式碼:

function UpdateAspectRatio {
    if ($checkboxMaintainAspectRatio.Checked -and $originalWidth -gt 0 -and $originalHeight -gt 0) {
        if ($textboxWidth.Focused) {
            $height = [int]($textboxWidth.Text) * $originalHeight / $originalWidth
            $textboxHeight.Text = [string]$height
        } elseif ($textboxHeight.Focused) {
            $width = [int]($textboxHeight.Text) * $originalWidth / $originalHeight
            $textboxWidth.Text = [string]$width
        }
    }
}

# 省略與上一段程式碼相同的部分...

這樣在尚未拖曳圖片時,修改尺寸不會觸發錯誤。

Hollen9

我發現 $originalWidth 和 $originalHeight 在圖片拖曳進去的時候的確有正確數值,但當我在讓 長或 寬的 textbox 去 focus 的時候,$originalWidth 和 $originalHeight 都是 ""

GPT4

抱歉,這是因為 $originalWidth$originalHeightUpdateAspectRatio 函數內部作為局部變量使用,導致在 UpdateAspectRatio 函數中無法訪問它們的值。為了解決這個問題,請將 $originalWidth$originalHeight 定義為全局變量,並在 Add_DragDrop 事件處理程序中更新它們的值。以下是修改後的程式碼:

$originalWidth = 0
$originalHeight = 0

$labelDropImage.Add_DragDrop({
    $files = $_.Data.GetData([System.Windows.Forms.DataFormats]::FileDrop)
    if ($files -and $files.Count -gt 0) {
        $filePath = $files[0]
        $image = [System.Drawing.Image]::FromFile($filePath)
        $originalWidth = $image.Width
        $originalHeight = $image.Height
        $textboxWidth.Text = [string]$originalWidth
        $textboxHeight.Text = [string]$originalHeight
    }
})

# 省略與上一段程式碼相同的部分...

這樣應該可以解決 $originalWidth$originalHeightUpdateAspectRatio 函數中無法訪問的問題。

Hollen9

總之我程式現在如下所示,到了 UpdateAspectRatio 那兩個變數還是恆為 0。

Add-Type -AssemblyName System.Windows.Forms
Add-Type -TypeDefinition @"
using System;
using System.Windows.Forms;

public class FileDropLabel : Label
{
    public FileDropLabel()
    {
        AllowDrop = true;
        DragEnter += (s, e) =>
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop)) e.Effect = DragDropEffects.Copy;
        };
    }
}
"@ -ReferencedAssemblies @('System.Windows.Forms.dll', 'System.Drawing.dll')

$originalWidth = 0
$originalHeight = 0

function UpdateAspectRatio {
    if ($checkboxMaintainAspectRatio.Checked -and $originalWidth -gt 0 -and $originalHeight -gt 0) {
        if ($textboxWidth.Focused) {
            $height = [int]($textboxWidth.Text) * $originalHeight / $originalWidth
            $textboxHeight.Text = [string]$height
        } elseif ($textboxHeight.Focused) {
            $width = [int]($textboxHeight.Text) * $originalWidth / $originalHeight
            $textboxWidth.Text = [string]$width
        }
    }
}

$mainForm = New-Object System.Windows.Forms.Form
$mainForm.Text = 'Image Resizer'
$mainForm.Width = 400
$mainForm.Height = 250

$labelDropImage = New-Object FileDropLabel
$labelDropImage.Text = 'Drag and drop an image here'
$labelDropImage.Size = New-Object System.Drawing.Size(350, 50)
$labelDropImage.Location = New-Object System.Drawing.Point(20, 20)
$labelDropImage.BackColor = [System.Drawing.SystemColors]::ControlLight
$labelDropImage.TextAlign = [System.Drawing.ContentAlignment]::MiddleCenter
$labelDropImage.BorderStyle = [System.Windows.Forms.BorderStyle]::FixedSingle
$labelDropImage.Add_DragDrop({
    $files = $_.Data.GetData([Windows.Forms.DataFormats]::FileDrop)
    if ($files.Count -eq 1 -and [System.IO.File]::Exists($files[0])) {
        $imageExtensions = @('.jpg', '.jpeg', '.png', '.bmp', '.gif')
        $fileExtension = [System.IO.Path]::GetExtension($files[0]).ToLower()
        if ($imageExtensions -contains $fileExtension) {
            $originalImage = [System.Drawing.Image]::FromFile($files[0])
            $originalWidth = $originalImage.Width
            $originalHeight = $originalImage.Height
            $textboxWidth.Text = $originalWidth
            $textboxHeight.Text = $originalHeight
            $inputImagePath = $files[0]
            $labelDropImage.Text = $inputImagePath
        } else {
            [System.Windows.Forms.MessageBox]::Show('Unsupported image format.', 'Error', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
        }
    }
})
$mainForm.Controls.Add($labelDropImage)

$labelWidth = New-Object System.Windows.Forms.Label
$labelWidth.Text = 'Width:'
$labelWidth.Location = New-Object System.Drawing.Point(20, 80)
$labelWidth.Size = New-Object System.Drawing.Size(50, 20)
$mainForm.Controls.Add($labelWidth)

$textboxWidth = New-Object System.Windows.Forms.TextBox
$textboxWidth.Location = New-Object System.Drawing.Point(80, 80)
$textboxWidth.Size = New-Object System.Drawing.Size(50, 20)
$textboxWidth.Add_Leave({ UpdateAspectRatio })
$mainForm.Controls.Add($textboxWidth)

$labelHeight = New-Object System.Windows.Forms.Label
$labelHeight.Text = 'Height:'
$labelHeight.Location = New-Object System.Drawing.Point(150, 80)
$labelHeight.Size = New-Object System.Drawing.Size(50, 20) 

$mainForm.Controls.Add($labelHeight)

$textboxHeight = New-Object System.Windows.Forms.TextBox
$textboxHeight.Location = New-Object System.Drawing.Point(210, 80)
$textboxHeight.Size = New-Object System.Drawing.Size(50, 20)
$textboxHeight.Add_Leave({ UpdateAspectRatio })
$mainForm.Controls.Add($textboxHeight)

$checkboxMaintainAspectRatio = New-Object System.Windows.Forms.CheckBox
$checkboxMaintainAspectRatio.Text = 'Maintain Aspect Ratio'
$checkboxMaintainAspectRatio.Location = New-Object System.Drawing.Point(20, 110)
$checkboxMaintainAspectRatio.Checked = $true
$mainForm.Controls.Add($checkboxMaintainAspectRatio)

$buttonResize = New-Object System.Windows.Forms.Button
$buttonResize.Text = 'Resize Image'
$buttonResize.Location = New-Object System.Drawing.Point(20, 140)
$buttonResize.Size = New-Object System.Drawing.Size(100, 30)
$buttonResize.Add_Click({
    if (-not [string]::IsNullOrEmpty($inputImagePath)) {
        $outputImagePath = [System.IO.Path]::ChangeExtension($inputImagePath, '_resized' + [System.IO.Path]::GetExtension($inputImagePath))
        $resizeCommand = "magick `"$inputImagePath`" -resize $textboxWidth.Text`x$textboxHeight.Text `"$outputImagePath`""
        try {
            $resizeResult = Invoke-Expression -Command $resizeCommand
            [System.Windows.Forms.MessageBox]::Show("Image resized and saved as `n$outputImagePath", 'Success', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Information)
        } catch {
            [System.Windows.Forms.MessageBox]::Show('Error occurred during resizing.', 'Error', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
        }
    } else {
        [System.Windows.Forms.MessageBox]::Show('Please drag and drop an image to be resized.', 'Error', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
    }
})
$mainForm.Controls.Add($buttonResize)

$mainForm.Add_Closing({
    $mainForm.Dispose()
})
[void][System.Windows.Forms.Application]::EnableVisualStyles()
[void][System.Windows.Forms.Application]::Run($mainForm)

GPT4

謝謝您的反饋。我注意到您使用 Add_Leave 事件,但是它在離開輸入框時才會觸發。為了解決這個問題,請將原本的 Add_Leave 事件更改為 Add_TextChanged 事件。這樣一來,在您修改寬度或高度的時候,它就會立即更新另一個數值,保持寬高比。

修改後的程式碼:

$textboxWidth.Add_TextChanged({ UpdateAspectRatio })
$mainForm.Controls.Add($textboxWidth)

# ...

$textboxHeight.Add_TextChanged({ UpdateAspectRatio })
$mainForm.Controls.Add($textboxHeight)

這樣修改後,應該可以在輸入框中修改寬度或高度時立即更新另一個數值,並且保持寬高比。請注意,如果您在輸入框中輸入非數字字符,可能會導致錯誤。如果需要防止非數字字符的輸入,可以進一步修改腳本以檢查輸入值。

Hollen9

這個修改不錯是不錯,我也有想做。但你沒有討懂我的問題:
我說恆為零,是因為 Drop 事件中存取的 $originalWidth 和 $originalHeight 是區域變數的樣子,在不同 Scope 的 UpdateAspectRatio() 沒辦法獲得變數的新值,才會一直都是最初宣告的 0

GPT4

抱歉,我理解錯誤。請將 $originalWidth$originalHeight 放在全局變量的位置,可以將它們定義為 [ref] 類型,以便在多個範疇中存取和修改它們。

請將以下程式碼:

$originalWidth = 0
$originalHeight = 0

替換為:

$global:originalWidth = [ref]0
$global:originalHeight = [ref]0

然後,在 UpdateAspectRatio 函數和拖放事件中,用 $global:originalWidth.Value$global:originalHeight.Value 替換 $originalWidth$originalHeight

以下是修改後的 UpdateAspectRatio 函數和拖放事件:

function UpdateAspectRatio {
    if ($checkboxMaintainAspectRatio.Checked -and $global:originalWidth.Value -gt 0 -and $global:originalHeight.Value -gt 0) {
        if ($textboxWidth.Focused) {
            $height = [int]($textboxWidth.Text) * $global:originalHeight.Value / $global:originalWidth.Value
            $textboxHeight.Text = [string]$height
        } elseif ($textboxHeight.Focused) {
            $width = [int]($textboxHeight.Text) * $global:originalWidth.Value / $global:originalHeight.Value
            $textboxWidth.Text = [string]$width
        }
    }
}

$labelDropImage.Add_DragDrop({
    $files = $_.Data.GetData([Windows.Forms.DataFormats]::FileDrop)
    if ($files.Count -eq 1 -and [System.IO.File]::Exists($files[0])) {
        $imageExtensions = @('.jpg', '.jpeg', '.png', '.bmp', '.gif')
        $fileExtension = [System.IO.Path]::GetExtension($files[0]).ToLower()
        if ($imageExtensions -contains $fileExtension) {
            $originalImage = [System.Drawing.Image]::FromFile($files[0])
            $global:originalWidth.Value = $originalImage.Width
            $global:originalHeight.Value = $originalImage.Height
            $textboxWidth.Text = $global:originalWidth.Value
            $textboxHeight.Text = $global:originalHeight.Value
            $inputImagePath = $files[0]
            $labelDropImage.Text = $inputImagePath
        } else {
            [System.Windows.Forms.MessageBox]::Show('Unsupported image format.', 'Error', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
        }
    }
})

現在,當您修改寬度或高度時,UpdateAspectRatio 函數應該能夠正確地讀取和更新 $global:originalWidth.Value$global:originalHeight.Value

Hollen9

長寬問題解決了,但我發現 $inputImagePath 等變數也有類似的問題

GPT4

對於 $inputImagePath,您可以採用與 $originalWidth$originalHeight 相同的解決方案。將 $inputImagePath 定義為全局 [ref] 變量,並在需要時使用 $global:inputImagePath.Value 存取和修改它。

首先,將以下程式碼:

$inputImagePath = ""

替換為:

$global:inputImagePath = [ref]""

然後在拖放事件和按鈕點擊事件中,使用 $global:inputImagePath.Value 替換 $inputImagePath

以下是修改後的拖放事件和按鈕點擊事件:

$labelDropImage.Add_DragDrop({
    $files = $_.Data.GetData([Windows.Forms.DataFormats]::FileDrop)
    if ($files.Count -eq 1 -and [System.IO.File]::Exists($files[0])) {
        $imageExtensions = @('.jpg', '.jpeg', '.png', '.bmp', '.gif')
        $fileExtension = [System.IO.Path]::GetExtension($files[0]).ToLower()
        if ($imageExtensions -contains $fileExtension) {
            $originalImage = [System.Drawing.Image]::FromFile($files[0])
            $global:originalWidth.Value = $originalImage.Width
            $global:originalHeight.Value = $originalImage.Height
            $textboxWidth.Text = $global:originalWidth.Value
            $textboxHeight.Text = $global:originalHeight.Value
            $global:inputImagePath.Value = $files[0]
            $labelDropImage.Text = $global:inputImagePath.Value
        } else {
            [System.Windows.Forms.MessageBox]::Show('Unsupported image format.', 'Error', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
        }
    }
})

$buttonResize.Add_Click({
    if (-not [string]::IsNullOrEmpty($global:inputImagePath.Value)) {
        $outputImagePath = [System.IO.Path]::ChangeExtension($global:inputImagePath.Value, '_resized' + [System.IO.Path]::GetExtension($global:inputImagePath.Value))
        $resizeCommand = "magick `"$global:inputImagePath.Value`" -resize $textboxWidth.Text`x$textboxHeight.Text `"$outputImagePath`""
        try {
            $resizeResult = Invoke-Expression -Command $resizeCommand
            [System.Windows.Forms.MessageBox]::Show("Image resized and saved as `n$outputImagePath", 'Success', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Information)
        } catch {
            [System.Windows.Forms.MessageBox]::Show('Error occurred during resizing.', 'Error', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
        }
    } else {
        [System.Windows.Forms.MessageBox]::Show('Please drag and drop an image to be resized.', 'Error', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
    }
})

現在,$global:inputImagePath.Value 應該在需要時正確地存取和修改。

Hollen9

catch {

    }

我要怎麼改成 能夠顯示錯誤訊息的 像是 e.Message 之類的

GPT4

要在錯

Hollen9

剛剛 OpenAI 出現錯誤,我看到你的回答長這樣:

要在錯

GPT4

抱歉剛才的回答被截斷了。以下是完整的回答:

要在錯誤對話框中顯示特定的錯誤訊息,您可以使用 $_ 變量來獲取當前錯誤的詳細信息。在 catch 塊中,您可以使用 Exception.Message 屬性來獲取有關異常的更多信息。您可以通過修改 catch 塊中的代碼來顯示錯誤訊息,如下所示:

catch {
    $errorMessage = $_.Exception.Message
    [System.Windows.Forms.MessageBox]::Show("Error occurred during resizing: `n$errorMessage", 'Error', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
}

這將在錯誤對話框中顯示當前異常的錯誤訊息。

Hollen9

我看到顯示成功的 MsgBox,但是沒有真的成功 (沒有新的圖片檔)
且 Console 印出以下訊息:

magick.exe: unable to open image 'System.Management.Automation.PSReference1[System.String].Value': No such file or directory @ error/blob.c/OpenBlob/3569.
magick.exe: unable to open module file 'C:\Program Files\ImageMagick\modules\coders\IM_MOD_RL_VALUE_.dll': No such file or directory @ warning/module.c/GetMagickModulePath/677.
magick.exe: no decode delegate for this image format `VALUE' @ error/constitute.c/ReadImage/746.

GPT4

這個錯誤是因為在命令行中的變量引用不正確。您需要將 $inputImagePath$outputImagePath 變量的值直接傳遞給 magick 命令。請修改 $buttonResize.Add_Click 腳本塊如下:

$buttonResize.Add_Click({
    if (-not [string]::IsNullOrEmpty($global:inputImagePath)) {
        $outputImagePath = [System.IO.Path]::ChangeExtension($global:inputImagePath, '_resized' + [System.IO.Path]::GetExtension($global:inputImagePath))
        $resizeCommand = "magick `"$($global:inputImagePath)`" -resize $($textboxWidth.Text)`x$($textboxHeight.Text) `"$($outputImagePath)`""
        try {
            $resizeResult = Invoke-Expression -Command $resizeCommand
            [System.Windows.Forms.MessageBox]::Show("Image resized and saved as `n$outputImagePath", 'Success', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Information)
        } catch {
            $errorMessage = $_.Exception.Message
            [System.Windows.Forms.MessageBox]::Show("Error occurred during resizing: `n$errorMessage", 'Error', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
        }
    } else {
        [System.Windows.Forms.MessageBox]::Show('Please drag and drop an image to be resized.', 'Error', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
    }
})

這樣應該可以解決問題。請確保您使用的是 global: 修飾符來訪問全局變量。

Hollen9

Cannot convert value "\" to type "System.Int32". Error: "Input string was not in a correct format."
At C:\Program Files (Portable)\SomePowershell\ImageResize - DEV.ps1:27 char:13
+             $height = [int]($textboxWidth.Text) * $global:originalHei ...
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvalidCastFromStringToInteger

Cannot convert value "\" to type "System.Int32". Error: "Input string was not in a correct format."
At C:\Program Files (Portable)\SomePowershell\ImageResize - DEV.ps1:27 char:13
+             $height = [int]($textboxWidth.Text) * $global:originalHei ...
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvalidCastFromStringToInteger

magick.exe: unable to open image 'System.Management.Automation.PSReference1[System.String]': No such file or directory @ error/blob.c/OpenBlob/3569.
magick.exe: no decode delegate for this image format `' @ error/constitute.c/ReadImage/746.

我現在全部的程式長這樣:

Add-Type -AssemblyName System.Windows.Forms
Add-Type -TypeDefinition @"
using System;
using System.Windows.Forms;

public class FileDropLabel : Label
{
    public FileDropLabel()
    {
        AllowDrop = true;
        DragEnter += (s, e) =>
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop)) e.Effect = DragDropEffects.Copy;
        };
    }
}
"@ -ReferencedAssemblies @('System.Windows.Forms.dll', 'System.Drawing.dll')

$global:originalWidth = [ref]0
$global:originalHeight = [ref]0
$global:inputImagePath = [ref]""

function UpdateAspectRatio {
    if ($checkboxMaintainAspectRatio.Checked -and $global:originalWidth.Value -gt 0 -and $global:originalHeight.Value -gt 0) {
        if ($textboxWidth.Focused) {
            $height = [int]($textboxWidth.Text) * $global:originalHeight.Value / $global:originalWidth.Value
            $textboxHeight.Text = [string]$height
        } elseif ($textboxHeight.Focused) {
            $width = [int]($textboxHeight.Text) * $global:originalWidth.Value / $global:originalHeight.Value
            $textboxWidth.Text = [string]$width
        }
    }
}

$mainForm = New-Object System.Windows.Forms.Form
$mainForm.Text = 'Image Resizer'
$mainForm.Width = 400
$mainForm.Height = 250

$labelDropImage = New-Object FileDropLabel
$labelDropImage.Text = 'Drag and drop an image here'
$labelDropImage.Size = New-Object System.Drawing.Size(350, 50)
$labelDropImage.Location = New-Object System.Drawing.Point(20, 20)
$labelDropImage.BackColor = [System.Drawing.SystemColors]::ControlLight
$labelDropImage.TextAlign = [System.Drawing.ContentAlignment]::MiddleCenter
$labelDropImage.BorderStyle = [System.Windows.Forms.BorderStyle]::FixedSingle
$labelDropImage.Add_DragDrop({
    $files = $_.Data.GetData([Windows.Forms.DataFormats]::FileDrop)
    if ($files.Count -eq 1 -and [System.IO.File]::Exists($files[0])) {
        $imageExtensions = @('.jpg', '.jpeg', '.png', '.bmp', '.gif')
        $fileExtension = [System.IO.Path]::GetExtension($files[0]).ToLower()
        if ($imageExtensions -contains $fileExtension) {
            $originalImage = [System.Drawing.Image]::FromFile($files[0])
            $global:originalWidth.Value = $originalImage.Width
            $global:originalHeight.Value = $originalImage.Height
            $textboxWidth.Text = $global:originalWidth.Value
            $textboxHeight.Text = $global:originalHeight.Value
            $global:inputImagePath.Value = $files[0]
            $labelDropImage.Text = $global:inputImagePath.Value
        } else {
            [System.Windows.Forms.MessageBox]::Show('Unsupported image format.', 'Error', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
        }
    }
})

$mainForm.Controls.Add($labelDropImage)

$labelWidth = New-Object System.Windows.Forms.Label
$labelWidth.Text = 'Width:'
$labelWidth.Location = New-Object System.Drawing.Point(20, 80)
$labelWidth.Size = New-Object System.Drawing.Size(50, 20)
$mainForm.Controls.Add($labelWidth)

$textboxWidth = New-Object System.Windows.Forms.TextBox
$textboxWidth.Location = New-Object System.Drawing.Point(80, 80)
$textboxWidth.Size = New-Object System.Drawing.Size(50, 20)
# $textboxWidth.Add_Leave({ UpdateAspectRatio })
$textboxWidth.Add_TextChanged({ UpdateAspectRatio })
$mainForm.Controls.Add($textboxWidth)

$labelHeight = New-Object System.Windows.Forms.Label
$labelHeight.Text = 'Height:'
$labelHeight.Location = New-Object System.Drawing.Point(150, 80)
$labelHeight.Size = New-Object System.Drawing.Size(50, 20) 

$mainForm.Controls.Add($labelHeight)

$textboxHeight = New-Object System.Windows.Forms.TextBox
$textboxHeight.Location = New-Object System.Drawing.Point(210, 80)
$textboxHeight.Size = New-Object System.Drawing.Size(50, 20)
# $textboxHeight.Add_Leave({ UpdateAspectRatio })
$textboxHeight.Add_TextChanged({ UpdateAspectRatio })
$mainForm.Controls.Add($textboxHeight)

$checkboxMaintainAspectRatio = New-Object System.Windows.Forms.CheckBox
$checkboxMaintainAspectRatio.Text = 'Maintain Aspect Ratio'
$checkboxMaintainAspectRatio.Location = New-Object System.Drawing.Point(20, 110)
$checkboxMaintainAspectRatio.Checked = $true
$mainForm.Controls.Add($checkboxMaintainAspectRatio)

$buttonResize = New-Object System.Windows.Forms.Button
$buttonResize.Text = 'Resize Image'
$buttonResize.Location = New-Object System.Drawing.Point(20, 140)
$buttonResize.Size = New-Object System.Drawing.Size(100, 30)
$buttonResize.Add_Click({
    if (-not [string]::IsNullOrEmpty($global:inputImagePath)) {
        $outputImagePath = [System.IO.Path]::ChangeExtension($global:inputImagePath, '_resized' + [System.IO.Path]::GetExtension($global:inputImagePath))
        $resizeCommand = "magick `"$($global:inputImagePath)`" -resize $($textboxWidth.Text)`x$($textboxHeight.Text) `"$($outputImagePath)`""
        try {
            $resizeResult = Invoke-Expression -Command $resizeCommand
            [System.Windows.Forms.MessageBox]::Show("Image resized and saved as `n$outputImagePath", 'Success', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Information)
        } catch {
            $errorMessage = $_.Exception.Message
            [System.Windows.Forms.MessageBox]::Show("Error occurred during resizing: `n$errorMessage", 'Error', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
        }
    } else {
        [System.Windows.Forms.MessageBox]::Show('Please drag and drop an image to be resized.', 'Error', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
    }
})

$mainForm.Controls.Add($buttonResize)

$mainForm.Add_Closing({
    $mainForm.Dispose()
})
[void][System.Windows.Forms.Application]::EnableVisualStyles()
[void][System.Windows.Forms.Application]::Run($mainForm)

GPT4

對不起,我看到問題了。問題出在將文字框中的值轉換為整數時,可能會有不允許的字符導致轉換失敗。為了解決這個問題,我們可以在進行轉換之前檢查文字框中的值是否為有效的整數。請將UpdateAspectRatio函數更改為以下:

function UpdateAspectRatio {
    if ($checkboxMaintainAspectRatio.Checked -and $global:originalWidth.Value -gt 0 -and $global:originalHeight.Value -gt 0) {
        if ($textboxWidth.Focused) {
            if ([int32]::TryParse($textboxWidth.Text, [ref]$null)) {
                $height = [int]($textboxWidth.Text) * $global:originalHeight.Value / $global:originalWidth.Value
                $textboxHeight.Text = [string]$height
            }
        } elseif ($textboxHeight.Focused) {
            if ([int32]::TryParse($textboxHeight.Text, [ref]$null)) {
                $width = [int]($textboxHeight.Text) * $global:originalWidth.Value / $global:originalHeight.Value
                $textboxWidth.Text = [string]$width
            }
        }
    }
}

這樣應該可以解決輸入的轉換問題。

Hollen9

MsgBox:

Image resized and saved as
System.Management.Automation.PSReference`1[System._resized.String]

Console:

magick.exe: unable to open image 'System.Management.Automation.PSReference1[System.String]': No such file or directory @ error/blob.c/OpenBlob/3569.
magick.exe: no decode delegate for this image format `' @ error/constitute.c/ReadImage/746.

還是失敗

GPT4

對不起,我犯了一個錯誤。我們需要去掉$global:inputImagePath$outputImagePath的引用([ref])。請將以下兩行更改為:

$global:inputImagePath = ""

並將:

$outputImagePath = [System.IO.Path]::ChangeExtension($global:inputImagePath, '_resized' + [System.IO.Path]::GetExtension($global:inputImagePath))

更新為:

$outputImagePath = [System.IO.Path]::ChangeExtension($global:inputImagePath.Value, '_resized' + [System.IO.Path]::GetExtension($global:inputImagePath.Value))

這樣應該可以解決問題。請再試一次,看看這是否有效。

Hollen9

改完之後,我只是拖曳圖片進去,就出錯了,本來還正常的:

The property 'Value' cannot be found on this object. Verify that the property exists and can be set.
At C:\Program Files (Portable)\SomePowershell\ImageResize - DEV.ps1:64 char:13
+             $global:inputImagePath.Value = $files[0]
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : PropertyAssignmentException

我現在的整體程式長這樣:

Add-Type -AssemblyName System.Windows.Forms
Add-Type -TypeDefinition @"
using System;
using System.Windows.Forms;

public class FileDropLabel : Label
{
    public FileDropLabel()
    {
        AllowDrop = true;
        DragEnter += (s, e) =>
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop)) e.Effect = DragDropEffects.Copy;
        };
    }
}
"@ -ReferencedAssemblies @('System.Windows.Forms.dll', 'System.Drawing.dll')

$global:originalWidth = [ref]0
$global:originalHeight = [ref]0
$global:inputImagePath = ""

function UpdateAspectRatio {
    if ($checkboxMaintainAspectRatio.Checked -and $global:originalWidth.Value -gt 0 -and $global:originalHeight.Value -gt 0) {
        if ($textboxWidth.Focused) {
            if ([int32]::TryParse($textboxWidth.Text, [ref]$null)) {
                $height = [int]($textboxWidth.Text) * $global:originalHeight.Value / $global:originalWidth.Value
                $textboxHeight.Text = [string]$height
            }
        } elseif ($textboxHeight.Focused) {
            if ([int32]::TryParse($textboxHeight.Text, [ref]$null)) {
                $width = [int]($textboxHeight.Text) * $global:originalWidth.Value / $global:originalHeight.Value
                $textboxWidth.Text = [string]$width
            }
        }
    }
}

$mainForm = New-Object System.Windows.Forms.Form
$mainForm.Text = 'Image Resizer'
$mainForm.Width = 400
$mainForm.Height = 250

$labelDropImage = New-Object FileDropLabel
$labelDropImage.Text = 'Drag and drop an image here'
$labelDropImage.Size = New-Object System.Drawing.Size(350, 50)
$labelDropImage.Location = New-Object System.Drawing.Point(20, 20)
$labelDropImage.BackColor = [System.Drawing.SystemColors]::ControlLight
$labelDropImage.TextAlign = [System.Drawing.ContentAlignment]::MiddleCenter
$labelDropImage.BorderStyle = [System.Windows.Forms.BorderStyle]::FixedSingle
$labelDropImage.Add_DragDrop({
    $files = $_.Data.GetData([Windows.Forms.DataFormats]::FileDrop)
    if ($files.Count -eq 1 -and [System.IO.File]::Exists($files[0])) {
        $imageExtensions = @('.jpg', '.jpeg', '.png', '.bmp', '.gif')
        $fileExtension = [System.IO.Path]::GetExtension($files[0]).ToLower()
        if ($imageExtensions -contains $fileExtension) {
            $originalImage = [System.Drawing.Image]::FromFile($files[0])
            $global:originalWidth.Value = $originalImage.Width
            $global:originalHeight.Value = $originalImage.Height
            $textboxWidth.Text = $global:originalWidth.Value
            $textboxHeight.Text = $global:originalHeight.Value
            $global:inputImagePath.Value = $files[0]
            $labelDropImage.Text = $global:inputImagePath.Value
        } else {
            [System.Windows.Forms.MessageBox]::Show('Unsupported image format.', 'Error', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
        }
    }
})

$mainForm.Controls.Add($labelDropImage)

$labelWidth = New-Object System.Windows.Forms.Label
$labelWidth.Text = 'Width:'
$labelWidth.Location = New-Object System.Drawing.Point(20, 80)
$labelWidth.Size = New-Object System.Drawing.Size(50, 20)
$mainForm.Controls.Add($labelWidth)

$textboxWidth = New-Object System.Windows.Forms.TextBox
$textboxWidth.Location = New-Object System.Drawing.Point(80, 80)
$textboxWidth.Size = New-Object System.Drawing.Size(50, 20)
# $textboxWidth.Add_Leave({ UpdateAspectRatio })
$textboxWidth.Add_TextChanged({ UpdateAspectRatio })
$mainForm.Controls.Add($textboxWidth)

$labelHeight = New-Object System.Windows.Forms.Label
$labelHeight.Text = 'Height:'
$labelHeight.Location = New-Object System.Drawing.Point(150, 80)
$labelHeight.Size = New-Object System.Drawing.Size(50, 20) 

$mainForm.Controls.Add($labelHeight)

$textboxHeight = New-Object System.Windows.Forms.TextBox
$textboxHeight.Location = New-Object System.Drawing.Point(210, 80)
$textboxHeight.Size = New-Object System.Drawing.Size(50, 20)
# $textboxHeight.Add_Leave({ UpdateAspectRatio })
$textboxHeight.Add_TextChanged({ UpdateAspectRatio })
$mainForm.Controls.Add($textboxHeight)

$checkboxMaintainAspectRatio = New-Object System.Windows.Forms.CheckBox
$checkboxMaintainAspectRatio.Text = 'Maintain Aspect Ratio'
$checkboxMaintainAspectRatio.Location = New-Object System.Drawing.Point(20, 110)
$checkboxMaintainAspectRatio.Checked = $true
$mainForm.Controls.Add($checkboxMaintainAspectRatio)

$buttonResize = New-Object System.Windows.Forms.Button
$buttonResize.Text = 'Resize Image'
$buttonResize.Location = New-Object System.Drawing.Point(20, 140)
$buttonResize.Size = New-Object System.Drawing.Size(100, 30)
$buttonResize.Add_Click({
    if (-not [string]::IsNullOrEmpty($global:inputImagePath)) {
        $outputImagePath = [System.IO.Path]::ChangeExtension($global:inputImagePath.Value, '_resized' + [System.IO.Path]::GetExtension($global:inputImagePath.Value))

        $resizeCommand = "magick `"$($global:inputImagePath)`" -resize $($textboxWidth.Text)`x$($textboxHeight.Text) `"$($outputImagePath)`""
        try {
            $resizeResult = Invoke-Expression -Command $resizeCommand
            [System.Windows.Forms.MessageBox]::Show("Image resized and saved as `n$outputImagePath", 'Success', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Information)
        } catch {
            $errorMessage = $_.Exception.Message
            [System.Windows.Forms.MessageBox]::Show("Error occurred during resizing: `n$errorMessage", 'Error', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
        }
    } else {
        [System.Windows.Forms.MessageBox]::Show('Please drag and drop an image to be resized.', 'Error', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
    }
})

$mainForm.Controls.Add($buttonResize)

$mainForm.Add_Closing({
    $mainForm.Dispose()
})
[void][System.Windows.Forms.Application]::EnableVisualStyles()
[void][System.Windows.Forms.Application]::Run($mainForm)

GPT4

抱歉剛才的更改導致問題。現在我明白了問題所在。請將以下代碼:

$global:inputImagePath = ""

更改為:

$global:inputImagePath = New-Object System.Management.Automation.PSReference("")

然後將:

$global:inputImagePath.Value = $files[0]

更新為:

$global:inputImagePath.Value = $files[0].ToString()

這樣應該可以解決您遇到的問題。請再次嘗試執行腳本。

Hollen9

MsgBox 正常了。
但是關鍵的圖片產出還是失敗:
Console

magick.exe: unable to open image 'System.Management.Automation.PSReference': No such file or directory @ error/blob.c/OpenBlob/3569.
magick.exe: unable to open module file 'C:\Program Files\ImageMagick\modules\coders\IM_MOD_RL_PSREFERENCE_.dll': No such file or directory @ warning/module.c/GetMagickModulePath/677.
magick.exe: no decode delegate for this image format `PSREFERENCE' @ error/constitute.c/ReadImage/746.

GPT4

請將以下代碼:

$resizeCommand = "magick `"$($global:inputImagePath)`" -resize $($textboxWidth.Text)`x$($textboxHeight.Text) `"$($outputImagePath)`""

更改為:

$resizeCommand = "magick `"$($global:inputImagePath.Value)`" -resize $($textboxWidth.Text)`x$($textboxHeight.Text) `"$($outputImagePath)`""

這樣應該可以解決您遇到的問題。請再次嘗試執行腳本。

Hollen9

成功了!

GPT4

(當掉沒有回應)