diff --git a/Docs/Users/ChangeLog.html b/Docs/Users/ChangeLog.html
index c22c24187b6..184ddd71ead 100644
--- a/Docs/Users/ChangeLog.html
+++ b/Docs/Users/ChangeLog.html
@@ -51,6 +51,7 @@
File filters
Installer
- BugFix: fix bug of Registry path (PR #2086)
+- BugFix: "Register Windows 11 Shell Extension" fails because PowerShell script doesn't escape special chars correctly (#2109)
Translations
diff --git a/Docs/Users/ChangeLog.md b/Docs/Users/ChangeLog.md
index eba8c886dee..fa26bea54a4 100644
--- a/Docs/Users/ChangeLog.md
+++ b/Docs/Users/ChangeLog.md
@@ -37,6 +37,8 @@
### Installer
- BugFix: fix bug of Registry path (PR #2086)
+- BugFix: "Register Windows 11 Shell Extension" fails because PowerShell script
+ doesn't escape special chars correctly (#2109)
### Translations
diff --git a/Docs/Users/ReleaseNotes.html b/Docs/Users/ReleaseNotes.html
index e99938ec584..b65e60638df 100644
--- a/Docs/Users/ReleaseNotes.html
+++ b/Docs/Users/ReleaseNotes.html
@@ -60,6 +60,7 @@ File filters
Installer
- BugFix: fix bug of Registry path (PR #2086)
+- BugFix: "Register Windows 11 Shell Extension" fails because PowerShell script doesn't escape special chars correctly (#2109)
Translations
diff --git a/Docs/Users/ReleaseNotes.md b/Docs/Users/ReleaseNotes.md
index 9236d9c75db..0639819aa74 100644
--- a/Docs/Users/ReleaseNotes.md
+++ b/Docs/Users/ReleaseNotes.md
@@ -50,6 +50,8 @@ Please submit bug reports to our bug-tracker.
### Installer
- BugFix: fix bug of Registry path (PR #2086)
+- BugFix: "Register Windows 11 Shell Extension" fails because PowerShell script
+ doesn't escape special chars correctly (#2109)
### Translations
diff --git a/Installer/InnoSetup/WinMergeARM64.is6.iss b/Installer/InnoSetup/WinMergeARM64.is6.iss
index 330828a77e8..ae5f6579ed1 100644
--- a/Installer/InnoSetup/WinMergeARM64.is6.iss
+++ b/Installer/InnoSetup/WinMergeARM64.is6.iss
@@ -782,7 +782,7 @@ Filename: {sys}\regsvr32.exe; Parameters: "/s ""{app}\{#ShellExtension64bit}""";
Filename: {sys}\regsvr32.exe; Parameters: "/s /n /i:user ""{app}\{#ShellExtension64bit}"""; Flags: waituntilterminated; Check: not IsAdminInstallMode and not IsWindows11OrLater
Filename: {app}\WinMerge32BitPluginProxy.exe; Parameters: "/RegServer"; Flags: waituntilidle; Check: IsAdminInstallMode
Filename: {app}\WinMerge32BitPluginProxy.exe; Parameters: "/RegServerPerUser"; Flags: waituntilidle; Check: not IsAdminInstallMode
-Filename: {win}\sysnative\WindowsPowerShell\v1.0\PowerShell.exe; Parameters: "-c ""$host.ui.RawUI.WindowTitle = 'Registering WinMergeContextMenu package...'; if ((Get-AppxPackage -name WinMerge) -eq $null) {{ Add-AppxPackage '{app}\WinMergeContextMenuPackage.msix' -ExternalLocation '{app}'}"""; Flags: waituntilterminated; Check: IsWindows11OrLater
+Filename: {win}\sysnative\WindowsPowerShell\v1.0\PowerShell.exe; Parameters: "-c ""$host.ui.RawUI.WindowTitle = 'Registering WinMergeContextMenu package...'; if ((Get-AppxPackage -name WinMerge) -eq $null) {{ Add-AppxPackage \""{app}\WinMergeContextMenuPackage.msix\"" -ExternalLocation \""{app}\""}"""; Flags: waituntilterminated; Check: IsWindows11OrLater
[UninstallRun]
Filename: {syswow64}\regsvr32.exe; Parameters: "/s /u ""{app}\{#ShellExtension32bit}"""; Flags: waituntilterminated; Check: IsAdminInstallMode; Components: ShellExtension32bit
diff --git a/Installer/InnoSetup/WinMergeX64.is6.iss b/Installer/InnoSetup/WinMergeX64.is6.iss
index 11ca241a8b4..879040becc4 100644
--- a/Installer/InnoSetup/WinMergeX64.is6.iss
+++ b/Installer/InnoSetup/WinMergeX64.is6.iss
@@ -781,7 +781,7 @@ Filename: {sys}\regsvr32.exe; Parameters: "/s ""{app}\{#ShellExtension64bit}""";
Filename: {sys}\regsvr32.exe; Parameters: "/s /n /i:user ""{app}\{#ShellExtension64bit}"""; Flags: waituntilterminated; Check: not IsAdminInstallMode and not IsWindows11OrLater
Filename: {app}\WinMerge32BitPluginProxy.exe; Parameters: "/RegServer"; Flags: waituntilidle; Check: IsAdminInstallMode
Filename: {app}\WinMerge32BitPluginProxy.exe; Parameters: "/RegServerPerUser"; Flags: waituntilidle; Check: not IsAdminInstallMode
-Filename: {win}\sysnative\WindowsPowerShell\v1.0\PowerShell.exe; Parameters: "-c ""$host.ui.RawUI.WindowTitle = 'Registering WinMergeContextMenu package...'; if ((Get-AppxPackage -name WinMerge) -eq $null) {{ Add-AppxPackage '{app}\WinMergeContextMenuPackage.msix' -ExternalLocation '{app}'}"""; Flags: waituntilterminated; Check: IsWindows11OrLater
+Filename: {win}\sysnative\WindowsPowerShell\v1.0\PowerShell.exe; Parameters: "-c ""$host.ui.RawUI.WindowTitle = 'Registering WinMergeContextMenu package...'; if ((Get-AppxPackage -name WinMerge) -eq $null) {{ Add-AppxPackage \""{app}\WinMergeContextMenuPackage.msix\"" -ExternalLocation \""{app}\""}"""; Flags: waituntilterminated; Check: IsWindows11OrLater
[UninstallRun]
Filename: {syswow64}\regsvr32.exe; Parameters: "/s /u ""{app}\{#ShellExtension32bit}"""; Flags: waituntilterminated; Check: IsAdminInstallMode; Components: ShellExtension32bit
diff --git a/Installer/InnoSetup/WinMergeX64.iss b/Installer/InnoSetup/WinMergeX64.iss
index b9e5f1754dd..a4a26bc2223 100644
--- a/Installer/InnoSetup/WinMergeX64.iss
+++ b/Installer/InnoSetup/WinMergeX64.iss
@@ -766,7 +766,7 @@ Filename: {app}\WinMergeU.exe; Description: {cm:LaunchProgram,WinMerge}; Flags:
Filename: {sys}\regsvr32.exe; Parameters: "/s ""{app}\{#ShellExtension64bit}"""; Flags: waituntilterminated; Check: not IsWindows11OrLater
Filename: {app}\WinMerge32BitPluginProxy.exe; Parameters: "/RegServer"; Flags: waituntilidle
-Filename: {win}\sysnative\WindowsPowerShell\v1.0\PowerShell.exe; Parameters: "-c ""$host.ui.RawUI.WindowTitle = 'Registering WinMergeContextMenu package...'; if ((Get-AppxPackage -name WinMerge) -eq $null) {{ Add-AppxPackage '{app}\WinMergeContextMenuPackage.msix' -ExternalLocation '{app}'}"""; Flags: waituntilterminated; Check: IsWindows11OrLater
+Filename: {win}\sysnative\WindowsPowerShell\v1.0\PowerShell.exe; Parameters: "-c ""$host.ui.RawUI.WindowTitle = 'Registering WinMergeContextMenu package...'; if ((Get-AppxPackage -name WinMerge) -eq $null) {{ Add-AppxPackage \""{app}\WinMergeContextMenuPackage.msix\"" -ExternalLocation \""{app}\""}"""; Flags: waituntilterminated; Check: IsWindows11OrLater
[UninstallRun]
Filename: {sys}\regsvr32.exe; Parameters: "/s /u ""{app}\{#ShellExtension64bit}"""; Flags: waituntilterminated
diff --git a/Installer/InnoSetup/WinMergeX64NonAdmin.iss b/Installer/InnoSetup/WinMergeX64NonAdmin.iss
index 3d050fded69..2338e9ab5d5 100644
--- a/Installer/InnoSetup/WinMergeX64NonAdmin.iss
+++ b/Installer/InnoSetup/WinMergeX64NonAdmin.iss
@@ -763,7 +763,7 @@ Filename: {app}\WinMergeU.exe; Description: {cm:LaunchProgram,WinMerge}; Flags:
Filename: {syswow64}\regsvr32.exe; Parameters: "/s /n /i:user ""{app}\{#ShellExtension32bit}"""; Flags: waituntilterminated; Components: ShellExtension32bit
Filename: {sys}\regsvr32.exe; Parameters: "/s /n /i:user ""{app}\{#ShellExtension64bit}"""; Flags: waituntilterminated; Check: not IsWindows11OrLater
Filename: {app}\WinMerge32BitPluginProxy.exe; Parameters: "/RegServerPerUser"; Flags: waituntilidle
-Filename: {win}\sysnative\WindowsPowerShell\v1.0\PowerShell.exe; Parameters: "-c ""$host.ui.RawUI.WindowTitle = 'Registering WinMergeContextMenu package...'; if ((Get-AppxPackage -name WinMerge) -eq $null) {{ Add-AppxPackage '{app}\WinMergeContextMenuPackage.msix' -ExternalLocation '{app}'}"""; Flags: waituntilterminated; Check: IsWindows11OrLater
+Filename: {win}\sysnative\WindowsPowerShell\v1.0\PowerShell.exe; Parameters: "-c ""$host.ui.RawUI.WindowTitle = 'Registering WinMergeContextMenu package...'; if ((Get-AppxPackage -name WinMerge) -eq $null) {{ Add-AppxPackage \""{app}\WinMergeContextMenuPackage.msix\"" -ExternalLocation \""{app}\""}"""; Flags: waituntilterminated; Check: IsWindows11OrLater
[UninstallRun]
Filename: {syswow64}\regsvr32.exe; Parameters: "/s /u /n /i:user ""{app}\{#ShellExtension32bit}"""; Flags: waituntilterminated; Components: ShellExtension32bit
diff --git a/Installer/InnoSetup/WinMergeX86.iss b/Installer/InnoSetup/WinMergeX86.iss
index eae12e0586b..40886f9dddc 100755
--- a/Installer/InnoSetup/WinMergeX86.iss
+++ b/Installer/InnoSetup/WinMergeX86.iss
@@ -787,7 +787,7 @@ Filename: {win}\Explorer.exe; Description: {cm:ViewStartMenuFolder}; Parameters:
Filename: {app}\WinMergeU.exe; Description: {cm:LaunchProgram,WinMerge}; Flags: nowait postinstall skipifsilent runmaximized
Filename: {sys}\regsvr32.exe; Parameters: "/s ""{app}\{#ShellExtension64bit}"""; Flags: waituntilterminated; Check: not IsWindows11OrLater
-Filename: {win}\sysnative\WindowsPowerShell\v1.0\PowerShell.exe; Parameters: "-c ""$host.ui.RawUI.WindowTitle = 'Registering WinMergeContextMenu package...'; if ((Get-AppxPackage -name WinMerge) -eq $null) {{ Add-AppxPackage '{app}\WinMergeContextMenuPackage.msix' -ExternalLocation '{app}'}"""; Flags: waituntilterminated; Check: IsWindows11OrLater
+Filename: {win}\sysnative\WindowsPowerShell\v1.0\PowerShell.exe; Parameters: "-c ""$host.ui.RawUI.WindowTitle = 'Registering WinMergeContextMenu package...'; if ((Get-AppxPackage -name WinMerge) -eq $null) {{ Add-AppxPackage \""{app}\WinMergeContextMenuPackage.msix\"" -ExternalLocation \""{app}\""}"""; Flags: waituntilterminated; Check: IsWindows11OrLater
[UninstallRun]
Filename: {sys}\regsvr32.exe; Parameters: "/s /u ""{app}\{#ShellExtension64bit}"""; Flags: waituntilterminated
diff --git a/Src/PropShell.cpp b/Src/PropShell.cpp
index b16cc451694..8a316506ac7 100644
--- a/Src/PropShell.cpp
+++ b/Src/PropShell.cpp
@@ -125,7 +125,7 @@ static bool RegisterWinMergeContextMenu(bool unregister)
String progpath = env::GetProgPath();
String packagepath = paths::ConcatPath(progpath, _T("WinMergeContextMenuPackage.msix"));
if (!unregister)
- cmd = strutils::format(_T("powershell -c \"Add-AppxPackage '%s' -ExternalLocation '%s'; if (!$?) { pause }\""), packagepath, progpath);
+ cmd = strutils::format(_T("powershell -c \"Add-AppxPackage \\\"%s\\\" -ExternalLocation \\\"%s\\\"; if (!$?) { pause }\""), packagepath, progpath);
else
cmd = _T("powershell -c \"Get-AppxPackage -name WinMerge | Remove-AppxPackage; if (!$?) { pause }\"");