diff --git a/.gitignore b/.gitignore index 0de6ea6..8c59fe6 100644 --- a/.gitignore +++ b/.gitignore @@ -245,4 +245,9 @@ ModelManifest.xml [Gg]enerated/ # Setup Build Files -[Oo]thers/ \ No newline at end of file +[Oo]thers/ + +# Arm Build Files +arm_build.bat +ArmBuild.ps1 +package.zip \ No newline at end of file diff --git a/AppxPackage/PriFileNative.cs b/AppxPackage/PriFileNative.cs index 09fe3b3..9bf5c4c 100644 --- a/AppxPackage/PriFileNative.cs +++ b/AppxPackage/PriFileNative.cs @@ -168,6 +168,46 @@ namespace AppxPackage return result; } + [StructLayout (LayoutKind.Sequential)] + internal struct WSTRWSTRPAIR + { + public IntPtr lpKey; // LPWSTR + public IntPtr lpValue; // LPWSTR + } + [DllImport (DLL, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr GetPriLocaleResourceAllValuesList ( + PCSPRIFILE pFilePri, + [MarshalAs (UnmanagedType.LPWStr)] string lpResName); + [DllImport (DLL, CallingConvention = CallingConvention.Cdecl)] + public static extern void DestroyLocaleResourceAllValuesList (IntPtr list); + [DllImport (DLL, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr GetPriFileResourceAllValuesList ( + PCSPRIFILE pFilePri, + [MarshalAs (UnmanagedType.LPWStr)] string lpResName); + /// + /// 将 HWSWSPAIRLIST 解析为 Dictionary<string, string>(语言代码 → 字符串值) + /// + public static Dictionary ParseWSWSPAIRLIST (IntPtr ptr) + { + if (ptr == IntPtr.Zero) return null; + + uint count = (uint)Marshal.ReadInt32 (ptr); // dwLength + IntPtr pFirst = IntPtr.Add (ptr, sizeof (uint)); // 跳过 dwLength + int elementSize = Marshal.SizeOf (typeof (WSTRWSTRPAIR)); + + var dict = new Dictionary ((int)count); + for (int i = 0; i < count; i++) + { + IntPtr pItem = IntPtr.Add (pFirst, i * elementSize); + var item = (WSTRWSTRPAIR)Marshal.PtrToStructure (pItem, typeof (WSTRWSTRPAIR)); + + string key = item.lpKey != IntPtr.Zero ? Marshal.PtrToStringUni (item.lpKey) : null; + string value = item.lpValue != IntPtr.Zero ? Marshal.PtrToStringUni (item.lpValue) : null; + if (key != null) + dict [key] = value; + } + return dict; + } } public static class LpcwstrListHelper { diff --git a/AppxPackage/PriReader.cs b/AppxPackage/PriReader.cs index 6bb09f2..2a9933b 100644 --- a/AppxPackage/PriReader.cs +++ b/AppxPackage/PriReader.cs @@ -239,6 +239,69 @@ namespace AppxPackage return task.Result; } + /// + /// 获取指定字符串资源的所有语言变体(语言代码 → 字符串值) + /// + public Dictionary LocaleResourceAllValue (string resName) + { + var task = Task.Factory.StartNew (() => + { + IntPtr ptr = IntPtr.Zero; + try + { + // 修正:第一个参数应为 m_hPriFile,而不是 ptr + ptr = PriFileHelper.GetPriLocaleResourceAllValuesList (m_hPriFile, resName); + if (ptr == IntPtr.Zero) + return new Dictionary (); + + // 解析 HWSWSPAIRLIST 为 Dictionary + var raw = PriFileHelper.ParseWSWSPAIRLIST (ptr); + return raw ?? new Dictionary (); + } + finally + { + if (ptr != IntPtr.Zero) + PriFileHelper.DestroyLocaleResourceAllValuesList (ptr); + } + }); + return task.Result; + } + /// + /// 获取指定文件资源的所有缩放/对比度/目标大小变体(PriResourceKey → 文件路径) + /// + public Dictionary PathResourceAllValue (string resName) + { + var task = Task.Factory.StartNew (() => + { + IntPtr ptr = IntPtr.Zero; + try + { + ptr = PriFileHelper.GetPriFileResourceAllValuesList (m_hPriFile, resName); + if (ptr == IntPtr.Zero) + return new Dictionary (); + + // 解析 HDWSPAIRLIST 为 Dictionary + var raw = PriFileHelper.ParseDWSPAIRLIST (ptr); + if (raw == null) + return new Dictionary (); + + // 将 uint 键转换为 PriResourceKey + var result = new Dictionary (); + foreach (var kv in raw) + { + var key = new PriResourceKey (kv.Key); + result [key] = kv.Value; + } + return result; + } + finally + { + if (ptr != IntPtr.Zero) + PriFileHelper.DestroyPriResourceAllValueList (ptr); // 注意:使用对应的释放函数 + } + }); + return task.Result; + } } public class PriReaderBundle: IDisposable { diff --git a/priformatcli/priformatcli.cpp b/priformatcli/priformatcli.cpp index 2768fe6..0cc61d4 100644 --- a/priformatcli/priformatcli.cpp +++ b/priformatcli/priformatcli.cpp @@ -1217,7 +1217,6 @@ HWSDSPAIRLIST GetPriResourcesAllValuesList (PCSPRIFILE pPriFile, const LPCWSTR * return CreateWSDSPAIRLISTFromMap (rnout); } -#ifndef ELDER_FUNC size_t GetPriLocaleStringResources ( PCSPRIFILE pPriFile, const std::vector &resnames, @@ -1332,6 +1331,8 @@ size_t GetPriLocaleStringResources ( resourceMapSection = nullptr; } } + +#ifndef ELDER_FUNC std::wstring GetConfirmLocaleResources (const std::map &strvalue, const std::wnstring &lang) { for (auto &it : strvalue) @@ -1464,4 +1465,113 @@ LPWSTR GetPriResource (PCSPRIFILE pFilePri, LPCWSTR lpswResId) } LPWSTR GetPriStringResource (PCSPRIFILE pFilePri, LPCWSTR lpswUri) { return GetPriResource (pFilePri, lpswUri); } LPWSTR GetPriPathResource (PCSPRIFILE pFilePri, LPCWSTR lpswFilePath) { return GetPriResource (pFilePri, lpswFilePath); } -#endif \ No newline at end of file +#endif + +HWSWSPAIRLIST CreateWSWSPAIRLISTFromMap (const std::map& input) +{ + DWORD count = (DWORD)input.size (); + if (count == 0) return nullptr; + + size_t totalSize = sizeof (WSWSPAIRLIST) + sizeof (WSTRWSTRPAIR) * (count - 1); + HWSWSPAIRLIST list = (HWSWSPAIRLIST)malloc (totalSize); + if (!list) return nullptr; + + list->dwLength = count; + DWORD index = 0; + for (const auto& pair : input) + { + list->lpArray [index].lpKey = _wcsdup (pair.first.c_str ()); + list->lpArray [index].lpValue = _wcsdup (pair.second.c_str ()); + ++index; + } + return list; +} +HWSWSPAIRLIST GetPriLocaleResourceAllValuesList (PCSPRIFILE pPriFile, LPCWSTR lpResName) +{ + if (!pPriFile || !lpResName || !*lpResName) + { + SetPriLastError (L"Invalid parameters"); + return nullptr; + } + + std::vector resnames = { lpResName }; + std::map> output; + + try + { + GetPriLocaleStringResources (pPriFile, resnames, output); + } + catch (System::Exception^ e) + { + SetPriLastError (MPStringToStdW (e->Message)); + return nullptr; + } + catch (const std::exception& e) + { + SetPriLastError (StringToWString (e.what ())); + return nullptr; + } + catch (...) + { + SetPriLastError (L"Unknown exception in GetPriLocaleStringResources"); + return nullptr; + } + auto it = output.find (std::wnstring (lpResName)); + if (it == output.end () || it->second.empty ()) + { + SetPriLastError (L"Resource not found or has no language variants"); + return nullptr; + } + return CreateWSWSPAIRLISTFromMap (it->second); +} +void DestroyLocaleResourceAllValuesList (HWSWSPAIRLIST list) +{ + if (!list) return; + for (DWORD i = 0; i < list->dwLength; ++i) + { + if (list->lpArray [i].lpKey) + free (list->lpArray [i].lpKey); + if (list->lpArray [i].lpValue) + free (list->lpArray [i].lpValue); + } + free (list); +} +HDWSPAIRLIST GetPriFileResourceAllValuesList (PCSPRIFILE pPriFile, LPCWSTR lpResName) +{ + if (!pPriFile || !lpResName || !*lpResName) + { + SetPriLastError (L"Invalid parameters"); + return nullptr; + } + + std::vector resnames = { lpResName }; + std::map> output; + + try + { + GetPriScaleAndTargetSizeFileList (pPriFile, resnames, output); + } + catch (System::Exception^ e) + { + SetPriLastError (MPStringToStdW (e->Message)); + return nullptr; + } + catch (const std::exception& e) + { + SetPriLastError (StringToWString (e.what ())); + return nullptr; + } + catch (...) + { + SetPriLastError (L"Unknown exception in GetPriScaleAndTargetSizeFileList"); + return nullptr; + } + + auto it = output.find (std::wnstring (lpResName)); + if (it == output.end () || it->second.empty ()) + { + SetPriLastError (L"Resource not found or has no variants"); + return nullptr; + } + return CreateDWSPAIRLISTFromMap (it->second); +} \ No newline at end of file diff --git a/priformatcli/priformatcli.h b/priformatcli/priformatcli.h index 9a6b48e..05316b0 100644 --- a/priformatcli/priformatcli.h +++ b/priformatcli/priformatcli.h @@ -113,6 +113,19 @@ extern "C" { // 16 λ // Scale TargetSize LCID PRIFORMATCLI_API HWSDSPAIRLIST GetPriResourcesAllValuesList (PCSPRIFILE pPriFile, const LPCWSTR *lpResNames, DWORD dwCount); + typedef struct WSTRWSTRPAIR__ + { + LPWSTR lpKey _DEFAULT_VALUE_SET (NULL); + LPWSTR lpValue _DEFAULT_VALUE_SET (NULL); + } WSTRWSTRPAIR, *HWSTRWSTRPAIR; + typedef struct WSWSPAIRLIST__ + { + DWORD dwLength _DEFAULT_VALUE_SET (0); + WSTRWSTRPAIR lpArray [1]; + } WSWSPAIRLIST, *HWSWSPAIRLIST; + PRIFORMATCLI_API HWSWSPAIRLIST GetPriLocaleResourceAllValuesList (PCSPRIFILE pPriFile, LPCWSTR lpResName); + PRIFORMATCLI_API void DestroyLocaleResourceAllValuesList (HWSWSPAIRLIST list); + PRIFORMATCLI_API HDWSPAIRLIST GetPriFileResourceAllValuesList (PCSPRIFILE pPriFile, LPCWSTR lpResName); #ifdef _DEFAULT_VALUE_SET #undef _DEFAULT_VALUE_SET #endif diff --git a/shared/ArmInstall.ps1 b/shared/ArmInstall.ps1 new file mode 100644 index 0000000..646dd84 --- /dev/null +++ b/shared/ArmInstall.ps1 @@ -0,0 +1,169 @@ +#Requires -RunAsAdministrator + +Push-Location $PSScriptRoot +try { + # 语言检测函数 + function Get-Language { + $lang = [System.Globalization.CultureInfo]::CurrentUICulture.TwoLetterISOLanguageName + if ($lang -eq "zh") { return "zh" } + return "en" + } + + $lang = Get-Language + + # 本地化消息 + $messages = @{ + en = @{ + title = "Desktop App Installer Setup" + confirm = "Do you want to install Desktop App Installer? (y/n)" + invalid = "Invalid input. Please enter y or n." + cancelled = "Installation cancelled." + arch_error = "Error: Cannot continue installation because the computer's processor architecture is not ARM." + creating_shortcuts = "Creating shortcuts in Start Screen..." + registering = "Registering..." + complete = "Installation complete!" + } + zh = @{ + title = "Desktop App Installer 安装程序" + confirm = "是否安装 Desktop App Installer?(y/n)" + invalid = "无效输入,请输入 y 或 n。" + cancelled = "安装已取消。" + arch_error = "错误:无法继续安装,因为计算机的处理器架构不是 ARM。" + creating_shortcuts = "正在创建开始屏幕快捷方式..." + registering = "正在注册..." + complete = "安装完成!" + } + } + + $msg = $messages[$lang] + + # 函数定义 + function Create-Shortcut { + param( + [string]$LnkPath, + [string]$TargetPath, + [string]$AppId + ) + $toolShortcutPath = Join-Path $PSScriptRoot "shortcut.exe" + if (-not (Test-Path $toolShortcutPath)) { + throw "Error: cannot find file 'shortcut.exe' in folder '$PSScriptRoot'" + } + & $toolShortcutPath $LnkPath $TargetPath $AppId + return $LASTEXITCODE + } + + function Set-DesktopInit { + param( + [string]$IniPath, + [string]$Section, + [string]$Key, + [string]$Value + ) + $toolDesktopIniPath = Join-Path $PSScriptRoot "desktopini.exe" + if (-not (Test-Path $toolDesktopIniPath)) { + throw "Error: cannot find file 'desktopini.exe' in folder '$PSScriptRoot'" + } + & $toolDesktopIniPath $IniPath $Section $Key $Value + return $LASTEXITCODE + } + + # 检查处理器架构 + if ($env:PROCESSOR_ARCHITECTURE.Trim() -ne "ARM") { + throw $msg.arch_error + } + + # 确认安装 + do { + $response = Read-Host $msg.confirm + $response = $response.ToLower() + if ($response -eq 'y') { + $confirmed = $true + break + } elseif ($response -eq 'n') { + Write-Host $msg.cancelled + exit 0 + } else { + Write-Host $msg.invalid + } + } while ($true) + + # 安装目录和快捷方式目录 + $appStartMenuFolder = "Desktop App Installer" + $appPublicStartMenuFolder = [System.IO.Path]::Combine($env:ProgramData, "Microsoft\Windows\Start Menu\Programs") + $startitemfolder = [System.IO.Path]::Combine($appPublicStartMenuFolder, $appStartMenuFolder) + $AppFolder = $PSScriptRoot + + Write-Output $msg.creating_shortcuts + if (-not (Test-Path $startitemfolder)) { + New-Item -ItemType Directory -Path $startitemfolder -Force | Out-Null + } + + $shortcuts = @( + @{ + LnkPath = Join-Path $startitemfolder "App Installer.lnk" + TargetPath = Join-Path $AppFolder "appinstaller.exe" + AppId = "Microsoft.DesktopAppInstaller!App" + }, + @{ + LnkPath = Join-Path $startitemfolder "Settings.lnk" + TargetPath = Join-Path $AppFolder "settings.exe" + AppId = "WindowsModern.PracticalToolsProject!Settings" + }, + @{ + LnkPath = Join-Path $startitemfolder "Package Manager.lnk" + TargetPath = Join-Path $AppFolder "Manager.exe" + AppId = "WindowsModern.PracticalToolsProject!Manager" + }, + @{ + LnkPath = Join-Path $startitemfolder "Update.lnk" + TargetPath = Join-Path $AppFolder "Update.exe" + AppId = "WindowsModern.PracticalToolsProject!Update" + }, + @{ + LnkPath = Join-Path $startitemfolder "Package Reader.lnk" + TargetPath = Join-Path $AppFolder "Reader.exe" + AppId = "WindowsModern.PracticalToolsProject!Reader" + } + ) + + foreach ($item in $shortcuts) { + $exitCode = Create-Shortcut -LnkPath $item.LnkPath -TargetPath $item.TargetPath -AppId $item.AppId + } + + # $desktopini = Join-Path $startitemfolder "desktop.ini" + $desktopini = $startitemfolder + Set-DesktopInit -IniPath $desktopini -Section ".ShellClassInfo" -Key "ConfirmFileOp" -Value 0 + Set-DesktopInit -IniPath $desktopini -Section "LocalizedFileNames" -Key "App Installer.lnk" -Value "@$AppFolder\appinstaller.exe,-300" + Set-DesktopInit -IniPath $desktopini -Section "LocalizedFileNames" -Key "Settings.lnk" -Value "@$AppFolder\settings.exe,-200" + Set-DesktopInit -IniPath $desktopini -Section "LocalizedFileNames" -Key "Update.lnk" -Value "@$AppFolder\reslib.dll,-103" + Set-DesktopInit -IniPath $desktopini -Section "LocalizedFileNames" -Key "Package Manager.lnk" -Value "@$AppFolder\reslib.dll,-228" + Set-DesktopInit -IniPath $desktopini -Section "LocalizedFileNames" -Key "Uninstall.lnk" -Value "@$AppFolder\reslib.dll,-131" + Set-DesktopInit -IniPath $desktopini -Section ".ShellClassInfo" -Key "LocalizedResourceName" -Value "@$AppFolder\appinstaller.exe,-300" + + Write-Output $msg.registering + $reg = [Microsoft.Win32.Registry]::ClassesRoot + $key = $reg.CreateSubKey("Microsoft.DesktopAppInstaller") + $key.SetValue("", "Windows Store App Package") + $key.Close() + $subKey = $reg.CreateSubKey("Microsoft.DesktopAppInstaller\Shell\Open\Command") + $subKey.SetValue("", "`"$AppFolder\appinstaller.exe`" `"%1`"") + $subKey.Close() + $subKey = $reg.CreateSubKey("Microsoft.DesktopAppInstaller\DefaultIcon") + $subKey.SetValue("", "$AppFolder\appinstaller.exe,2") + $subKey.Close() + $subKey = $reg.CreateSubKey("Applications\AppInstaller.exe\DefaultIcon") + $subKey.SetValue("", "$AppFolder\appinstaller.exe,-136") + $subKey.Close() + $subKey = $reg.CreateSubKey(".appx") + $subKey.SetValue("", "Microsoft.DesktopAppInstaller") + $subKey.Close() + $subKey = $reg.CreateSubKey(".appxbundle") + $subKey.SetValue("", "Microsoft.DesktopAppInstaller") + $subKey.Close() + + Write-Output "" + Write-Output $msg.complete + Start-Sleep -Seconds 5 +} finally { + Pop-Location +} \ No newline at end of file diff --git a/shared/ArmUninstall.ps1 b/shared/ArmUninstall.ps1 new file mode 100644 index 0000000..a68affe --- /dev/null +++ b/shared/ArmUninstall.ps1 @@ -0,0 +1,153 @@ +#Requires -RunAsAdministrator + +Push-Location $PSScriptRoot +try { + # 语言检测函数 + function Get-Language { + $lang = [System.Globalization.CultureInfo]::CurrentUICulture.TwoLetterISOLanguageName + if ($lang -eq "zh") { return "zh" } + return "en" + } + + $lang = Get-Language + + # 本地化消息 + $messages = @{ + en = @{ + title = "Uninstall Desktop App Installer" + confirm = "Are you sure you want to uninstall Desktop App Installer? (y/n)" + invalid = "Invalid input. Please enter y or n." + removing_start = "Removing Start Menu folder..." + removing_reg = "Removing registry entries..." + removing_dir = "Removing installation directory..." + confirm_dir = "Do you also want to delete the installation directory? (y/n)" + complete = "Uninstallation complete." + error = "Error: " + cancelled = "Uninstall cancelled." + } + zh = @{ + title = "卸载 Desktop App Installer" + confirm = "确定要卸载 Desktop App Installer 吗?(y/n)" + invalid = "无效输入,请输入 y 或 n。" + removing_start = "正在删除开始菜单文件夹..." + removing_reg = "正在删除注册表项..." + removing_dir = "正在删除安装目录..." + confirm_dir = "是否同时删除安装目录?(y/n)" + complete = "卸载完成。" + error = "错误:" + cancelled = "卸载已取消。" + } + } + + $msg = $messages[$lang] + + if ($env:PROCESSOR_ARCHITECTURE.Trim() -ne "ARM") { + throw "Error: Cannot continue installation because the computer's processor architecture is not ARM." + } + + # 确认卸载(控制台交互) + do { + $response = Read-Host $msg.confirm + $response = $response.ToLower() + if ($response -eq 'y') { + $confirmed = $true + break + } elseif ($response -eq 'n') { + Write-Host $msg.cancelled + exit 0 + } else { + Write-Host $msg.invalid + } + } while ($true) + + # 定义路径 + $appStartMenuFolder = "Desktop App Installer" + $appPublicStartMenuFolder = [System.IO.Path]::Combine($env:ProgramData, "Microsoft\Windows\Start Menu\Programs") + $startitemfolder = [System.IO.Path]::Combine($appPublicStartMenuFolder, $appStartMenuFolder) + $AppFolder = $PSScriptRoot + + # 删除开始菜单文件夹 + Write-Host $msg.removing_start + if (Test-Path $startitemfolder) { + Remove-Item -Path $startitemfolder -Recurse -Force -ErrorAction SilentlyContinue + if (Test-Path $startitemfolder) { + Write-Warning "$msg.error Could not remove $startitemfolder" + } else { + Write-Output "Removed $startitemfolder" + } + } else { + Write-Output "Start Menu folder not found, skipping." + } + + # 删除注册表项 + Write-Host $msg.removing_reg + $reg = [Microsoft.Win32.Registry]::ClassesRoot + + $keysToDelete = @( + "Microsoft.DesktopAppInstaller", + ".appx", + ".appxbundle" + ) + foreach ($keyName in $keysToDelete) { + try { + if ($reg.OpenSubKey($keyName) -ne $null) { + $reg.DeleteSubKeyTree($keyName) + Write-Output "Removed registry key: HKCR\$keyName" + } else { + Write-Output "Registry key not found: HKCR\$keyName" + } + } catch { + Write-Warning "$msg.error Could not remove HKCR\$keyName : $_" + } + } + + # 删除 Applications\AppInstaller.exe 下的 DefaultIcon + $appPath = "Applications\AppInstaller.exe" + try { + $appKey = $reg.OpenSubKey($appPath, $true) + if ($appKey) { + $subKeyNames = $appKey.GetSubKeyNames() + if ($subKeyNames -contains "DefaultIcon") { + $appKey.DeleteSubKey("DefaultIcon") + Write-Output "Removed registry key: HKCR\$appPath\DefaultIcon" + } + $appKey.Close() + } else { + Write-Output "Registry key not found: HKCR\$appPath" + } + } catch { + Write-Warning "$msg.error Could not process HKCR\$appPath : $_" + } + + # 删除安装目录 + Write-Host $msg.removing_dir + do { + $respDir = Read-Host $msg.confirm_dir + $respDir = $respDir.ToLower() + if ($respDir -eq 'y') { + if (Test-Path $AppFolder) { + Remove-Item -Path $AppFolder -Recurse -Force -ErrorAction SilentlyContinue + if (Test-Path $AppFolder) { + Write-Warning "$msg.error Could not delete $AppFolder" + } else { + Write-Output "Deleted installation directory." + } + } else { + Write-Output "Installation directory not found." + } + break + } elseif ($respDir -eq 'n') { + Write-Output "Skipped deleting installation directory." + break + } else { + Write-Host $msg.invalid + } + } while ($true) + + Write-Host $msg.complete + Start-Sleep -Seconds 3 +} catch { + Write-Error "Uninstall failed: $_" +} finally { + Pop-Location +} \ No newline at end of file diff --git a/shared/arm_install.bat b/shared/arm_install.bat new file mode 100644 index 0000000..9824460 --- /dev/null +++ b/shared/arm_install.bat @@ -0,0 +1,13 @@ +@echo off +if exist "%SystemRoot%\SysWOW64" path %path%;%windir%\SysNative;%SystemRoot%\SysWOW64;%~dp0 +bcdedit >nul +if '%errorlevel%' NEQ '0' (goto UACPrompt) else (goto UACAdmin) +:UACPrompt +%1 start "" mshta vbscript:createobject("shell.application").shellexecute("""%~0""","::",,"runas",1)(window.close)&exit +exit /B +:UACAdmin +cd /d "%~dp0" + +set SCRIPT_DIR=%~dp0 +powershell -NoProfile -ExecutionPolicy Bypass -File "%SCRIPT_DIR%ArmInstall.ps1" +pause \ No newline at end of file diff --git a/shared/arm_readme.txt b/shared/arm_readme.txt new file mode 100644 index 0000000..43c436b --- /dev/null +++ b/shared/arm_readme.txt @@ -0,0 +1,6 @@ +对于 Windows RT 用户,请以管理员身份运行 arm_install.bat 或 arm_uninstall.bat 进行安装或卸载。安装前请务必将压缩包中的所有文件放置在一个独立的文件夹中,该文件夹请勿随意移动或删除,不建议放置在桌面上。若需更新或移动程序,请先执行原卸载脚本,然后再进行安装操作。x86、x64 以及支持 x86 兼容层的 ARM64 系统请使用标准安装程序,本方案仅适用于 ARM 设备。 +感谢“冰糖XH”(主页:https://github.com/bingtangxh)帮助我完成了针对 ARM 架构的程序编译。 + +(Translated by DeepSeek) +For Windows RT users, please run arm_install.bat or arm_uninstall.bat as an administrator to install or uninstall. Before installation, extract all files from the compressed package into a dedicated folder; do not move or delete this folder arbitrarily, and it is not recommended to place it on the desktop. If you need to update or relocate the program, first run the original uninstall script, then proceed with the installation. For x86, x64, and ARM64 systems that support the x86 compatibility layer, please use the standard installer; this solution is specifically for ARM devices. +Thanks to "BingTangXH" (Homepage: https://github.com/bingtangxh) for helping me complete the program compilation for the ARM architecture. diff --git a/shared/arm_uninstall.bat b/shared/arm_uninstall.bat new file mode 100644 index 0000000..9d839d1 --- /dev/null +++ b/shared/arm_uninstall.bat @@ -0,0 +1,13 @@ +@echo off +if exist "%SystemRoot%\SysWOW64" path %path%;%windir%\SysNative;%SystemRoot%\SysWOW64;%~dp0 +bcdedit >nul +if '%errorlevel%' NEQ '0' (goto UACPrompt) else (goto UACAdmin) +:UACPrompt +%1 start "" mshta vbscript:createobject("shell.application").shellexecute("""%~0""","::",,"runas",1)(window.close)&exit +exit /B +:UACAdmin +cd /d "%~dp0" + +set SCRIPT_DIR=%~dp0 +powershell -NoProfile -ExecutionPolicy Bypass -File "%SCRIPT_DIR%ArmUninstall.ps1" +pause \ No newline at end of file diff --git a/shared/html/js/rdinit.js b/shared/html/js/rdinit.js index a6480f4..229b3e6 100644 --- a/shared/html/js/rdinit.js +++ b/shared/html/js/rdinit.js @@ -24,9 +24,6 @@ return Bridge.String.tolower(Bridge.String.trim(item.Identity.FullName)); }); var themeColor = Bridge.UI.themeColor; - var appbar = document.getElementById("appBar"); - var appbarControl = new AppBar.AppBar(appbar); - appbarControl.enabled = false; pagemgr.register("reader", document.getElementById("tag-reader"), document.getElementById("page-reader")); pagemgr.go("reader"); }); diff --git a/shared/html/reader.html b/shared/html/reader.html index 3307a78..b6f8626 100644 --- a/shared/html/reader.html +++ b/shared/html/reader.html @@ -21,8 +21,7 @@ - - + @@ -47,21 +46,37 @@