├── .github └── workflows │ └── build.yml ├── .gitignore ├── Lang.ini ├── README-en_US.md ├── README.md ├── RunFirefox.au3 ├── icons ├── FireDoge.ico ├── Firefox.ico ├── Floorp.ico ├── LibreWolf.ico ├── Mercury.ico ├── WaterFox.ico └── ZenBrowser.ico ├── libs ├── AppUserModelId.au3 ├── BinaryCall.au3 ├── JSON.au3 ├── Polices.au3 ├── ScriptingDictionary.au3 ├── UpgradeHelper.au3 └── _String.au3 ├── mozlz4-win32.exe └── mozlz4-win64.exe /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: [master] 6 | tags: 7 | - "v*" 8 | pull_request: 9 | branches: [master] 10 | workflow_dispatch: 11 | 12 | jobs: 13 | build: 14 | runs-on: windows-latest 15 | if: startsWith(github.ref, 'refs/tags/v') 16 | 17 | steps: 18 | - name: Debug Info 19 | run: | 20 | echo "github.ref: ${{ github.ref }}" 21 | echo "github.event_name: ${{ github.event_name }}" 22 | shell: bash 23 | 24 | - uses: actions/checkout@v3 25 | 26 | - uses: liudonghua123/action-setup-autoit@main 27 | 28 | - name: Get the version 29 | id: get_version 30 | run: echo "VERSION=${GITHUB_REF#*\/v}" >> $GITHUB_OUTPUT 31 | shell: bash 32 | 33 | - name: Update the version 34 | shell: bash 35 | run: | 36 | sed -i "s/#AutoIt3Wrapper_Res_Fileversion.*/#AutoIt3Wrapper_Res_Fileversion=${{ steps.get_version.outputs.VERSION }}.0/" RunFirefox.au3 37 | sed -i "s/Global Const \$AppVersion.*/Global Const \$AppVersion = \"${{ steps.get_version.outputs.VERSION }}\"/" RunFirefox.au3 38 | 39 | - name: Generate scripts for all icons 40 | shell: bash 41 | run: | 42 | for icon in icons/*.ico; do 43 | basename=$(basename "$icon" .ico) 44 | # 排除原始Firefox图标 45 | if [ "$basename" != "Firefox" ]; then 46 | cp RunFirefox.au3 "Run${basename}.au3" 47 | sed -i "s/Firefox.ico/${basename}.ico/" "Run${basename}.au3" 48 | sed -i "s/Global Const \$CustomArch.*/Global Const \$CustomArch = \"Run${basename}\"/" "Run${basename}.au3" 49 | sed -i "s/RunFirefox.exe/Run${basename}.exe/" "Run${basename}.au3" 50 | sed -i "s/RunFirefox_x64.exe/Run${basename}_x64.exe/" "Run${basename}.au3" 51 | fi 52 | done 53 | 54 | - name: Build scripts in parallel 55 | shell: pwsh 56 | run: | 57 | $autoItPath = "C:\Program Files (x86)\AutoIt3\AutoIt3.exe" 58 | $wrapperPath = "C:\Program Files (x86)\AutoIt3\SciTE\AutoIt3Wrapper\AutoIt3Wrapper.au3" 59 | 60 | # 获取所有需要编译的.au3文件 61 | $scripts = Get-ChildItem -Filter *.au3 62 | 63 | # 并行编译,最多4个同时运行 64 | $scripts | ForEach-Object -Parallel { 65 | Start-Process -FilePath $using:autoItPath -ArgumentList "`"$using:wrapperPath`" /in `"$($_.FullName)`" /NoStatus" -NoNewWindow -Wait 66 | } -ThrottleLimit 4 67 | 68 | - name: Check the output 69 | shell: bash 70 | run: | 71 | ls -l 72 | 73 | - name: Package the binaries 74 | shell: bash 75 | run: | 76 | # 仅处理以Run开头的exe文件 77 | for exe in Run*.exe; do 78 | # 提取基础名称和架构标识 79 | if [[ "$exe" == *_x64.exe ]]; then 80 | basename="${exe%_x64.exe}" 81 | arch="_x64" 82 | else 83 | basename="${exe%.exe}" 84 | arch="" 85 | fi 86 | 87 | # 生成最终文件名 88 | zip_name="${basename}_${{ steps.get_version.outputs.VERSION }}${arch}.zip" 89 | 90 | # 打包命令 91 | 7z a -tzip "$zip_name" "$exe" 92 | done 93 | 94 | - uses: xresloader/upload-to-github-release@v1 95 | env: 96 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 97 | with: 98 | file: "*.zip" 99 | tags: true 100 | draft: false 101 | overwrite: true 102 | 103 | - name: Create changelog text 104 | id: changelog 105 | uses: endaft/action-changelog@v0.0.3 106 | with: 107 | token: ${{ secrets.GITHUB_TOKEN }} 108 | exclude_types: other,doc,chore 109 | 110 | - name: Update release 111 | uses: ColinPitrat/update-release@v1.0.1 112 | with: 113 | files: "README.md" 114 | token: ${{ secrets.GITHUB_TOKEN }} 115 | tag: v${{ steps.get_version.outputs.VERSION }} 116 | body: ${{ steps.changelog.outputs.changes }} 117 | 118 | - uses: EndBug/add-and-commit@v9 119 | with: 120 | push: origin HEAD:master 121 | add: "*.txt RunFirefox.au3" 122 | fetch: true 123 | message: "Bump update information" -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /RunFirefox_x64.exe 2 | /RunFirefox.exe 3 | /RunFirefox_stripped.au3 4 | /RunFirefox.vbs 5 | /RunFirefox.ini 6 | -------------------------------------------------------------------------------- /Lang.ini: -------------------------------------------------------------------------------- 1 | [en-US] 2 | LangTitle=English 3 | LangSupportAuthor=Ryan 4 | LangSupportUrl=https://doufu.ru 5 | UILanguage=Language 6 | RestartToApplyLanguage={AppName} will restart to apply new language! 7 | UpdateAvailable={AppName} {Version} already released,Release notes:\n\n\n{Notes}\nWould you like to update {AppName} to this version? 8 | CancelAppUpdate=Canceling update ... 9 | StartToDownloadApp=Starting to download {AppName} 10 | AppDownloadProgress=Downloading {AppName}\n%i KB already downloaded. 11 | CancelAppUpdateConfirm=Downloading {AppName}, sure to cancel? 12 | ApplyingUpdate=Applying {AppName} update 13 | FailToDeCompressUpdateFile=Unpacking the update file failed. 14 | FailToDownloadUpdateFile=Failed to download update file. 15 | UpdateSuccessConfirm={AppName} has been updated to {Version}!\nOriginal{ScriptName} has been backuped to {ScriptNameBak} 16 | UpdateFailedConfirm=Automatic update RunFirefox failed: \n%s\n\nDo you go to the software release page and download RunFirefox manually? 17 | AppTitle={AppName} - Build your own portable version of Firefox 18 | AppCopyright={AppName} by Ryan 19 | AppOriginalCopyright=Original Version By cnjackchen 20 | ClickToOpenPublishPage=Click to open the {AppName} release page 21 | ClickToOpenOriginalPage=Click to open the original myFirefox release page 22 | General=General 23 | BrowserFiles=Browser program files 24 | FirefoxPath=Firefox Path 25 | BrowserExecutablePath=Browser executable path 26 | Browse=Browse 27 | ChoosePortableBrowser=Select the executable file of the browser \n the main program (firefox.exe) 28 | UpdateChannel=Update Channel 29 | BrowserAutoUpdate=Auto update 30 | DownloadFirefox=Download Firefox: 31 | DownloadFirefoxX64=%s x64 32 | DownloadFirefoxX86=%s x86 33 | ProfileFiles=Browser profile files 34 | ProfileDirectory=Profile Directory 35 | ProfileDirectoryTooltip=Browser profile Directory 36 | ChooseProfileDirectory=Choose Profile Directory 37 | ExtractProfileFromSystem= Extract Firefox profile from the system 38 | RunFirefoxOptions={AppName} options 39 | NoticeMeWhenNewVersionPublished= Notify me of new {AppName} releases 40 | KeepRunFirefoxRunning= {AppName} runs in the background until the browser quits 41 | Advanced=Advanced 42 | PluginsDirectory=Plugins Directory 43 | PluginsDirectoryTooltip=Browser plugins directory\nleave blank = default location 44 | SpecifyPluginsDirectory=Specify Plugins Directory 45 | CacheDirectory=Cache Directory 46 | CacheDirectoryTooltip=Browser cache location\nLeave blank = default location 47 | SpecifyCacheDirectory=Specify Cache Directory 48 | CacheSize=Cache Size 49 | CacheSizeTooltip=Cache size\nLeave blank = default size 50 | CacheSizeControl= Automatic cache size control 51 | CommandLineArguments=Command Line Arguments 52 | CommandLineArgumentsTooltip=Firefox command line parameters, write one parameter per line.\nsupports environment variables such as %TEMP%,\nin addition, %APP% represents the directory where RunFirefox is located 53 | ExternalPrograms=External Programs 54 | RunOnBrowserStart=# Run on browser startup 55 | AutoCloseAfterBrowserExit=# Auto-close after browser exit 56 | RunOnBrowserStartTooltip=External programs that run when the browser starts, support batch, vbs files, etc.\nIf you want to start parameters, you can add them after the program path 57 | Add=Add 58 | SelectExtraApp=Select Extra App 59 | RunAfterBrowserExit=#run after browser exit 60 | RunAfterBrowserExitTooltip=External programs that run after the browser exits, support batch, vbs files, etc.\nIf you want to start parameters, you can add them after the program path 61 | CheckForUpdateManually= Check for updates 62 | Confirm=Confirm 63 | ConfirmTooltip=Save the settings and start the browser 64 | Cancel=Cancel 65 | CancelTooltip=Do not save settings and exit 66 | Apply=Apply 67 | ApplyTooltip=Save settings 68 | DoublieClickToOpenSettingsWindow=Double-click the "%s.vbs" in the software directory to open this window 69 | ChooseExtraApp=Select the external programs to be run when the browser starts 70 | ExtraAppAllFiles=All files (*.*) 71 | ManuallyDownloadMessage=Please download the Firefox installation package, open it with WinRAR, 7z, etc., \n extract the "core" folder from it, and you will get the program files required for Firefox Portable. \n\nThe download address has been copied to the clipboard, click "OK" to open the download page in the browser. 72 | RunInBackgroundMessage=Allowing RunFirefox to run in the background can bring better user experience. If you cancel this option, please note the following points: \n\n 1. After locking the browser to the taskbar or setting it as the default browser, you need to run RunFirefox again to take effect; \n\n 2. The functions/options with "#" symbol in the RunFirefox settings screen will not be executed, including closing external programs, running external programs, etc. after the browser exits. \n2. \Are you sure you want to remove this option? 73 | FirefoxPathErrorMessage=Firefox path is wrong, please reset it. \n\n%s 74 | PleaseProfileFolder=Please Set Profile Folder 75 | CannotExtratProfileFromSystem=The browser is running and cannot extract the configuration file! \nPlease close Firefox and continue. 76 | ExtractingProfile=The configuration file is being extracted, please wait ... 77 | ExtractProfileSuccess=Extracted profile successfully! 78 | ExtractProfileFailed=Extracted profile failed! 79 | ChooseFirefoxExecutable=Choose Firefox executable(firefox.exe) 80 | ExecutableFile=Executable(*.exe) 81 | SpecifyProfileDirectory=Specify Profile Directory -------------------------------------------------------------------------------- /README-en_US.md: -------------------------------------------------------------------------------- 1 | # RunFirefox 2 | 3 | Derived from MyFirefox, this is a portable version launcher for Firefox. 4 | 5 | Features: 6 | 1. Customizable location for Firefox program files, data folders, and cache folders. 7 | 2. Ability to create a portable version of Firefox that can be set as the default browser (just like the installed version, set in the browser settings). 8 | 3. Support for running external programs when the browser starts or exits. 9 | 4. Support for launching the browser by clicking on the taskbar icon (right-click and select "Pin to taskbar" after opening the browser). 10 | 11 | ### Latest updates 12 | 13 | 2023.04.15 Added browser auto-update switch 14 | 15 | 2023.04.12 Added support for multiple languages 16 | 17 | 2022.12.16 Fixed an issue where the 64-bit version was updated to the 32-bit version 18 | 19 | 2022.12.08 If there is no shifting, the extension path will no longer be processed, optimizing the cold start speed 20 | 21 | 2022.11.14 Attempted to fix the issue of missing extension icons after shifting, added automatic construction of FireDoge and Floorp icons 22 | 23 | 2022.10.18 Attempted to add automatic extension path update functionality (to prevent extensions from becoming invalid after shifting) 24 | 25 | ### How to download 26 | 27 | Click on the "Latest" button on the right. If you have trouble finding it, press Ctrl+F and search for the text "Latest" on this page. 28 | 29 | ### Other notes 30 | 31 | mozlz4-win32.exe and mozlz4-win64.exe are from [jusw85/mozlz4: Decompress / compress mozlz4 files, with precompiled binaries for Windows and Linux](https://github.com/jusw85/mozlz4) 32 | 33 | ### Thanks to 34 | 35 | cnjackchen: https://github.com/cnjackchen/ 36 | 37 | Justin Wong: https://github.com/jusw85 38 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RunFirefox 2 | 3 | [English Version](README-en_US.md) 4 | 5 | 从 MyFirefox 修改而来,是 Firefox 的便携版引导器 6 | 7 | 1. 自定义Firefox浏览器程序文件、数据文件夹、缓存文件夹的位置等。 8 | 2. 制作Firefox便携版,可设为默认浏览器(与安装版一样,在浏览器设置里设置即可)。 9 | 3. 支持浏览器启动/退出时运行外部程序。 10 | 4. 支持锁定到任务栏后点击启动(打开浏览器后在任务栏右键锁定即可) 11 | 12 | ### 最近更新 13 | 14 | 2025.03.30 支持增加图标后自动构建对应图标的 RunFirefox 15 | 16 | 2024.03.24 修复缓存设置失效的问题 17 | 18 | 2023.10.24 移除旧版本的更新地址,修复一直以来各种更新问题,支持设置 GitHub Mirror 选项 19 | 20 | 2023.04.15 新增浏览器自动更新开关 21 | 22 | 2023.04.12 支持多语言 23 | 24 | 2022.12.16 修复64位被更新为32位的问题 25 | 26 | 2022.12.08 检测到没有移位后不再处理扩展路径,优化冷启动速度 27 | 28 | 2022.11.14 尝试修复移位后扩展图标丢失,新增 FireDoge 和 Floorp 图标自动构建 29 | 30 | 2022.10.18 尝试增加扩展路径自动更新的功能(防止移位后扩展失效) 31 | 32 | ### 如何自定义图标构建 33 | 34 | 1. 克隆此项目 35 | 2. `icons`目录删除`Firefox.ico`以外的文件 36 | 3. 添加你想用于构建的图标,然后提交到 Github 37 | 4. 打 tag 后,push 到 GitHub 后会自动构建 38 | 39 | ### 如何下载 40 | 41 | 右边 Latest,如果你视力不好,按 Ctrl + F 在此页面查找文本 Latest 42 | 43 | ### 其他说明 44 | 45 | mozlz4-win32.exe 和 mozlz4-win64.exe 来自 [jusw85/mozlz4: Decompress / compress mozlz4 files, with precompiled binaries for Windows and Linux](https://github.com/jusw85/mozlz4) 46 | 47 | ### 感谢 48 | 49 | 甲壳虫 https://github.com/cnjackchen/ 50 | 51 | Justin Wong https://github.com/jusw85 52 | -------------------------------------------------------------------------------- /RunFirefox.au3: -------------------------------------------------------------------------------- 1 | #NoTrayIcon 2 | #Region ;**** Directives created by AutoIt3Wrapper_GUI **** 3 | #AutoIt3Wrapper_Icon=icons\Firefox.ico 4 | #AutoIt3Wrapper_Outfile=RunFirefox.exe 5 | #AutoIt3Wrapper_Outfile_x64=RunFirefox_x64.exe 6 | #AutoIt3Wrapper_UseUpx=y 7 | #AutoIt3Wrapper_Compile_Both=y 8 | #AutoIt3Wrapper_UseX64=y 9 | #AutoIt3Wrapper_Res_Comment=Firefox Portable 10 | #AutoIt3Wrapper_Res_Description=Firefox Portable 11 | #AutoIt3Wrapper_Res_Fileversion=2.7.9.0 12 | #AutoIt3Wrapper_Res_LegalCopyright=Ryan 13 | #AutoIt3Wrapper_Res_Language=2052 14 | #AutoIt3Wrapper_Res_requestedExecutionLevel=None 15 | #AutoIt3Wrapper_AU3Check_Parameters=-q 16 | #AutoIt3Wrapper_Run_Au3Stripper=y 17 | #Au3Stripper_Parameters=/sf=1 /sv=1 18 | #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** 19 | #cs ---------------------------------------------------------------------------- 20 | AutoIt Version: 3.3.14.2 21 | Author: Ryan, 甲壳虫 22 | Link https://github.com/benzBrake/RunFirefox 23 | OldLink: http://code.taobao.org/p/RunFirefox/wiki/index/ 24 | Script Function: 25 | 自定义Firefox程序和配置文件夹的路径,用来制作Firefox便携版,便携版可设为默认浏览器。 26 | #ce 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include "libs\_String.au3" 43 | #include "libs\AppUserModelId.au3" 44 | #include "libs\Polices.au3" 45 | #include "libs\ScriptingDictionary.au3" 46 | #include "libs\UpgradeHelper.au3" 47 | 48 | Opt("GUIOnEventMode", 1) 49 | Opt("WinTitleMatchMode", 4) 50 | 51 | Global Const $CustomArch = "RunFirefox" 52 | Global Const $AppVersion = "2.7.9" 53 | Global $FirstRun, $FirefoxExe, $FirefoxDir 54 | Global $TaskBarDir = @AppDataDir & "\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar" 55 | Global $AppPID, $TaskBarLastChange 56 | Global $AllowBrowserUpdate, $CheckAppUpdate, $AppUpdateLastCheck, $RunInBackground, $FirefoxPath, $ProfileDir 57 | Global $CustomPluginsDir, $CustomCacheDir, $CacheSize, $CacheSizeSmart, $CheckDefaultBrowser, $Params 58 | Global $ExApp, $ExAppAutoExit, $ExApp2 59 | 60 | Global $DefaultProfDir, $hSettings, $hFirefoxPath, $hProfileDir, $hlanguage 61 | Global $hCopyProfile, $hCustomPluginsDir, $hGetPluginsDir 62 | Global $hCustomCacheDir, $hGetCacheDir, $hCacheSize, $hCacheSizeSmart 63 | Global $hParams, $hStatus, $SettingsOK 64 | Global $hAllowBrowserUpdate, $hCheckAppUpdate, $hRunInBackground, $hChannel, $hDownloadFirefox32, $hDownloadFirefox64, $FirefoxURL 65 | Global $hExApp, $hExAppAutoExit, $hExApp2 66 | Global $aExApp, $aExApp2, $aExAppPID[2] 67 | 68 | Global $hEvent, $ClientKey, $FileAsso, $URLAsso 69 | Global $aREG[7][3] = [[$HKEY_CURRENT_USER, 'Software\Clients\StartMenuInternet'], _ 70 | [$HKEY_LOCAL_MACHINE, 'Software\Clients\StartMenuInternet'], _ 71 | [$HKEY_CLASSES_ROOT, 'ftp'], _ 72 | [$HKEY_CLASSES_ROOT, 'http'], _ 73 | [$HKEY_CLASSES_ROOT, 'https'], _ 74 | [$HKEY_CLASSES_ROOT, ''], _ ; FirefoxHTML 75 | [$HKEY_CLASSES_ROOT, '']] ; FirefoxURL 76 | 77 | ; Global Const $KEY_WOW64_32KEY = 0x0200 ; Access a 32-bit key from either a 32-bit or 64-bit application 78 | ; Global Const $KEY_WOW64_64KEY = 0x0100 ; Access a 64-bit key from either a 32-bit or 64-bit application 79 | 80 | If Not @AutoItX64 Then ; 32-bit Autoit 81 | $HKLM_Software_32 = "HKLM\SOFTWARE" 82 | $HKLM_Software_64 = "HKLM64\SOFTWARE" 83 | Else ; 64-bit Autoit 84 | $HKLM_Software_32 = "HKLM\SOFTWARE\Wow6432Node" 85 | $HKLM_Software_64 = "HKLM64\SOFTWARE" 86 | EndIf 87 | 88 | FileChangeDir(@ScriptDir) 89 | $ScriptNameWithOutSuffix = StringRegExpReplace(@ScriptName, "\.[^.]*$", "") 90 | $inifile = @ScriptDir & "\" & $ScriptNameWithOutSuffix & ".ini" 91 | If Not FileExists($inifile) Then 92 | $FirstRun = 1 93 | IniWrite($inifile, "Settings", "AppVersion", $AppVersion) 94 | IniWrite($inifile, "Settings", "CheckAppUpdate", 1) 95 | IniWrite($inifile, "Settings", "AppUpdateLastCheck", "2015/01/01 00:00:00") 96 | IniWrite($inifile, "Settings", "RunInBackground", 1) 97 | IniWrite($inifile, "Settings", "AllowBrowserUpdate", 1) 98 | IniWrite($inifile, "Settings", "FirefoxPath", ".\Firefox\firefox.exe") 99 | IniWrite($inifile, "Settings", "ProfileDir", ".\profiles") 100 | IniWrite($inifile, "Settings", "CustomPluginsDir", "") 101 | IniWrite($inifile, "Settings", "CustomCacheDir", "") 102 | IniWrite($inifile, "Settings", "CacheSize", "") 103 | IniWrite($inifile, "Settings", "CacheSizeSmart", 1) 104 | IniWrite($inifile, "Settings", "CheckDefaultBrowser", 1) 105 | IniWrite($inifile, "Settings", "Params", "") 106 | IniWrite($inifile, "Settings", "ExApp", "") 107 | IniWrite($inifile, "Settings", "ExAppAutoExit", 1) 108 | IniWrite($inifile, "Settings", "ExApp2", "") 109 | IniWrite($inifile, "Settings", "LastPlatformDir", "") 110 | IniWrite($inifile, "Settings", "LastProfileDir", "") 111 | IniWrite($inifile, "Settings", "GithubMirror", "https://mirror.serv00.net/gh") 112 | EndIf 113 | 114 | $CheckAppUpdate = IniRead($inifile, "Settings", "CheckAppUpdate", 1) * 1 115 | $AppUpdateLastCheck = IniRead($inifile, "Settings", "AppUpdateLastCheck", "") 116 | If Not $AppUpdateLastCheck Then 117 | $AppUpdateLastCheck = "2015/01/01 00:00:00" 118 | EndIf 119 | $AllowBrowserUpdate = IniRead($inifile, "Settings", "AllowBrowserUpdate", 1) * 1 120 | $RunInBackground = IniRead($inifile, "Settings", "RunInBackground", 1) * 1 121 | $FirefoxPath = IniRead($inifile, "Settings", "FirefoxPath", ".\Firefox\firefox.exe") 122 | $ProfileDir = IniRead($inifile, "Settings", "ProfileDir", ".\profiles") 123 | $CustomPluginsDir = IniRead($inifile, "Settings", "CustomPluginsDir", "") 124 | $CustomCacheDir = IniRead($inifile, "Settings", "CustomCacheDir", "") 125 | $CacheSize = IniRead($inifile, "Settings", "CacheSize", "") 126 | $CacheSizeSmart = IniRead($inifile, "Settings", "CacheSizeSmart", 1) * 1 127 | $CheckDefaultBrowser = IniRead($inifile, "Settings", "CheckDefaultBrowser", 1) * 1 128 | $Params = IniRead($inifile, "Settings", "Params", "") 129 | $ExApp = IniRead($inifile, "Settings", "ExApp", "") 130 | $ExAppAutoExit = IniRead($inifile, "Settings", "ExAppAutoExit", 1) * 1 131 | $ExApp2 = IniRead($inifile, "Settings", "ExApp2", "") 132 | $LastPlatformDir = IniRead($inifile, "Settings", "LastPlatformDir", 1) 133 | $LastProfileDir = IniRead($inifile, "Settings", "LastProfileDir", "") 134 | $LANGUAGE = IniRead($inifile, "Settings", "Language", "zh-CN") 135 | $GithubMirror = IniRead($inifile, "Settings", "GithubMirror", "https://mirror.serv00.net/gh") 136 | If Not $LANGUAGE Then 137 | $LANGUAGE = 'zh-CN' 138 | EndIf 139 | $LANG_FILE = _GetLangFile() 140 | $LANGUAGES = _GetLanguages() 141 | 142 | ; 检查是否是首次启动(刚下载,刚更新) 143 | If $AppVersion <> IniRead($inifile, "Settings", "AppVersion", "") Then 144 | $FirstRun = 1 145 | IniWrite($inifile, "Settings", "AppVersion", $AppVersion) 146 | EndIf 147 | 148 | Opt("ExpandEnvStrings", 1) 149 | EnvSet("APP", @ScriptDir) 150 | 151 | ;~ 第一个启动参数为“-set”,或第一次运行,Firefox、配置文件夹、插件目录不存在,则显示设置窗口 152 | If ($cmdline[0] = 1 And $cmdline[1] = "-set") Or $FirstRun Or Not FileExists($FirefoxPath) Or Not FileExists($ProfileDir) Then 153 | CreateSettingsShortcut(@ScriptDir & "\" & $ScriptNameWithOutSuffix & ".vbs") 154 | Settings() 155 | EndIf 156 | 157 | ;~ 转换成绝对路径 158 | $FirefoxPath = FullPath($FirefoxPath) 159 | SplitPath($FirefoxPath, $FirefoxDir, $FirefoxExe) 160 | $ProfileDir = FullPath($ProfileDir) 161 | 162 | ;~ 创建禁止检查默认浏览器策略,使用 RunFirefox 后检测默认浏览器结果不准确 163 | UpdatePolices($FirefoxDir, "DontCheckDefaultBrowser", true) 164 | 165 | ;~ 创建禁用自动更新策略 166 | UpdatePolices($FirefoxDir, "DisableAppUpdate", $AllowBrowserUpdate == 0) 167 | 168 | If IsAdmin() And $cmdline[0] = 1 And $cmdline[1] = "-SetDefaultGlobal" Then 169 | CheckDefaultBrowser($FirefoxPath) 170 | Exit 171 | EndIf 172 | 173 | ;~ 插件目录 174 | If $CustomPluginsDir <> "" Then 175 | $CustomPluginsDir = FullPath($CustomPluginsDir) 176 | EnvSet("MOZ_PLUGIN_PATH", $CustomPluginsDir) ; 设置环境变量 177 | EndIf 178 | 179 | ;~ 给带空格的外部参数加上引号。 180 | For $i = 1 To $cmdline[0] 181 | If StringInStr($cmdline[$i], " ") Then 182 | $Params &= ' "' & $cmdline[$i] & '"' 183 | Else 184 | $Params &= ' ' & $cmdline[$i] 185 | EndIf 186 | Next 187 | 188 | FileDelete($FirefoxDir & "\defaults\pref\runfirefox.js") 189 | Local $FirefoxIsRunning = ProfileInUse($ProfileDir) 190 | If Not $FirefoxIsRunning Then 191 | Local $config = CheckPrefs() 192 | If $config Then 193 | FileWrite($FirefoxDir & "\defaults\pref\runfirefox.js", $config) 194 | EndIf 195 | EndIf 196 | 197 | ;~ Fix Addons not Found 198 | If $LastPlatformDir <> "" Or $LastProfileDir <> "" Then 199 | If $LastPlatformDir <> $FirefoxDir Or $LastProfileDir <> $ProfileDir Then 200 | UpdateAddonStarup() 201 | UpdateExtensionsJson() 202 | EndIf 203 | EndIf 204 | 205 | ;~ Start Firefox 206 | $AppPID = Run($FirefoxPath & ' -profile "' & $ProfileDir & '" ' & $Params, $FirefoxDir) 207 | 208 | FileChangeDir(@ScriptDir) 209 | CreateSettingsShortcut(@ScriptDir & "\" & $ScriptNameWithOutSuffix & ".vbs") 210 | 211 | If $FirefoxIsRunning Then 212 | $exe = StringRegExpReplace(@AutoItExe, ".*\\", "") 213 | $list = ProcessList($exe) 214 | For $i = 1 To $list[0][0] 215 | If $list[$i][1] <> @AutoItPID And GetProcPath($list[$i][1]) = @AutoItExe Then 216 | Exit ;exit if another instance of myfirefox is running 217 | EndIf 218 | Next 219 | EndIf 220 | 221 | ; Start external apps 222 | If $ExApp <> "" Then 223 | $aExApp = StringSplit($ExApp, "||", 1) 224 | ReDim $aExAppPID[$aExApp[0] + 1] 225 | $aExAppPID[0] = $aExApp[0] 226 | For $i = 1 To $aExApp[0] 227 | $match = StringRegExp($aExApp[$i], '^"(.*?)" *(.*)', 1) 228 | If @error Then 229 | $file = $aExApp[$i] 230 | $args = "" 231 | Else 232 | $file = $match[0] 233 | $args = $match[1] 234 | EndIf 235 | $file = FullPath($file) 236 | $aExAppPID[$i] = ProcessExists(StringRegExpReplace($file, '.*\\', '')) 237 | If Not $aExAppPID[$i] And FileExists($file) Then 238 | $aExAppPID[$i] = ShellExecute($file, $args, StringRegExpReplace($file, '\\[^\\]+$', '')) 239 | EndIf 240 | Next 241 | EndIf 242 | 243 | If $CheckDefaultBrowser Then 244 | CheckDefaultBrowser($FirefoxPath) 245 | EndIf 246 | 247 | WinWait("[REGEXPCLASS:(?i)MozillaWindowClass;REGEXPTITLE:(?i)Firefox]", "", 15) 248 | $hWnd_browser = GethWndbyPID($AppPID, "MozillaWindowClass") 249 | 250 | Global $AppUserModelId 251 | If FileExists($TaskBarDir) Then ; win 7+ 252 | $AppUserModelId = _WindowAppId($hWnd_browser) 253 | CheckPinnedPrograms($FirefoxPath) 254 | EndIf 255 | 256 | ;~ Check myfirefox update 257 | If $CheckAppUpdate And _DateDiff("h", $AppUpdateLastCheck, _NowCalc()) >= 48 Then 258 | CheckAppUpdate() 259 | EndIf 260 | 261 | If Not $RunInBackground Then 262 | Exit 263 | EndIf 264 | ; ========================= app ended if not run in background ================================ 265 | 266 | If $CheckDefaultBrowser Then ; register REG for notification 267 | $hEvent = _WinAPI_CreateEvent() 268 | For $i = 0 To UBound($aREG) - 1 269 | If $aREG[$i][1] Then 270 | $aREG[$i][2] = _WinAPI_RegOpenKey($aREG[$i][0], $aREG[$i][1], $KEY_NOTIFY) 271 | If $aREG[$i][2] Then 272 | _WinAPI_RegNotifyChangeKeyValue($aREG[$i][2], $REG_NOTIFY_CHANGE_LAST_SET, 1, 1, $hEvent) 273 | EndIf 274 | EndIf 275 | Next 276 | EndIf 277 | OnAutoItExitRegister("OnExit") 278 | 279 | ReduceMemory() 280 | AdlibRegister("ReduceMemory", 300000) 281 | 282 | ; wait for firefox exit 283 | $AppIsRunning = 0 284 | While 1 285 | Sleep(500) 286 | 287 | If $hWnd_browser Then 288 | $AppIsRunning = WinExists($hWnd_browser) 289 | Else ; ProcessExists() is resource consuming than WinExists() 290 | $AppIsRunning = ProcessExists($AppPID) 291 | EndIf 292 | 293 | If Not $AppIsRunning Then 294 | ; check other chrome instance 295 | $AppPID = AppIsRunning($FirefoxPath) 296 | If Not $AppPID Then 297 | ExitLoop 298 | EndIf 299 | $AppIsRunning = 1 300 | $hWnd_browser = GethWndbyPID($AppPID, "MozillaWindowClass") 301 | EndIf 302 | 303 | If $TaskBarLastChange Then 304 | CheckPinnedPrograms($FirefoxPath) 305 | EndIf 306 | 307 | If $hEvent And Not _WinAPI_WaitForSingleObject($hEvent, 0) Then 308 | ; MsgBox(0, "", "Reg changed!") 309 | Sleep(500) 310 | CheckDefaultBrowser($FirefoxPath) 311 | For $i = 0 To UBound($aREG) - 1 312 | If $aREG[$i][2] Then 313 | _WinAPI_RegNotifyChangeKeyValue($aREG[$i][2], $REG_NOTIFY_CHANGE_LAST_SET, 1, 1, $hEvent) 314 | EndIf 315 | Next 316 | EndIf 317 | WEnd 318 | 319 | If $ExAppAutoExit And $ExApp <> "" Then 320 | $cmd = '' 321 | For $i = 1 To $aExAppPID[0] 322 | If Not $aExAppPID[$i] Then ContinueLoop 323 | $cmd &= ' /PID ' & $aExAppPID[$i] 324 | Next 325 | If $cmd Then 326 | $cmd = 'taskkill' & $cmd & ' /T /F' 327 | Run(@ComSpec & ' /c ' & $cmd, '', @SW_HIDE) 328 | EndIf 329 | EndIf 330 | 331 | ; Start external apps 332 | If $ExApp2 <> "" Then 333 | $aExApp2 = StringSplit($ExApp2, "||") 334 | For $i = 1 To $aExApp2[0] 335 | $match = StringRegExp($aExApp2[$i], '^"(.*?)" *(.*)', 1) 336 | If @error Then 337 | $file = $aExApp2[$i] 338 | $args = "" 339 | Else 340 | $file = $match[0] 341 | $args = $match[1] 342 | EndIf 343 | $file = FullPath($file) 344 | If Not ProcessExists(StringRegExpReplace($file, '.*\\', '')) Then 345 | If FileExists($file) Then 346 | ShellExecute($file, $args, StringRegExpReplace($file, '\\[^\\]+$', '')) 347 | EndIf 348 | EndIf 349 | Next 350 | EndIf 351 | 352 | Exit 353 | 354 | ;~ =================================== 以上为自动执行部分 =============================== 355 | 356 | Func AppIsRunning($AppPath) 357 | Local $exe = StringRegExpReplace($AppPath, '.*\\', '') 358 | Local $list = ProcessList($exe) 359 | For $i = 1 To $list[0][0] 360 | If StringInStr(GetProcPath($list[$i][1]), $AppPath) Then 361 | Return $list[$i][1] 362 | EndIf 363 | Next 364 | Return 0 365 | EndFunc ;==>AppIsRunning 366 | 367 | 368 | Func GethWndbyPID($pid, $class = "") 369 | $list = WinList("[REGEXPCLASS:(?i)" & $class & "]") 370 | For $i = 1 To $list[0][0] 371 | If Not BitAND(WinGetState($list[$i][1]), 2) Then ContinueLoop ; ignore hidden windows 372 | If $pid = WinGetProcess($list[$i][1]) Then 373 | ;ConsoleWrite("--> " & $list[$i][1] & "-" & $list[$i][0] & @CRLF) 374 | Return $list[$i][1] 375 | EndIf 376 | Next 377 | EndFunc ;==>GethWndbyPID 378 | 379 | 380 | Func OnExit() 381 | If $hEvent Then 382 | _WinAPI_CloseHandle($hEvent) 383 | For $i = 0 To UBound($aREG) - 1 384 | _WinAPI_RegCloseKey($aREG[$i][2]) 385 | Next 386 | EndIf 387 | IniWrite($inifile, "Settings", "LastPlatformDir", $FirefoxDir) 388 | IniWrite($inifile, "Settings", "LastProfileDir", $ProfileDir) 389 | EndFunc ;==>OnExit 390 | 391 | 392 | ;~ 查检 RunFirefox更新 393 | Func CheckAppUpdate() 394 | Local $AppUpdateLastCheck, $repo = 'benzBrake/RunFirefox', $latestVersion, $releaseNotes, $downloadUrl, $MirrorAddress = $GithubMirror 395 | if Not _StringEndsWith($MirrorAddress, "/") Then 396 | $MirrorAddress = $MirrorAddress & "/" 397 | EndIf 398 | $AppUpdateLastCheck = _NowCalc() 399 | IniWrite($inifile, "Settings", "AppUpdateLastCheck", $AppUpdateLastCheck) 400 | 401 | HttpSetProxy(0) ; Use IE defaults for proxy 402 | $latestVersion = GetLatestReleaseVersion($repo, $MirrorAddress); 403 | ;~ 获取的版本号不对则返回 404 | If Not _StringStartsWith($latestVersion, 'v') Then Return 405 | ;~ 去除版本号开头的 v 406 | $latestVersion = StringTrimLeft($latestVersion, 1) 407 | ;~ 比较版本号,如果版本号相同则返回 408 | If VersionCompare($latestVersion, $AppVersion) <= 0 Then Return 409 | ;~ 获取更新日志 410 | $releaseNotes = GetReleaseNotesByVersion($repo, "v" & $latestVersion, $MirrorAddress); 411 | 412 | $UpdateAvailable = _t("UpdateAvailable", "{AppName} {Version} 已发布,更新内容:\n\n\n{Notes}\n是否自动更新?") 413 | $UpdateAvailable = StringReplace($UpdateAvailable, "{AppName}", $CustomArch) 414 | $UpdateAvailable = StringReplace($UpdateAvailable, "{Version}", $latestVersion) 415 | $UpdateAvailable = StringReplace($UpdateAvailable, "{Notes}", $releaseNotes) 416 | $msg = MsgBox(68, $CustomArch, $UpdateAvailable); 417 | If $msg <> 6 Then Return 418 | 419 | ;~ 拼接下载链接 420 | $archStr = ''; 421 | If @AutoItX64 Then 422 | $archStr &= "_x64" 423 | EndIf 424 | $downloadUrl = $MirrorAddress & 'https://github.com/' & $repo & '/releases/download/v' & $latestVersion & '/' & $CustomArch & '_' & $latestVersion & $archStr &'.zip' 425 | ConsoleWrite($downloadUrl) 426 | 427 | Local $temp = @ScriptDir & "\RunFirefox_temp" 428 | $file = $temp & "\RunFirefox.zip" 429 | If Not FileExists($temp) Then DirCreate($temp) 430 | Opt("TrayAutoPause", 0) 431 | Opt("TrayMenuMode", 3) ; Default tray menu items (Script Paused/Exit) will not be shown. 432 | TraySetState(1) 433 | TraySetClick(8) 434 | TraySetToolTip($CustomArch) 435 | Local $hCancelAppUpdate = TrayCreateItem(_t("CancelAppUpdate", "取消更新...")) 436 | TrayTip("", _t("StartToDownloadApp", "开始下载 {AppName}"), 10, 1) 437 | Local $hDownload = InetGet($downloadUrl, $file, 19, 1) 438 | Local $DownloadSuccessful, $DownloadCancelled, $UpdateSuccessful, $error 439 | Do 440 | Switch TrayGetMsg() 441 | Case $TRAY_EVENT_PRIMARYDOWN 442 | TrayTip("", _t("AppDownloadProgress", "正在下载 {AppName}\n已下载 %i KB", Round(InetGetInfo($hDownload, 0) / 1024)), 5, 1) 443 | Case $hCancelAppUpdate 444 | $msg = MsgBox(4 + 32 + 256, $CustomArch,_t("CancelAppUpdateConfirm", "正在下载 {AppName},确定要取消吗?")) 445 | If $msg = 6 Then 446 | $DownloadCancelled = 1 447 | ExitLoop 448 | EndIf 449 | EndSwitch 450 | Until InetGetInfo($hDownload, 2) 451 | $DownloadSuccessful = InetGetInfo($hDownload, 3) 452 | InetClose($hDownload) 453 | If Not $DownloadCancelled Then 454 | If $DownloadSuccessful Then 455 | TrayTip("", _t("ApplyingUpdate", "正在应用 {AppName} 更新"), 10, 1) 456 | FileSetAttrib($file, "+A") 457 | _Zip_UnzipAll($file, $temp) 458 | $FileName = $CustomArch & ".exe" 459 | If @AutoItX64 Then 460 | $FileName = $CustomArch & "_x64.exe" 461 | EndIf 462 | If FileExists($temp & "\" & $FileName) Then 463 | FileMove(@ScriptFullPath, @ScriptDir & "\" & @ScriptName & ".bak", 9) 464 | FileMove($temp & "\" & $FileName, @ScriptFullPath, 9) 465 | FileDelete($file) 466 | DirCopy($temp, @ScriptDir, 1) 467 | $UpdateSuccessful = 1 468 | Else 469 | $error = _t("FailToDeCompressUpdateFile", "解压更新文件失败。") 470 | EndIf 471 | Else 472 | $error = _t("FailToDownloadUpdateFile", "下载更新文件失败。") 473 | EndIf 474 | If $UpdateSuccessful Then 475 | Local $UpdateSuccessfulMsg = _t("UpdateSuccessConfirm", "{AppName} 已更新至 {Version} !\n原 {ScriptName} 已备份为 {ScriptNameBak}") 476 | $UpdateSuccessfulMsg = StringReplace($UpdateSuccessfulMsg, "{Version}", $latestVersion) 477 | $UpdateSuccessfulMsg = StringReplace($UpdateSuccessfulMsg, "{ScriptNameBak}", @ScriptName & ".bak") 478 | MsgBox(64, $CustomArch, $UpdateSuccessfulMsg) 479 | Else 480 | Local $UpdateFailedConfirmMsg = _t("UpdateFailedConfirm", "{AppName} 自动更新失败:\n%s\n\n是否去软件发布页手动下载 {AppName}?", $error) 481 | $msg = MsgBox(20, $CustomArch, $UpdateFailedConfirmMsg) 482 | If $msg = 6 Then ; Yes 483 | ShellExecute("https://github.com/benzBrake/RunFirefox/releases") 484 | EndIf 485 | EndIf 486 | EndIf 487 | DirRemove($temp, 1) 488 | TrayItemDelete($hCancelAppUpdate) 489 | TraySetState(2) 490 | EndFunc ;==>CheckAppUpdate 491 | 492 | 493 | Func DeleteCfgFiles() 494 | FileDelete($FirefoxDir & "\defaults\pref\runfirefox.js") 495 | FileDelete($FirefoxDir & "\runfirefox.cfg") 496 | EndFunc ;==>DeleteCfgFiles 497 | 498 | Func CheckPrefs() 499 | Local $var, $cfg 500 | Local $prefs = FileRead($ProfileDir & "\prefs.js") 501 | 502 | If Not StringRegExp($prefs, '(?i)(?m)^\Quser_pref("browser.shell.checkDefaultBrowser",\E *\Qfalse);\E') Then 503 | $cfg &= 'pref("browser.shell.checkDefaultBrowser", false);' & @CRLF 504 | EndIf 505 | 506 | $CustomCacheDir = FullPath($CustomCacheDir) 507 | If $CustomCacheDir = "" Or $CustomCacheDir = $ProfileDir Then ; profile\ is the default chache dir 508 | If StringInStr($prefs, 'user_pref("browser.cache.disk.parent_directory",') Then 509 | $cfg &= 'clearPref("browser.cache.disk.parent_directory");' & @CRLF 510 | EndIf 511 | Else 512 | $var = StringReplace($CustomCacheDir, '\', '\\') 513 | $cfg &= 'pref("browser.cache.disk.parent_directory", "' & $var & '");' & @CRLF 514 | EndIf 515 | 516 | If $CacheSize = "" Or $CacheSize = 250 Then ; 250 is the default 517 | If StringInStr($prefs, 'user_pref("browser.cache.disk.capacity",') Then 518 | $cfg &= 'clearPref("browser.cache.disk.capacity");' & @CRLF 519 | EndIf 520 | Else 521 | $var = $CacheSize * 1024 522 | $cfg &= 'pref("browser.cache.disk.capacity", ' & $var & ');' & @CRLF 523 | EndIf 524 | 525 | If $CacheSizeSmart = 1 Then 526 | $cfg &= 'pref("browser.cache.disk.smart_size.enabled", true);' & @CRLF 527 | Else 528 | $cfg &= 'pref("browser.cache.disk.smart_size.enabled", false);' & @CRLF 529 | EndIf 530 | If $cfg Then 531 | $cfg = '//' & @CRLF & $cfg 532 | EndIf 533 | $prefs = '' 534 | Return $cfg 535 | EndFunc ;==>CheckPrefs 536 | 537 | ; for win7+ 538 | ; Group different app icons on Taskbar need the same AppUserModelIDs 539 | ; http://msdn.microsoft.com/en-us/library/dd378459%28VS.85%29.aspx 540 | Func CheckPinnedPrograms($browser_path) 541 | If Not FileExists($TaskBarDir) Then 542 | Return 543 | EndIf 544 | Local $ftime = FileGetTime($TaskBarDir, 0, 1) 545 | If $ftime = $TaskBarLastChange Then 546 | Return 547 | EndIf 548 | 549 | $TaskBarLastChange = $ftime 550 | Local $search = FileFindFirstFile($TaskBarDir & "\*.lnk") 551 | If $search = -1 Then Return 552 | Local $file, $ShellObj, $objShortcut, $shortcut_appid 553 | $ShellObj = ObjCreate("WScript.Shell") 554 | If Not @error Then 555 | While 1 556 | $file = $TaskBarDir & "\" & FileFindNextFile($search) 557 | If @error Then ExitLoop 558 | $objShortcut = $ShellObj.CreateShortCut($file) 559 | $path = $objShortcut.TargetPath 560 | If $path == $browser_path Or $path == @ScriptFullPath Then 561 | If $path == $browser_path Then 562 | $objShortcut.TargetPath = @ScriptFullPath 563 | $objShortcut.Save 564 | $TaskBarLastChange = FileGetTime($TaskBarDir, 0, 1) 565 | EndIf 566 | $shortcut_appid = _ShortcutAppId($file) 567 | 568 | If Not $AppUserModelId Then 569 | ;Sleep(3000) 570 | ; usually fails to get firefox's window appid while succeeds on chrome, 571 | ; what's wrong? 572 | $AppUserModelId = _WindowAppId($hWnd_browser) 573 | If Not $AppUserModelId Then 574 | $AppUserModelId = AppIdFromRegistry() 575 | If Not $AppUserModelId Then 576 | ; helper.exe writes AppUserModelIDs to SOFTWARE\Mozilla\Firefox\TaskBarIDs 577 | Local $pid = Run($FirefoxDir & "\uninstall\helper.exe /UpdateShortcutAppUserModelIds") 578 | ProcessWaitClose($pid, 5) 579 | $AppUserModelId = AppIdFromRegistry() 580 | EndIf 581 | 582 | If Not $AppUserModelId Then 583 | If $shortcut_appid Then 584 | $AppUserModelId = $shortcut_appid 585 | Else ; if no window appid found,set an id for the window 586 | $AppUserModelId = "RunFirefox." & StringTrimLeft(_WinAPI_HashString(@ScriptFullPath, 0, 16), 2) 587 | EndIf 588 | EndIf 589 | _WindowAppId($hWnd_browser, $AppUserModelId) 590 | EndIf 591 | EndIf 592 | If $shortcut_appid <> $AppUserModelId Then 593 | _ShortcutAppId($file, $AppUserModelId) 594 | $TaskBarLastChange = FileGetTime($TaskBarDir, 0, 1) 595 | EndIf 596 | ExitLoop 597 | EndIf 598 | WEnd 599 | $objShortcut = "" 600 | $ShellObj = "" 601 | EndIf 602 | FileClose($search) 603 | EndFunc ;==>CheckPinnedPrograms 604 | 605 | Func AppIdFromRegistry() 606 | Local $appid 607 | If @OSArch = "X86" Then 608 | Local $aRoot[2] = ["HKCU\SOFTWARE", $HKLM_Software_32] 609 | Else 610 | Local $aRoot[3] = ["HKCU\SOFTWARE", $HKLM_Software_32, $HKLM_Software_64] 611 | EndIf 612 | For $i = 0 To UBound($aRoot) - 1 613 | $appid = RegRead($aRoot[$i] & "\Mozilla\Firefox\TaskBarIDs", $FirefoxDir) 614 | If $appid Then ExitLoop 615 | Next 616 | Return $appid 617 | EndFunc ;==>AppIdFromRegistry 618 | 619 | Func CreateSettingsShortcut($fname) 620 | Local $var = FileRead($fname) 621 | If $var <> 'CreateObject("shell.application").ShellExecute "' & @ScriptName & '", "-set"' Then 622 | FileDelete($fname) 623 | FileWrite($fname, 'CreateObject("shell.application").ShellExecute "' & @ScriptName & '", "-set"') 624 | EndIf 625 | EndFunc ;==>CreateSettingsShortcut 626 | 627 | 628 | Func CheckDefaultBrowser($BrowserPath) 629 | Local $InternetClient, $key, $i, $j, $var, $RegWriteError = 0 630 | If Not $ClientKey Then 631 | If @OSArch = "X86" Then 632 | Local $aRoot[2] = ["HKCU\SOFTWARE", $HKLM_Software_32] 633 | Else 634 | Local $aRoot[3] = ["HKCU\SOFTWARE", $HKLM_Software_32, $HKLM_Software_64] 635 | EndIf 636 | For $i = 0 To UBound($aRoot) - 1 ; search FIREFOX.EXE in internetclient 637 | $j = 1 638 | While 1 639 | $InternetClient = RegEnumKey($aRoot[$i] & "\Clients\StartMenuInternet", $j) 640 | If @error <> 0 Then ExitLoop 641 | $key = $aRoot[$i] & '\Clients\StartMenuInternet\' & $InternetClient 642 | $var = RegRead($key & '\DefaultIcon', '') 643 | If StringInStr($var, $BrowserPath) Then 644 | $ClientKey = $key 645 | $FileAsso = RegRead($ClientKey & '\Capabilities\FileAssociations', '.html') 646 | $URLAsso = RegRead($ClientKey & '\Capabilities\URLAssociations', 'http') 647 | ExitLoop 2 648 | EndIf 649 | $j += 1 650 | WEnd 651 | Next 652 | EndIf 653 | If $ClientKey Then 654 | $var = RegRead($ClientKey & '\shell\open\command', '') 655 | If Not StringInStr($var, @ScriptFullPath) Then 656 | $RegWriteError += Not RegWrite($ClientKey & '\shell\open\command', '', 'REG_SZ', '"' & @ScriptFullPath & '"') 657 | RegWrite($ClientKey & '\shell\properties\command', '', 'REG_SZ', '"' & @ScriptFullPath & '" -preferences') 658 | RegWrite($ClientKey & '\shell\safemode\command', '', 'REG_SZ', '"' & @ScriptFullPath & '" -safe-mode') 659 | EndIf 660 | EndIf 661 | 662 | If Not $FileAsso Then 663 | If StringInStr(RegRead('HKCR\FirefoxHTML\DefaultIcon', ''), $BrowserPath) Then 664 | $FileAsso = "FirefoxHTML" 665 | EndIf 666 | EndIf 667 | If Not $URLAsso Then 668 | If StringInStr(RegRead('HKCR\FirefoxURL\DefaultIcon', ''), $BrowserPath) Then 669 | $URLAsso = "FirefoxURL" 670 | EndIf 671 | EndIf 672 | 673 | Local $aAsso[2] = [$FileAsso, $URLAsso] 674 | For $i = 0 To 1 675 | If Not $aAsso[$i] Then ContinueLoop 676 | $var = RegRead('HKCR\' & $aAsso[$i] & '\shell\open\command', '') 677 | If Not StringInStr($var, @ScriptFullPath) Then 678 | $RegWriteError += Not RegWrite('HKCR\' & $aAsso[$i] & '\shell\open\command', _ 679 | '', 'REG_SZ', '"' & @ScriptFullPath & '" -url "%1"') 680 | RegDelete('HKCR\' & $aAsso[$i] & '\shell\open\command', 'DelegateExecute') 681 | RegWrite('HKCR\' & $aAsso[$i] & '\shell\open\ddeexec', '', 'REG_SZ', '') 682 | EndIf 683 | If Not $aREG[5 + $i][1] Then 684 | $aREG[5 + $i][1] = $aAsso[$i] ; for reg notification 685 | $aREG[5 + $i][2] = _WinAPI_RegOpenKey($aREG[5 + $i][0], $aREG[5 + $i][1], $KEY_NOTIFY) 686 | EndIf 687 | Next 688 | 689 | Local $aUrlAsso[3] = ['ftp', 'http', 'https'] 690 | For $i = 0 To 2 691 | $var = RegRead('HKCR\' & $aUrlAsso[$i] & '\DefaultIcon', '') 692 | If StringInStr($var, $BrowserPath) Then 693 | $var = RegRead('HKCR\' & $aUrlAsso[$i] & '\shell\open\command', '') 694 | If Not StringInStr($var, @ScriptFullPath) Then 695 | $RegWriteError += Not RegWrite('HKCR\' & $aUrlAsso[$i] & '\shell\open\command', _ 696 | '', 'REG_SZ', '"' & @ScriptFullPath & '" -url "%1"') 697 | RegDelete('HKCR\' & $aUrlAsso[$i] & '\shell\open\command', 'DelegateExecute') 698 | RegWrite('HKCR\' & $aUrlAsso[$i] & '\shell\open\ddeexec', '', 'REG_SZ', '') 699 | EndIf 700 | EndIf 701 | Next 702 | 703 | If $RegWriteError And Not _IsUACAdmin() And @extended Then 704 | If @Compiled Then 705 | ShellExecute(@ScriptName, "-SetDefaultGlobal", @ScriptDir, "runas") 706 | Else 707 | ShellExecute(@AutoItExe, '"' & @ScriptFullPath & '" -SetDefaultGlobal', @ScriptDir, "runas") 708 | EndIf 709 | EndIf 710 | EndFunc ;==>CheckDefaultBrowser 711 | 712 | Func UpdateAddonStarup() 713 | Local $mozlz4Exe, $addonStarup, $addonStarupLz4 714 | 715 | ; Extract mozlz4 716 | If @OSArch = "X86" Then 717 | $mozlz4Exe = @ScriptDir & "\" & "mozlz4-win32.exe" 718 | FileInstall("mozlz4-win32.exe", $mozlz4Exe) 719 | Else 720 | $mozlz4Exe = @ScriptDir & "\" & "mozlz4-win64.exe" 721 | FileInstall("mozlz4-win32.exe", $mozlz4Exe) 722 | EndIf 723 | 724 | $addonStarupLz4 = $ProfileDir & "\" & "addonStartup.json.lz4"; 725 | $addonStarup = $ProfileDir & "\" & "addonStartup.json"; 726 | 727 | ; Extract addonStartup.json.lz4 728 | If FileExists($addonStarupLz4) Then 729 | FileDelete($addonStarup); 730 | RunWait($mozlz4Exe & ' ' & $addonStarupLz4 & ' ' & $addonStarup, @ScriptDir, @SW_HIDE); 731 | EndIf 732 | 733 | If FileExists($addonStarup) Then 734 | Local $fileOpen, $fileContent, $matches 735 | $fileOpen = FileOpen($addonStarup, $FO_READ) 736 | If $fileOpen <> -1 Then 737 | $fileContent = FileRead($fileOpen) 738 | FileClose($fileOpen) 739 | $fileContent = ReplaceJarPath($fileContent) 740 | $fileOpen = FileOpen($addonStarup, $FO_OVERWRITE) 741 | If $fileOpen <> -1 Then 742 | FileWrite($fileOpen, $fileContent) 743 | FileClose($fileOpen) 744 | RunWait($mozlz4Exe & ' -z ' & $addonStarup & ' ' & $addonStarupLz4, @ScriptDir, @SW_HIDE); 745 | EndIf 746 | EndIf 747 | FileDelete($addonStarup) 748 | EndIf 749 | 750 | FileDelete(@ScriptDir & "\" & "mozlz4-win32.exe") 751 | FileDelete(@ScriptDir & "\" & "mozlz4-win64.exe") 752 | EndFunc ;==>UpdateAddonStarup 753 | 754 | ; 替换 jar 文件路径 755 | Func ReplaceJarPath($content) 756 | Local $matches = StringRegExp($content, 'jar:file[^"]+', $STR_REGEXPARRAYGLOBALMATCH) 757 | For $i = 0 To UBound($matches) - 1 758 | ; 替换有所文件地址 759 | Local $prevPath = $matches[$i]; 760 | Local $tempPath = StringReplace($prevPath, "jar:file:///", "") 761 | $tempPath = StringReplace($tempPath, "!/", "") 762 | Local $dir, $name, $newPath = "" 763 | SplitPath($tempPath, $dir, $name, "/") 764 | If (_StringEndsWith($dir, "/browser/features")) Then 765 | $newPath = "jar:file:///" & $FirefoxDir & "/browser/features/" & $name & "!/"; 766 | EndIf 767 | If (_StringEndsWith($dir, "/extensions")) Then 768 | $newPath = "jar:file:///" & $ProfileDir & "/extensions/" & $name & "!/"; 769 | EndIf 770 | If $newPath <> "" Then 771 | $newPath = StringReplace($newPath, "\", "/") 772 | $content = StringReplace($content, $prevPath, $newPath) 773 | EndIf 774 | Next 775 | Return $content 776 | EndFunc ;==>ReplaceJarPath 777 | 778 | Func UpdateExtensionsJson() 779 | Local $extensions 780 | $extensions = $ProfileDir & "\" & "extensions.json"; 781 | If FileExists($extensions) Then 782 | Local $fileOpen, $fileContent, $matches 783 | $fileOpen = FileOpen($extensions, $FO_READ) 784 | If $fileOpen <> -1 Then 785 | $fileContent = FileRead($fileOpen) 786 | FileClose($fileOpen) 787 | $fileContent = ReplaceLocalPath($fileContent) 788 | $fileOpen = FileOpen($extensions, $FO_OVERWRITE) 789 | If $fileOpen <> -1 Then 790 | FileWrite($fileOpen, $fileContent) 791 | FileClose($fileOpen) 792 | EndIf 793 | EndIf 794 | EndIf 795 | EndFunc ;==>UpdateExtensionsJson 796 | 797 | Func ReplaceLocalPath($content) 798 | Local $matches = StringRegExp($content, '"path":"[^"]+', $STR_REGEXPARRAYGLOBALMATCH) 799 | For $i = 0 To UBound($matches) - 1 800 | Local $prevPath = $matches[$i]; 801 | $prevPath = StringReplace($prevPath, '"path":"', '') 802 | $prevPath = StringReplace($prevPath, '\\', '\') 803 | Local $dir, $name, $newPath = "" 804 | SplitPath($prevPath, $dir, $name, "\") 805 | If (_StringEndsWith($dir, "\browser\features")) Then 806 | $newPath = $FirefoxDir & "\browser\features\" & $name; 807 | EndIf 808 | If (_StringEndsWith($dir, "\extensions")) Then 809 | $newPath = $ProfileDir & "\extensions\" & $name; 810 | EndIf 811 | If $newPath <> "" Then 812 | $prevPath = StringReplace($prevPath, "\", "\\") 813 | $newPath = StringReplace($newPath, "\", "\\") 814 | $content = StringReplace($content, "\\\\", "\\") 815 | $content = StringReplace($content, $prevPath, $newPath) 816 | EndIf 817 | Next 818 | Return $content 819 | EndFunc ;==>ReplaceLocalPath 820 | 821 | Func Settings() 822 | $DefaultProfDir = IniRead(@AppDataDir & '\Mozilla\Firefox\profiles.ini', 'Profile0', 'Path', '') ; 读取Firefox原版配置文件夹路径 823 | If $DefaultProfDir <> "" Then 824 | $DefaultProfDir = StringReplace($DefaultProfDir, "/", "\") 825 | $DefaultProfDir = @AppDataDir & '\Mozilla\Firefox\' & $DefaultProfDir 826 | EndIf 827 | 828 | Opt("ExpandEnvStrings", 0) 829 | $hSettings = GUICreate(_t("AppTitle", "{AppName} - 打造自己的 Firefox 便携版"), 500, 490) 830 | GUISetOnEvent($GUI_EVENT_CLOSE, "ExitApp") 831 | GUICtrlCreateLabel(_t("AppCopyright", "{AppName} by Ryan "), 5, 10, 490, -1, $SS_CENTER) 832 | GUICtrlSetCursor(-1, 0) 833 | GUICtrlSetColor(-1, 0x0000FF) 834 | GUICtrlSetTip(-1, _t("ClickToOpenPublishPage", "点击打开 {AppName} 主页")) 835 | GUICtrlSetOnEvent(-1, "Website") 836 | GUICtrlCreateLabel(_t("AppOriginalCopyright", "原版 by 甲壳虫"), 5, 30, 490, -1, $SS_CENTER) 837 | GUICtrlSetCursor(-1, 0) 838 | GUICtrlSetColor(-1, 0x0000FF) 839 | GUICtrlSetTip(-1, _t("ClickToOpenOriginalPage", "点击打开甲壳虫原版主页")) 840 | GUICtrlSetOnEvent(-1, "OriginalWebsite") 841 | 842 | ;常规 843 | GUICtrlCreateTab(5, 50, 490, 390) 844 | GUICtrlCreateTabItem(_t("General", "常规")) 845 | 846 | GUICtrlCreateGroup(_t("BrowserFiles", "浏览器程序文件"), 10, 80, 480, 120) 847 | GUICtrlCreateLabel(_t("FirefoxPath", "Firefox 路径"), 20, 100, 120, 20) 848 | $hFirefoxPath = GUICtrlCreateEdit($FirefoxPath, 140, 95, 270, 20, $ES_AUTOHSCROLL) 849 | GUICtrlSetTip(-1, _t("BrowserExecutablePath", "浏览器主程序路径")) 850 | GUICtrlSetOnEvent(-1, "OnFirefoxPathChange") 851 | GUICtrlCreateButton(_t("Browse", "浏览"), 420, 95, 60, 20) 852 | GUICtrlSetTip(-1, _t("ChoosePortableBrowser", "选择便携版浏览器\n主程序(firefox.exe)")) 853 | GUICtrlSetOnEvent(-1, "GetFirefoxPath") 854 | 855 | GUICtrlCreateLabel(_t("UpdateChannel", "更新通道"), 20, 130, 120, 20) 856 | $hChannel = GUICtrlCreateCombo("", 140, 125, 150, 20, $CBS_DROPDOWNLIST) 857 | GUICtrlSetData($hChannel, "esr|release|beta|aurora|nightly|default", "release") 858 | GUICtrlSetOnEvent(-1, "ChangeChannel") 859 | 860 | $hAllowBrowserUpdate = GUICtrlCreateCheckbox(_t("BrowserAutoUpdate", " 自动更新"),310, 125, -1, 20) 861 | If $AllowBrowserUpdate Then 862 | GUICtrlSetState(-1, $GUI_CHECKED) 863 | EndIf 864 | 865 | ;~ $hDownloadFirefox = GUICtrlCreateLabel("去下载 " & GUICtrlRead($hChannel), 300, 130, 180, 20) 866 | ;~ GUICtrlSetCursor(-1, 0) 867 | ;~ GUICtrlSetColor(-1, 0x0000FF) 868 | ;~ GUICtrlSetTip(-1, "去下载 Firefox") 869 | ;~ GUICtrlSetOnEvent(-1, "DownloadFirefox") 870 | 871 | ;https://product-details.mozilla.org/1.0/firefox_versions.json 将来实现自动更新 872 | 873 | GUICtrlCreateLabel(_t("DownloadFirefox", "下载 Firefox:"), 20, 160, 120, 20) 874 | $hDownloadFirefox32 = GUICtrlCreateLabel(_t("DownloadFirefoxX64", "%s 32位", "release"), 140, 160, 140, 20) 875 | GUICtrlSetCursor(-1, 0) 876 | GUICtrlSetColor(-1, 0x0000FF) 877 | GUICtrlSetOnEvent(-1, "DownloadFirefox") 878 | 879 | $hDownloadFirefox64 = GUICtrlCreateLabel(_t("DownloadFirefoxX64", "%s 32位", "release"), 280, 160, 140, 20) 880 | GUICtrlSetCursor(-1, 0) 881 | GUICtrlSetColor(-1, 0x0000FF) 882 | If @OSArch <> "X86" Then 883 | GUICtrlSetOnEvent(-1, "DownloadFirefox") 884 | EndIf 885 | 886 | GUICtrlCreateGroup(_t("ProfileFiles", "浏览器用户数据文件"), 10, 210, 480, 80) 887 | GUICtrlCreateLabel(_t("ProfileDirectory", "配置文件夹"), 20, 230, 120, 20) 888 | $hProfileDir = GUICtrlCreateEdit($ProfileDir, 140, 225, 270, 20, $ES_AUTOHSCROLL) 889 | GUICtrlSetTip(-1, _t("ProfileDirectoryTooltip", "浏览器配置文件夹")) 890 | GUICtrlCreateButton(_t("Browse", "浏览"), 420, 225, 60, 20) 891 | GUICtrlSetTip(-1, _t("ChooseProfileDirectory", "指定浏览器配置文件夹")) 892 | GUICtrlSetOnEvent(-1, "GetProfileDir") 893 | $hCopyProfile = GUICtrlCreateCheckbox(_t("ExtractProfileFromSystem", " 从系统中提取 Firefox 配置文件"), 30, 250, -1, 20) 894 | 895 | GUICtrlCreateGroup(_t("RunFirefoxOptions", "{AppName} 设置"), 10, 300, 480, 120) 896 | GUICtrlCreateLabel(_t("UILanguage", "显示语言/Language"), 20, 320, 120, 20) 897 | $hlanguage = GUICtrlCreateCombo("", 140, 315, 100, 20, $CBS_DROPDOWNLIST) 898 | $sLang = '简体中文' 899 | If _ItemExists($LANGUAGES, $LANGUAGE) Then 900 | $sLang = _Item($LANGUAGES, $LANGUAGE) 901 | EndIf 902 | $sLangEnum = _ArrayToString(_GetItems($LANGUAGES)) 903 | GUICtrlSetData(-1, $sLangEnum, $slang) 904 | GUICtrlSetOnEvent(-1, "ChangeLanguage") 905 | 906 | $hCheckAppUpdate = GUICtrlCreateCheckbox(_t("NoticeMeWhenNewVersionPublished", " {AppName} 发布新版时通知我"), 20, 350) 907 | If $CheckAppUpdate Then 908 | GUICtrlSetState(-1, $GUI_CHECKED) 909 | EndIf 910 | $hRunInBackground = GUICtrlCreateCheckbox(_t("KeepRunFirefoxRunning", " {AppName} 在后台运行直至浏览器退出"), 20, 380) 911 | GUICtrlSetOnEvent(-1, "RunInBackground") 912 | If $RunInBackground Then 913 | GUICtrlSetState($hRunInBackground, $GUI_CHECKED) 914 | EndIf 915 | 916 | ; 高级 917 | GUICtrlCreateTabItem(_t("Advanced", "高级")) 918 | GUICtrlCreateLabel(_t("PluginsDirectory", "插件目录"), 20, 90, 120, 20) 919 | $hCustomPluginsDir = GUICtrlCreateEdit($CustomPluginsDir, 140, 85, 270, 20, $ES_AUTOHSCROLL) 920 | GUICtrlSetTip(-1, _t("PluginsDirectoryToolTip", "浏览器插件目录\n空白=默认位置")) 921 | $hGetPluginsDir = GUICtrlCreateButton(_t("Browse", "浏览"), 420, 85, 60, 20) 922 | GUICtrlSetTip(-1, _t("SpecifyPluginsDirectory", "指定浏览器插件目录")) 923 | GUICtrlSetOnEvent(-1, "GetPluginsDir") 924 | 925 | GUICtrlCreateLabel(_t("CacheDirectory", "缓存位置"), 20, 130, 120, 20) 926 | $hCustomCacheDir = GUICtrlCreateEdit($CustomCacheDir, 140, 125, 270, 20, $ES_AUTOHSCROLL) 927 | GUICtrlSetTip(-1, _t("CacheDirectoryTooltip", "浏览器缓存位置\n空白=默认位置")) 928 | $hGetCacheDir = GUICtrlCreateButton(_t("Browse", "浏览"), 420, 125, 60, 20) 929 | GUICtrlSetTip(-1, _t("SpecifyCacheDirectory", "指定浏览器缓存位置")) 930 | GUICtrlSetOnEvent(-1, "GetCacheDir") 931 | 932 | GUICtrlCreateLabel(_t("CacheSize", "缓存大小"), 20, 170, 120, 20) 933 | $hCacheSize = GUICtrlCreateEdit($CacheSize, 140, 165, 60, 20, BitOR($ES_NUMBER, $ES_AUTOHSCROLL)) 934 | GUICtrlSetTip(-1, _t("CacheSizeTooltip", "缓存大小\n空白=默认大小")) 935 | GUICtrlCreateLabel("MB", 215, 170, 35, 20) 936 | $hCacheSizeSmart = GUICtrlCreateCheckbox(_t("CacheSizeControl", " 自动控制缓存大小"), 250, 165, -1, 20) 937 | If $CacheSizeSmart Then GUICtrlSetState(-1, $GUI_CHECKED) 938 | 939 | GUICtrlCreateLabel(_t("CommandLineArguments", "命令行参数"), 20, 325, -1, 20) 940 | $hParams = GUICtrlCreateEdit("", 20, 345, 460, 70, BitOR($ES_WANTRETURN, $WS_VSCROLL, $ES_AUTOVSCROLL)) 941 | If $Params <> "" Then 942 | GUICtrlSetData(-1, StringReplace($Params, " -", @CRLF & "-")) 943 | EndIf 944 | GUICtrlSetTip(-1, _t("CommandLineArgumentsTooltip", "Firefox 命令行参数,每行写一个参数。\n支持%TEMP%等环境变量,\n另外,%APP%代表 RunFirefox 所在目录")) 945 | 946 | ; 外部程序 947 | GUICtrlCreateTabItem(_t("ExternalPrograms", "外部程序")) 948 | GUICtrlCreateLabel(_t("RunOnBrowserStart", "#浏览器启动时运行"), 20, 90, -1, 20) 949 | $hExAppAutoExit = GUICtrlCreateCheckbox(_t("AutoCloseAfterBrowserExit", " #浏览器退出后自动关闭"), 240, 85, -1, 20) 950 | If $ExAppAutoExit = 1 Then 951 | GUICtrlSetState($hExAppAutoExit, $GUI_CHECKED) 952 | EndIf 953 | $hExApp = GUICtrlCreateEdit("", 20, 110, 410, 50, BitOR($ES_WANTRETURN, $WS_VSCROLL, $ES_AUTOVSCROLL)) 954 | If $ExApp <> "" Then 955 | GUICtrlSetData(-1, StringReplace($ExApp, "||", @CRLF) & @CRLF) 956 | EndIf 957 | GUICtrlSetTip(-1, _t("RunOnBrowserStartTooltip", "浏览器启动时运行的外部程序,支持批处理、vbs文件等\n如需启动参数,可添加在程序路径之后")) 958 | GUICtrlCreateButton(_t("Add", "添加"), 440, 110, 40, 20) 959 | GUICtrlSetTip(-1, _t("SelectExtraApp", "选择外部程序")) 960 | GUICtrlSetOnEvent(-1, "AddExApp") 961 | 962 | GUICtrlCreateLabel(_t("RunAfterBrowserExit", "#浏览器退出后运行"), 20, 190, -1, 20) 963 | $hExApp2 = GUICtrlCreateEdit("", 20, 210, 410, 50, BitOR($ES_WANTRETURN, $WS_VSCROLL, $ES_AUTOVSCROLL)) 964 | If $ExApp2 <> "" Then 965 | GUICtrlSetData(-1, StringReplace($ExApp2, "||", @CRLF) & @CRLF) 966 | EndIf 967 | GUICtrlSetTip(-1, _t("RunAfterBrowserExitTooltip", "浏览器退出后运行的外部程序,支持批处理、vbs文件等\n如需启动参数,可添加在程序路径之后")) 968 | GUICtrlCreateButton(_t("Add", "添加"), 440, 210, 40, 20) 969 | GUICtrlSetTip(-1, _t("SelectExtraApp", "选择外部程序")) 970 | GUICtrlSetOnEvent(-1, "AddExApp2") 971 | 972 | GUICtrlCreateTabItem("") 973 | GUICtrlCreateButton(_t("CheckForUpdateManually", "检查更新"), 80, 440, 130, 20) 974 | GUICtrlSetTip(-1, _t("ConfirmTooltip", "立即更新 {AppName}")) 975 | GUICtrlSetOnEvent(-1, "CheckAppUpdate") 976 | GUICtrlCreateTabItem("") 977 | GUICtrlCreateButton(_t("Confirm", "确定"), 235, 440, 70, 20) 978 | GUICtrlSetTip(-1, _t("ConfirmTooltip", "保存设置并启动浏览器")) 979 | GUICtrlSetOnEvent(-1, "SettingsOK") 980 | GUICtrlSetState(-1, $GUI_FOCUS) 981 | GUICtrlCreateButton(_t("Cancel", "取消"), 330, 440, 70, 20) 982 | GUICtrlSetTip(-1, _t("CancelTooltip", "不保存设置并退出")) 983 | GUICtrlSetOnEvent(-1, "ExitApp") 984 | GUICtrlCreateButton(_t("Apply", "应用"), 425, 440, 70, 20) 985 | GUICtrlSetTip(-1, _t("ApplyTooltip", "保存设置")) 986 | GUICtrlSetOnEvent(-1, "SettingsApply") 987 | $hStatus = _GUICtrlStatusBar_Create($hSettings, -1, _t("DoublieClickToOpenSettingsWindow", '双击软件目录下的 "%s.vbs" 文件可调出此窗口', $ScriptNameWithOutSuffix)) 988 | Opt("ExpandEnvStrings", 1) 989 | 990 | ;~ 复制配置文件选项有效/无效 991 | If FileExists($DefaultProfDir) Then 992 | GUICtrlSetState($hCopyProfile, $GUI_ENABLE) 993 | If $FirstRun And Not FileExists($ProfileDir & "\prefs.js") Then GUICtrlSetState($hCopyProfile, $GUI_CHECKED) 994 | Else 995 | GUICtrlSetState($hCopyProfile, $GUI_DISABLE) 996 | EndIf 997 | 998 | OnFirefoxPathChange() 999 | 1000 | GUISetState(@SW_SHOW) 1001 | While Not $SettingsOK 1002 | Sleep(100) 1003 | WEnd 1004 | GUIDelete($hSettings) 1005 | EndFunc ;==>Settings 1006 | 1007 | 1008 | Func AddExApp() 1009 | Local $path 1010 | $path = FileOpenDialog(_t("ChooseExtraApp", "选择浏览器启动时需运行的外部程序"), @ScriptDir, _ 1011 | _t("ExtraAppAllFiles", "所有文件 (*.*)"), 1 + 2, "", $hSettings) 1012 | If $path = "" Then Return 1013 | $path = RelativePath($path) 1014 | $ExApp = GUICtrlRead($hExApp) & '"' & $path & '"' & @CRLF 1015 | GUICtrlSetData($hExApp, $ExApp) 1016 | EndFunc ;==>AddExApp 1017 | Func AddExApp2() 1018 | Local $path 1019 | $path = FileOpenDialog(_t("ChooseExtraApp", "选择浏览器启动时需运行的外部程序"), @ScriptDir, _ 1020 | _t("ExtraAppAllFiles", "所有文件 (*.*)"), 1 + 2, "", $hSettings) 1021 | If $path = "" Then Return 1022 | $path = RelativePath($path) 1023 | $ExApp2 = GUICtrlRead($hExApp2) & '"' & $path & '"' & @CRLF 1024 | GUICtrlSetData($hExApp2, $ExApp2) 1025 | EndFunc ;==>AddExApp2 1026 | 1027 | Func OnFirefoxPathChange() 1028 | ShowCurrentChannel() 1029 | ChangeChannel() 1030 | EndFunc ;==>OnFirefoxPathChange 1031 | 1032 | Func ChangeChannel() 1033 | Local $Channel = GUICtrlRead($hChannel) 1034 | If $Channel = "default" Then $Channel = "release" 1035 | GUICtrlSetData($hDownloadFirefox32, _t("DownloadFirefoxX86", "%s 32位", $Channel)) 1036 | GUICtrlSetData($hDownloadFirefox64, _t("DownloadFirefoxX64", "%s 64位", $Channel)) 1037 | EndFunc ;==>ChangeChannel 1038 | 1039 | Func ShowCurrentChannel() 1040 | Local $path = GUICtrlRead($hFirefoxPath) 1041 | If Not FileExists($path) Then Return 1042 | Local $ChannelPath = StringRegExpReplace($path, "\\?[^\\]+$", "") & "\defaults\pref\channel-prefs.js" 1043 | Local $var = FileRead($ChannelPath) 1044 | Local $match = StringRegExp($var, '(?i)(?m)^\Qpref("app.update.channel",\E *"(.*)\Q");\E', 1) 1045 | If @error Then Return 1046 | $Channel = $match[0] 1047 | _GUICtrlComboBox_SelectString($hChannel, $Channel) 1048 | EndFunc ;==>ShowCurrentChannel 1049 | 1050 | Func DownloadFirefox() 1051 | Local $os 1052 | 1053 | If @GUI_CtrlId = $hDownloadFirefox32 Then 1054 | $os = "win" 1055 | Else 1056 | $os = "win64" 1057 | EndIf 1058 | 1059 | Local $ChannelString = GUICtrlRead($hChannel) 1060 | Local $Channel = StringRegExpReplace($ChannelString, " *-.*", "") 1061 | 1062 | ; http://ftp.mozilla.org/pub/firefox/ 1063 | If $Channel = "release" Or $Channel = "default" Then 1064 | $FirefoxURL = "https://download.mozilla.org/?product=firefox-latest&os=" & $os & "&lang=zh-CN" 1065 | ElseIf $Channel = "beta" Then 1066 | $FirefoxURL = "https://download.mozilla.org/?product=firefox-beta-latest&os=" & $os & "&lang=zh-CN" 1067 | ElseIf $Channel = "esr" Then 1068 | $FirefoxURL = "https://download.mozilla.org/?product=firefox-esr-latest&os=" & $os & "&lang=zh-CN" 1069 | ElseIf $Channel = "aurora" Then 1070 | $FirefoxURL = "https://download.mozilla.org/?product=firefox-aurora-latest-l10n&os=" & $os & "&lang=zh-CN" 1071 | Else ;If $Channel = "nightly" Then 1072 | $FirefoxURL = "https://download.mozilla.org/?product=firefox-nightly-latest&os=" & $os & "&lang=zh-CN" 1073 | EndIf 1074 | 1075 | ClipPut($FirefoxURL) 1076 | Local $msg = MsgBox(65, "RunFirefox", _t("ManuallyDownloadMessage", '请下载 Firefox 安装包,用 WinRAR、7z 等解压软件打开安装包,\n将其中的 core 文件夹提取出来,即得到 Firefox 便携版所需的程序文件。\n\n下载地址已复制到剪贴板,点击"确定"将在浏览器中打开下载页面。'), 0, $hSettings) 1077 | If $msg = 1 Then 1078 | ShellExecute($FirefoxURL) 1079 | EndIf 1080 | EndFunc ;==>DownloadFirefox 1081 | 1082 | Func RunInBackground() 1083 | If GUICtrlRead($hRunInBackground) = $GUI_CHECKED Then 1084 | Return 1085 | EndIf 1086 | Local $msg = MsgBox(36 + 256, "RunFirefox", '允许 RunFirefox 在后台运行可以带来更好的用户体验。若取消此选项,请注意以下几点:\n\n 1. 将浏览器锁定到任务栏或设为默认浏览器后,需再运行一次 RunFirefox 才能生效;\n2. RunFirefox 设置界面中带“#”符号的功能/选项将不会执行,包括浏览器退出后关闭外部程序、运行外部程序等。\n\n确定要取消此选项吗?', 0, $hSettings) 1087 | If $msg <> 6 Then 1088 | GUICtrlSetState($hRunInBackground, $GUI_CHECKED) 1089 | EndIf 1090 | EndFunc ;==>RunInBackground 1091 | 1092 | ;~ 设置界面取消 1093 | Func ExitApp() 1094 | Exit 1095 | EndFunc ;==>ExitApp 1096 | 1097 | ;~ 设置界面确定按钮 1098 | Func SettingsOK() 1099 | SettingsApply() 1100 | If @error Then Return 1101 | $SettingsOK = 1 1102 | EndFunc ;==>SettingsOK 1103 | 1104 | 1105 | 1106 | ;~ 设置界面应用按钮 1107 | Func SettingsApply() 1108 | Local $msg, $var 1109 | FileChangeDir(@ScriptDir) 1110 | 1111 | Opt("ExpandEnvStrings", 0) 1112 | $FirefoxPath = RelativePath(GUICtrlRead($hFirefoxPath)) 1113 | 1114 | If GUICtrlRead($hAllowBrowserUpdate) = $GUI_CHECKED Then 1115 | $AllowBrowserUpdate = 1 1116 | Else 1117 | $AllowBrowserUpdate = 0 1118 | EndIf 1119 | $ProfileDir = RelativePath(GUICtrlRead($hProfileDir)) 1120 | $CustomPluginsDir = RelativePath(GUICtrlRead($hCustomPluginsDir)) 1121 | $CustomCacheDir = RelativePath(GUICtrlRead($hCustomCacheDir)) 1122 | $CacheSize = GUICtrlRead($hCacheSize) 1123 | If GUICtrlRead($hCacheSizeSmart) = $GUI_CHECKED Then 1124 | $CacheSizeSmart = 1 1125 | Else 1126 | $CacheSizeSmart = 0 1127 | EndIf 1128 | $var = GUICtrlRead($hParams) 1129 | $var = StringStripWS($var, 3) 1130 | $Params = StringReplace($var, @CRLF, " ") ; 换行符换成空格 1131 | If GUICtrlRead($hCheckAppUpdate) = $GUI_CHECKED Then 1132 | $CheckAppUpdate = 1 1133 | Else 1134 | $CheckAppUpdate = 0 1135 | EndIf 1136 | If GUICtrlRead($hRunInBackground) = $GUI_CHECKED Then 1137 | $RunInBackground = 1 1138 | Else 1139 | $RunInBackground = 0 1140 | EndIf 1141 | Local $var = GUICtrlRead($hExApp) 1142 | $var = StringStripWS($var, 3) 1143 | $var = StringReplace($var, @CRLF, "||") 1144 | $var = StringRegExpReplace($var, "\|+\s*\|+", "\|\|") 1145 | $ExApp = $var 1146 | If GUICtrlRead($hExAppAutoExit) = $GUI_CHECKED Then 1147 | $ExAppAutoExit = 1 1148 | Else 1149 | $ExAppAutoExit = 0 1150 | EndIf 1151 | $var = GUICtrlRead($hExApp2) 1152 | $var = StringStripWS($var, 3) 1153 | $var = StringReplace($var, @CRLF, "||") 1154 | $var = StringRegExpReplace($var, "\|+\s*\|+", "\|\|") 1155 | $ExApp2 = $var 1156 | 1157 | IniWrite($inifile, "Settings", "CheckAppUpdate", $CheckAppUpdate) 1158 | IniWrite($inifile, "Settings", "RunInBackground", $RunInBackground) 1159 | IniWrite($inifile, "Settings", "AllowBrowserUpdate", $AllowBrowserUpdate) 1160 | IniWrite($inifile, "Settings", "FirefoxPath", $FirefoxPath) 1161 | IniWrite($inifile, "Settings", "ProfileDir", $ProfileDir) 1162 | IniWrite($inifile, "Settings", "CustomPluginsDir", $CustomPluginsDir) 1163 | IniWrite($inifile, "Settings", "CustomCacheDir", $CustomCacheDir) 1164 | IniWrite($inifile, "Settings", "CacheSize", $CacheSize) 1165 | IniWrite($inifile, "Settings", "CacheSizeSmart", $CacheSizeSmart) 1166 | IniWrite($inifile, "Settings", "Params", $Params) 1167 | $var = $ExApp 1168 | If StringRegExp($var, '^".*"$') Then $var = '"' & $var & '"' 1169 | IniWrite($inifile, "Settings", "ExApp", $var) 1170 | IniWrite($inifile, "Settings", "ExAppAutoExit", $ExAppAutoExit) 1171 | $var = $ExApp2 1172 | If StringRegExp($var, '^".*"$') Then $var = '"' & $var & '"' 1173 | IniWrite($inifile, "Settings", "ExApp2", $var) 1174 | 1175 | Opt("ExpandEnvStrings", 1) 1176 | 1177 | ;Firefox path 1178 | If Not FileExists($FirefoxPath) Then 1179 | MsgBox(16, "RunFirefox", _t("FirefoxPathErrorMessage", "Firefox 路径错误,请重新设置。\n\n%s", $FirefoxPath), 0, $hSettings) 1180 | GUICtrlSetState($hFirefoxPath, $GUI_FOCUS) 1181 | Return SetError(1) 1182 | EndIf 1183 | 1184 | Local $ChannelString = GUICtrlRead($hChannel) 1185 | Local $Channel = StringRegExpReplace($ChannelString, " -.*", "") 1186 | Local $ChannelPath = StringRegExpReplace($FirefoxPath, "\\?[^\\]+$", "") & "\defaults\pref\channel-prefs.js" 1187 | Local $var = FileRead($ChannelPath) 1188 | If Not StringInStr($var, 'pref("app.update.channel", "' & $Channel & '");') Then 1189 | FileDelete($ChannelPath) 1190 | FileWrite($ChannelPath, '// Changed by RunFirefox' & @CRLF & 'pref("app.update.channel", "' & $Channel & '");' & @CRLF) 1191 | EndIf 1192 | 1193 | ;profiles dir 1194 | If $ProfileDir = "" Then 1195 | MsgBox(16, "RunFirefox", _t("PleaseProfileFolder", "请设置配置文件夹!"), 0, $hSettings) 1196 | GUICtrlSetState($hProfileDir, $GUI_FOCUS) 1197 | Return SetError(2) 1198 | ElseIf Not FileExists($ProfileDir) Then 1199 | DirCreate($ProfileDir) 1200 | EndIf 1201 | 1202 | ; 提取Firefox原版配置文件 1203 | If GUICtrlRead($hCopyProfile) = $GUI_CHECKED Then 1204 | While ProfileInUse($ProfileDir) 1205 | $msg = MsgBox(49, "RunFirefox", _t("CannotExtratProfileFromSystem", "浏览器正运行,无法提取配置文件!\n请关闭 Firefox 后继续。"), 0, $hSettings) 1206 | If $msg <> 1 Then ExitLoop 1207 | WEnd 1208 | If $msg = 1 Then 1209 | SplashTextOn("RunFirefox", _t("ExtractingProfile", "正在提取配置文件,请稍候 ..."), 300, 100) 1210 | Local $var = DirCopy($DefaultProfDir, $ProfileDir, 1) 1211 | SplashOff() 1212 | If $var Then 1213 | _GUICtrlStatusBar_SetText($hStatus, _t("ExtractProfileSuccess", "提取配置文件成功!")) 1214 | Else 1215 | _GUICtrlStatusBar_SetText($hStatus, _t("ExtractProfileFailed", "提取配置文件失败!")) 1216 | EndIf 1217 | EndIf 1218 | GUICtrlSetState($hCopyProfile, $GUI_UNCHECKED) 1219 | EndIf 1220 | 1221 | ; plugins dir 1222 | If $CustomPluginsDir <> "" And Not FileExists($CustomPluginsDir) Then 1223 | DirCreate($CustomPluginsDir) 1224 | EndIf 1225 | EndFunc ;==>SettingsApply 1226 | 1227 | ;~ 打开网站 1228 | Func Website() 1229 | ShellExecute("https://github.com/benzBrake/RunFirefox") 1230 | EndFunc ;==>Website 1231 | 1232 | ;~ 打开原版网站 1233 | Func OriginalWebsite() 1234 | ShellExecute("https://github.com/cnjackchen/my-firefox") 1235 | EndFunc ;==>Website 1236 | 1237 | ;~ 查找Firefox主程序 1238 | Func GetFirefoxPath() 1239 | Local $path = FileOpenDialog(_t("ChooseFirefoxExecutable", "选择浏览器主程序(firefox.exe)"), @ScriptDir, _t("ExecutableFile", "可执行文件(*.exe)"), 1 + 2, "firefox.exe", $hSettings) 1240 | FileChangeDir(@ScriptDir) ; FileOpenDialog 会改变 @workingdir,将它改回来 1241 | If $path = "" Then Return 1242 | $FirefoxPath = RelativePath($path) 1243 | GUICtrlSetData($hFirefoxPath, $FirefoxPath) 1244 | OnFirefoxPathChange() 1245 | EndFunc ;==>GetFirefoxPath 1246 | 1247 | ;~ 指定配置文件夹 1248 | Func GetProfileDir() 1249 | Local $dir = FileSelectFolder(_t("SpecifyProfileDirectory", "指定 Firefox 配置文件夹"), "", 1 + 4, @ScriptDir, $hSettings) 1250 | FileChangeDir(@ScriptDir) 1251 | If $dir = "" Then Return 1252 | $ProfileDir = RelativePath($dir) 1253 | GUICtrlSetData($hProfileDir, $ProfileDir) 1254 | EndFunc ;==>GetProfileDir 1255 | 1256 | ;~ 指定插件目录 1257 | Func GetPluginsDir() 1258 | Local $dir = FileSelectFolder(_t("SpecifyPluginsDirectory", "指定 Firefox 插件目录"), "", 1 + 4, @ScriptDir, $hSettings) 1259 | FileChangeDir(@ScriptDir) 1260 | If $dir = "" Then Return 1261 | $CustomPluginsDir = RelativePath($dir) 1262 | GUICtrlSetData($hCustomPluginsDir, $CustomPluginsDir) 1263 | EndFunc ;==>GetPluginsDir 1264 | 1265 | ;~ 指定缓存位置 1266 | Func GetCacheDir() 1267 | Local $dir = FileSelectFolder(_t("SpecifyCacheDirectory", "指定 Firefox 缓存文件夹"), "", 1 + 4, @ScriptDir, $hSettings) 1268 | FileChangeDir(@ScriptDir) 1269 | If $dir = "" Then Return 1270 | $CustomCacheDir = RelativePath($dir) 1271 | GUICtrlSetData($hCustomCacheDir, $CustomCacheDir) 1272 | EndFunc ;==>GetCacheDir 1273 | 1274 | ;~ 判断配置文件是否正在使用 1275 | ;~ 参考:http://kb.mozillazine.org/Profile_in_use 1276 | Func ProfileInUse($ProfDir) 1277 | Return FileExists($ProfDir & "\parent.lock") And Not FileDelete($ProfDir & "\parent.lock") 1278 | EndFunc ;==>ProfileInUse 1279 | 1280 | ; #FUNCTION# ;=============================================================================== 1281 | ; Name...........: SplitPath 1282 | ; Description ...: 路径分割 1283 | ; Syntax.........: SplitPath($path, ByRef $dir, ByRef $file, [...$spliter]) 1284 | ; $path - 路径 1285 | ; $dir - 目录 1286 | ; $file - 文件名 1287 | ; Return values .: Success - 1288 | ; Failure - 1289 | ; Author ........: 甲壳虫 1290 | ; Mode ..........: Ryan 1291 | ;============================================================================================ 1292 | Func SplitPath($path, ByRef $dir, ByRef $file, $spliter = "\") 1293 | Local $pos = StringInStr($path, $spliter, 0, -1) 1294 | If $pos = 0 Then 1295 | $dir = "." 1296 | $file = $path 1297 | Else 1298 | $dir = StringLeft($path, $pos - 1) 1299 | $file = StringMid($path, $pos + 1) 1300 | EndIf 1301 | EndFunc ;==>SplitPath 1302 | 1303 | ;~ 绝对路径转成相对于脚本目录的相对路径, 1304 | ;~ 如 .\dir1\dir2 或 ..\dir2 1305 | Func RelativePath($path) 1306 | If $path = "" Then Return $path 1307 | If StringLeft($path, 1) = "%" Then Return $path 1308 | If Not StringInStr($path, ":") And StringLeft($path, 2) <> "\\" Then Return $path 1309 | If StringLeft(@ScriptDir, 3) <> StringLeft($path, 3) Then Return $path ; different driver 1310 | If StringRight($path, 1) <> "\" Then $path &= "\" 1311 | Local $r = '.\' 1312 | Local $pos, $dir = @ScriptDir & "\" 1313 | While 1 1314 | $path = StringReplace($path, $dir, $r) 1315 | If @extended Then ExitLoop 1316 | $pos = StringInStr($dir, "\", 0, -2) 1317 | If $pos = 0 Then ExitLoop 1318 | $dir = StringLeft($dir, $pos) 1319 | If StringLeft($r, 2) = '.\' Then 1320 | $r = '..\' 1321 | Else 1322 | $r = '..\' & $r 1323 | EndIf 1324 | WEnd 1325 | If StringRight($path, 1) = "\" Then $path = StringTrimRight($path, 1) 1326 | Return $path 1327 | EndFunc ;==>RelativePath 1328 | 1329 | ;~ 相对于脚本目录的相对路径转换成绝对路径,输出结果结尾没有 “\”。 1330 | Func FullPath($path) 1331 | If $path = "" Then Return $path 1332 | If StringLeft($path, 1) = "%" Then Return $path 1333 | If StringInStr($path, ":\") Or StringLeft($path, 2) = "\\" Then Return $path 1334 | If StringRight($path, 1) <> "\" Then $path &= "\" 1335 | Local $dir = @ScriptDir 1336 | If StringLeft($path, 2) = ".\" Then 1337 | $path = StringReplace($path, '.', $dir, 1) 1338 | ElseIf StringLeft($path, 3) <> "..\" Then 1339 | $path = $dir & "\" & $path 1340 | Else 1341 | Local $i, $n, $pos 1342 | $path = StringReplace($path, "..\", "") 1343 | $n = @extended 1344 | For $i = 1 To $n 1345 | $pos = StringInStr($dir, "\", 0, -1) 1346 | If $pos = 0 Then ExitLoop 1347 | $dir = StringLeft($dir, $pos - 1) 1348 | Next 1349 | $path = $dir & "\" & $path 1350 | EndIf 1351 | If StringRight($path, 1) = "\" Then $path = StringTrimRight($path, 1) 1352 | Return $path 1353 | EndFunc ;==>FullPath 1354 | 1355 | ;~ 函数。整理内存 1356 | ;~ http://www.autoitscript.com/forum/index.php?showtopic=13399&hl=GetCurrentProcessId&st=20 1357 | Func ReduceMemory() 1358 | Local $ai_Handle = DllCall("kernel32.dll", 'int', 'OpenProcess', 'int', 0x1f0fff, 'int', False, 'int', @AutoItPID) 1359 | Local $ai_Return = DllCall("psapi.dll", 'int', 'EmptyWorkingSet', 'long', $ai_Handle[0]) 1360 | DllCall('kernel32.dll', 'int', 'CloseHandle', 'int', $ai_Handle[0]) 1361 | Return $ai_Return[0] 1362 | EndFunc ;==>ReduceMemory 1363 | 1364 | ; #FUNCTION# ;=============================================================================== 1365 | ; 参考 http://www.autoitscript.com/forum/topic/63947-read-full-exe-path-of-a-known-windowprogram/ 1366 | ; Name...........: GetProcPath 1367 | ; Description ...: 取得进程路径 1368 | ; Syntax.........: GetProcPath($Process_PID) 1369 | ; Parameters ....: $Process_PID - 进程的 pid 1370 | ; Return values .: Success - 完整路径 1371 | ; Failure - set @error 1372 | ;============================================================================================ 1373 | Func GetProcPath($pid = @AutoItPID) 1374 | If @OSArch <> "X86" And Not @AutoItX64 And Not _WinAPI_IsWow64Process($pid) Then ; much slow than dllcall method 1375 | Local $colItems = "" 1376 | Local $objWMIService = ObjGet("winmgmts:\\localhost\root\CIMV2") 1377 | $colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_Process WHERE ProcessId = " & $pid, "WQL", _ 1378 | 0x10 + 0x20) 1379 | If IsObj($colItems) Then 1380 | For $objItem In $colItems 1381 | If $objItem.ExecutablePath Then Return $objItem.ExecutablePath 1382 | Next 1383 | EndIf 1384 | Return "" 1385 | Else 1386 | Local $hProcess = DllCall('kernel32.dll', 'ptr', 'OpenProcess', 'dword', BitOR(0x0400, 0x0010), 'int', 0, 'dword', $pid) 1387 | If (@error) Or (Not $hProcess[0]) Then Return SetError(1, 0, '') 1388 | Local $ret = DllCall(@SystemDir & '\psapi.dll', 'int', 'GetModuleFileNameExW', 'ptr', $hProcess[0], 'ptr', 0, 'wstr', '', 'int', 1024) 1389 | If (@error) Or (Not $ret[0]) Then Return SetError(1, 0, '') 1390 | Return $ret[3] 1391 | EndIf 1392 | EndFunc ;==>GetProcPath 1393 | 1394 | ; #FUNCTION# ==================================================================================================================== 1395 | ; Name...........: _GUICtrlComboBox_SelectString 1396 | ; Description ...: Searches the ListBox of a ComboBox for an item that begins with the characters in a specified string 1397 | ; Syntax.........: _GUICtrlComboBox_SelectString($hWnd, $sText[, $iIndex = -1]) 1398 | ; Parameters ....: $hWnd - Handle to control 1399 | ; $sText - String that contains the characters for which to search 1400 | ; $iIndex - Specifies the zero-based index of the item preceding the first item to be searched 1401 | ; Return values .: Success - The index of the selected item 1402 | ; Failure - -1 1403 | ; Author ........: Gary Frost (gafrost) 1404 | ; Modified.......: 1405 | ; Remarks .......: When the search reaches the bottom of the list, it continues from the top of the list back to the 1406 | ; item specified by the wParam parameter. 1407 | ;+ 1408 | ; If $iIndex is ?, the entire list is searched from the beginning. 1409 | ; A string is selected only if the characters from the starting point match the characters in the 1410 | ; prefix string 1411 | ;+ 1412 | ; If a matching item is found, it is selected and copied to the edit control 1413 | ; Related .......: _GUICtrlComboBox_FindString, _GUICtrlComboBox_FindStringExact, _GUICtrlComboBoxEx_FindStringExact 1414 | ; Link ..........: 1415 | ; Example .......: Yes 1416 | ; =============================================================================================================================== 1417 | Func _GUICtrlComboBox_SelectString($hWnd, $sText, $iIndex = -1) 1418 | ;~ If $Debug_CB Then __UDF_ValidateClassName($hWnd, $__COMBOBOXCONSTANT_ClassName) 1419 | If Not IsHWnd($hWnd) Then $hWnd = GUICtrlGetHandle($hWnd) 1420 | 1421 | Return _SendMessage($hWnd, $CB_SELECTSTRING, $iIndex, $sText, 0, "wparam", "wstr") 1422 | EndFunc ;==>_GUICtrlComboBox_SelectString 1423 | 1424 | 1425 | ; #FUNCTION# ==================================================================================================================== 1426 | ; Name ..........: _IsUACAdmin 1427 | ; Description ...: Determines if process has Admin privileges and whether running under UAC. 1428 | ; Syntax ........: _IsUACAdmin() 1429 | ; Parameters ....: None 1430 | ; Return values .: Success - 1 - User has full Admin rights (Elevated Admin w/ UAC) 1431 | ; Failure - 0 - User is not an Admin, sets @extended: 1432 | ; | 0 - User cannot elevate 1433 | ; | 1 - User can elevate 1434 | ; Author ........: Erik Pilsits 1435 | ; Modified ......: 1436 | ; Remarks .......: THE GOOD STUFF: returns 0 w/ @extended = 1 > UAC Protected Admin 1437 | ; Related .......: 1438 | ; Link ..........: 1439 | ; Example .......: No 1440 | ; =============================================================================================================================== 1441 | Func _IsUACAdmin() 1442 | If StringRegExp(@OSVersion, "_(XP|2003)") Or RegRead("HKLM64\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System", "EnableLUA") <> 1 Then 1443 | Return SetExtended(0, IsAdmin()) 1444 | EndIf 1445 | 1446 | Local $hToken = _Security__OpenProcessToken(_WinAPI_GetCurrentProcess(), $TOKEN_QUERY) 1447 | Local $tTI = _Security__GetTokenInformation($hToken, $TOKENGROUPS) 1448 | _WinAPI_CloseHandle($hToken) 1449 | 1450 | Local $pTI = DllStructGetPtr($tTI) 1451 | Local $cbSIDATTR = DllStructGetSize(DllStructCreate("ptr;dword")) 1452 | Local $count = DllStructGetData(DllStructCreate("dword", $pTI), 1) 1453 | Local $pGROUP1 = DllStructGetPtr(DllStructCreate("dword;STRUCT;ptr;dword;ENDSTRUCT", $pTI), 2) 1454 | Local $tGROUP, $sGROUP = "" 1455 | 1456 | ; S-1-5-32-544 > BUILTINAdministrators > $SID_ADMINISTRATORS 1457 | ; S-1-16-8192 > Mandatory LabelMedium Mandatory Level (Protected Admin) > $SID_MEDIUM_MANDATORY_LEVEL 1458 | ; S-1-16-12288 > Mandatory LabelHigh Mandatory Level (Elevated Admin) > $SID_HIGH_MANDATORY_LEVEL 1459 | ; SE_GROUP_USE_FOR_DENY_ONLY = 0x10 1460 | 1461 | Local $inAdminGrp = False, $denyAdmin = False, $elevatedAdmin = False, $sSID 1462 | For $i = 0 To $count - 1 1463 | $tGROUP = DllStructCreate("ptr;dword", $pGROUP1 + ($cbSIDATTR * $i)) 1464 | $sSID = _Security__SidToStringSid(DllStructGetData($tGROUP, 1)) 1465 | If StringInStr($sSID, "S-1-5-32-544") Then ; member of Administrators group 1466 | $inAdminGrp = True 1467 | ; check for deny attribute 1468 | If (BitAND(DllStructGetData($tGROUP, 2), 0x10) = 0x10) Then $denyAdmin = True 1469 | ElseIf StringInStr($sSID, "S-1-16-12288") Then 1470 | $elevatedAdmin = True 1471 | EndIf 1472 | Next 1473 | 1474 | If $inAdminGrp Then 1475 | ; check elevated 1476 | If $elevatedAdmin Then 1477 | ; check deny status 1478 | If $denyAdmin Then 1479 | ; protected Admin CANNOT elevate 1480 | Return SetExtended(0, 0) 1481 | Else 1482 | ; elevated Admin 1483 | Return SetExtended(1, 1) 1484 | EndIf 1485 | Else 1486 | ; protected Admin 1487 | Return SetExtended(1, 0) 1488 | EndIf 1489 | Else 1490 | ; not an Admin 1491 | Return SetExtended(0, 0) 1492 | EndIf 1493 | EndFunc ;==>_IsUACAdmin 1494 | 1495 | ; Return $v1 - $v1 1496 | Func VersionCompare($v1, $v2) 1497 | Local $i, $a1, $a2, $ret = 0 1498 | $a1 = StringSplit($v1, ".", 2) 1499 | $a2 = StringSplit($v2, ".", 2) 1500 | If UBound($a1) > UBound($a2) Then 1501 | ReDim $a2[UBound($a1)] 1502 | Else 1503 | ReDim $a1[UBound($a2)] 1504 | EndIf 1505 | For $i = 0 To UBound($a1) - 1 1506 | $ret = $a1[$i] - $a2[$i] 1507 | If $ret <> 0 Then ExitLoop 1508 | Next 1509 | Return $ret 1510 | EndFunc ;==>VersionCompare 1511 | 1512 | 1513 | ; https://www.autoitscript.com/forum/topic/73425-zipau3-udf-in-pure-autoit/ 1514 | ; https://www.autoitscript.com/forum/topic/116565-zip-udf-zipfldrdll-library/ 1515 | ; #FUNCTION# ==================================================================================================== 1516 | ; Name...........: _Zip_UnzipAll 1517 | ; Description....: Extract all files contained in a ZIP archive 1518 | ; Syntax.........: _Zip_UnzipAll($sZipFile, $sDestPath[, $iFlag = 20]) 1519 | ; Parameters.....: $sZipFile - Full path to ZIP file 1520 | ; $sDestPath - Full path to the destination 1521 | ; $iFlag - [Optional] File copy flags (Default = 4+16) 1522 | ; | 4 - No progress box 1523 | ; | 8 - Rename the file if a file of the same name already exists 1524 | ; | 16 - Respond "Yes to All" for any dialog that is displayed 1525 | ; | 64 - Preserve undo information, if possible 1526 | ; | 256 - Display a progress dialog box but do not show the file names 1527 | ; | 512 - Do not confirm the creation of a new directory if the operation requires one to be created 1528 | ; |1024 - Do not display a user interface if an error occurs 1529 | ; |2048 - Version 4.71. Do not copy the security attributes of the file 1530 | ; |4096 - Only operate in the local directory, don't operate recursively into subdirectories 1531 | ; |8192 - Version 5.0. Do not copy connected files as a group, only copy the specified files 1532 | ; 1533 | ; Return values..: Success - 1 1534 | ; Failure - 0 and sets @error 1535 | ; | 1 - zipfldr.dll does not exist 1536 | ; | 2 - Library not installed 1537 | ; | 3 - Not a full path 1538 | ; | 4 - ZIP file does not exist 1539 | ; | 5 - Failed to create destination (if necessary) 1540 | ; | 6 - Failed to extract file(s) 1541 | ; Author.........: wraithdu, torels 1542 | ; Modified.......: 1543 | ; Remarks........: Overwriting of destination files is controlled solely by the file copy flags (ie $iFlag = 1 is NOT valid). 1544 | ; Related........: 1545 | ; Link...........: 1546 | ; Example........: 1547 | ; =============================================================================================================== 1548 | Func _Zip_UnzipAll($sZipFile, $sDestPath, $flag = 20) 1549 | If Not FileExists(@SystemDir & "\zipfldr.dll") Then Return SetError(1, 0, 0) 1550 | If Not RegRead("HKCR\CLSID\{E88DCCE0-B7B3-11d1-A9F0-00AA0060FA31}", "") Then Return SetError(2, 0, 0) 1551 | 1552 | If Not StringInStr($sZipFile, ":\") Then Return SetError(3, 0) ;zip file isn't a full path 1553 | If Not FileExists($sZipFile) Then Return SetError(4, 0, 0) ;no zip file 1554 | If Not FileExists($sDestPath) Then 1555 | DirCreate($sDestPath) 1556 | If @error Then Return SetError(5, 0, 0) 1557 | EndIf 1558 | 1559 | Local $aArray[1] 1560 | $oApp = ObjCreate("Shell.Application") 1561 | $oNs = $oApp.Namespace($sZipFile) 1562 | $oApp.Namespace($sDestPath).CopyHere($oNs.Items, $flag) 1563 | 1564 | If FileExists($sDestPath & "\" & $oNs.Items().Item($oNs.Items().Count - 1).Name) Then 1565 | ; success... most likely 1566 | ; checks for existence of last item from source in destination 1567 | Return 1 1568 | Else 1569 | ; failure 1570 | Return SetError(6, 0, 0) 1571 | EndIf 1572 | EndFunc ;==>_Zip_UnzipAll 1573 | 1574 | ; 切换自动更新状态 1575 | Func ChangeAutoUpdateStatus() 1576 | 1577 | EndFunc 1578 | 1579 | ; 语言检测 1580 | Func _GetLangFile() 1581 | Local $filePath = @ScriptDir & "\" & "Lang.ini" 1582 | Local $fileCustomPath = @ScriptDir & "\" & "LangCustom.ini" 1583 | FileInstall("Lang.ini", $filePath, 1) 1584 | If FileExists($fileCustomPath) Then 1585 | $filePath = $fileCustomPath 1586 | EndIf 1587 | Return $filePath 1588 | EndFunc ;==>_GetLangFile 1589 | 1590 | ; 获取语言支持 1591 | Func _GetLanguages() 1592 | Local $LDic = _InitDictionary() 1593 | If $LANG_FILE Then 1594 | Local $langs = IniReadSectionNames($LANG_FILE) 1595 | If Not @error Then 1596 | For $i = 1 To $langs[0] ; 第一个参数存放长度 1597 | local $title = IniRead($LANG_FILE, $langs[$i], "LangTitle", $langs[$i]) 1598 | _AddItem($LDic, $langs[$i], $title) 1599 | Next 1600 | EndIf 1601 | EndIf 1602 | If _ItemExists($LDic, "zh-CN") = False Then 1603 | _AddItem($LDic, "zh-CN", "简体中文"); 1604 | EndIf 1605 | Return $LDic 1606 | EndFunc 1607 | 1608 | ; 获取翻译文本 1609 | Func _t($key, $defaultString, $replaceString = "") 1610 | local $str = $defaultString; 1611 | If $LANG_FILE Then 1612 | If $LANGUAGE <> "zh-CN" Then 1613 | $str = IniRead($LANG_FILE, $LANGUAGE, $key, $defaultString); 1614 | Else 1615 | $str = $defaultString 1616 | EndIf 1617 | EndIf 1618 | $str = StringReplace($str, "{AppName}", $CustomArch) 1619 | $str = StringReplace($str, "{ScriptName}", @ScriptName) 1620 | If ($replaceString <> "") Then 1621 | $str = StringFormat($str, $replaceString) 1622 | EndIf 1623 | Return StringReplace($str, "\n", @CRLF) ; 换行符号处理 1624 | EndFunc ;==>_t 1625 | 1626 | ; 更换语言 Thanks MyChrome 1627 | Func ChangeLanguage() 1628 | $newLang = SaveLang(); 1629 | If $newLang <> $LANGUAGE Then 1630 | $LANGUAGE = $newLang 1631 | MsgBox(64, $CustomArch, _t("RestartToApplyLanguage", "语言设置将在重启 {AppName} 后生效")) 1632 | GUIDelete($hSettings) 1633 | If @Compiled Then 1634 | ShellExecute(@ScriptName, "-Set", @ScriptDir) 1635 | Else 1636 | ShellExecute(@AutoItExe, '"' & @ScriptFullPath & '" -Set', @ScriptDir) 1637 | EndIf 1638 | EndIf 1639 | EndFunc ;==>ChangeLanguage 1640 | ; 保存语言 1641 | Func SaveLang() 1642 | local $slang = GUICtrlRead($hlanguage), $index = -1, $keys = $LANGUAGES.Keys, $newLang = "" 1643 | For $i = 0 To UBound($keys) - 1 1644 | Local $key = $keys[$i] 1645 | if _Item($LANGUAGES, $key) = $sLang Then 1646 | $index = $i 1647 | EndIf 1648 | Next 1649 | 1650 | If ($index <> -1) Then 1651 | $newLang = $keys[$index] 1652 | IniWrite($inifile, "Settings", "Language", $newLang) 1653 | EndIf 1654 | Return $newLang 1655 | EndFunc ;==>SaveLang -------------------------------------------------------------------------------- /icons/FireDoge.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benzBrake/RunFirefox/423b1c50c1e1ed2ab846f59f8767777d09749b09/icons/FireDoge.ico -------------------------------------------------------------------------------- /icons/Firefox.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benzBrake/RunFirefox/423b1c50c1e1ed2ab846f59f8767777d09749b09/icons/Firefox.ico -------------------------------------------------------------------------------- /icons/Floorp.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benzBrake/RunFirefox/423b1c50c1e1ed2ab846f59f8767777d09749b09/icons/Floorp.ico -------------------------------------------------------------------------------- /icons/LibreWolf.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benzBrake/RunFirefox/423b1c50c1e1ed2ab846f59f8767777d09749b09/icons/LibreWolf.ico -------------------------------------------------------------------------------- /icons/Mercury.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benzBrake/RunFirefox/423b1c50c1e1ed2ab846f59f8767777d09749b09/icons/Mercury.ico -------------------------------------------------------------------------------- /icons/WaterFox.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benzBrake/RunFirefox/423b1c50c1e1ed2ab846f59f8767777d09749b09/icons/WaterFox.ico -------------------------------------------------------------------------------- /icons/ZenBrowser.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benzBrake/RunFirefox/423b1c50c1e1ed2ab846f59f8767777d09749b09/icons/ZenBrowser.ico -------------------------------------------------------------------------------- /libs/AppUserModelId.au3: -------------------------------------------------------------------------------- 1 | #include-once 2 | ; file name: AppUserModelId.au3 3 | 4 | ; #### Title #### 5 | ; ================================================================================ 6 | ; Get / Set AppUserModelId for a window or a shortcut file(*.lnk) 7 | ; Thanks to binhnx, LarsJ and others 8 | ; - jackchen 9 | ; ================================================================================ 10 | 11 | ; #### FUNCTIONS #### 12 | ; ================================================================================ 13 | ; _WindowAppId 14 | ; _ShortcutAppId 15 | ; ================================================================================ 16 | 17 | #include 18 | 19 | #Region ====================== #### CONSTANTS #### ====================== 20 | ; https://www.autoitscript.com/forum/topic/161067-get-clsid-from-iid/ 21 | Global Const $CLSID_ShellLink = "{00021401-0000-0000-C000-000000000046}" 22 | Global Const $sIID_IShellLinkW = "{000214F9-0000-0000-C000-000000000046}" 23 | Global Const $tag_IShellLinkW = _ 24 | "GetPath hresult(long;long;long;long);" & _ 25 | "GetIDList hresult(long);" & _ 26 | "SetIDList hresult(long);" & _ 27 | "GetDescription hresult(long;long);" & _ 28 | "SetDescription hresult(wstr);" & _ 29 | "GetWorkingDirectory hresult(long;long);" & _ 30 | "SetWorkingDirectory hresult(long;long);" & _ 31 | "GetArguments hresult(long;long);" & _ 32 | "SetArguments hresult(ptr);" & _ 33 | "GetHotkey hresult(long);" & _ 34 | "SetHotkey hresult(word);" & _ 35 | "GetShowCmd hresult(long);" & _ 36 | "SetShowCmd hresult(int);" & _ 37 | "GetIconLocation hresult(long;long;long);" & _ 38 | "SetIconLocation hresult(wstr;int);" & _ 39 | "SetRelativePath hresult(long;long);" & _ 40 | "Resolve hresult(long;long);" & _ 41 | "SetPath hresult(wstr);" 42 | 43 | Global Const $tag_IPersist = "GetClassID hresult(long);" 44 | Global Const $sIID_IPersistFile = "{0000010b-0000-0000-C000-000000000046}" 45 | Global Const $tag_IPersistFile = $tag_IPersist & _ ; Inherits from IPersist 46 | "IsDirty hresult();" & _ 47 | "Load hresult(wstr;dword);" & _ 48 | "Save hresult(wstr;bool);" & _ 49 | "SaveCompleted hresult(long);" & _ 50 | "GetCurFile hresult(long);" 51 | 52 | ; https://msdn.microsoft.com/en-us/library/windows/desktop/aa380337(v=vs.85).aspx 53 | Global Const $STGM_READ = 0x00000000 54 | Global Const $STGM_READWRITE = 0x00000002 55 | Global Const $STGM_SHARE_DENY_NONE = 0x00000040 56 | 57 | ; Global Const $tagPROPERTYKEY = $tagGUID & ';DWORD pid' 58 | Global Const $tagPROPERTYKEY = 'struct;ulong Data1;ushort Data2;ushort Data3;byte Data4[8];DWORD pid;endstruct' 59 | Global $tagPROPVARIANT = _ 60 | 'USHORT vt;' & _ ;typedef unsigned short VARTYPE; - in WTypes.h 61 | 'WORD wReserved1;' & _ 62 | 'WORD wReserved2;' & _ 63 | 'WORD wReserved3;' & _ 64 | 'LONG;PTR' ;union, use the largest member (BSTRBLOB, which is 96-bit in x64) 65 | 66 | Global Const $sIID_IPropertyStore = '{886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99}' 67 | Global Const $VT_EMPTY = 0, $VT_LPWSTR = 31 68 | #EndRegion ====================== #### CONSTANTS #### ====================== 69 | 70 | 71 | ; #FUNCTION# ;=============================================================================== 72 | ; Name...........: _WindowAppId 73 | ; Description ...: Get / Set AppUerModelId(AppId) of a window 74 | ; Syntax.........: _WindowAppId($hWnd, $appid = Default) 75 | ; Parameters ....: $hWnd - Handle of a window. 76 | ; $appid - [optional] AppId to set. 77 | ; Return values .: Success - Returns current AppId 78 | ; Failure - Returns "" and sets @error: 79 | ; Author ........: binhnx, jackchen 80 | ; Link ..........: https://www.autoitscript.com/forum/topic/168099-how-to-prevent-multiple-guis-from-combining-in-the-taskbar/ 81 | ;============================================================================================ 82 | Func _WindowAppId($hWnd, $appid = Default) 83 | Local $tpIPropertyStore = DllStructCreate('ptr') 84 | _WinAPI_SHGetPropertyStoreForWindow($hWnd, $sIID_IPropertyStore, $tpIPropertyStore) 85 | Local $pPropertyStore = DllStructGetData($tpIPropertyStore, 1) 86 | Local $oPropertyStore = ObjCreateInterface($pPropertyStore, $sIID_IPropertyStore, _ 87 | 'GetCount HRESULT(PTR);GetAt HRESULT(DWORD; PTR);GetValue HRESULT(PTR;PTR);' & _ 88 | 'SetValue HRESULT(PTR;PTR);Commit HRESULT()') 89 | If Not IsObj($oPropertyStore) Then Return SetError(1, 0, '') 90 | 91 | Local $tPKEY = _PKEY_AppUserModel_ID() 92 | Local $tPROPVARIANT = DllStructCreate($tagPROPVARIANT) 93 | Local $sAppId 94 | If $appid = Default Then 95 | $oPropertyStore.GetValue(DllStructGetPtr($tPKEY), DllStructGetPtr($tPROPVARIANT)) 96 | ; Extracts a string value from a PROPVARIANT structure 97 | ; http://deletethis.net/dave/dev/setappusermodelid/ 98 | ; https://msdn.microsoft.com/en-us/library/windows/desktop/bb776559(v=vs.85).aspx 99 | If DllStructGetData($tPROPVARIANT, 'vt') <> $VT_EMPTY Then 100 | Local $buf = DllStructCreate('wchar[128]') 101 | DllCall('Propsys.dll', 'long', 'PropVariantToString', _ 102 | 'ptr', DllStructGetPtr($tPROPVARIANT), _ 103 | 'ptr', DllStructGetPtr($buf), _ 104 | 'uint', DllStructGetSize($buf)) 105 | If Not @error Then 106 | $sAppId = DllStructGetData($buf, 1) 107 | EndIf 108 | EndIf 109 | Else 110 | _WinAPI_InitPropVariantFromString($appId, $tPROPVARIANT) 111 | $oPropertyStore.SetValue(DllStructGetPtr($tPKEY), DllStructGetPtr($tPROPVARIANT)) 112 | $oPropertyStore.Commit() 113 | $sAppId = $appid 114 | EndIf 115 | 116 | ;$oPropertyStore.Release() ; this line crashes Autoit 117 | Return SetError(($sAppId == '')*2, 0, $sAppId) 118 | EndFunc 119 | 120 | 121 | ; #FUNCTION# ;=============================================================================== 122 | ; Name...........: _ShortcutAppId 123 | ; Description ...: Get AppUerModelId(AppId) from a .lnk shortcut file or 124 | ; set the shortcut's AppId if $appid is provided. 125 | ; Syntax.........: _ShortcutAppId($lnkfile, $appid = Default) 126 | ; Parameters ....: $lnkfile - path of shortcut file. 127 | ; $appid - [optional] AppId to set. 128 | ; Return values .: Success - Returns current AppId 129 | ; Failure - Returns "" and sets @error: 130 | ; Author ........: jackchen 131 | ; Linlk .........: https://code.google.com/p/win7appid/ 132 | ;============================================================================================ 133 | Func _ShortcutAppId($lnkfile, $appid = Default) 134 | Local $oIShellLinkW = ObjCreateInterface($CLSID_ShellLink , $sIID_IShellLinkW, $tag_IShellLinkW ) 135 | If Not IsObj( $oIShellLinkW ) Then Return SetError(1, 0, '') 136 | 137 | Local $pIPersistFile, $oIPersistFile, $oPropertyStore, $ret, $sAppId 138 | Local $tRIID_IPersistFile = _WinAPI_GUIDFromString( $sIID_IPersistFile ) 139 | $oIShellLinkW.QueryInterface( $tRIID_IPersistFile, $pIPersistFile ) 140 | $oIPersistFile = ObjCreateInterface( $pIPersistFile, $sIID_IPersistFile, $tag_IPersistFile ) 141 | If IsObj( $oIPersistFile ) Then 142 | If $appid == Default Then ; read only 143 | $ret = $oIPersistFile.Load($lnkfile, BitOR($STGM_READ, $STGM_SHARE_DENY_NONE)) 144 | Else 145 | $ret = $oIPersistFile.Load($lnkfile, $STGM_READWRITE) 146 | EndIf 147 | If $ret = 0 Then 148 | Local $tPKEY = _PKEY_AppUserModel_ID() 149 | Local $tPROPVARIANT = DllStructCreate($tagPROPVARIANT) 150 | 151 | $tRIID_IPropertyStore = _WinAPI_GUIDFromString($sIID_IPropertyStore) 152 | 153 | Local $pPropertyStore 154 | $oIShellLinkW.QueryInterface($tRIID_IPropertyStore, $pPropertyStore) 155 | 156 | $oPropertyStore = ObjCreateInterface($pPropertyStore, $sIID_IPropertyStore, _ 157 | 'GetCount HRESULT(PTR);GetAt HRESULT(DWORD;PTR);GetValue HRESULT(PTR;PTR);' & _ 158 | 'SetValue HRESULT(PTR;PTR);Commit HRESULT()') 159 | If IsObj($oPropertyStore) Then 160 | If $appid == Default Then ; get appid 161 | $oPropertyStore.GetValue(DllStructGetPtr($tPKEY), DllStructGetPtr($tPROPVARIANT)) 162 | If DllStructGetData($tPROPVARIANT, 'vt') <> $VT_EMPTY Then 163 | ; Extracts a string value from a PROPVARIANT structure 164 | ; http://deletethis.net/dave/dev/setappusermodelid/ 165 | ; https://msdn.microsoft.com/en-us/library/windows/desktop/bb776559(v=vs.85).aspx 166 | Local $buf = DllStructCreate('wchar[128]') 167 | DllCall('Propsys.dll', 'long', 'PropVariantToString', _ 168 | 'ptr', DllStructGetPtr($tPROPVARIANT), _ 169 | 'ptr', DllStructGetPtr($buf), _ 170 | 'uint', DllStructGetSize($buf)) 171 | $sAppId = DllStructGetData($buf, 1) 172 | EndIf 173 | Else ; set appid 174 | _WinAPI_InitPropVariantFromString($appid, $tPROPVARIANT) 175 | $oPropertyStore.SetValue(DllStructGetPtr($tPKEY), DllStructGetPtr($tPROPVARIANT)) 176 | $oPropertyStore.Commit() 177 | $oIPersistFile.Save($lnkfile, True) 178 | $sAppId = $appid 179 | EndIf 180 | EndIf 181 | EndIf 182 | EndIf 183 | If IsObj($oPropertyStore) Then $oPropertyStore.Release() 184 | If IsObj($oIPersistFile) Then $oIPersistFile.Release() 185 | If IsObj($oIShellLinkW) Then $oIShellLinkW.Release() 186 | Return SetError(($sAppId == '')*2, 0, $sAppId) 187 | EndFunc 188 | 189 | ; https://www.autoitscript.com/forum/topic/168099-how-to-prevent-multiple-guis-from-combining-in-the-taskbar/ 190 | ; This function is not exposed in any dll, but inlined in propvarutil.h so we need to rewrite it entirely in AutoIt 191 | Func _WinAPI_InitPropVariantFromString($sUnicodeString, ByRef $tPROPVARIANT) 192 | DllStructSetData($tPROPVARIANT, 'vt', $VT_LPWSTR) 193 | Local $aRet = DllCall('Shlwapi.dll', 'LONG', 'SHStrDupW', _ 194 | 'WSTR', $sUnicodeString, 'PTR', DllStructGetPtr($tPROPVARIANT) + 8) 195 | 196 | If @error Then Return SetError(@error, @extended, False) 197 | Local $bSuccess = $aRet[0] == 0 198 | 199 | ; If fails, zero memory of the current PROPVARIANT struct 200 | If (Not $bSuccess) Then $tPROPVARIANT = DllStructCreate($tagPROPVARIANT) 201 | Return SetExtended($aRet[0], $bSuccess) 202 | EndFunc 203 | 204 | ; https://www.autoitscript.com/forum/topic/168099-how-to-prevent-multiple-guis-from-combining-in-the-taskbar/ 205 | Func _PKEY_AppUserModel_ID() 206 | Local $tPKEY = DllStructCreate($tagPROPERTYKEY) 207 | ;PKEY_AppUserModel_ID = { {0x9F4C2855, 0x9F79, 0x4B39, 208 | ; {0xA8, 0xD0, 0xE1, 0xD4, 0x2D, 0xE1, 0xD5, 0xF3}}, 5 } 209 | _WinAPI_GUIDFromStringEx('{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}', _ 210 | DllStructGetPtr($tPKEY)) 211 | DllStructSetData($tPKEY, 'pid', 5) 212 | Return $tPKEY 213 | EndFunc 214 | 215 | ; https://www.autoitscript.com/forum/topic/168099-how-to-prevent-multiple-guis-from-combining-in-the-taskbar/ 216 | Func _WinAPI_SHGetPropertyStoreForWindow($hWnd, $sIID, ByRef $tPointer) 217 | Local $tIID = _WinAPI_GUIDFromString($sIID) 218 | Local $pp = IsPtr($tPointer)? $tPointer : DllStructGetPtr($tPointer) 219 | Local $aRet = DllCall('Shell32.dll', 'LONG', 'SHGetPropertyStoreForWindow', _ 220 | 'HWND', $hWnd, 'STRUCT*', $tIID, 'PTR', $pp) 221 | If @error Then Return SetError(@error, @extended, False) 222 | Return SetExtended($aRet[0], ($aRet[0] = 0)) 223 | EndFunc -------------------------------------------------------------------------------- /libs/BinaryCall.au3: -------------------------------------------------------------------------------- 1 | ; ============================================================================= 2 | ; AutoIt BinaryCall UDF (2014.7.24) 3 | ; Purpose: Allocate, Decompress, And Prepare Binary Machine Code 4 | ; Author: Ward 5 | ; ============================================================================= 6 | 7 | #Include-once 8 | 9 | Global $__BinaryCall_Kernel32dll = DllOpen('kernel32.dll') 10 | Global $__BinaryCall_Msvcrtdll = DllOpen('msvcrt.dll') 11 | Global $__BinaryCall_LastError = "" 12 | 13 | Func _BinaryCall_GetProcAddress($Module, $Proc) 14 | Local $Ret = DllCall($__BinaryCall_Kernel32dll, 'ptr', 'GetProcAddress', 'ptr', $Module, 'str', $Proc) 15 | If @Error Or Not $Ret[0] Then Return SetError(1, @Error, 0) 16 | Return $Ret[0] 17 | EndFunc 18 | 19 | Func _BinaryCall_LoadLibrary($Filename) 20 | Local $Ret = DllCall($__BinaryCall_Kernel32dll, "handle", "LoadLibraryW", "wstr", $Filename) 21 | If @Error Then Return SetError(1, @Error, 0) 22 | Return $Ret[0] 23 | EndFunc 24 | 25 | Func _BinaryCall_lstrlenA($Ptr) 26 | Local $Ret = DllCall($__BinaryCall_Kernel32dll, "int", "lstrlenA", "ptr", $Ptr) 27 | If @Error Then Return SetError(1, @Error, 0) 28 | Return $Ret[0] 29 | EndFunc 30 | 31 | Func _BinaryCall_Alloc($Code, $Padding = 0) 32 | Local $Length = BinaryLen($Code) + $Padding 33 | Local $Ret = DllCall($__BinaryCall_Kernel32dll, "ptr", "VirtualAlloc", "ptr", 0, "ulong_ptr", $Length, "dword", 0x1000, "dword", 0x40) 34 | If @Error Or Not $Ret[0] Then Return SetError(1, @Error, 0) 35 | If BinaryLen($Code) Then 36 | Local $Buffer = DllStructCreate("byte[" & $Length & "]", $Ret[0]) 37 | DllStructSetData($Buffer, 1, $Code) 38 | EndIf 39 | Return $Ret[0] 40 | EndFunc 41 | 42 | Func _BinaryCall_RegionSize($Ptr) 43 | Local $Buffer = DllStructCreate("ptr;ptr;dword;uint_ptr;dword;dword;dword") 44 | Local $Ret = DllCall($__BinaryCall_Kernel32dll, "int", "VirtualQuery", "ptr", $Ptr, "ptr", DllStructGetPtr($Buffer), "uint_ptr", DllStructGetSize($Buffer)) 45 | If @Error Or $Ret[0] = 0 Then Return SetError(1, @Error, 0) 46 | Return DllStructGetData($Buffer, 4) 47 | EndFunc 48 | 49 | Func _BinaryCall_Free($Ptr) 50 | Local $Ret = DllCall($__BinaryCall_Kernel32dll, "bool", "VirtualFree", "ptr", $Ptr, "ulong_ptr", 0, "dword", 0x8000) 51 | If @Error Or $Ret[0] = 0 Then 52 | $Ret = DllCall($__BinaryCall_Kernel32dll, "bool", "GlobalFree", "ptr", $Ptr) 53 | If @Error Or $Ret[0] <> 0 Then Return SetError(1, @Error, False) 54 | EndIf 55 | Return True 56 | EndFunc 57 | 58 | Func _BinaryCall_Release($CodeBase) 59 | Local $Ret = _BinaryCall_Free($CodeBase) 60 | Return SetError(@Error, @Extended, $Ret) 61 | EndFunc 62 | 63 | Func _BinaryCall_MemorySearch($Ptr, $Length, $Binary) 64 | Static $CodeBase 65 | If Not $CodeBase Then 66 | If @AutoItX64 Then 67 | $CodeBase = _BinaryCall_Create('0x4883EC084D85C94889C8742C4C39CA72254C29CA488D141131C9EB0848FFC14C39C97414448A1408453A140874EE48FFC04839D076E231C05AC3', '', 0, True, False) 68 | Else 69 | $CodeBase = _BinaryCall_Create('0x5589E58B4D14578B4508568B550C538B7D1085C9742139CA721B29CA8D341031D2EB054239CA740F8A1C17381C1074F34039F076EA31C05B5E5F5DC3', '', 0, True, False) 70 | EndIf 71 | If Not $CodeBase Then Return SetError(1, 0, 0) 72 | EndIf 73 | 74 | $Binary = Binary($Binary) 75 | Local $Buffer = DllStructCreate("byte[" & BinaryLen($Binary) & "]") 76 | DllStructSetData($Buffer, 1, $Binary) 77 | 78 | Local $Ret = DllCallAddress("ptr:cdecl", $CodeBase, "ptr", $Ptr, "uint", $Length, "ptr", DllStructGetPtr($Buffer), "uint", DllStructGetSize($Buffer)) 79 | Return $Ret[0] 80 | EndFunc 81 | 82 | Func _BinaryCall_Base64Decode($Src) 83 | Static $CodeBase 84 | If Not $CodeBase Then 85 | If @AutoItX64 Then 86 | $CodeBase = _BinaryCall_Create('0x41544989CAB9FF000000555756E8BE000000534881EC000100004889E7F3A44C89D6E98A0000004439C87E0731C0E98D0000000FB66E01440FB626FFC00FB65E020FB62C2C460FB62424408A3C1C0FB65E034189EB41C1E4024183E3308A1C1C41C1FB044509E34080FF634189CC45881C08744C440FB6DFC1E5044489DF4088E883E73CC1FF0209C7418D44240241887C08014883C10380FB63742488D841C1E3064883C60483E03F4409D841884408FF89F389C84429D339D30F8C67FFFFFF4881C4000100005B5E5F5D415CC35EC3E8F9FFFFFF000000000000000000000000000000000000000000000000000000000000000000000000000000000000003E0000003F3435363738393A3B3C3D00000063000000000102030405060708090A0B0C0D0E0F101112131415161718190000000000001A1B1C1D1E1F202122232425262728292A2B2C2D2E2F30313233', '', 132, True, False) 87 | Else 88 | $CodeBase = _BinaryCall_Create('0x55B9FF00000089E531C05756E8F10000005381EC0C0100008B55088DBDF5FEFFFFF3A4E9C00000003B45140F8FC20000000FB65C0A028A9C1DF5FEFFFF889DF3FEFFFF0FB65C0A038A9C1DF5FEFFFF889DF2FEFFFF0FB65C0A018985E8FEFFFF0FB69C1DF5FEFFFF899DECFEFFFF0FB63C0A89DE83E630C1FE040FB6BC3DF5FEFFFFC1E70209FE8B7D1089F3881C074080BDF3FEFFFF63745C0FB6B5F3FEFFFF8BBDECFEFFFF8B9DE8FEFFFF89F083E03CC1E704C1F80209F88B7D1088441F0189D883C00280BDF2FEFFFF6374278A85F2FEFFFFC1E60683C10483E03F09F088441F0289D883C0033B4D0C0F8C37FFFFFFEB0231C081C40C0100005B5E5F5DC35EC3E8F9FFFFFF000000000000000000000000000000000000000000000000000000000000000000000000000000000000003E0000003F3435363738393A3B3C3D00000063000000000102030405060708090A0B0C0D0E0F101112131415161718190000000000001A1B1C1D1E1F202122232425262728292A2B2C2D2E2F30313233', '', 132, True, False) 89 | EndIf 90 | If Not $CodeBase Then Return SetError(1, 0, Binary("")) 91 | EndIf 92 | 93 | $Src = String($Src) 94 | Local $SrcLen = StringLen($Src) 95 | Local $SrcBuf = DllStructCreate("char[" & $SrcLen & "]") 96 | DllStructSetData($SrcBuf, 1, $Src) 97 | 98 | Local $DstLen = Int(($SrcLen + 2) / 4) * 3 + 1 99 | Local $DstBuf = DllStructCreate("byte[" & $DstLen & "]") 100 | 101 | Local $Ret = DllCallAddress("uint:cdecl", $CodeBase, "ptr", DllStructGetPtr($SrcBuf), "uint", $SrcLen, "ptr", DllStructGetPtr($DstBuf), "uint", $DstLen) 102 | If $Ret[0] = 0 Then Return SetError(2, 0, Binary("")) 103 | Return BinaryMid(DllStructGetData($DstBuf, 1), 1, $Ret[0]) 104 | EndFunc 105 | 106 | Func _BinaryCall_Base64Encode($Src) 107 | Static $CodeBase 108 | If Not $CodeBase Then 109 | If @AutoItX64 Then 110 | $CodeBase = _BinaryCall_Create('AwAAAARiAQAAAAAAAAArkuFQDAlvIp0qAgbDnjr76UDZs1EPNIP2K18t9s6SNTbd43IB7HfdyPM8VfD/o36z4AmSW2m2AIsC6Af3fKNsHU4BdQKGd0PQXHxPSX0iNqp1YAKovksqQna06NeKMoOYqryTUX4WgpHjokhp6zY2sEFSIjcL7dW3FDoNVz4bGPyZHRvjFwmqvr7YGlNYKwNoh+SYCXmIgVPVZ63Vz1fbT33/QFpWmWOeBRqs4J+c8Qp6zJFsK345Pjw0I8kMSsnho4F4oNzQ2OsAbmIioaQ6Ma2ziw5NH+M+t4SpEeHDnBdUTTL20sxWZ0yKruFAsBIRoHvM7LYcid2eBV2d5roSjnkwMG0g69LNjs1fHjbI/9iU/hJwpSsgl4fltXdZG659/li13UFY89M7UfckiZ9XOeBM0zadgNsy8r8M3rEAAA==') 111 | Else 112 | $CodeBase = _BinaryCall_Create('AwAAAARVAQAAAAAAAAAqr7blBndrIGnmhhfXD7R1fkOTKhicg1W6MCtStbz+CsneBEg0bbHH1sqTLmLfY7A6LqZl6LYWT5ULVj6MXgugPbBn9wKsSU2ZCcBBPNkx09HVPdUaKnbqghDGj/C5SHoF+A/5g+UgE1C5zJZORjJ8ljs5lt2Y9lA4BsY7jVKX2vmDvHK1NnSR6nVwh7Pb+Po/UpNcy5sObVWDKkYSCCtCIjKIYqOe3c6k8Xsp4eritCUprXEVvCFi7K5Z6HFXdm3nZsFcE+eSJ1WkRnVQbWcmpjGMGka61C68+CI7tsQ13UnCFWNSpDrCbzUejMZh8HdPgEc5vCg3pKMKin/NavNpB6+87Y9y7HIxmKsPdjDT30u9hUKWnYiRe3nrwKyVDsiYpKU/Nse368jHag5B5or3UKA+nb2+eY8JwzgA') 113 | EndIf 114 | If Not $CodeBase Then Return SetError(1, 0, Binary("")) 115 | EndIf 116 | 117 | $Src = Binary($Src) 118 | Local $SrcLen = BinaryLen($Src) 119 | Local $SrcBuf = DllStructCreate("byte[" & $SrcLen & "]") 120 | DllStructSetData($SrcBuf, 1, $Src) 121 | 122 | Local $DstLen = Int(($SrcLen + 2) / 3) * 4 + 1 123 | Local $DstBuf = DllStructCreate("char[" & $DstLen & "]") 124 | 125 | Local $Ret = DllCallAddress("uint:cdecl", $CodeBase, "ptr", DllStructGetPtr($SrcBuf), "uint", $SrcLen, "ptr", DllStructGetPtr($DstBuf), "uint", $DstLen) 126 | If $Ret[0] = 0 Then Return Binary("") 127 | Return StringMid(DllStructGetData($DstBuf, 1), 1, $Ret[0]) 128 | EndFunc 129 | 130 | Func _BinaryCall_LzmaDecompress($Src) 131 | Static $CodeBase 132 | If Not $CodeBase Then 133 | If @AutoItX64 Then 134 | $CodeBase = _BinaryCall_Create(_BinaryCall_Base64Decode('QVcxwEFWQVVBVFVXSInXVkiJzlMx20iB7OgAAABEiiFBgPzgdgnpyQAAAEGD7C1BiMf/wEGA/Cx38THA6wRBg+wJQYjG/8BBgPwId/GLRglEi24FQQ+2zkyJRCQoRQ+2/0HB5xBBiQFBD7bEAcG4AAMAANPgjYQAcA4AAEhjyOjIBAAATInpSInF6L0EAABIicMxwEyJ8kSI4EyLRCQoiNQl//8A/0QJ+EiF24lFAHQoTYXtdCNIjVfzSI1MJDhIg8YNTIkEJE2J6UmJ2EiJ7+g2AAAAicbrBb4BAAAASInp6IQEAACF9nQKSInZMdvodgQAAEiJ2EiBxOgAAABbXl9dQVxBXUFeQV/DVVNBV0FWQVVBVEFQTQHBQVFNicVRVkgB8lJIieX8SYn0iwdMjX8Eik8Cg8r/0+L30olV6Ijhg8r/0+L30olV5ADBiUXsuAEAAACJReCJRdyJRdhIiUXQRSnJKfaDy/8A0bgAAwAA0+BIjYg2BwAAuAAEAARMif/R6fOrvwUAAADoUAMAAP/PdfdEie9EicgrfSDB4ARBifpEI1XoRAHQTY0cR+hAAwAAD4WTAAAAik3sI33k0+eA6Qj22dPuAfe4AQAAAEiNPH++AAEAAMHnCEGD+QdNjbR/bA4AAHI0TInvSCt90A+2P9HnQYnzIf5BAfNPjRxe6O8CAACJwcHuCIPhATnOvgABAAB1DjnGd9jrDE2J8+jQAgAAOfBy9EyJ76pEiclBg/kEcg65AwAAAEGD+QpyA4PBA0EpyelDAgAAT42cT4ABAADomgIAAHUsi0XcQYP5B4lF4BnAi1XY99CLTdCD4AOJVdxBicGJTdhNjbdkBgAA6akAAABPjZxPmAEAAOhfAgAAdUZEicjB4AREAdBNjZxH4AEAAOhHAgAAdWpBg/kHuQkAAAByA4PBAkGJyUyJ70grfdBIO30gD4L9AQAAigdIA33QqumzAQAAT42cT7ABAADoCgIAAIt12HQhT42cT8gBAADo+AEAAIt13HQJi03ci3XgiU3gi03YiU3ci03QiU3YiXXQQYP5B7kIAAAAcgODwQNBiclNjbdoCgAATYnz6LsBAAB1FESJ0CnJweADvggAAABJjXxGBOs2TY1eAuicAQAAdRpEidC5CAAAAMHgA74IAAAASY28RgQBAADrEUmNvgQCAAC5EAAAAL4AAQAAiU3MuAEAAABJifvoYQEAAInCKfJy8gNVzEGD+QSJVcwPg7kAAABBg8EHuQMAAAA50XICidHB4Qa4AQAAAEmNvE9gAwAAvkAAAABJifvoHwEAAEGJwkEp8nLwQYP6BHJ4RInWRIlV0NHug2XQAf/Og03QAkGD+g5zFYnx0mXQi0XQRCnQTY20R14FAADrLIPuBOi6AAAA0evRZdBBOdhyBv9F0EEp2P/OdedNjbdEBgAAwWXQBL4EAAAAvwEAAACJ+E2J8+ioAAAAqAF0Awl90NHn/8516+sERIlV0P9F0EyJ74tNzEiJ+IPBAkgrRSBIOUXQd1RIif5IK3XQSItVGKyqSDnXcwT/yXX1SYn9D7bwTDttGA+C9fz//+gwAAAAKcBIi1UQTCtlCESJIkiLVWBMK20gRIkqSIPEKEFcQV1BXUFfW13DXli4AQAAAOvSgfsAAAABcgHDweMITDtlAHPmQcHgCEWKBCRJg8QBwynATY0cQ4H7AAAAAXMVweMITDtlAHPBQcHgCEWKBCRJg8QBidlBD7cTwekLD6/KQTnIcxOJy7kACAAAKdHB6QVmQQELAcDDKcvB6gVBKchmQSkTAcCDwAHDSLj////////////gbXN2Y3J0LmRsbHxtYWxsb2MASLj////////////gZnJlZQA=')) 135 | Else 136 | $CodeBase = _BinaryCall_Create(_BinaryCall_Base64Decode('VYnlVzH/VlOD7EyLXQiKC4D54A+HxQAAADHA6wWD6S2I0ID5LI1QAXfziEXmMcDrBYPpCYjQgPkIjVABd/OIReWLRRSITeSLUwkPtsmLcwWJEA+2ReUBwbgAAwAA0+CNhABwDgAAiQQk6EcEAACJNCSJRdToPAQAAItV1InHi0Xkhf+JArgBAAAAdDaF9nQyi0UQg8MNiRQkiXQkFIl8JBCJRCQYjUXgiUQkDItFDIlcJASD6A2JRCQI6CkAAACLVdSJRdSJFCToAQQAAItF1IXAdAqJPCQx/+jwAwAAg8RMifhbXl9dw1dWU1WJ5YtFJAFFKFD8i3UYAXUcVot1FK2SUopO/oPI/9Pg99BQiPGDyP/T4PfQUADRifeD7AwpwEBQUFBQUFcp9laDy/+4AAMAANPgjYg2BwAAuAAEAATR6fOragVZ6MoCAADi+Yt9/ItF8Ct9JCH4iUXosADoywIAAA+FhQAAAIpN9CN97NPngOkI9tnT7lgB916NPH/B5wg8B1qNjH5sDgAAUVa+AAEAAFCwAXI0i338K33cD7Y/i23M0eeJ8SH+AfGNbE0A6JgCAACJwcHuCIPhATnOvgABAAB1DjnwctfrDIttzOh5AgAAOfBy9FqD+gSJ0XIJg/oKsQNyArEGKcpS60mwwOhJAgAAdRRYX1pZWln/NCRRUrpkBgAAsQDrb7DM6CwCAAB1LLDw6BMCAAB1U1g8B7AJcgKwC1CLdfwrddw7dSQPgs8BAACsi338qumOAQAAsNjo9wEAAIt12HQbsOTo6wEAAIt11HQJi3XQi03UiU3Qi03YiU3Ui03ciU3YiXXcWF9ZumgKAACxCAH6Ulc8B4jIcgIEA1CLbczovAEAAHUUi0Xoi33MweADKclqCF6NfEcE6zWLbcyDxQLomwEAAHUYi0Xoi33MweADaghZaghejbxHBAEAAOsQvwQCAAADfcxqEFm+AAEAAIlN5CnAQIn96GYBAACJwSnxcvMBTeSDfcQED4OwAAAAg0XEB4tN5IP5BHIDagNZi33IweEGKcBAakBejbxPYAMAAIn96CoBAACJwSnxcvOJTeiJTdyD+QRyc4nOg2XcAdHug03cAk6D+Q5zGbivAgAAKciJ8dJl3ANF3NHgA0XIiUXM6y2D7gToowAAANHr0WXcOV3gcgb/RdwpXeBOdei4RAYAAANFyIlFzMFl3ARqBF4p/0eJ+IttzOi0AAAAqAF0Awl93NHnTnXs6wD/RdyLTeSDwQKLffyJ+CtFJDlF3HdIif4rddyLVSisqjnXcwNJdfeJffwPtvA7fSgPgnH9///oKAAAACnAjWwkPItVIIt1+Ct1GIkyi1Usi338K30kiTrJW15fw15YKcBA69qB+wAAAAFyAcPB4whWi3X4O3Ucc+SLReDB4AisiUXgiXX4XsOLTcQPtsDB4QQDRegByOsGD7bAA0XEi23IjWxFACnAjWxFAIH7AAAAAXMci0wkOMFkJCAIO0wkXHOcihH/RCQ4weMIiFQkIInZD7dVAMHpCw+vyjlMJCBzF4nLuQAIAAAp0cHpBWYBTQABwI1sJEDDweoFKUwkICnLZilVAAHAg8ABjWwkQMO4///////gbXN2Y3J0LmRsbHxtYWxsb2MAuP//////4GZyZWUA')) 137 | EndIf 138 | If Not $CodeBase Then Return SetError(1, 0, Binary("")) 139 | EndIf 140 | 141 | $Src = Binary($Src) 142 | Local $SrcLen = BinaryLen($Src) 143 | Local $SrcBuf = DllStructCreate("byte[" & $SrcLen & "]") 144 | DllStructSetData($SrcBuf, 1, $Src) 145 | 146 | Local $Ret = DllCallAddress("ptr:cdecl", $CodeBase, "ptr", DllStructGetPtr($SrcBuf), "uint_ptr", $SrcLen, "uint_ptr*", 0, "uint*", 0) 147 | If $Ret[0] Then 148 | Local $DstBuf = DllStructCreate("byte[" & $Ret[3] & "]", $Ret[0]) 149 | Local $Output = DllStructGetData($DstBuf, 1) 150 | DllCall($__BinaryCall_Msvcrtdll, "none:cdecl", "free", "ptr", $Ret[0]) 151 | 152 | Return $Output 153 | EndIf 154 | Return SetError(2, 0, Binary("")) 155 | EndFunc 156 | 157 | Func _BinaryCall_Relocation($Base, $Reloc) 158 | Local $Size = Int(BinaryMid($Reloc, 1, 2)) 159 | 160 | For $i = 3 To BinaryLen($Reloc) Step $Size 161 | Local $Offset = Int(BinaryMid($Reloc, $i, $Size)) 162 | Local $Ptr = $Base + $Offset 163 | DllStructSetData(DllStructCreate("ptr", $Ptr), 1, DllStructGetData(DllStructCreate("ptr", $Ptr), 1) + $Base) 164 | Next 165 | EndFunc 166 | 167 | Func _BinaryCall_ImportLibrary($Base, $Length) 168 | Local $JmpBin, $JmpOff, $JmpLen, $DllName, $ProcName 169 | If @AutoItX64 Then 170 | $JmpBin = Binary("0x48B8FFFFFFFFFFFFFFFFFFE0") 171 | $JmpOff = 2 172 | Else 173 | $JmpBin = Binary("0xB8FFFFFFFFFFE0") 174 | $JmpOff = 1 175 | EndIf 176 | $JmpLen = BinaryLen($JmpBin) 177 | 178 | Do 179 | Local $Ptr = _BinaryCall_MemorySearch($Base, $Length, $JmpBin) 180 | If $Ptr = 0 Then ExitLoop 181 | 182 | Local $StringPtr = $Ptr + $JmpLen 183 | Local $StringLen = _BinaryCall_lstrlenA($StringPtr) 184 | Local $String = DllStructGetData(DllStructCreate("char[" & $StringLen & "]", $StringPtr), 1) 185 | Local $Split = StringSplit($String, "|") 186 | 187 | If $Split[0] = 1 Then 188 | $ProcName = $Split[1] 189 | ElseIf $Split[0] = 2 Then 190 | If $Split[1] Then $DllName = $Split[1] 191 | $ProcName = $Split[2] 192 | EndIf 193 | 194 | If $DllName And $ProcName Then 195 | Local $Handle = _BinaryCall_LoadLibrary($DllName) 196 | If Not $Handle Then 197 | $__BinaryCall_LastError = "LoadLibrary fail on " & $DllName 198 | Return SetError(1, 0, False) 199 | EndIf 200 | 201 | Local $Proc = _BinaryCall_GetProcAddress($Handle, $ProcName) 202 | If Not $Proc Then 203 | $__BinaryCall_LastError = "GetProcAddress failed on " & $ProcName 204 | Return SetError(2, 0, False) 205 | EndIf 206 | 207 | DllStructSetData(DllStructCreate("ptr", $Ptr + $JmpOff), 1, $Proc) 208 | EndIf 209 | 210 | Local $Diff = Int($Ptr - $Base + $JmpLen + $StringLen + 1) 211 | $Base += $Diff 212 | $Length -= $Diff 213 | 214 | Until $Length <= $JmpLen 215 | Return True 216 | EndFunc 217 | 218 | Func _BinaryCall_CodePrepare($Code) 219 | If Not $Code Then Return "" 220 | If IsBinary($Code) Then Return $Code 221 | 222 | $Code = String($Code) 223 | If StringLeft($Code, 2) = "0x" Then Return Binary($Code) 224 | If StringIsXDigit($Code) Then Return Binary("0x" & $Code) 225 | 226 | Return _BinaryCall_LzmaDecompress(_BinaryCall_Base64Decode($Code)) 227 | EndFunc 228 | 229 | Func _BinaryCall_SymbolFind($CodeBase, $Identify, $Length = Default) 230 | $Identify = Binary($Identify) 231 | 232 | If IsKeyword($Length) Then 233 | $Length = _BinaryCall_RegionSize($CodeBase) 234 | EndIf 235 | 236 | Local $Ptr = _BinaryCall_MemorySearch($CodeBase, $Length, $Identify) 237 | If $Ptr = 0 Then Return SetError(1, 0, 0) 238 | 239 | Return $Ptr + BinaryLen($Identify) 240 | EndFunc 241 | 242 | Func _BinaryCall_SymbolList($CodeBase, $Symbol) 243 | If Not IsArray($Symbol) Or $CodeBase = 0 Then Return SetError(1, 0, 0) 244 | 245 | Local $Tag = "" 246 | For $i = 0 To UBound($Symbol) - 1 247 | $Tag &= "ptr " & $Symbol[$i] & ";" 248 | Next 249 | 250 | Local $SymbolList = DllStructCreate($Tag) 251 | If @Error Then Return SetError(1, 0, 0) 252 | 253 | For $i = 0 To UBound($Symbol) - 1 254 | $CodeBase = _BinaryCall_SymbolFind($CodeBase, $Symbol[$i]) 255 | DllStructSetData($SymbolList, $Symbol[$i], $CodeBase) 256 | Next 257 | Return $SymbolList 258 | EndFunc 259 | 260 | Func _BinaryCall_Create($Code, $Reloc = '', $Padding = 0, $ReleaseOnExit = True, $LibraryImport = True) 261 | Local $BinaryCode = _BinaryCall_CodePrepare($Code) 262 | If Not $BinaryCode Then Return SetError(1, 0, 0) 263 | 264 | Local $BinaryCodeLen = BinaryLen($BinaryCode) 265 | Local $TotalCodeLen = $BinaryCodeLen + $Padding 266 | 267 | Local $CodeBase = _BinaryCall_Alloc($BinaryCode, $Padding) 268 | If Not $CodeBase Then Return SetError(2, 0, 0) 269 | 270 | If $Reloc Then 271 | $Reloc = _BinaryCall_CodePrepare($Reloc) 272 | If Not $Reloc Then Return SetError(3, 0, 0) 273 | _BinaryCall_Relocation($CodeBase, $Reloc) 274 | EndIf 275 | 276 | If $LibraryImport Then 277 | If Not _BinaryCall_ImportLibrary($CodeBase, $BinaryCodeLen) Then 278 | _BinaryCall_Free($CodeBase) 279 | Return SetError(4, 0, 0) 280 | EndIf 281 | EndIf 282 | 283 | If $ReleaseOnExit Then 284 | _BinaryCall_ReleaseOnExit($CodeBase) 285 | EndIf 286 | 287 | Return SetError(0, $TotalCodeLen, $CodeBase) 288 | EndFunc 289 | 290 | Func _BinaryCall_CommandLineToArgv($CommandLine, ByRef $Argc, $IsUnicode = False) 291 | Static $SymbolList 292 | If Not IsDllStruct($SymbolList) Then 293 | Local $Code 294 | If @AutoItX64 Then 295 | $Code = 'AwAAAASuAgAAAAAAAAAkL48ClEB9jTEOeYv4yYTosNjFNgf81Ag4vS2VP4y4wxFa+4yMI7GDB7CG+xn4JE3cdEVvk8cMp4oIuS3DgTxlcKHGVIg94tvzG/256bizZfGtAETQUCPQjW5+JSx2C/Y4C0VNJMKTlSCHiV5AzXRZ5gw3WFghbtkCCFxWOX+RDSI2oH/vROEOnqc0jfKTo17EBjqX+dW3QxrUe45xsbyYTZ9ccIGySgcOAxetbRiSxQnz8BOMbJyfrbZbuVJyGpKrXFLh/5MlBZ09Cim9qgflbGzmkrGStT9QL1f+O2krzyOzgaWWqhWL6S+y0G32RWVi0uMLR/JOGLEW/+Yg/4bzkeC0lKELT+RmWAatNa38BRfaitROMN12moRDHM6LYD1lzPLnaiefSQRVti561sxni/AFkYoCb5Lkuyw4RIn/r/flRiUg5w48YkqBBd9rXkaXrEoKwPg6rmOvOCZadu//B6HN4+Ipq5aYNuZMxSJXmxwXVRSQZVpSfLS2ATZMd9/Y7kLqrKy1H4V76SgI/d9OKApfKSbQ8ZaKIHBCsoluEip3UDOB82Z21zd933UH5l0laGWLIrTz7xVGkecjo0NQzR7LyhhoV3xszlIuw2v8q0Q/S9LxB5G6tYbOXo7lLjNIZc0derZz7DNeeeJ9dQE9hp8unubaTBpulPxTNtRjog==' 296 | Else 297 | $Code = 'AwAAAAR6AgAAAAAAAABcQfD553vjya/3DmalU0BKqABevUb/60GZ55rMwmzpQfPSRUlIl04lEiS8RDrXpS0EoBUe+uzDgZd37nVu9wsJ4fykqYvLoMz3ApxQbTBKleOIRSla6I0V8dNP3P7rHeUfjH0jCho0RvhhVpf0o4ht/iZptauxaoy1zQ19TkPZ/vf5Im8ecY6qEdHNzjo2H60jVwiOJ+1J47TmQRwxJ+yKLakq8QNxtKkRIB9B9ugfo3NAL0QslDxbyU0dSgw2aOPxV+uttLzYNnWbLBZVQbchcKgLRjC/32U3Op576sOYFolB1Nj4/33c7MRgtGLjlZfTB/4yNvd4/E+u3U6/Q4MYApCfWF4R/d9CAdiwgIjCYUkGDExKjFtHbAWXfWh9kQ7Q/GWUjsfF9BtHO6924Cy1Ou+BUKksqsxmIKP4dBjvvmz9OHc1FdtR9I63XKyYtlUnqVRtKwlNrYAZVCSFsyAefMbteq1ihU33sCsLkAnp1LRZ2wofgT1/JtT8+GO2s/n52D18wM70RH2n5uJJv8tlxQc1lwbmo4XQvcbcE91U2j9glvt2wC1pkP0hF23Nr/iiIEZHIPAOAHvhervlHE830LSHyUx8yh5Tjojr0gdLvQ==' 298 | EndIf 299 | Local $CodeBase = _BinaryCall_Create($Code) 300 | If @Error Then Return SetError(1, 0, 0) 301 | 302 | Local $Symbol[] = ["ToArgvW","ToArgvA"] 303 | $SymbolList = _BinaryCall_SymbolList($CodeBase, $Symbol) 304 | If @Error Then Return SetError(1, 0, 0) 305 | EndIf 306 | 307 | Local $Ret 308 | If $IsUnicode Then 309 | $Ret = DllCallAddress("ptr:cdecl", DllStructGetData($SymbolList, "ToArgvW"), "wstr", $CommandLine, "int*", 0) 310 | Else 311 | $Ret = DllCallAddress("ptr:cdecl", DllStructGetData($SymbolList, "ToArgvA"), "str", $CommandLine, "int*", 0) 312 | EndIf 313 | 314 | If Not @Error And $Ret[0] <> 0 Then 315 | _BinaryCall_ReleaseOnExit($Ret[0]) 316 | $Argc = $Ret[2] 317 | Return $Ret[0] 318 | Else 319 | Return SetError(2, 0, 0) 320 | EndIf 321 | EndFunc 322 | 323 | Func _BinaryCall_StdioRedirect($Filename = "CON", $Flag = 1 + 2 + 4) 324 | Static $SymbolList 325 | If Not IsDllStruct($SymbolList) Then 326 | Local $Code, $Reloc 327 | If @AutoItX64 Then 328 | $Code = 'AwAAAASjAQAAAAAAAAAkL48ClEB9jTEOeYv4yYTosNjFM1rLNdMULriZUDxTj+ZdkQ01F5zKL+WDCScfQKKLn66EDmcA+gXIkPcZV4lyz8VPw8BPZlNB5KymydM15kCA+uqvmBc1V0NJfzgsF0Amhn0JhM/ZIguYCHxywMQ1SgKxUb05dxDg8WlX/2aPfSolcX47+4/72lPDNTeT7d7XRdm0ND+eCauuQcRH2YOahare9ASxuU4IMHCh2rbZYHwmTNRiQUB/8dLGtph93yhmwdHtyMPLX2x5n6sdA1mxua9htLsLTulE05LLmXbRYXylDz0A' 329 | $Reloc = 'AwAAAAQIAAAAAAAAAAABAB7T+CzGn9ScQAC=' 330 | Else 331 | $Code = 'AwAAAASVAQAAAAAAAABcQfD553vjya/3DmalU0BKqABaUcndypZ3mTYUkHxlLV/lKZPrXYWXgNATjyiowkUQGDVYUy5THQwK4zYdU7xuGf7qfVDELc1SNbiW3NgD4D6N6ZM7auI1jPaThsPfA/ouBcx2aVQX36fjmViTZ8ZLzafjJeR7d5OG5s9sAoIzFLTZsqrFlkIJedqDAOfhA/0mMrkavTWnsio6yTbic1dER0DcEsXpLn0vBNErKHoagLzAgofHNLeFRw5yHWz5owR5CYL7rgiv2k51neHBWGx97A==' 332 | $Reloc = 'AwAAAAQgAAAAAAAAAAABABfyHS/VRkdjBBzbtGPD6vtmVH/IsGHYvPsTv2lGuqJxGlAA' 333 | EndIf 334 | 335 | Local $CodeBase = _BinaryCall_Create($Code, $Reloc) 336 | If @Error Then Return SetError(1, 0, 0) 337 | 338 | Local $Symbol[] = ["StdinRedirect","StdoutRedirect","StderrRedirect"] 339 | $SymbolList = _BinaryCall_SymbolList($CodeBase, $Symbol) 340 | If @Error Then Return SetError(1, 0, 0) 341 | EndIf 342 | 343 | If BitAND($Flag, 1) Then DllCallAddress("none:cdecl", DllStructGetData($SymbolList, "StdinRedirect"), "str", $Filename) 344 | If BitAND($Flag, 2) Then DllCallAddress("none:cdecl", DllStructGetData($SymbolList, "StdoutRedirect"), "str", $Filename) 345 | If BitAND($Flag, 4) Then DllCallAddress("none:cdecl", DllStructGetData($SymbolList, "StderrRedirect"), "str", $Filename) 346 | EndFunc 347 | 348 | Func _BinaryCall_StdinRedirect($Filename = "CON") 349 | Local $Ret = _BinaryCall_StdioRedirect($Filename, 1) 350 | Return SetError(@Error, @Extended, $Ret) 351 | EndFunc 352 | 353 | Func _BinaryCall_StdoutRedirect($Filename = "CON") 354 | Local $Ret = _BinaryCall_StdioRedirect($Filename, 2) 355 | Return SetError(@Error, @Extended, $Ret) 356 | EndFunc 357 | 358 | Func _BinaryCall_StderrRedirect($Filename = "CON") 359 | Local $Ret = _BinaryCall_StdioRedirect($Filename, 4) 360 | Return SetError(@Error, @Extended, $Ret) 361 | EndFunc 362 | 363 | Func _BinaryCall_ReleaseOnExit($Ptr) 364 | OnAutoItExitRegister('__BinaryCall_DoRelease') 365 | __BinaryCall_ReleaseOnExit_Handle($Ptr) 366 | EndFunc 367 | 368 | Func __BinaryCall_DoRelease() 369 | __BinaryCall_ReleaseOnExit_Handle() 370 | EndFunc 371 | 372 | Func __BinaryCall_ReleaseOnExit_Handle($Ptr = Default) 373 | Static $PtrList 374 | 375 | If @NumParams = 0 Then 376 | If IsArray($PtrList) Then 377 | For $i = 1 To $PtrList[0] 378 | _BinaryCall_Free($PtrList[$i]) 379 | Next 380 | EndIf 381 | Else 382 | If Not IsArray($PtrList) Then 383 | Local $InitArray[1] = [0] 384 | $PtrList = $InitArray 385 | EndIf 386 | 387 | If IsPtr($Ptr) Then 388 | Local $Array = $PtrList 389 | Local $Size = UBound($Array) 390 | ReDim $Array[$Size + 1] 391 | $Array[$Size] = $Ptr 392 | $Array[0] += 1 393 | $PtrList = $Array 394 | EndIf 395 | EndIf 396 | EndFunc 397 | -------------------------------------------------------------------------------- /libs/JSON.au3: -------------------------------------------------------------------------------- 1 | ; ============================================================================================================================ 2 | ; File : Json.au3 (2022.09.18) 3 | ; Purpose : A Non-Strict JavaScript Object Notation (JSON) Parser UDF 4 | ; Author : Ward 5 | ; Dependency: BinaryCall.au3 6 | ; Website : http://www.json.org/index.html 7 | ; 8 | ; Source : jsmn.c 9 | ; Author : zserge 10 | ; Website : http://zserge.com/jsmn.html 11 | ; 12 | ; Source : json_string_encode.c, json_string_decode.c 13 | ; Author : Ward 14 | ; Jos - Added Json_Dump() 15 | ; TheXMan - Json_ObjGetItems and some Json_Dump Fixes. 16 | ; Jos - Changed Json_ObjGet() and Json_ObjExists() to allow for multilevel object in string. 17 | ; TheXman - Changed Json_Get() and Json_Put() to handle all valid key names 18 | ; ============================================================================================================================ 19 | 20 | ; ============================================================================================================================ 21 | ; Public Functions: 22 | ; Json_StringEncode($String, $Option = 0) 23 | ; Json_StringDecode($String) 24 | ; Json_IsObject(ByRef $Object) 25 | ; Json_IsNull(ByRef $Null) 26 | ; Json_Encode($Data, $Option = 0, $Indent = Default, $ArraySep = Default, $ObjectSep = Default, $ColonSep = Default) 27 | ; Json_Decode($Json, $InitTokenCount = 1000) 28 | ; Json_ObjCreate() 29 | ; Json_ObjPut(ByRef $Object, $Key, $Value) 30 | ; Json_ObjGet(ByRef $Object, $Key) 31 | ; Json_ObjDelete(ByRef $Object, $Key) 32 | ; Json_ObjExists(ByRef $Object, $Key) 33 | ; Json_ObjGetCount(ByRef $Object) 34 | ; Json_ObjGetKeys(ByRef $Object) 35 | ; Json_ObjGetItems(ByRef $Object) 36 | ; Json_ObjClear(ByRef $Object) 37 | ; Json_Put(ByRef $Var, $Notation, $Data, $CheckExists = False) 38 | ; Json_Get(ByRef $Var, $Notation) 39 | ; Json_Dump($String) 40 | ; ============================================================================================================================ 41 | 42 | #include-once 43 | #include "BinaryCall.au3" 44 | 45 | ; The following constants can be combined to form options for Json_Encode() 46 | Global Const $JSON_UNESCAPED_UNICODE = 1 ; Encode multibyte Unicode characters literally 47 | Global Const $JSON_UNESCAPED_SLASHES = 2 ; Don't escape / 48 | Global Const $JSON_HEX_TAG = 4 ; All < and > are converted to \u003C and \u003E 49 | Global Const $JSON_HEX_AMP = 8 ; All &s are converted to \u0026 50 | Global Const $JSON_HEX_APOS = 16 ; All ' are converted to \u0027 51 | Global Const $JSON_HEX_QUOT = 32 ; All " are converted to \u0022 52 | Global Const $JSON_UNESCAPED_ASCII = 64 ; Don't escape ascii charcters between chr(1) ~ chr(0x1f) 53 | Global Const $JSON_PRETTY_PRINT = 128 ; Use whitespace in returned data to format it 54 | Global Const $JSON_STRICT_PRINT = 256 ; Make sure returned JSON string is RFC4627 compliant 55 | Global Const $JSON_UNQUOTED_STRING = 512 ; Output unquoted string if possible (conflicting with $Json_STRICT_PRINT) 56 | 57 | ; Error value returnd by Json_Decode() 58 | Global Const $JSMN_ERROR_NOMEM = -1 ; Not enough tokens were provided 59 | Global Const $JSMN_ERROR_INVAL = -2 ; Invalid character inside JSON string 60 | Global Const $JSMN_ERROR_PART = -3 ; The string is not a full JSON packet, more bytes expected 61 | Global $Total_JSON_DUMP_Output = "" 62 | 63 | Func __Jsmn_RuntimeLoader($ProcName = "") 64 | Static $SymbolList 65 | If Not IsDllStruct($SymbolList) Then 66 | Local $Code 67 | If @AutoItX64 Then 68 | $Code = 'AwAAAAQfCAAAAAAAAAA1HbEvgTNrvX54gCiWSTVmt5v7RCdoFJ/zhkKmwcm8yVqZPjJBoVhNHHAIzrHWKbZh1J0QAUaHB5zyQTilTmWa9O0OKeLrk/Jg+o7CmMzjEk74uPongdHv37nwYXvg97fiHvjP2bBzI9gxSkKq9Cqh/GxSHIlZPYyW76pXUt//25Aqs2Icfpyay/NFd50rW7eMliH5ynkrp16HM1afithVrO+LpSaz/IojowApmXnBHUncHliDqbkx6/AODUkyDm1hj+AiEZ9Me1Jy+hBQ1/wC/YnuuYSJvNAKp6XDnyc8Nwr54Uqx5SbUW2CezwQQ7aXX/HFiHSKpQcFW/gi8oSx5nsoxUXVjxeNI/L7z6GF2mfu3Tnpt7hliWEdA2r2VB+TIM7Pgwl9X3Ge0T3KJQUaRtLJZcPvVtOuKXr2Q9wy7hl80hVRrt9zYrbjBHXLrRx/HeIMkZwxhmKo/dD/vvaNgE+BdU8eeJqFBJK2alrK2rh2WkRynftyepm1WrdKrz/5KhQPp/4PqH+9IADDjoGBbfvJQXdT+yiO8DtfrVnd+JOEKsKEsdgeM3UXx5r6tEHO9rYWbzbnyEiX7WozZemry+vBZMMtHn1aA63+RcDQED73xOsnj00/9E5Z6hszM5Hi8vi6Hw3iOgf3cHwcXG44aau0JpuA2DlrUvnJOYkNnY+bECeSdAR1UQkFNyqRoH2xm4Y7gYMCPsFtPBlwwleEKI27SsUq1ZHVQvFCoef7DXgf/GwPCAvwDMIQfb3hJtIVubOkASRQZVNIJ/y4KPrn/gcASV7fvMjE34loltTVlyqprUWxpI51tN6vhTOLAp+CHseKxWaf9g1wdbVs0e/5xAiqgJbmKNi9OYbhV/blpp3SL63XKxGiHdxhK1aR+4rUY4eckNbaHfW7ob+q7aBoHSs6LVX9lWakb/xWxwQdwcX/7/C+TcQSOOg6rLoWZ8wur9qp+QwzoCbXkf04OYpvD5kqgEiwQnB90kLtcA+2XSbDRu+aq02eNNCzgkZujeL/HjVISjf2EuQKSsZkBhS15eiXoRgPaUoQ5586VS7t7rhM8ng5LiVzoUQIZ0pNKxWWqD+gXRBvOMIXY2yd0Ei4sE5KFIEhbs3u8vwP7nFLIpZ/RembPTuc0ZlguGJgJ2F5iApfia+C2tRYRNjVCqECCveWw6P2Btfaq9gw7cWWmJflIQbjxtccDqsn52cftLqXSna9zk05mYdJSV8z2W7vM1YJ5Rd82v0j3kau710A/kQrN41bdaxmKjL+gvSRlOLB1bpvkCtf9+h+eVA4XIkIXKFydr1OjMZ8wq2FIxPJXskAe4YMgwQmeWZXMK1KBbLB3yQR1YOYaaHk1fNea9KsXgs5YLbiP/noAusz76oEDo/DJh1aw7cUwdhboVPg1bNq88mRb5RGa13KDK9uEET7OA02KbSL+Q4HOtyasLUoVrZzVyd8iZPoGrV36vHnj+yvG4fq6F/fkug/sBRp186yVZQVmdAgFd+WiRLnUjxHUKJ6xBbpt4FTP42E/PzPw3JlDb0UQtXTDnIL0CWqbns2E7rZ5PBwrwQYwvBn/gaEeLVGDSh84DfW4zknIneGnYDXdVEHC+ITzejAnNxb1duB+w2aVTk64iXsKHETq53GMH6DuFi0oUeEFb/xp0HsRyNC8vBjOq3Kk7NZHxCQLh7UATFttG7sH+VIqGjjNwmraGJ0C92XhpQwSgfAb3KHucCHGTTti0sn6cgS3vb36BkjGKsRhXVuoQCFH96bvTYtl8paQQW9ufRfvxPqmU0sALdR0fIvZwd7Z8z0UoEec6b1Sul4e60REj/H4scb6N2ryHBR9ua5N1YxJu1uwgoLXUL2wT9ZPBjPjySUzeqXikUIKKYgNlWy+VlNIiWWTPtKpCTr508logA==' 69 | Else 70 | $Code = 'AwAAAASFBwAAAAAAAAA1HbEvgTNrvX54gCiqsa1mt5v7RCdoAFjCfVE40DZbE5UfabA9UKuHrjqOMbvjSoB2zBJTEYEQejBREnPrXL3VwpVOW+L9SSfo0rTfA8U2W+Veqo1uy0dOsPhl7vAHbBHrvJNfEUe8TT0q2eaTX2LeWpyrFEm4I3mhDJY/E9cpWf0A78e+y4c7NxewvcVvAakIHE8Xb8fgtqCTVQj3Q1eso7n1fKQj5YsQ20A86Gy9fz8dky78raeZnhYayn0b1riSUKxGVnWja2i02OvAVM3tCCvXwcbSkHTRjuIAbMu2mXF1UpKci3i/GzPmbxo9n/3aX/jpR6UvxMZuaEDEij4yzfZv7EyK9WCNBXxMmtTp3Uv6MZsK+nopXO3C0xFzZA/zQObwP3zhJ4sdatzMhFi9GAM70R4kgMzsxQDNArueXj+UFzbCCFZ89zXs22F7Ixi0FyFTk3jhH56dBaN65S+gtPztNGzEUmtk4M8IanhQSw8xCXr0x0MPDpDFDZs3aN5TtTPYmyk3psk7OrmofCQGG5cRcqEt9902qtxQDOHumfuCPMvU+oMjzLzBVEDnBbj+tY3y1jvgGbmEJguAgfB04tSeAt/2618ksnJJK+dbBkDLxjB4xrFr3uIFFadJQWUckl5vfh4MVXbsFA1hG49lqWDa7uSuPCnOhv8Yql376I4U4gfcF8LcgorkxS+64urv2nMUq6AkBEMQ8bdkI64oKLFfO7fGxh5iMNZuLoutDn2ll3nq4rPi4kOyAtfhW0UPyjvqNtXJ/h0Wik5Mi8z7BVxaURTDk81TP8y9+tzjySB/uGfHFAzjF8DUY1vqJCgn0GQ8ANtiiElX/+Wnc9HWi2bEEXItbm4yv97QrEPvJG9nPRBKWGiAQsIA5J+WryX5NrfEfRPk0QQwyl16lpHlw6l0UMuk7S21xjQgyWo0MywfzoBWW7+t4HH9sqavvP4dYAw81BxXqVHQhefUOS23en4bFUPWE98pAN6bul+kS767vDK34yTC3lA2a8wLrBEilmFhdB74fxbAl+db91PivhwF/CR4Igxr35uLdof7+jAYyACopQzmsbHpvAAwT2lapLix8H03nztAC3fBqFSPBVdIv12lsrrDw4dfhJEzq7AbL/Y7L/nIcBsQ/3UyVnZk4kZP1KzyPCBLLIQNpCVgOLJzQuyaQ6k2QCBy0eJ0ppUyfp54LjwVg0X7bwncYbAomG4ZcFwTQnC2AX3oYG5n6Bz4SLLjxrFsY+v/SVa+GqH8uePBh1TPkHVNmzjXXymEf5jROlnd+EjfQdRyitkjPrg2HiQxxDcVhCh5J2L5+6CY9eIaYgrbd8zJnzAD8KnowHwh2bi4JLgmt7ktJ1XGizox7cWf3/Dod56KAcaIrSVw9XzYybdJCf0YRA6yrwPWXbwnzc/4+UDkmegi+AoCEMoue+cC7vnYVdmlbq/YLE/DWJX383oz2Ryq8anFrZ8jYvdoh8WI+dIugYL2SwRjmBoSwn56XIaot/QpMo3pYJIa4o8aZIZrjvB7BXO5aCDeMuZdUMT6AXGAGF1AeAWxFd2XIo1coR+OplMNDuYia8YAtnSTJ9JwGYWi2dJz3xrxsTQpBONf3yn8LVf8eH+o5eXc7lzCtHlDB+YyI8V9PyMsUPOeyvpB3rr9fDfNy263Zx33zTi5jldgP2OetUqGfbwl+0+zNYnrg64bluyIN/Awt1doDCQkCKpKXxuPaem/SyCHrKjg' 71 | EndIf 72 | 73 | Local $Symbol[] = ["jsmn_parse", "jsmn_init", "json_string_decode", "json_string_encode"] 74 | Local $CodeBase = _BinaryCall_Create($Code) 75 | If @error Then Exit MsgBox(16, "Json", "Startup Failure!") 76 | 77 | $SymbolList = _BinaryCall_SymbolList($CodeBase, $Symbol) 78 | If @error Then Exit MsgBox(16, "Json", "Startup Failure!") 79 | EndIf 80 | If $ProcName Then Return DllStructGetData($SymbolList, $ProcName) 81 | EndFunc ;==>__Jsmn_RuntimeLoader 82 | 83 | Func Json_StringEncode($String, $Option = 0) 84 | Static $Json_StringEncode = __Jsmn_RuntimeLoader("json_string_encode") 85 | Local $Length = StringLen($String) * 6 + 1 86 | Local $Buffer = DllStructCreate("wchar[" & $Length & "]") 87 | Local $Ret = DllCallAddress("int:cdecl", $Json_StringEncode, "wstr", $String, "ptr", DllStructGetPtr($Buffer), "uint", $Length, "int", $Option) 88 | Return SetError($Ret[0], 0, DllStructGetData($Buffer, 1)) 89 | EndFunc ;==>Json_StringEncode 90 | 91 | Func Json_StringDecode($String) 92 | Static $Json_StringDecode = __Jsmn_RuntimeLoader("json_string_decode") 93 | Local $Length = StringLen($String) + 1 94 | Local $Buffer = DllStructCreate("wchar[" & $Length & "]") 95 | Local $Ret = DllCallAddress("int:cdecl", $Json_StringDecode, "wstr", $String, "ptr", DllStructGetPtr($Buffer), "uint", $Length) 96 | Return SetError($Ret[0], 0, DllStructGetData($Buffer, 1)) 97 | EndFunc ;==>Json_StringDecode 98 | 99 | Func Json_Decode($Json, $InitTokenCount = 1000) 100 | Static $Jsmn_Init = __Jsmn_RuntimeLoader("jsmn_init"), $Jsmn_Parse = __Jsmn_RuntimeLoader("jsmn_parse") 101 | If $Json = "" Then $Json = '""' 102 | Local $TokenList, $Ret 103 | Local $Parser = DllStructCreate("uint pos;int toknext;int toksuper") 104 | Do 105 | DllCallAddress("none:cdecl", $Jsmn_Init, "ptr", DllStructGetPtr($Parser)) 106 | $TokenList = DllStructCreate("byte[" & ($InitTokenCount * 20) & "]") 107 | $Ret = DllCallAddress("int:cdecl", $Jsmn_Parse, "ptr", DllStructGetPtr($Parser), "wstr", $Json, "ptr", DllStructGetPtr($TokenList), "uint", $InitTokenCount) 108 | $InitTokenCount *= 2 109 | Until $Ret[0] <> $JSMN_ERROR_NOMEM 110 | 111 | Local $Next = 0 112 | Return SetError($Ret[0], 0, _Json_Token($Json, DllStructGetPtr($TokenList), $Next)) 113 | EndFunc ;==>Json_Decode 114 | 115 | Func _Json_Token(ByRef $Json, $Ptr, ByRef $Next) 116 | If $Next = -1 Then Return Null 117 | 118 | Local $Token = DllStructCreate("int;int;int;int", $Ptr + ($Next * 20)) 119 | Local $Type = DllStructGetData($Token, 1) 120 | Local $Start = DllStructGetData($Token, 2) 121 | Local $End = DllStructGetData($Token, 3) 122 | Local $Size = DllStructGetData($Token, 4) 123 | $Next += 1 124 | 125 | If $Type = 0 And $Start = 0 And $End = 0 And $Size = 0 Then ; Null Item 126 | $Next = -1 127 | Return Null 128 | EndIf 129 | 130 | Switch $Type 131 | Case 0 ; Json_PRIMITIVE 132 | Local $Primitive = StringMid($Json, $Start + 1, $End - $Start) 133 | Switch $Primitive 134 | Case "true" 135 | Return True 136 | Case "false" 137 | Return False 138 | Case "null" 139 | Return Null 140 | Case Else 141 | If StringRegExp($Primitive, "^[+\-0-9]") Then 142 | Return Number($Primitive) 143 | Else 144 | Return Json_StringDecode($Primitive) 145 | EndIf 146 | EndSwitch 147 | 148 | Case 1 ; Json_OBJECT 149 | Local $Object = Json_ObjCreate() 150 | For $i = 0 To $Size - 1 Step 2 151 | Local $Key = _Json_Token($Json, $Ptr, $Next) 152 | Local $Value = _Json_Token($Json, $Ptr, $Next) 153 | If Not IsString($Key) Then $Key = Json_Encode($Key) 154 | 155 | If $Object.Exists($Key) Then $Object.Remove($Key) 156 | $Object.Add($Key, $Value) 157 | Next 158 | Return $Object 159 | 160 | Case 2 ; Json_ARRAY 161 | Local $Array[$Size] 162 | For $i = 0 To $Size - 1 163 | $Array[$i] = _Json_Token($Json, $Ptr, $Next) 164 | Next 165 | Return $Array 166 | 167 | Case 3 ; Json_STRING 168 | Return Json_StringDecode(StringMid($Json, $Start + 1, $End - $Start)) 169 | EndSwitch 170 | EndFunc ;==>_Json_Token 171 | 172 | Func Json_IsObject(ByRef $Object) 173 | Return (IsObj($Object) And ObjName($Object) = "Dictionary") 174 | EndFunc ;==>Json_IsObject 175 | 176 | Func Json_IsNull(ByRef $Null) 177 | Return IsKeyword($Null) Or (Not IsObj($Null) And VarGetType($Null) = "Object") 178 | EndFunc ;==>Json_IsNull 179 | 180 | Func Json_Encode_Compact($Data, $Option = 0) 181 | Local $Json = "" 182 | 183 | Select 184 | Case IsString($Data) 185 | Return '"' & Json_StringEncode($Data, $Option) & '"' 186 | 187 | Case IsNumber($Data) 188 | Return $Data 189 | 190 | Case IsArray($Data) And UBound($Data, 0) = 1 191 | $Json = "[" 192 | For $i = 0 To UBound($Data) - 1 193 | $Json &= Json_Encode_Compact($Data[$i], $Option) & "," 194 | Next 195 | If StringRight($Json, 1) = "," Then $Json = StringTrimRight($Json, 1) 196 | Return $Json & "]" 197 | 198 | Case Json_IsObject($Data) 199 | $Json = "{" 200 | Local $Keys = $Data.Keys() 201 | For $i = 0 To UBound($Keys) - 1 202 | $Json &= '"' & Json_StringEncode($Keys[$i], $Option) & '":' & Json_Encode_Compact($Data.Item($Keys[$i]), $Option) & "," 203 | Next 204 | If StringRight($Json, 1) = "," Then $Json = StringTrimRight($Json, 1) 205 | Return $Json & "}" 206 | 207 | Case IsBool($Data) 208 | Return StringLower($Data) 209 | 210 | Case IsPtr($Data) 211 | Return Number($Data) 212 | 213 | Case IsBinary($Data) 214 | Return '"' & Json_StringEncode(BinaryToString($Data, 4), $Option) & '"' 215 | 216 | Case Else ; Keyword, DllStruct, Object 217 | Return "null" 218 | EndSelect 219 | EndFunc ;==>Json_Encode_Compact 220 | 221 | Func Json_Encode_Pretty($Data, $Option, $Indent, $ArraySep, $ObjectSep, $ColonSep, $ArrayCRLF = Default, $ObjectCRLF = Default, $NextIdent = "") 222 | Local $ThisIdent = $NextIdent, $Json = "", $String = "", $Match = "", $Keys = "" 223 | Local $Length = 0 224 | 225 | Select 226 | Case IsString($Data) 227 | $String = Json_StringEncode($Data, $Option) 228 | If BitAND($Option, $JSON_UNQUOTED_STRING) And Not BitAND($Option, $JSON_STRICT_PRINT) And Not StringRegExp($String, "[\s,:]") And Not StringRegExp($String, "^[+\-0-9]") Then 229 | Return $String 230 | Else 231 | Return '"' & $String & '"' 232 | EndIf 233 | 234 | Case IsArray($Data) And UBound($Data, 0) = 1 235 | If UBound($Data) = 0 Then Return "[]" 236 | If IsKeyword($ArrayCRLF) Then 237 | $ArrayCRLF = "" 238 | $Match = StringRegExp($ArraySep, "[\r\n]+$", 3) 239 | If IsArray($Match) Then $ArrayCRLF = $Match[0] 240 | EndIf 241 | 242 | If $ArrayCRLF Then $NextIdent &= $Indent 243 | $Length = UBound($Data) - 1 244 | For $i = 0 To $Length 245 | If $ArrayCRLF Then $Json &= $NextIdent 246 | $Json &= Json_Encode_Pretty($Data[$i], $Option, $Indent, $ArraySep, $ObjectSep, $ColonSep, $ArrayCRLF, $ObjectCRLF, $NextIdent) 247 | If $i < $Length Then $Json &= $ArraySep 248 | Next 249 | 250 | If $ArrayCRLF Then Return "[" & $ArrayCRLF & $Json & $ArrayCRLF & $ThisIdent & "]" 251 | Return "[" & $Json & "]" 252 | 253 | Case Json_IsObject($Data) 254 | If $Data.Count = 0 Then Return "{}" 255 | If IsKeyword($ObjectCRLF) Then 256 | $ObjectCRLF = "" 257 | $Match = StringRegExp($ObjectSep, "[\r\n]+$", 3) 258 | If IsArray($Match) Then $ObjectCRLF = $Match[0] 259 | EndIf 260 | 261 | If $ObjectCRLF Then $NextIdent &= $Indent 262 | $Keys = $Data.Keys() 263 | $Length = UBound($Keys) - 1 264 | For $i = 0 To $Length 265 | If $ObjectCRLF Then $Json &= $NextIdent 266 | $Json &= Json_Encode_Pretty(String($Keys[$i]), $Option, $Indent, $ArraySep, $ObjectSep, $ColonSep) & $ColonSep _ 267 | & Json_Encode_Pretty($Data.Item($Keys[$i]), $Option, $Indent, $ArraySep, $ObjectSep, $ColonSep, $ArrayCRLF, $ObjectCRLF, $NextIdent) 268 | If $i < $Length Then $Json &= $ObjectSep 269 | Next 270 | 271 | If $ObjectCRLF Then Return "{" & $ObjectCRLF & $Json & $ObjectCRLF & $ThisIdent & "}" 272 | Return "{" & $Json & "}" 273 | 274 | Case Else 275 | Return Json_Encode_Compact($Data, $Option) 276 | 277 | EndSelect 278 | EndFunc ;==>Json_Encode_Pretty 279 | 280 | Func Json_Encode($Data, $Option = 0, $Indent = Default, $ArraySep = Default, $ObjectSep = Default, $ColonSep = Default) 281 | If BitAND($Option, $JSON_PRETTY_PRINT) Then 282 | Local $Strict = BitAND($Option, $JSON_STRICT_PRINT) 283 | 284 | If IsKeyword($Indent) Then 285 | $Indent = @TAB 286 | Else 287 | $Indent = Json_StringDecode($Indent) 288 | If StringRegExp($Indent, "[^\t ]") Then $Indent = @TAB 289 | EndIf 290 | 291 | If IsKeyword($ArraySep) Then 292 | $ArraySep = "," & @CRLF 293 | Else 294 | $ArraySep = Json_StringDecode($ArraySep) 295 | If $ArraySep = "" Or StringRegExp($ArraySep, "[^\s,]|,.*,") Or ($Strict And Not StringRegExp($ArraySep, ",")) Then $ArraySep = "," & @CRLF 296 | EndIf 297 | 298 | If IsKeyword($ObjectSep) Then 299 | $ObjectSep = "," & @CRLF 300 | Else 301 | $ObjectSep = Json_StringDecode($ObjectSep) 302 | If $ObjectSep = "" Or StringRegExp($ObjectSep, "[^\s,]|,.*,") Or ($Strict And Not StringRegExp($ObjectSep, ",")) Then $ObjectSep = "," & @CRLF 303 | EndIf 304 | 305 | If IsKeyword($ColonSep) Then 306 | $ColonSep = ": " 307 | Else 308 | $ColonSep = Json_StringDecode($ColonSep) 309 | If $ColonSep = "" Or StringRegExp($ColonSep, "[^\s,:]|[,:].*[,:]") Or ($Strict And (StringRegExp($ColonSep, ",") Or Not StringRegExp($ColonSep, ":"))) Then $ColonSep = ": " 310 | EndIf 311 | 312 | Return Json_Encode_Pretty($Data, $Option, $Indent, $ArraySep, $ObjectSep, $ColonSep) 313 | 314 | ElseIf BitAND($Option, $JSON_UNQUOTED_STRING) Then 315 | Return Json_Encode_Pretty($Data, $Option, "", ",", ",", ":") 316 | Else 317 | Return Json_Encode_Compact($Data, $Option) 318 | EndIf 319 | EndFunc ;==>Json_Encode 320 | 321 | Func Json_ObjCreate() 322 | Local $Object = ObjCreate('Scripting.Dictionary') 323 | $Object.CompareMode = 0 324 | Return $Object 325 | EndFunc ;==>Json_ObjCreate 326 | 327 | Func Json_ObjPut(ByRef $Object, $Key, $Value) 328 | $Key = String($Key) 329 | If $Object.Exists($Key) Then $Object.Remove($Key) 330 | $Object.Add($Key, $Value) 331 | EndFunc ;==>Json_ObjPut 332 | 333 | Func Json_ObjGet(ByRef $Object, $Key) 334 | Local $DynObject = $Object 335 | Local $Keys = StringSplit($Key, ".") 336 | For $x = 1 To $Keys[0] 337 | If $DynObject.Exists($Keys[$x]) Then 338 | If $x = $Keys[0] Then 339 | Return $DynObject.Item($Keys[$x]) 340 | Else 341 | $DynObject = Json_ObjGet($DynObject, $Keys[$x]) 342 | EndIf 343 | EndIf 344 | Next 345 | Return SetError(1, 0, '') 346 | EndFunc ;==>Json_ObjGet 347 | 348 | Func Json_ObjDelete(ByRef $Object, $Key) 349 | $Key = String($Key) 350 | If $Object.Exists($Key) Then $Object.Remove($Key) 351 | EndFunc ;==>Json_ObjDelete 352 | 353 | Func Json_ObjExists(ByRef $Object, $Key) 354 | Local $DynObject = $Object 355 | Local $Keys = StringSplit($Key, ".") 356 | For $x = 1 To $Keys[0] 357 | If $DynObject.Exists($Keys[$x]) Then 358 | If $x = $Keys[0] Then 359 | Return True 360 | Else 361 | $DynObject = Json_ObjGet($DynObject, $Keys[$x]) 362 | If Not IsObj($DynObject) Then Return False ;Added by XTC 363 | EndIf 364 | Else 365 | Return False 366 | EndIf 367 | Next 368 | Return False 369 | EndFunc ;==>Json_ObjExists 370 | 371 | Func Json_ObjGetCount(ByRef $Object) 372 | Return $Object.Count 373 | EndFunc ;==>Json_ObjGetCount 374 | 375 | Func Json_ObjGetKeys(ByRef $Object) 376 | Return $Object.Keys() 377 | EndFunc ;==>Json_ObjGetKeys 378 | 379 | Func Json_ObjGetItems(ByRef $Object) 380 | Return $Object.Items() 381 | EndFunc ;==>Json_ObjGetItems 382 | 383 | Func Json_ObjClear(ByRef $Object) 384 | Return $Object.RemoveAll() 385 | EndFunc ;==>Json_ObjClear 386 | 387 | ; Both dot notation and square bracket notation can be supported 388 | Func Json_Put(ByRef $Var, $Notation, $Data, $CheckExists = False) 389 | ;Dot-notation and bracket-notation regular expressions 390 | Const $REGEX_DOT_WITH_STRING = '^\.("[^"]+")', _ 391 | $REGEX_DOT_WITH_LITERAL = '^\.([^.[]+)', _ 392 | $REGEX_BRACKET_WITH_STRING = '^\[("[^"]+")]', _ 393 | $REGEX_BRACKET_WITH_LITERAL = '^\[([^]]+)]' 394 | 395 | Local $Ret = 0, $Item = "", $Error = 0 396 | Local $Match = "" 397 | 398 | ;Set regular expression based on identified notation type. 399 | ;Note: The order below matters. Check "string" notations 400 | ;before their "literal" counterpart. 401 | Local $Regex = "" 402 | Select 403 | Case StringRegExp($Notation, $REGEX_DOT_WITH_STRING) 404 | $Regex = $REGEX_DOT_WITH_STRING 405 | Case StringRegExp($Notation, $REGEX_DOT_WITH_LITERAL) 406 | $Regex = $REGEX_DOT_WITH_LITERAL 407 | Case StringRegExp($Notation, $REGEX_BRACKET_WITH_STRING) 408 | $Regex = $REGEX_BRACKET_WITH_STRING 409 | Case StringRegExp($Notation, $REGEX_BRACKET_WITH_LITERAL) 410 | $Regex = $REGEX_BRACKET_WITH_LITERAL 411 | Case Else 412 | Return SetError(2, 0, "") ; invalid notation 413 | EndSelect 414 | 415 | ;Parse leading notation 416 | $Match = StringRegExp($Notation, $Regex, 2) 417 | If IsArray($Match) Then 418 | Local $Index 419 | If StringLeft($Match[0], 1) = "." Then 420 | $Index = String(Json_Decode($Match[1])) ;only string using dot-notation 421 | Else 422 | $Index = Json_Decode($Match[1]) 423 | EndIf 424 | $Notation = StringTrimLeft($Notation, StringLen($Match[0])) ;trim leading notation 425 | 426 | If IsString($Index) Then 427 | If $CheckExists And (Not Json_IsObject($Var) Or Not $Var.Exists($Index)) Then 428 | Return SetError(1, 0, False) ; no specific object 429 | EndIf 430 | 431 | If Not Json_IsObject($Var) Then $Var = Json_ObjCreate() 432 | If $Notation Then 433 | $Item = $Var.Item($Index) 434 | $Ret = Json_Put($Item, $Notation, $Data, $CheckExists) 435 | $Error = @error 436 | If Not $Error Then Json_ObjPut($Var, $Index, $Item) 437 | Return SetError($Error, 0, $Ret) 438 | Else 439 | Json_ObjPut($Var, $Index, $Data) 440 | Return True 441 | EndIf 442 | 443 | ElseIf IsInt($Index) Then 444 | If $Index < 0 Or ($CheckExists And (Not IsArray($Var) Or UBound($Var, 0) <> 1 Or $Index >= UBound($Var))) Then 445 | Return SetError(1, 0, False) ; no specific object 446 | EndIf 447 | 448 | If Not IsArray($Var) Or UBound($Var, 0) <> 1 Then 449 | Dim $Var[$Index + 1] 450 | ElseIf $Index >= UBound($Var) Then 451 | ReDim $Var[$Index + 1] 452 | EndIf 453 | 454 | If $Notation Then 455 | $Ret = Json_Put($Var[$Index], $Notation, $Data, $CheckExists) 456 | Return SetError(@error, 0, $Ret) 457 | Else 458 | $Var[$Index] = $Data 459 | Return True 460 | EndIf 461 | 462 | EndIf 463 | EndIf 464 | Return SetError(2, 0, False) ; invalid notation 465 | EndFunc ;==>Json_Put 466 | 467 | ; Both dot notation and square bracket notation can be supported 468 | Func Json_Get(ByRef $Var, $Notation) 469 | ;Dot-notation and bracket-notation regular expressions 470 | Const $REGEX_DOT_WITH_STRING = '^\.("[^"]+")', _ 471 | $REGEX_DOT_WITH_LITERAL = '^\.([^.[]+)', _ 472 | $REGEX_BRACKET_WITH_STRING = '^\[("[^"]+")]', _ 473 | $REGEX_BRACKET_WITH_LITERAL = '^\[([^]]+)]' 474 | 475 | ;Set regular expression based on identified notation type. 476 | ;Note: The order below matters. Check "string" notations 477 | ;before their "literal" counterpart. 478 | Local $Regex = "" 479 | Select 480 | Case StringRegExp($Notation, $REGEX_DOT_WITH_STRING) 481 | $Regex = $REGEX_DOT_WITH_STRING 482 | Case StringRegExp($Notation, $REGEX_DOT_WITH_LITERAL) 483 | $Regex = $REGEX_DOT_WITH_LITERAL 484 | Case StringRegExp($Notation, $REGEX_BRACKET_WITH_STRING) 485 | $Regex = $REGEX_BRACKET_WITH_STRING 486 | Case StringRegExp($Notation, $REGEX_BRACKET_WITH_LITERAL) 487 | $Regex = $REGEX_BRACKET_WITH_LITERAL 488 | Case Else 489 | Return SetError(2, 0, "") ; invalid notation 490 | EndSelect 491 | 492 | ;Parse leading notation 493 | Local $Match = StringRegExp($Notation, $Regex, 2) 494 | If IsArray($Match) Then 495 | Local $Index 496 | If StringLeft($Match[0], 1) = "." Then 497 | $Index = String(Json_Decode($Match[1])) ;only string using dot-notation 498 | Else 499 | $Index = Json_Decode($Match[1]) 500 | EndIf 501 | $Notation = StringTrimLeft($Notation, StringLen($Match[0])) ;trim leading notation 502 | 503 | Local $Item 504 | If IsString($Index) And Json_IsObject($Var) And $Var.Exists($Index) Then 505 | $Item = $Var.Item($Index) 506 | ElseIf IsInt($Index) And IsArray($Var) And UBound($Var, 0) = 1 And $Index >= 0 And $Index < UBound($Var) Then 507 | $Item = $Var[$Index] 508 | Else 509 | Return SetError(1, 0, "") ; no specific object 510 | EndIf 511 | 512 | If Not $Notation Then Return $Item 513 | 514 | Local $Ret = Json_Get($Item, $Notation) 515 | Return SetError(@error, 0, $Ret) 516 | EndIf 517 | EndFunc ;==>Json_Get 518 | 519 | ; List all JSON keys and their value to the Console 520 | Func Json_Dump($Json, $InitTokenCount = 1000) 521 | Static $Jsmn_Init = __Jsmn_RuntimeLoader("jsmn_init"), $Jsmn_Parse = __Jsmn_RuntimeLoader("jsmn_parse") 522 | If $Json = "" Then $Json = '""' 523 | Local $TokenList, $Ret 524 | $Total_JSON_DUMP_Output = "" ; reset totaldump variable at the start of the dump process (Use for testing) 525 | Local $Parser = DllStructCreate("uint pos;int toknext;int toksuper") 526 | Do 527 | DllCallAddress("none:cdecl", $Jsmn_Init, "ptr", DllStructGetPtr($Parser)) 528 | $TokenList = DllStructCreate("byte[" & ($InitTokenCount * 20) & "]") 529 | $Ret = DllCallAddress("int:cdecl", $Jsmn_Parse, "ptr", DllStructGetPtr($Parser), "wstr", $Json, "ptr", DllStructGetPtr($TokenList), "uint", $InitTokenCount) 530 | $InitTokenCount *= 2 531 | Until $Ret[0] <> $JSMN_ERROR_NOMEM 532 | 533 | Local $Next = 0 534 | _Json_TokenDump($Json, DllStructGetPtr($TokenList), $Next) 535 | EndFunc ;==>Json_Dump 536 | 537 | Func _Json_TokenDump(ByRef $Json, $Ptr, ByRef $Next, $ObjPath = "") 538 | If $Next = -1 Then Return Null 539 | 540 | Local $Token = DllStructCreate("int;int;int;int", $Ptr + ($Next * 20)) 541 | Local $Type = DllStructGetData($Token, 1) 542 | Local $Start = DllStructGetData($Token, 2) 543 | Local $End = DllStructGetData($Token, 3) 544 | Local $Size = DllStructGetData($Token, 4) 545 | Local $Value 546 | $Next += 1 547 | 548 | If $Type = 0 And $Start = 0 And $End = 0 And $Size = 0 Then ; Null Item 549 | $Next = -1 550 | Return Null 551 | EndIf 552 | 553 | Switch $Type 554 | Case 0 ; Json_PRIMITIVE 555 | Local $Primitive = StringMid($Json, $Start + 1, $End - $Start) 556 | Switch $Primitive 557 | Case "true" 558 | Return "True" 559 | Case "false" 560 | Return "False" 561 | Case "null" 562 | Return "Null" 563 | Case Else 564 | If StringRegExp($Primitive, "^[+\-0-9]") Then 565 | Return Number($Primitive) 566 | Else 567 | Return Json_StringDecode($Primitive) 568 | EndIf 569 | EndSwitch 570 | 571 | Case 1 ; Json_OBJECT 572 | For $i = 0 To $Size - 1 Step 2 573 | Local $Key = _Json_TokenDump($Json, $Ptr, $Next) 574 | Local $cObjPath = $ObjPath & "." & $Key 575 | $Value = _Json_TokenDump($Json, $Ptr, $Next, $ObjPath & "." & $Key) 576 | If Not (IsBool($Value) And $Value = False) Then 577 | If Not IsString($Key) Then 578 | $Key = Json_Encode($Key) 579 | EndIf 580 | ; show the key and its value 581 | ConsoleWrite("+-> " & $cObjPath & ' =' & $Value & @CRLF) 582 | $Total_JSON_DUMP_Output &= "+-> " & $cObjPath & ' =' & $Value & @CRLF 583 | EndIf 584 | Next 585 | Return False 586 | Case 2 ; Json_ARRAY 587 | Local $sObjPath = $ObjPath 588 | For $i = 0 To $Size - 1 589 | $sObjPath = $ObjPath & "[" & $i & "]" 590 | $Value = _Json_TokenDump($Json, $Ptr, $Next, $sObjPath) 591 | If Not (IsBool($Value) And $Value = False) Then ;XC - Changed line 592 | ; show the key and its value 593 | ConsoleWrite("+=> " & $sObjPath & "=>" & $Value & @CRLF) 594 | $Total_JSON_DUMP_Output &= "+=> " & $sObjPath & "=>" & $Value & @CRLF 595 | EndIf 596 | Next 597 | $ObjPath = $sObjPath 598 | Return False 599 | 600 | Case 3 ; Json_STRING 601 | Local $LastKey = Json_StringDecode(StringMid($Json, $Start + 1, $End - $Start)) 602 | Return $LastKey 603 | EndSwitch 604 | EndFunc ;==>_Json_TokenDump -------------------------------------------------------------------------------- /libs/Polices.au3: -------------------------------------------------------------------------------- 1 | #include "JSON.au3" 2 | #include 3 | #include 4 | 5 | Func UpdatePolices($FirefoxDir, $key, $value) 6 | Local $policiesFolder = $FirefoxDir & "\distribution" 7 | Local $policiesFile = $policiesFolder & "\policies.json" 8 | Local $FileContent, $JSONObj, $DisableObj 9 | 10 | ;~ 如果文件夹不存在则创建 11 | If Not FileExists($policiesFolder) Then 12 | DirCreate($policiesFolder) 13 | EndIf 14 | 15 | If Not FileExists($policiesFile) Then 16 | ;~ 如果文件不存在,创建默认策略对象 17 | $JSONObj = CreateDefaultPolicesObj() 18 | Else 19 | ;~ 如果文件存在,读取文件内容 20 | $FileContent = FileRead($policiesFile) 21 | $JSONObj = Json_Decode($FileContent) 22 | If Not Json_IsObject($JSONObj) Then 23 | ;~ 文件内容不是对象,创建默认策略对象 24 | $JSONObj = CreateDefaultPolicesObj() 25 | EndIf 26 | EndIf 27 | 28 | ;~ 更新或删除JSON对象 29 | If $value = "" Then 30 | ;~ 如果值为空,删除属性 31 | DeleteJsonObj($JSONObj, $key) 32 | Else 33 | ;~ 否则更新属性 34 | UpdateJsonObj($JSONObj, $key, $value) 35 | EndIf 36 | 37 | ;~ 格式化 JSON 字符串 38 | $FileContent = Json_Encode_Pretty($JSONObj, $JSON_PRETTY_PRINT, @TAB, "," & @CRLF, "," & @CRLF, ": ") 39 | 40 | ; 将 "true" 替换为 true,"false" 替换为 false 41 | $FileContent = StringReplace($FileContent, '"true"', 'true') 42 | $FileContent = StringReplace($FileContent, '"false"', 'false') 43 | 44 | ; 写入文件 45 | Local $hFile = FileOpen($policiesFile, $FO_CREATEPATH + $FO_OVERWRITE) 46 | If $hFile <> -1 Then 47 | FileWrite($hFile, $FileContent) 48 | FileClose($hFile) 49 | EndIf 50 | EndFunc 51 | 52 | ;~ 创建默认 Polices 对象 53 | Func CreateDefaultPolicesObj() 54 | $JSONObj = Json_ObjCreate() 55 | $DisableObj = Json_ObjCreate() 56 | Json_ObjPut($DisableObj, "DisableAppUpdate", true) 57 | Json_ObjPut($DisableObj, "DontCheckDefaultBrowser", true) 58 | Json_ObjPut($JSONObj, "policies", $DisableObj) 59 | Return $JSONObj 60 | EndFunc 61 | 62 | Func GetItemFromJsonObj($JSONObj, $key) 63 | Local $obj 64 | If Not Json_ObjExists($JSONObj, $key) Then 65 | $obj = Json_ObjCreate() 66 | Else 67 | $obj = Json_ObjGet($JSONObj, $key) 68 | EndIf 69 | Return $obj 70 | EndFunc 71 | 72 | ;~ 修改属性值 73 | Func UpdateJsonObj($JSONObj, $key, $value) 74 | $PolicesObj = GetItemFromJsonObj($JSONObj, "policies") 75 | Json_ObjPut($PolicesObj, $key, $value) 76 | EndFunc 77 | 78 | ;~ 删除属性 79 | Func DeleteJsonObj($JSONObj, $key) 80 | $PolicesObj = GetItemFromJsonObj($JSONObj, "policies") 81 | If Json_ObjExists($PolicesObj, $key) Then 82 | Json_ObjDelete($PolicesObj, $key) 83 | EndIf 84 | EndFunc -------------------------------------------------------------------------------- /libs/ScriptingDictionary.au3: -------------------------------------------------------------------------------- 1 | #cs 2 | Scripting Dictionary UDF 3 | 4 | Made by GaryFrost 5 | Modified by Jefrey 6 | #ce 7 | 8 | Func _InitDictionary() 9 | Return ObjCreate("Scripting.Dictionary") 10 | EndFunc ;==>_InitDictionary 11 | 12 | ; Adds a key and item pair to a Dictionary object. 13 | Func _AddItem($oDictionary, $v_key, $v_item) 14 | $oDictionary.ADD($v_key, $v_item) 15 | If @error Then Return SetError(1, 1, -1) 16 | EndFunc ;==>_AddItem 17 | 18 | ; Returns true if a specified key exists in the Dictionary object, false if it does not. 19 | Func _ItemExists($oDictionary, $v_key) 20 | Return $oDictionary.Exists($v_key) 21 | EndFunc ;==>_ItemExists 22 | 23 | ; Returns an item for a specified key in a Dictionary object 24 | Func _Item($oDictionary, $v_key) 25 | Return $oDictionary.Item($v_key) 26 | EndFunc ;==>_Item 27 | 28 | ; Sets an item for a specified key in a Dictionary object 29 | Func _ChangeItem($oDictionary, $v_key, $v_item) 30 | $oDictionary.Item($v_key) = $v_item 31 | EndFunc ;==>_ChangeItem 32 | 33 | ; Sets a key in a Dictionary object. 34 | Func _ChangeKey($oDictionary, $v_key, $v_newKey) 35 | $oDictionary.Key($v_key) = $v_newKey 36 | EndFunc ;==>_ChangeKey 37 | 38 | ; Removes a key, item pair from a Dictionary object. 39 | Func _ItemRemove($oDictionary, $v_key) 40 | $oDictionary.Remove($v_key) 41 | If @error Then Return SetError(1, 1, -1) 42 | EndFunc ;==>_ItemRemove 43 | 44 | ; Returns the number of items in a collection or Dictionary object. 45 | Func _ItemCount($oDictionary) 46 | Return $oDictionary.Count 47 | EndFunc ;==>_ItemCount 48 | 49 | ; Returns an array containing all the items in a Dictionary object 50 | Func _GetItems($oDictionary) 51 | Return $oDictionary.Items 52 | EndFunc ;==>_GetItems 53 | 54 | Func _Clear($oDictionary) 55 | Return $oDictionary.RemoveAll 56 | EndFunc -------------------------------------------------------------------------------- /libs/UpgradeHelper.au3: -------------------------------------------------------------------------------- 1 | Func RemoveHTMLTags($str) 2 | ;~ 使用正则表达式删除HTML标签 3 | Return StringRegExpReplace($str, '<[^>]*>', '') 4 | EndFunc 5 | 6 | Func GetLatestReleaseVersion($sRepositoryName, $sMirrorAddress = "https://mirror.ghproxy.com/") 7 | ;~ 构建 GitHub releases 页面的 URL 8 | Local $sURL = $sMirrorAddress & "https://github.com/" & $sRepositoryName & "/releases/" 9 | ;~ 从 URL 获取页面内容 10 | Local $sPageContent = BinaryToString(InetRead($sURL, 1)) 11 | 12 | If @error Then 13 | ;~ TrayTip("", StringFormat(_t("GetReleaseTagFailed", "获取更新信息失败!"))) 14 | Return '' 15 | EndIf 16 | 17 | ;~ 使用正则表达式提取版本号 18 | Local $aMatches = StringRegExp($sPageContent, '/' & $sRepositoryName & '/releases/tag/(v\d+\.\d+\.\d+)', 3) 19 | 20 | If @error Then 21 | ;~ TrayTip("", StringFormat(_t("GetReleaseTagFailed", "获取更新信息失败!"))) '' 22 | Return '' 23 | EndIf 24 | 25 | ;~ 获取最新版本号 26 | Local $sLatestVersion = $aMatches[0] 27 | 28 | Return $sLatestVersion 29 | EndFunc 30 | 31 | Func GetReleaseNotesByVersion($sRepositoryName, $version, $sMirrorAddress = "https://mirror.ghproxy.com/") 32 | ;~ 构建指定版本的 GitHub releases 页面的 URL 33 | Local $sURL = $sMirrorAddress & "https://github.com/" & $sRepositoryName & "/releases/tag/" & $version 34 | 35 | ;~ 从 URL 获取页面内容 36 | Local $sPageContent = BinaryToString(InetRead($sURL, 1), 4) 37 | 38 | If @error Then 39 | Return '' 40 | EndIf 41 | 42 | ;~ 定义开始和结束标记以提取发布说明部分 43 | Local $sStartTag = '"markdown-body my-3">' 44 | Local $sEndTag = '