Files
PhoenixPE/Projects/PhoenixPE/PhoenixAPI.script

1876 lines
94 KiB
Plaintext

[License]
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// This script is part of the PhoenixPE project and distributed under the MIT License.
//
// Additional 3rd party tools, encoded files, and programs used by the project are the property
// of their respective authors and may be subject to their own license agreement.
//
// Copyright (c) 2014-2023 Jonathan Holmgren (Homes32)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////
[Main]
Title=PhoenixPE API
Author=Homes32
Description=PhoenixPE scripting support library.
Version=1.7.0.0
Date=2023-01-15
Level=0
Selected=None
[Variables]
// Defines the configuration (pre-shell) processor used for things like creating shortcuts and auto-run entries.
// In the future this can be used to add support for replacement pre-shell processors.
// PECMD - Use PECMD (Default)
%_PhoenixAPI_ConfigMode%=PECMD
[Macros]
// Registry
RegLoadHives=Run,%API%,_PhoenixAPI_RegLoadHives
RegUnloadHives=Run,%API%,_PhoenixAPI_RegUnloadHives
RegCopyDriver=Run,%API%,_PhoenixAPI_RegCopyDriver
Associate=Run,%API%,_PhoenixAPI_Associate
// Shortcuts/Autorun
RunFromRam=Run,%API%,_PhoenixAPI_RunFromRam
AddAutoRun=Run,%API%,_PhoenixAPI_AddAutoRun
AddShortcut=Run,%API%,_PhoenixAPI_AddShortcut
PinShortcut=Run,%API%,_PhoenixAPI_PinShortcut
// File/Dir Handling
DirDeleteEx=Run,%API%,_PhoenixAPI_DirDeleteEx
FileCopyEx=Run,%API%,_PhoenixAPI_FileCopyEx
FileDeleteEx=Run,%API%,_PhoenixAPI_FileDeleteEx
InnoCleanup=Run,%API%,_PhoenixAPI_InnoCleanup
InnoRename=Run,%API%,_PhoenixAPI_InnoRename
// ACL Management
SetFileACL=Run,%API%,_PhoenixAPI_SetFileACL
SetRegACL=Run,%API%,_PhoenixAPI_SetRegACL
// Include Files
RequireDriver=Run,%API%,_PhoenixAPI_RequireDriver
RequireFile=Run,%API%,_PhoenixAPI_RequireFile
RequireFileEx=Run,%API%,_PhoenixAPI_RequireFileEx
// Utility
Binmay=Run,%API%,_PhoenixAPI_Binmay
ConvertImage=Run,%API%,_PhoenixAPI_ConvertImage
DISM=Run,%API%,_PhoenixAPI_DISM
AddPostProcess=Run,%API%,_PhoenixAPI_AddPostProcess
GetBinaryResource=Run,%API%,_PhoenixAPI_GetBinaryResource
//GetStringResource=Run,%API%,_PhoenixAPI_GetStringResource
// Compression/Decompression
7z=Run,%API%,_PhoenixAPI_7z
//7zExtract=NOT IMPLIMENTED
InnoExtract=Run,%API%,_PhoenixAPI_InnoExtract
Innounp=Run,%API%,_PhoenixAPI_Innounp
MSIExtract=Run,%API%,_PhoenixAPI_MSIExtract
WixExtract=Run,%API%,_PhoenixAPI_WixExtract
// JSON
JSONCompact=Run,%API%,_PhoenixAPI_JSONCompact
JSONDelete=Run,%API%,_PhoenixAPI_JSONDelete
JSONPretty=Run,%API%,_PhoenixAPI_JSONPretty
JSONRead=Run,%API%,_PhoenixAPI_JSONRead
//JSON2INI=NOT IMPLIMENTED
//INI2JSON=NOT IMPLIMENTED
JSONWrite=Run,%API%,_PhoenixAPI_JSONWrite
// XML
XMLAdd=Run,%API%,_PhoenixAPI_XMLAdd
XMLDelete=Run,%API%,_PhoenixAPI_XMLDelete
//XMLRead=NOT IMPLIMENTED
XMLRename=Run,%API%,_PhoenixAPI_XMLRename
XMLUpdate=Run,%API%,_PhoenixAPI_XMLUpdate
// Bitmask Handling
ApplyBitMask=Run,%API%,_PhoenixAPI_ApplyBitMask
BitClear=Run,%API%,_PhoenixAPI_BitClear
BitSet=Run,%API%,_PhoenixAPI_BitSet
BitToggle=Run,%API%,_PhoenixAPI_BitToggle
[#_PhoenixAPI_RegLoadHives#]
// ===============================================================================================================================
// Name...........: RegLoadHives
// Description....: Mount Source and Build registry hives.
// Syntax.........: RegLoadHives
// Parameters.....:
// Return values..:
// Author.........: Homes32
// Remarks........:
// Related........:
// ===============================================================================================================================
[_PhoenixAPI_RegLoadHives]
RegHiveLoad,Tmp_Default,%RegDefault%
RegHiveLoad,Tmp_Drivers,%RegDrivers%
RegHiveLoad,Tmp_Software,%RegSoftware%
RegHiveLoad,Tmp_System,%RegSystem%
RegHiveLoad,Tmp_Install_Default,%RegInstallDefault%
RegHiveLoad,Tmp_Install_Drivers,%RegInstallDrivers%
RegHiveLoad,Tmp_Install_Software,%RegInstallSoftware%
RegHiveLoad,Tmp_Install_System,%RegInstallSystem%
[#_PhoenixAPI_RegUnloadHives#]
// ===============================================================================================================================
// Name...........: RegUnloadHives
// Description....: UnMount Source and Build registry hives.
// Syntax.........: RegUnLoadHives[,FORCE][,HKEY=<HKEY>][,Target=<Dir>]
// Parameters.....: Force - Force hive unload using HiveUnload.exe
// HKEY=<HKEY> - Unload hives from this root key. (HKLM, HKU)
// Target=<Dir> - Unload hives from this directory.
// Return values..: ExitCode provided by the HiveUnload.exe application
// 0 - All registry hives unloaded successfully.
// 1 - Not all registry hives could be unloaded.
// 2 - No loaded registry hives were found.
// You must handle ExitCode. The script will not Exit/Halt.
// Author.........: Homes32
// Remarks........: HiveUnload.exe is open-source software developed by BlueLife
// Related........:
// ===============================================================================================================================
[_PhoenixAPI_RegUnloadHives]
System,SetLocal
GetParam,1,%Arg1%
GetParam,2,%Arg2%
GetParam,3,%Arg3%
Set,%ForceUnmount%,False
Set,%HKEY%,"HKLM"
Set,%UnloadTarget%,"ALL"
Run,%API%,__PhoenixAPI_RegUnloadHives_Process_Arg,%Arg1%
Run,%API%,__PhoenixAPI_RegUnloadHives_Process_Arg,%Arg2%
Run,%API%,__PhoenixAPI_RegUnloadHives_Process_Arg,%Arg3%
If,%ForceUnmount%,Equal,True,Begin
If,ExistFile,"%Tools%\x86\HiveUnload.exe",ShellExecute,Hide,"%Tools%\x86\HiveUnload.exe","/%HKEY% /Target:%UnloadTarget%"
If,%ExitCode%,Equal,0,Echo,"HiveUnload: All registry hives unloaded successfully."
If,%ExitCode%,Equal,1,Echo,"HiveUnload: Warning: Not all registry hives could be unloaded! Please verify that regedit is not running and try again.",Warn
If,%ExitCode%,Equal,2,Echo,"HiveUnload: No loaded registry hives were found."
End
Else,Begin
RegHiveUnload,Tmp_Default
RegHiveUnload,Tmp_Drivers
RegHiveUnload,Tmp_Software
RegHiveUnload,Tmp_System
RegHiveUnload,Tmp_Install_Default
RegHiveUnload,Tmp_Install_Drivers
RegHiveUnload,Tmp_Install_Software
RegHiveUnload,Tmp_Install_System
End
System,EndLocal
[#__PhoenixAPI_RegUnloadHives_Process_Arg#]
// ===============================================================================================================================
// Name...........: __PhoenixAPI_RegUnloadHives_Process_Arg
// Description....: Process RegUnloadHives optional arguments
// Syntax.........: __PhoenixAPI_RegUnloadHives_Process_Arg,<Arg>
// Parameters.....: #1 Arg - The argument to process
// Return values..:
// Author.........: Homes32
// Remarks........: Internal Function
// Do not call System,SetLocal here. We need this function to run in the same scope as the caller
// Related........: _PhoenixAPI_RegUnloadHives
// ===============================================================================================================================
[__PhoenixAPI_RegUnloadHives_Process_Arg]
If,#1,Equal,"Force",Set,%ForceUnmount%,True
Else,Begin
StrFormat,Split,#1,"=",1,%ArgKey%
If,Not,%ArgKey%,Equal,"",Begin
If,%ArgKey%,Equal,"HKEY",StrFormat,Split,#1,"=",2,%HKEY%
Else,If,%ArgKey%,Equal,"TARGET",StrFormat,Split,#1,"=",2,%UnloadTarget%
Else,Halt,"SYNTAX ERROR: Invalid Argument [#1]"
End
End
[#_PhoenixAPI_RegCopyDriver#]
// ===============================================================================================================================
// Name...........: RegCopyDriver
// Description....: Copy the driver entries from the INSTALL.WIM driver database to the target registry driver database.
// Both the DRIVERS hive and SYSTEM\Drivers store are processed.
// Syntax.........: RegCopyDriver,<filename.inf>
// Parameters.....: InfFile - The name of the driver's .inf file
// Return values..:
// Author.........: Homes32
// Remarks........: This function uses a modified version of ChrisR's RegAddDriver.cmd as PEBakery does not have a good way
// to enum/query registry keys yet...
// Registry hives Tmp_Install_Drivers, Tmp_Install_System, Tmp_Drivers, Tmp_System must be loaded before calling.
// Related........: Depends on %Tools%\RegCopyDriver.cmd
// ===============================================================================================================================
[_PhoenixAPI_RegCopyDriver]
System,SetLocal
Set,%Debug%,False
If,#1,Equal,"",Halt,"Syntax Error: You must specify the name of the driver's .inf to register."
GetParam,1,%InfFile%
Echo,"Processing [%InfFile%] registration..."
If,%Debug%,Equal,True,TXTReplace,"%Tools%\RegCopyDriver.cmd",":::",""
ShellExecute,Hide,"cmd.exe","/D /C RegCopyDriver.cmd #$q%InfFile%#$q",%Tools%
System,EndLocal
[#_PhoenixAPI_RequireDriver#]
// ===============================================================================================================================
// Name...........: RequireDriver
// Description....: Copy the driver support files and driver entries from the INSTALL.WIM driver database to the target registry driver database.
// Both the DRIVERS hive and SYSTEM\Drivers store are processed.
//
// You must still copy additional/supporting driver files yourself if they have a different name then the .inf file itself.
// Ex. RequireDriver,netrndis.inf - you still need to copy \Windows\System32\drivers\usb8023.sys yourself.
//
// Syntax.........: RequireDriver,<filename.inf>
// Parameters.....: InfFile - The name of the driver's .inf file
// NOREG - (Optional) Don't copy registry (driver database)
// Return values..:
// Author.........: Homes32
// Remarks........: This function uses a modified version of ChrisR's RegAddDriver.cmd as PEBakery does not have a good way
// to enum/query registry keys yet...
// Registry hives Tmp_Install_Drivers, Tmp_Install_System, Tmp_Drivers, Tmp_System must be loaded before calling.
// Related........: Depends on %Tools%\RegCopyDriver.cmd
// ===============================================================================================================================
[_PhoenixAPI_RequireDriver]
System,SetLocal
If,#1,Equal,"",Halt,"Syntax Error: You must specify the name of the driver's .inf to include/register."
GetParam,1,%InfFile%
GetParam,2,%Arg2%
If,%Arg2%,Equal,NOREG,Set,%NOREG%,True
Else,Set,%NOREG%,False
StrFormat,RTRIM,%InfFile%,3,%InfFileNoExt%
Set,%RequireDriver-Listfile%,%ProjectTemp%\RequireDriver-ListFile.txt
FileDeleteEx,%RequireDriver-Listfile%
Echo,"Extracting [%InfFile%] Driver Support Files..."
TxtAddline,%RequireDriver-Listfile%,"\Windows\INF\%InfFileNoExt%*",Append
TxtAddline,%RequireDriver-Listfile%,"\Windows\System32\%InfFileNoExt%*",Append
TxtAddline,%RequireDriver-Listfile%,"\Windows\System32\Drivers\%InfFileNoExt%*",Append
TxtAddline,%RequireDriver-Listfile%,"\Windows\System32\Driverstore\??-??\%InfFile%_loc",Append
TxtAddline,%RequireDriver-Listfile%,"\Windows\System32\DriverStore\FileRepository\%InfFile%*",Append
TxtAddline,%RequireDriver-Listfile%,"\Windows\System32\??-??\%InfFileNoExt%*",Append
TxtAddline,%RequireDriver-Listfile%,"\Windows\SystemResources\%InfFileNoExt%*",Append
WimExtractBulk,%SourceInstallWim%,%SourceInstallWimImage%,%RequireDriver-Listfile%,%TargetDir%,NOACL,NOATTRIB,NOERR
If,%NOREG%,Equal,False,Begin
Echo,"Registering [%InfFile%] Driver..."
RegCopyDriver,%InfFile%
End
System,EndLocal
[#_PhoenixAPI_7z#]
// ===============================================================================================================================
// Name...........: 7z
// Description....: Execute 7zip with the provided arguments.
// Syntax.........: 7z,<Args>[,<WorkDir>]
// Parameters.....: #1 Args - The arguments to pass to the 7z executable.
// #2 WorkDir - The full path to the working directory. Default is the exe path.
// Return values..: ExitCode provided by the 7zip application
// Author.........: Homes32
// Remarks........: *** Experimental - May be changed or removed without notice ***
// Related........:
// ===============================================================================================================================
[_PhoenixAPI_7z]
System,SetLocal
If,#1,Equal,"",Halt,"7zip Error: You must provide required 7z.exe arguments."
GetParam,1,%Args%
Getparam,2,%WorkDir%
ShellExecute,Hide,"%Tools%\%HostArch%\7z.exe",%Args%,%WorkDir%
Return,%ExitCode%
System,EndLocal
[#_PhoenixAPI_DISM#]
// ===============================================================================================================================
// Name...........: DISM
// Description....: Execute DISM with the provided arguments.
// Syntax.........: DISM,<Args>[,<WorkDir>]
// Parameters.....: #1 Args - The arguments to pass to the 7z executable.
// #2 WorkDir - The full path to the working directory. Default is the exe path.
// Return values..: ExitCode provided by the DISM application
// Author.........: Homes32
// Remarks........: This command is provided as compatibility shim to allow using DISM on Win10 images from a Win7 Host.
// The version of DISM provided with Win7 does not recognize Win10 images when using the /image: argument.
// In order to work around this limitation and allow DISM operations (Localization, driver integration, etc) on Win7
// we use DISM from Win10 AIK tools, downloaded using JFX's GetWaikTools.exe during Pre-Flight Check.
// * Win10+ - Executes DISM.exe from the HostOS
// * Win7/8 - Executes Win10 AIK DISM.exe
//
// Eventually GetWaikTools will no longer be able to download an AIK that works on Win7, at which time it will
// no longer be possible to build PhoenixPE on Win7. What do you expect running an unsupported OS? ;-)
//
// Related........: Depends on %Tools%\%HostArch%\GWT.exe
// ===============================================================================================================================
[_PhoenixAPI_DISM]
System,SetLocal
If,#1,Equal,"",Halt,"DISM Error: You must provide the dism.exe arguments."
GetParam,1,%Args%
Getparam,2,%WorkDir%
System,GetEnv,windir,%HostWinDir%
FileVersion,"%HostWinDir%\System32\ntdll.dll",%HostOSVer%
If,%HostOSVer%,Bigger,10.0.0.0,ShellExecute,Hide,"dism.exe",%Args%,%WorkDir%
Else,ShellExecute,Hide,"%Tools%\%HostArch%\DISM\dism.exe",%Args%,%WorkDir%
Return,%ExitCode%
System,EndLocal
[#_PhoenixAPI_AddPostProcess#]
// ===============================================================================================================================
// Name...........: AddPostProcess
// Description....: Define a section to process during Build Post-Process
// Syntax.........: AddPostProcess,<Script>,<Section>
// Parameters.....: #1 Script - The full path to the script containing the section to process.
// #2 Section - The name of the section to process.
// Return values..:
// Author.........: Homes32
// Remarks........: This command adds EXEC entries to %ProjectTemp%\PostProcessCommands.script
// The %ProjectTemp%\PostProcessCommands.script is run at the end of a build process, right be fore the .wim file captured.
//
// It can be useful to run commands at the end of the build that may depend on the result of scripts that have not run yet.
//
// Related........:
// ===============================================================================================================================
[_PhoenixAPI_AddPostProcess]
System,SetLocal
If,#1,Equal,"",Halt,"AddPostProcess Error: You must specify the script parameter."
If,#2,Equal,"",Halt,"AddPostProcess Error: You must specify the section to execute."
GetParam,1,%Script%
Getparam,2,%Section%
IniWriteTextLine,"%ProjectTemp%\PostProcessCommands.script","Process","Exec,%Script%,%Section%",APPEND
System,EndLocal
[#_PhoenixAPI_Innounp#]
// ===============================================================================================================================
// Name...........: Innounp
// Description....: Execute Innounp (Inno Setup Unpacker) with the provided arguments.
// Syntax.........: Innounp,<Args>[,<WorkDir>]
// Parameters.....: #1 Args - The arguments to pass to the Innounp executable.
// #2 WorkDir - The full path to the working directory. Default is the exe path.
//
// Return values..: ExitCode provided by the Innounp application
// Author.........: Homes32
// Remarks........: This command is a wrapper for Innounp.exe and passes any arguments directly to the executable. You are
// responsible for checking the return code and handling any errors. Unless you need advanced features such
// extracting using a @filelist or filemask it is recommended to use the Innounp macro instead.
// Innounp Website: http://innounp.sourceforge.net/
// Related........: Innounp.exe
// ===============================================================================================================================
[_PhoenixAPI_Innounp]
System,SetLocal
If,#1,Equal,"",Halt,"InnoUnp Syntax Error: You must provide the Innounp.exe arguments."
GetParam,1,%Args%
Getparam,2,%WorkDir%
ShellExecute,Hide,"%Tools%\x86\Innounp.exe","%Args%",%WorkDir%
Return,%ExitCode%
System,EndLocal
[#_PhoenixAPI_InnoExtract#]
// ===============================================================================================================================
// Name...........: InnoExtract
// Description....: Extract files from an Inno Setup installer.
// Syntax.........: InnoExtract,<SetupFile>,<DestDir>[,<Args>]
// Parameters.....: #1 SetupFile - The inno-setup file to unpack.
// #2 DestDir - The full path to the directory where the files will be unpacked.
// #3-#5 - Additional Arguments:
// PASSWORD=<Password> - Password required to decrypt the setup file. (-p)
// CDIR=<CurrentDir> - Notifies innounp that you are only interested in paths from the current directory and below. (-c)
// LIST=<FileList.txt> - Instructs innounp to use a list file to determine the files to extract (@listfile)
// Return values..:
// Author.........: Homes32
// Remarks........: *** Experimental - May be changed or removed without notice ***
// Related........: Innounp.exe
// ===============================================================================================================================
[_PhoenixAPI_InnoExtract]
System,SetLocal
If,#1,Equal,"",Halt,"InnoExtract Syntax Error: You must specify the setup file."
If,#2,Equal,"",Halt,"InnoExtract Syntax Error: You must specify the destination directory."
GetParam,1,%SetupFile%
Getparam,2,%DestDir%
Getparam,3,%Arg3%
Getparam,4,%Arg4%
Getparam,5,%Arg5%
Set,%Password%,""
Set,%CurrentDir%,""
Set,%ListFile%,""
Run,%API%,__PhoenixAPI_InnoExtract_Process_Arg,%Arg3%
Run,%API%,__PhoenixAPI_InnoExtract_Process_Arg,%Arg4%
Run,%API%,__PhoenixAPI_InnoExtract_Process_Arg,%Arg5%
ShellExecute,Hide,"%Tools%\x86\Innounp.exe","-x -b -y -a -d#$q%DestDir%#$q %Password%%CurrentDir%#$q%SetupFile%#$q%ListFile%"
If,Not,%ExitCode%,Equal,0,Begin
FileVersion,"%Tools%\x86\Innounp.exe",%InnounpVer%
Halt,"InnoExtract Error: Failed to unpack setup file#$x#$x[%SetupFile%]#$x#$xThe command returned: [%ExitCode%].#$xYou are using Innounp.exe version [%InnounpVer%]."
End
System,EndLocal
[#__PhoenixAPI_InnoExtract_Process_Arg#]
// ===============================================================================================================================
// Name...........: __PhoenixAPI_InnoExtract_Process_Arg
// Description....: Process InnoExtract optional arguments
// Syntax.........: __PhoenixAPI_InnoExtract_Process_Arg,<Arg>
// Parameters.....: #1 Arg - The argument to process
// Return values..:
// Author.........: Homes32
// Remarks........: Internal Function
// Do not call System,SetLocal here. We need this function to run in the same scope as PhoenixAPI_InnoExtract
// Related........: _PhoenixAPI_InnoExtract
// ===============================================================================================================================
[__PhoenixAPI_InnoExtract_Process_Arg]
StrFormat,Split,#1,"=",1,%ArgKey%
If,Not,%ArgKey%,Equal,"",Begin
If,%ArgKey%,Equal,"PASSWORD",Begin
StrFormat,Split,#1,"=",2,%Password%
Set,%Password%," -p#$q%Password%#$q "
End
Else,If,%ArgKey%,Equal,"CDIR",Begin
StrFormat,Split,#1,"=",2,%CurrentDir%
Set,%CurrentDir%," -c#$q%CurrentDir%#$q "
End
Else,If,%ArgKey%,Equal,"LIST",Begin
StrFormat,Split,#1,"=",2,%ListFile%
Set,%ListFile%," #$q@%ListFile%#$q"
End
Else,Halt,"InnoExtract SYNTAX ERROR: Invalid Argument [#1]."
End
[#_PhoenixAPI_MSIExtract#]
// ===============================================================================================================================
// Name...........: MSIExtract
// Description....: Extract files from an .msi installer.
// Syntax.........: MSIExtract,<MSIFile>,<DestDir>
// Parameters.....: #1 SetupFile - The .msi file to unpack.
// #2 DestDir - The full path to the directory where the files will be unpacked.
// Return values..:
// Author.........: Homes32
// Remarks........: Note: DestDir MUST end with a \ or lessmsi will consider it a file name to extract. We play it safe by trimming
// any \ from the user provided directory and add it ourselves.
// In the future it would be nice to have the option to extract individual files. lessmsi supports this but
// does not provide a usable exit code if the file can't be found.
// Related........: Depends on lessmsi.exe for extraction. (http://lessmsi.activescott.com/)
// ===============================================================================================================================
[_PhoenixAPI_MSIExtract]
System,SetLocal
If,#1,Equal,"",Halt,"MSIExtract Syntax Error: You must specify the setup file."
If,#2,Equal,"",Halt,"MSIExtract Syntax Error: You must specify the destination directory."
GetParam,1,%SetupFile%
GetParam,2,%DestDir%
StrFormat,CTrim,%DestDir%,"\","%DestDir%"
ShellExecute,Hide,"%Tools%\anycpu\lessmsi\lessmsi.exe","x #$q%SetupFile%#$q #$q%DestDir%\#$q"
If,Not,%ExitCode%,Equal,0,Begin
FileVersion,"%Tools%\anycpu\lessmsi\lessmsi.exe",%lessmsiVer%
Halt,"MSIExtract Error: Failed to unpack .msi file#$x#$x[%SetupFile%]#$x#$xThe command returned: [%ExitCode%].#$xYou are using lessmsi.exe version [%lessmsiVer%]."
End
System,EndLocal
[#_PhoenixAPI_WixExtract#]
// ===============================================================================================================================
// Name...........: WixExtract
// Description....: Extract files from an WIX based installer.
// Syntax.........: WixExtract,<SetupFile>,<DestDir>
// Parameters.....: #1 SetupFile - The WIX exe file to unpack.
// #2 DestDir - The full path to the directory where the files will be unpacked.
// Return values..:
// Author.........: Homes32
// Remarks........: *** Experimental - May be changed or removed without notice ***
// Related........: Depends on dark.exe for extraction. (https://wixtoolset.org/)
// ===============================================================================================================================
[_PhoenixAPI_WixExtract]
System,SetLocal
If,#1,Equal,"",Halt,"WixExtract Syntax Error: You must specify the setup file."
If,#2,Equal,"",Halt,"WixExtract Syntax Error: You must specify the destination directory."
GetParam,1,%SetupFile%
Getparam,2,%DestDir%
StrFormat,CTrim,%DestDir%,"\","%DestDir%"
ShellExecute,Hide,"%Tools%\anycpu\wix\dark.exe","-x #$q%DestDir%#$q #$q%SetupFile%#$q"
If,Not,%ExitCode%,Equal,0,Begin
FileVersion,"%Tools%\anycpu\wix\dark.exe",%DarkVer%
Halt,"WixExtract Error: Failed to unpack the setup file#$x#$x[%SetupFile%]#$x#$xThe command returned: [%ExitCode%].#$xYou are using dark.exe version [%DarkVer%]."
End
System,EndLocal
[#_PhoenixAPI_Binmay#]
// ===============================================================================================================================
// Name...........: Binmay
// Description....: Binary Search and Replace Tool
// Syntax.........: Binmay,<Args>[,<WorkDir>]
// Parameters.....: #1 Args - The arguments to pass to the Binmay executable.
// #2 WorkDir - The full path to the working directory. Default is the exe path.
// Return values..: ExitCode provided by the Binmay application
// Author.........: Homes32
// Remarks........: *** Experimental - May be changed or removed without notice ***
// Related........:
// ===============================================================================================================================
[_PhoenixAPI_Binmay]
System,SetLocal
If,#1,Equal,"",Halt,"Binmay Syntax Error: You must provide the Binmay.exe arguments."
GetParam,1,%Args%
Getparam,2,%WorkDir%
ShellExecute,Hide,"%Tools%\%HostArch%\Binmay.exe","%Args%",%WorkDir%
Return,%ExitCode%
System,EndLocal
[#_PhoenixAPI_ConvertImage#]
// ===============================================================================================================================
// Name...........: ConvertImage
// Description....: Convert an image to the specified format.
// Syntax.........: ConvertImage,<Source>,<Target>[,<Resize>]
// Parameters.....: #1 Source - The full path to the image file.
// #2 Target - The full path to the converted image file.
// #3 Resize - (Optional) Resize the image.
// Return values..:
// Author.........: Homes32
// Remarks........: Depends on ImageConvert.exe in %Tools%.
// ImageConvert.exe <input_image> <output_image> [--resize:WxH]
// Related........:
// ===============================================================================================================================
[_PhoenixAPI_ConvertImage]
System,SetLocal
If,#1,Equal,"",Halt,"ConvertImage Syntax Error: You must specify the path to the source image."
If,#2,Equal,"",Halt,"ConvertImage Syntax Error: You must specify the path to the destination image."
GetParam,1,%SourceImage%
Getparam,2,%TargetImage%
Getparam,3,%ResizeTo%
StrFormat,EXT,%TargetImage%,%NewImageExt%
Echo,"Converting [%SourceImage%] to a [%NewImageExt%] image..."
If,Not,%ResizeTo%,Equal,"",Set,%ResizeParam%," --resize:%ResizeTo%"
ShellExecute,Hide,"%Tools%\%HostArch%\ImageConvert.exe","#$q%SourceImage%#$q #$q%TargetImage%#$q --silent%ResizeParam%"
If,Not,%ExitCode%,Equal,0,Halt,"ERROR: Image conversion failed. [%ExitCode%]"
System,EndLocal
[#_PhoenixAPI_GetBinaryResource#]
// ===============================================================================================================================
// Name...........: GetBinaryResource
// Description....: Extract a binary resource from an executable file.
// Syntax.........: GetBinaryResource,<Source>,<ResourceType>,<ResourceID>,<OutputPath>[,NOERR]
// Parameters.....: #1 Source - The full path to the source file (.exe, .dll, .mui, .mun, .sys, etc.).
// #2 ResourceType - Can be a named resource type eg. RT_RCDATA or an ordinal number prefixed with # eg. #100
// #3 ResourceID - ID of the resource to extract. eg. NTDRIVER or #1000
// #4 OutputPath - The full path where the resource will be saved.
// #5 NOERR - (Optional) Do not Halt on error, just return the exit code passed by GetBinaryResource.exe
// Return values..: 0 - Success
// 1 - Could not load exe
// 2 - Could not find resource
// 3 - Could not load resource
// 4 - Could not lock resource
// 5 - Could not save resource to file
// 99 - Syntax Error
// Author.........: Homes32
// Remarks........: Depends on GetBinaryResource.exe in %Tools%.
// GetBinaryResource.exe <Source> <ResourceType> <ResourceID> <OutputPath>
// Related........:
// ===============================================================================================================================
[_PhoenixAPI_GetBinaryResource]
System,SetLocal
If,#1,Equal,"",Halt,"GetBinaryResource Syntax Error: You must specify the path to the source file."
If,#2,Equal,"",Halt,"GetBinaryResource Syntax Error: You must specify the resource type."
If,#3,Equal,"",Halt,"GetBinaryResource Syntax Error: You must specify the ID of the string to extract."
If,#4,Equal,"",Halt,"GetBinaryResource Syntax Error: You must specify the path to extract the file."
GetParam,1,%Source%
GetParam,2,%ResourceType%
GetParam,3,%ResourceID%
GetParam,4,%OutputPath%
GetParam,5,%Arg5%
If,%Arg5%,Equal,"NOERR",Set,%NOERR%,"True"
ShellExecute,Hide,"%Tools%\%HostArch%\GetBinaryResource.exe","#$q%Source%#$q %ResourceType% %ResourceID% #$q%OutputPath%#$q"
If,%ExitCode%,Equal,0,Return,%ExitCode%
Else,If,%NOERR%,Equal,"True",Return,%ExitCode%
Else,Halt,"GetBinaryResource Error: Unable to extract resource [%ResourceID%]. The command returned [%ExitCode%]."
System,EndLocal
[#_PhoenixAPI_Associate#]
// ===============================================================================================================================
// Name...........: Associate
// Description....: Associate a file extension with a program.
// Syntax.........: Associate,<FileExtension>,<ProgramExe>[,<Icon>]
// Parameters.....: #1 FileExtension - The file extension to associate.
// #2 ProgramExe - The full path to the executable to which the file extension will be associated with.
//
// Example: Associate,.ini,"C:\Windows\System32\notepad.exe"
//
// Return values..:
// Author.........: Homes32
// Remarks........:
// Related........:
// ===============================================================================================================================
[_PhoenixAPI_Associate]
System,SetLocal
If,#1,Equal,"",Halt,"Associate Syntax Error: You must specify the file extension to associate."
If,#2,Equal,"",Halt,"Associate Syntax Error: You must specify the program to associate with the file extension."
GetParam,1,%FileExt%
Getparam,2,%Program%
Set,%ExeExtList%,".exe|.cmd|.bat|.com|.js|.vbs|.wsf"
// Are hives already loaded? - We don't want to unload them if they were loaded by a script
If,ExistRegSubKey,HKLM,"Tmp_Software",Set,%RegHivesLoaded%,True
Else,Set,%RegHivesLoaded%,False
// Remove . from the file extension if present.
StrFormat,CTRIM,%FileExt%,".",%FileExt%
StrFormat,FILENAME,%Program%,%ProgramFileName%
StrFormat,EXT,%ProgramFileName%,%ProgramExt%
List,Pos,%ExeExtList%,%ProgramExt%,%IsExecutable%
If,%IsExecutable%,Equal,0,Halt,"Associate Error: [%Program%] is not an executable file (%ExeExtList%)."
Else,Begin
Echo,"Associating file extension [.%FileExt%] with [%Program%]..."
If,%RegHivesLoaded%,Equal,False,RegHiveLoad,Tmp_Software,%RegSoftware%
RegWrite,HKLM,0x1,"Tmp_Software\Classes\.%FileExt%","","%FileExt%file"
RegWrite,HKLM,0x1,"Tmp_Software\Classes\%FileExt%file","","%FileExt% File"
RegWrite,HKLM,0x2,"Tmp_Software\Classes\%FileExt%file\DefaultIcon","","#$q%Program%#$q"
RegWrite,HKLM,0x2,"Tmp_Software\Classes\%FileExt%file\shell\open\command","","#$q%Program%#$q #$q#$p1#$q"
If,%RegHivesLoaded%,Equal,False,RegHiveUnLoad,Tmp_Software
Echo,""
End
System,EndLocal
[#_PhoenixAPI_SetFileACL#]
// ===============================================================================================================================
// Name...........: SetFileACL
// Description....: Give full control for "Everyone" on a file or directory using Helge Klein's SetAcl.exe
// Syntax.........: SetFileACL,<Path>
// Parameters.....: #1 Path - The file or directory to modify.
// Return values..:
// Author.........: Homes32
// Remarks........: Depends on SetAcl.exe in %Tools% <https://helgeklein.com/setacl/>
// Related........:
// ===============================================================================================================================
[_PhoenixAPI_SetFileACL]
System,SetLocal
If,#1,Equal,"",Halt,"SetFileACL Syntax Error: You must specify the file or directory to modify."
Echo,"Granting full access to [#1] ...#$X#$XThis can take awhile, please be patient."
ShellExecute,Hide,%Tools%\%HostArch%\SetAcl.exe," -ot #$qfile#$q -on #$q#1#$q -actn ace -actn setprot -op #$qdacl:p_nc#$q -ace #$qn:S-1-1-0;p:full;s:y#$q"
If,Not,%ExitCode%,Equal,0,Halt,"Error: Could not grant full permission on#$x#$x#1#$x#$xThe command returned: [%ExitCode%]."
System,EndLocal
[#_PhoenixAPI_SetRegACL#]
// ===============================================================================================================================
// Name...........: SetRegACL
// Description....: Take ownership and grant full control for "Everyone" on a registry key using Helge Klein's SetAcl.exe
// Syntax.........: SetRegACL,<Path>
// Parameters.....: #1 Path - Registry key to modify. The hive must already be mounted.
// Return values..:
// Author.........: Homes32
// Remarks........: Depends on SetAcl.exe in %Tools% <https://helgeklein.com/setacl/>
// Related........:
// ===============================================================================================================================
[_PhoenixAPI_SetRegACL]
System,SetLocal
If,#1,Equal,"",Halt,"SetRegACL Syntax Error: You must specify the Registry Key to modify."
Echo,"Taking ownership of [#1] ...#$X#$XThis can take awhile, please be patient."
ShellExecute,Hide,%Tools%\%HostArch%\SetAcl.exe,"-on #$q#1#$q -ot reg -rec yes -actn setowner -ownr #$qn:S-1-1-0;s:y#$q -silent"
If,Not,%ExitCode%,Equal,0,Halt,"SetRegACL Error: Could not take ownership of#$x#$x#1#$x#$xThe command returned: [%ExitCode%]."
Echo,"Granting full access to [#1] ...#$X#$XThis can take awhile, please be patient."
ShellExecute,Hide,%Tools%\%HostArch%\SetAcl.exe,"-on #$q#1#$q -ot reg -rec yes -actn ace -ace #$qn:S-1-1-0;p:full;s:y#$q -silent"
If,Not,%ExitCode%,Equal,0,Halt,"Error: Could not grant full permission on#$x#$x#1#$x#$xThe command returned: [%ExitCode%]."
System,EndLocal
[#_PhoenixAPI_FileCopyEx#]
// ===============================================================================================================================
// Name...........: FileCopyEx
// Description....: Copy a single file and it's .mui's (if they exist) from a specified directory.
// Syntax.........: FileCopyEx,<SourcePath>,<DestPath>
// Parameters.....: #1 SourcePath - Full path to the source file to copy. Wildcards are NOT supported.
// #2 DestPath - Full path to the destination.
// Return values..:
// Author.........: Homes32
// Remarks........: Wildcards are not supported. If you need wildcards use FileCopy instead.
// Related........:
// ===============================================================================================================================
[_PhoenixAPI_FileCopyEx]
System,SetLocal
If,#1,Equal,"",Halt,"FileCopyEx Syntax Error: Source file was not specified."
If,#2,Equal,"",Halt,"FileCopyEx Syntax Error: Destination was not specified."
GetParam,1,%SrcFile%
GetParam,2,%DestPath%
StrFormat,Pos,%SrcFile%,*,%WildCard%
If,Not,%WildCard%,Equal,0,Halt,"FileCopyEx Syntax Error: Wildcards are not supported."
StrFormat,Pos,%SrcFile%,?,%WildCard%
If,Not,%WildCard%,Equal,0,Halt,"FileCopyEx Syntax Error: Wildcards are not supported."
FileCopy,%SrcFile%,%DestPath%
StrFormat,FileName,%SrcFile%,%Filename%
StrFormat,Split,%DestPath%,"\",1,%DriveLtr%
If,ExistFile,"%DriveLtr%\Windows\SystemResources\%Filename%.mun",FileCopy,"%DriveLtr%\Windows\SystemResources\%Filename%.mun",APPEND
StrFormat,FileName,%SrcFile%,%FileName%
StrFormat,Ext,%SrcFile%,%FileExt%
StrFormat,DirPath,%SrcFile%,%SrcDirPath%
StrFormat,DirPath,%DestPath%,%DestDirPath%
ForEach,%Language%,%SourceFallbackLang%,Begin
If,%FileExt%,Equal,.msc,FileCopy,"%SrcDirPath%%Language%\%FileName%","%DestPath%\%Language%\%FileName%"
Else,If,ExistFile,"%SrcDirPath%%Language%\%FileName%.mui",FileCopy,"%SrcDirPath%%Language%\%FileName%.mui","%DestDirPath%%Language%\%FileName%.mui"
End
System,EndLocal
[#_PhoenixAPI_RequireFile#]
// ===============================================================================================================================
// Name...........: RequireFile
// Description....: Extract a single file and it's .mui's (if they exist) from Install.wim
// Syntax.........: RequireFileEx,<FilePath>[,NOMUI]
// Parameters.....: #1 FilePath - Path to the file to extract relative to the root of Install.wim
// #2 NOMUI - Don't extract .mui files.
// Return values..:
// Author.........: Homes32
// Remarks........: This command is an alias to RequireFileEx,ExtractFile
// Related........: _PhoenixAPI_RequireFileEx
// ===============================================================================================================================
[_PhoenixAPI_RequireFile]
Run,%API%,_PhoenixAPI_RequireFileEx,ExtractFile,#1,#2
[#_PhoenixAPI_RequireFileEx#]
// ===============================================================================================================================
// Name...........: RequireFileEx
// Description....: Extract files and their .mui's (if they exist) from Install.wim
// Syntax.........: RequireFileEx,<Action>,<FilePath>[,NOMUI]
// Parameters.....: #1 Action:
// AppendList - Append the file to a list (bulk extraction). You must call RequireFileEx,ExtractList
// in order to perform the actual extraction of the list.
// ExtractFile - Single file extraction
// ExtractList - Extract the list created with Append
// #2 Path to the file to extract relative to the root of Install.wim
// #3 NOMUI - (Optional) Don't extract .mui files.
// If you know the file to be extracted isn't localized you can save a some time by not checking
// for .mui files that don't exist.
// Return values..:
// Author.........: Homes32
// Remarks........: RequireFileEx uses WimExtractBulk in NOERR mode so it does not verify that files exist before trying to extract.
// Check the build log for WimExtract warnings.
// Right now we are lazy and just add the .mun files to the list files regardless of whether or not it exists,
// and let WimExtractBulk log a warning if it doesn't. In order to reduce log clutter with false positive warnings
// we should check if the files exist first using WimExistFile, but it slows things down too much with large lists.
// Related........:
// ===============================================================================================================================
[_PhoenixAPI_RequireFileEx]
If,#1,Equal,"",Halt,"RequireFileEx Syntax Error: Action was not specified."
System,SetLocal
GetParam,1,%Action%
GetParam,2,%GLOB%
GetParam,3,%Arg3%
If,%Arg3%,Equal,NOMUI,Set,%ExtractMui%,False
Else,Set,%ExtractMui%,True
Set,%BulkFileList%,%ProjectTemp%\RequireFileEx-BulkFileList.txt
Set,%SingleFileList%,%ProjectTemp%\RequireFileEx-SingleFileList.txt
// For .mun file check
StrFormat,FileName,%GLOB%,%FileName%
If,%Action%,Equal,"AppendList",Begin
If,%GLOB%,Equal,"",Halt,"RequireFileEx Syntax Error: File was not specified."
If,Not,ExistFile,%BulkFileList%,FileCreateBlank,%BulkFileList%
TXTAddLine,%BulkFileList%,%GLOB%,APPEND
TXTAddLine,%BulkFileList%,\Windows\SystemResources\%FileName%.mun,APPEND
If,%ExtractMui%,Equal,True,ForEach,%Language%,%SourceFallbackLang%,Run,%API%,__PhoenixAPI_RequireFileEx_ProcessMUI,%GLOB%,%Language%,%BulkFileList%
End
Else,If,%Action%,Equal,"ExtractFile",Begin
Echo,"Extracting required file(s) [%GLOB%]..."
If,%GLOB%,Equal,"",Halt,"RequireFileEx Syntax Error: File was not specified."
If,Not,ExistFile,%SingleFileList%,FileCreateBlank,%SingleFileList%
TXTAddLine,%SingleFileList%,%GLOB%,APPEND
TXTAddLine,%SingleFileList%,\Windows\SystemResources\%FileName%.mun,APPEND
If,%ExtractMui%,Equal,True,ForEach,%Language%,%SourceFallbackLang%,Run,%API%,__PhoenixAPI_RequireFileEx_ProcessMUI,%GLOB%,%Language%,%SingleFileList%
WimExtractBulk,%SourceInstallWim%,%SourceInstallWimImage%,%SingleFileList%,%TargetDir%,NOACL,NOATTRIB,NOERR,NOWARN
FileDeleteEx,%SingleFileList%
End
Else,If,%Action%,Equal,"ExtractList",Begin
If,Not,ExistFile,%BulkFileList%,Halt,"RequireFileEx Error: You must create a list using [RequireFileEx,AppendList] before you can extract it!"
Echo,"Extracting required files..."
WimExtractBulk,%SourceInstallWim%,%SourceInstallWimImage%,%BulkFileList%,%TargetDir%,NOACL,NOATTRIB,NOERR,NOWARN
FileDeleteEx,%BulkFileList%
End
Else,Halt,"RequireFileEx Syntax Error: Invalid Action [#1]."
System,EndLocal
[#__PhoenixAPI_RequireFileEx_ProcessMUI#]
// ===============================================================================================================================
// Name...........: RequireFileEx_ProcessMUI
// Description....: Extract a file's .mui from Install.wim
// Syntax.........: RequireFileEx_ProcessMUI,<FilePath>,<Language>,<ListFile>
// Parameters.....: #1 FilePath - Path to the file relative to the root of Install.wim
// #2 Language - Language to extract
// #3 ListFile - ListFile to write the MUI path
// Return values..:
// Author.........: Homes32
// Remarks........: Internal Function
// Right now we are lazy and just add the .mui files to the list files regardless of whether or not it exists,
// and let WimExtractBulk log a warning if it doesn't. In order to reduce log clutter with false positive warnings
// we should check if the files exist first using WimExistFile, but it slows things down too much with large lists.
// Related........: RequireFileEx
// ===============================================================================================================================
[__PhoenixAPI_RequireFileEx_ProcessMUI]
System,SetLocal
GetParam,1,%GLOB%
GetParam,2,%Language%
GetParam,3,%FileList%
StrFormat,FileName,%GLOB%,%FileName%
StrFormat,Ext,%GLOB%,%FileExt%
StrFormat,DirPath,%GLOB%,%DirPath%
StrFormat,Len,%FileExt%,%FileExtLen%
StrFormat,RTrim,%FileName%,%FileExtLen%,%FileNameNoExt%
If,%FileExt%,Equal,".mof",TXTAddLine,%FileList%,"%DirPath%%Language%\%FileNameNoExt%.mfl",APPEND
Else,If,%FileExt%,Equal,".msc",TXTAddLine,%FileList%,"%DirPath%%Language%\%FileName%",APPEND
Else,TXTAddLine,%FileList%,"%DirPath%%Language%\%FileName%.mui",APPEND
System,EndLocal
[#_PhoenixAPI_AddAutoRun#]
// ===============================================================================================================================
// Name...........: AddAutoRun
// Description....: Run a program when the PE Environment starts
// Syntax.........: AddAutoRun,<RunGroup>,<Mode>,<Title>,<ProgramExe>,[Parameters]
// Parameters.....: #1 RunGroup
// PreShell - Run before the shell (ie. Explorer) is loaded.
// PostShell - Run after the shell is loaded.
// RunOnce - Run during startup via HKLM\Software\Microsoft\Windows\CurrentVersion\RunOnce
// AfterNetwork - Run after network connectivity has been established by PENetwork.
// #2 Mode
// NoWait - Do not wait for the program to terminate.
// Wait - Wait for the program to terminate before moving on.
// HideNoWait - Run the program hidden and do not wait for it to terminate.
// HideWait - Run the program hidden and wait for it to terminate.
// #3 Title - Title that may be shown in a progress window while the program is running.
// #4 ProgramExe - The full path to the program to be executed.
// #5 Parameters - (Optional) Parameters that will be passed to the program.
// Return values..:
// Author.........: Homes32
// Remarks........: PECMD: EXEC {[-hide] [-wait]} <ProgramExe> [Parameters]
// Related........:
// ===============================================================================================================================
[_PhoenixAPI_AddAutoRun]
System,SetLocal
If,#1,Equal,"",Halt,"AddAutoRun Syntax Error: Run position was not specified."
If,#2,Equal,"",Halt,"AddAutoRun Syntax Error: Run mode was not specified."
// #3 Title is required but may be empty.
If,#4,Equal,"",Halt,"AddAutoRun Syntax Error: Program Executable was not specified."
GetParam,1,%RunGroup%
GetParam,2,%Mode%
GetParam,3,%Title%
GetParam,4,%ProgramExe%
GetParam,5,%Parameters%
If,%_PhoenixAPI_ConfigMode%,Equal,PECMD,Begin
If,%Mode%,Equal,NoWait,Set,%ExecMode%,""
Else,If,%Mode%,Equal,Wait,Set,%ExecMode%,"-wait "
Else,If,%Mode%,Equal,HideNoWait,Set,%ExecMode%,"-hide "
Else,If,%Mode%,Equal,HideWait,Set,%ExecMode%,"-hide -wait "
Else,Halt,"AddAutoRun Syntax Error: [%Mode%] is not a valid run mode."
If,%RunGroup%,Equal,"Preshell",TXTReplace,"%TargetSystem32%\pecmd.ini","_END Preshell","TEXT %Title%##0xFFFFFF L59 T39 $20#$xEXEC %ExecMode%%ProgramExe% %Parameters%#$x#$x_END Preshell"
Else,If,%RunGroup%,Equal,"Postshell",TXTReplace,"%TargetSystem32%\pecmd.ini","_END PostShell","TEXT %Title%##0xFFFFFF L59 T39 $20#$xEXEC %ExecMode%%ProgramExe% %Parameters%#$x#$x_END PostShell"
Else,If,%RunGroup%,Equal,"NetInit",TXTReplace,"%TargetSystem32%\pecmd.ini","_END NetInit","TEXT %Title%##0xFFFFFF L59 T39 $20#$xEXEC %ExecMode%%ProgramExe% %Parameters%#$x#$x_END NetInit"
Else,If,%RunGroup%,Equal,"RunOnce",Run,%API%,__PhoenixAPI_AddAutoRun_RunOnce
Else,If,%RunGroup%,Equal,"AfterNetwork",Run,%API%,__PhoenixAPI_AddAutoRun_AfterNetwork
Else,Halt,"AddAutoRun Syntax Error: [%RunGroup%] is not a supported Run method."
End
Else,Begin
// Shortcuts.exe - Not fully implemented yet...
If,%RunGroup%,Equal,"Preshell",IniWriteTextLine,%TargetSystem32%\PhoenixPE.cfg,PreConfig,"%Mode%|%Title%|%ProgramExe% %Parameters%"
Else,If,%RunGroup%,Equal,"Postshell",IniWriteTextLine,%TargetSystem32%\PhoenixPE.cfg,PostConfig,"%Mode%|%Title%|%ProgramExe% %Parameters%"
//Else,If,%RunGroup%,Equal,"?",IniWriteTextLine,%TargetSystem32%\PhoenixPE.cfg,Autorun,"%Mode%|%Title%|%ProgramExe% %Parameters%"
Else,Halt,"AddAutoRun Syntax Error: [%RunGroup%] is not a supported Run method."
End
System,EndLocal
[#__PhoenixAPI_AddAutoRun_RunOnce#]
// ===============================================================================================================================
// Name...........: PhoenixAPI_AddAutoRun_RunOnce
// Description....: Run a program during startup via HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnce
// RunOnce entries are always processed synchronously by Windows. NoWait and HideNoWait modes are not supported.
// Syntax.........: PhoenixAPI_AddAutoRun_RunOnce
// Parameters.....:
// Return values..:
// Author.........: Homes32
// Remarks........: Internal Function
// Requires hiderun.exe to exist in %SystemRoot% for run hidden.
// Do not call System,SetLocal here. We need this function to run in the same scope as PhoenixAPI_AddAutoRun
// Related........: PhoenixAPI_AddAutoRun
// ===============================================================================================================================
[__PhoenixAPI_AddAutoRun_RunOnce]
// Are hives already loaded? - We don't want to unload them if they were loaded by a script
If,ExistRegSubKey,HKLM,"Tmp_Default",Set,%RegHivesLoaded%,True
Else,Set,%RegHivesLoaded%,False
If,%RegHivesLoaded%,Equal,False,RegHiveLoad,Tmp_Default,%RegDefault%
Set,%ExecMode%,""
If,%Mode%,Equal,NoWait,Halt,"AddAutoRun Error: RunOnce does not support [%Mode%]."
Else,If,%Mode%,Equal,Wait,Set,%ExecMode%,""
Else,If,%Mode%,Equal,HideWait,Set,%ExecMode%,"hiderun.exe "
Else,If,%Mode%,Equal,HideNoWait,Halt,"AddAutoRun Error: RunOnce does not support [%Mode%]."
Else,Halt,"AddAutoRun Syntax Error: [%Mode%] is not a valid run mode."
RegWrite,HKLM,0x2,"Tmp_Default\Software\Microsoft\Windows\CurrentVersion\Run","%Title%","#$q%ExecMode%%ProgramExe%#$q #$q%Parameters%#$q"
If,%RegHivesLoaded%,Equal,False,RegHiveUnload,Tmp_Default
[#__PhoenixAPI_AddAutoRun_AfterNetwork#]
// ===============================================================================================================================
// Name...........: PhoenixAPI_AddAutoRun_AfterNetwork
// Description....: Run a program after PENetwork has established connectivity.
// Syntax.........: PhoenixAPI_AddAutoRun_AfterNetwork
// Parameters.....:
// Return values..:
// Author.........: Homes32
// Remarks........: Internal Function
// Requires hiderun.exe to exist in %SystemRoot% for run hidden.
// Requires PENetwork to be configured to execute System32\RunAfterNetwork.cmd
// Do not call System,SetLocal here. We need this function to run in the same scope as PhoenixAPI_AddAutoRun
// Related........: PhoenixAPI_AddAutoRun
// ===============================================================================================================================
[__PhoenixAPI_AddAutoRun_AfterNetwork]
Set,%ExecMode%,""
If,%Mode%,Equal,NoWait,Set,%ExecMode%,""
Else,If,%Mode%,Equal,Wait,Set,%ExecMode%,"/WAIT "
Else,If,%Mode%,Equal,HideWait,Set,%ExecMode%,"/WAIT hiderun.exe "
Else,If,%Mode%,Equal,HideNoWait,Set,%ExecMode%,"hiderun.exe "
Else,Halt,"AddAutoRun Syntax Error: [%Mode%] is not a valid run mode."
TxtAddLine,"%TargetSystem32%\RunAfterNetwork.cmd","START #$q%Title%#$q %ExecMode%#$q%ProgramExe%#$q %Parameters%",Append
[#_PhoenixAPI_AddShortcut#]
// ===============================================================================================================================
// Name...........: AddShortcut
// Description....: Create Shortcuts for programs in PE.
// Syntax.........: AddShortcut,<Type>,<StartMenuFolder>,<Title>,<PathProgramExe>,[Parameters],[WorkDir],[IconPath],[IconIndex],[State],[Hotkey],[Tooltip]
// Parameters.....: #1 Type
// Desktop - The shortcut will be created on the desktop.
// StartMenu - The shortcut will be created in the start menu.
// QuickLaunch - The shortcut will be created in the QuickLaunch folder. (used by WinXShell)
// #2 StartMenuFolder - The name of the start menu folder where the shortcut will be created.
// #3 Title - The name of the shortcut.
// #4 ProgramExe - The full path to the program to be executed.
// #5 Parameters - Parameters that will be passed to the program.
// #6 WorkDir - The work directory for the program.
// #7 IconPath - The full path to file containing the icon.
// #8 IconIndex - For files containing multiple icons this is Index of the icon to use.
// #9 WindowState - One of the following:
// Normal - Start the program normally.
// Minimized - Start the program minimized to the taskbar.
// Maximized - Start the program maximized.
// #10 Hotkey - Keyboard sequence used to active the shortcut.
// #11 Tooltip - Tooltip Text
// Return values..:
// Author.........: Homes32
// Remarks........: PECMD: LINK {[!] {[_]|[^]}} <ShortcutPath>, <TargetPath>, [Parameters], [IconPath[#IconIndex]], [Tooltip], [WorkDir], [HotKey]
// WindowState: ! - Hide, _ - Minimize, ^ - Maximize
//
// Shortcuts.exe: <ShortcutPath> | <Title> | <TargetPath> | [IconPath,IconIndex] | [Parameters]
//
// TODO: Shortcuts.exe needs to support all AddShortcut parameters. This requires rewriting a portion of shortcuts.exe
// Related........:
// ===============================================================================================================================
[_PhoenixAPI_AddShortcut]
System,SetLocal
If,#1,Equal,"",Halt,"AddShortcut Syntax Error: The shortcut type was not specified."
If,#3,Equal,"",Halt,"AddShortcut Syntax Error: The shortcut title was not specified."
If,#4,Equal,"",Halt,"AddShortcut Syntax Error: The shortcut's ProgramExe was not specified."
GetParam,1,%Type%
GetParam,2,%Folder%
GetParam,3,%Title%
GetParam,4,%ProgramExe%
GetParam,5,%Parameters%
GetParam,6,%WorkDir%
GetParam,7,%IconPath%
GetParam,8,%IconIndex%
GetParam,9,%WindowState%
GetParam,10,%Hotkey%
GetParam,11,%Tooltip%
// Space delimited list of illegal file name characters
Set,%IllegalFileNameChars%,"\ / : * ? #$q < > |"
// Strip illegal chars from Title
ForEach,%Char%,%IllegalFileNameChars%,Delim=#$s,StrFormat,Replace,%Title%,%Char%,"",%Title%
// Space delimited list of illegal directory name characters (\ is allowed here as we use it to signify a subdir)
Set,%IllegalDirNameChars%,"/ : * ? #$q < > |"
// Strip illegal chars from Folder
ForEach,%Char%,%IllegalDirNameChars%,Delim=#$s,StrFormat,Replace,%Folder%,%Char%,"",%Folder%
If,%_PhoenixAPI_ConfigMode%,Equal,PECMD,Begin
If,%Folder%,Equal,".",Set,%Folder%,""
Else,Set,%Folder%,"\%Folder%"
// Type
If,%Type%,Equal,"Desktop",Set,%Cmd%,"LINK #$pDesktop#$p\%Title%#$c%ProgramExe%#$c%Parameters%"
Else,If,%Type%,Equal,"StartMenu",Set,%Cmd%,"LINK #$pPrograms#$p%Folder%\%Title%#$c%ProgramExe%#$c%Parameters%"
Else,If,%Type%,Equal,"QuickLaunch",Set,%Cmd%,"LINK #$pQuickLaunch#$p\%Title%#$c%ProgramExe%#$c%Parameters%"
Else,Halt,"AddShortcut Syntax Error: Shortcut type [%Type%] is not supported."
// Window State
If,%WindowState%,Equal,"Minimized",StrFormat,Replace,%Cmd%,"LINK ","LINK _ ",%Cmd%
Else,If,%WindowState%,Equal,"Maximized",StrFormat,Replace,%Cmd%,"LINK ","LINK ^ ",%Cmd%
Else,Set,%WindowState%,""
// Icon
If,Not,%IconPath%,Equal,"",Begin
Set,%Cmd%,"%Cmd%#$c%IconPath%"
If,Not,%IconIndex%,Equal,"",Set,%Cmd%,"%Cmd%##%IconIndex%"
End
Else,Set,%Cmd%,"%Cmd%#$c"
// Tooltip
If,Not,%Tooltip%,Equal,"",Set,%Cmd%,"%Cmd%#$c%Tooltip%"
Else,Set,%Cmd%,"%Cmd%#$c"
// WorkDir
If,Not,%WorkDir%,Equal,"",Set,%Cmd%,"%Cmd%#$c%WorkDir%"
// Hotkey
If,Not,%Hotkey%,Equal,"",Set,%Cmd%,"%Cmd%#$c%HotKey%"
// Final LINK command
TXTReplace,"%TargetSystem32%\pecmd.ini","_END Shortcuts","%Cmd%#$x#$x_END Shortcuts"
End
Else,Begin
// Shortcuts.exe
// Window State
If,Not,%WindowState%,Equal,"",Echo,"Warning: Shortcuts.exe does not support the <WindowState> argument for AddShortcut.",Warn
// Icon
If,Not,%IconIndex%,Equal,"",Set,%Icon%,"%IconPath%#$c%IconIndex%"
Else,Set,%Icon%,%IconPath%
// Tooltip
If,Not,%Tooltip%,Equal,"",Echo,"Warning: Shortcuts.exe does not support the <Tooltip> argument for AddShortcut.",Warn
// WorkDir
If,Not,%WorkDir%,Equal,"",Echo,"Warning: Shortcuts.exe does not support the <WorkDir> argument for AddShortcut.",Warn
// Hotkey
If,Not,%Hotkey%,Equal,"",Echo,"Warning: Shortcuts.exe does not support the <Hotkey> argument for AddShortcut.",Warn
// Final Cfg Entry
If,%Type%,Equal,"Desktop",IniWriteTextLine,%TargetSystem32%\PhoenixPE.cfg,Shortcut,"%Folder%|%Title%|%ProgramExe%|%Icon%|%Parameters%"
If,%Type%,Equal,"StartMenu",IniWriteTextLine,%TargetSystem32%\PhoenixPE.cfg,Shortcut,"%Folder%|%Title%|%ProgramExe%|%Icon%|%Parameters%"
Else,Halt,"AddShortcut Syntax Error: Shortcut type [%Type%] is not supported."
End
System,EndLocal
[_PhoenixAPI_PinShortcut]
// ===============================================================================================================================
// Name...........: PinShortcut
// Description....: Pin a shortcut to the taskbar or start menu.
// Syntax.........: PinShortcut,<Location>,<Position>,<ProgramExe>
// Parameters.....: #1 Location
// StartMenu - Pin to the start menu.
// Taskbar - Pin to the taskbar.
// #2 Position
// Auto - (Default) Automatically determine the pin position.
// 1-99 - Pin the shortcut to a specific position [0-99].
// #3 ProgramExe - The full path to the program to be executed.
// Return values..:
// Author.........: Homes32
// Remarks........: This macro relies on PinUtil.exe to perform the actual pinning at boot.
//
// Explorer Shell:
// Normally Pins cannot target an executable located on removable media. To get around this restriction
// we trick Windows by creating a symlink on the ramdrive (B:\) to the Y:\Programs folder.
// PECMD takes care of the symlink creation on boot, so here we only need to point Pintool to B:\ instead of Y:\
//
// I don't like referencing individual scripts inside PhoenixAPI but this is a fairly important feature, and the alternatives are:
// - Do nothing: listen to users complain that Pin's don't work after they have changed the ramdrive letter.
// - Hardcode the ram drive letter: listen to users complain that they can't change the ram drive letter.
//
// WinXShell:
// WinXShell's taskbar does not have "Pin" verbs in it's context menu, instead it behaves like WinXP and uses QuickLaunch shortcuts.
//
// Related........: Depends on %ProjectDir%\Components\330-ImDisk.script for Ramdisk drive letter
// ===============================================================================================================================
[_PhoenixAPI_PinShortcut]
System,SetLocal
If,#1,Equal,"",Halt,"PinShortcut Syntax Error: Pin location was not specified."
If,#2,Equal,"",Halt,"PinShortcut Syntax Error: Pin position was not specified."
If,#3,Equal,"",Halt,"PinShortcut Syntax Error: Program Executable was not specified."
GetParam,1,%PinLocation%
GetParam,2,%PinPos%
GetParam,3,%ProgramExe%
If,Not,%PinLocation%,Equal,"StartMenu",If,Not,%PinLocation%,Equal,"Taskbar",Halt,"PinShortcut Syntax Error: [%PinLocation%] is not a valid pin location."
If,"%Shell%-%PinLocation%",Equal,"WinXShell-Taskbar",Begin
// WinXShell Taskbar
StrFormat,FileName,%ProgramExe%,%ProgramTitle%
AddShortcut,"QuickLaunch",,%ProgramTitle%,%ProgramExe%
End
Else,Begin
// Explorer Taskbar
If,%PinPos%,Equal,"Auto",Begin
// Find an unused pin position
ForRange,%i%,0,100,1,Begin
IniRead,"%TargetSystem32%\pecmd.ini","PinUtil",%PinLocation%%i%,%CurrentPos%
If,%CurrentPos%,Equal,"",Begin
Set,%PinPos%,%i%
Break
End
Else,Set,%PinPos%,-1
End
End
Else,If,%PinPos%,Smaller,0,Halt,"PinShortcut Syntax Error: [%PinPos%] is not a value from [0-99]."
Else,If,%PinPos%,Bigger,99,Halt,"PinShortcut Syntax Error: [%PinPos%] is not a value from [0-99]."
If,%PinPos%,Equal,-1,Begin
Echo,"PinShortcut Warning: Could not find an open [%PinLocation%] position for [%ProgramExe%].",Warn
Return
End
Else,Begin
// Check if user specified position will be overwritten
IniReadSection,"%TargetSystem32%\pecmd.ini","PinUtil",%IniSection%
List,Pos,%IniSection%,%PinLocation%%PinPos%,%Index%
If,Not,%Index%,Equal,0,Begin
IniRead,"%TargetSystem32%\pecmd.ini","PinUtil",%PinLocation%%PinPos%,%ExistingExe%
Echo,"PinShortcut Warning: Existing pin for [%ExistingExe%] in [%PinLocation%] position [%PinPos%] will be overwritten by [%ProgramExe%].",Warn
End
// Work around pin restrictions on removable media.
ReadInterface,Value,"%ProjectDir%\Components\330-ImDisk.script",Interface,cmb_DriveLetter,%RamDisk%
StrFormat,Replace,%ProgramExe%,"Y:\","%RamDisk%\",%ProgramExe%
IniWrite,"%TargetSystem32%\pecmd.ini","PinUtil",%PinLocation%%PinPos%,%ProgramExe%
End
End
System,EndLocal
[#_PhoenixAPI_RunFromRam#]
// ===============================================================================================================================
// Name...........: RunFromRam
// Description....: Choose to redirect the programs folder to Boot.wim
//
// This macro works by overwriting the GLOBAL %TargetPrograms% and %PEPrograms% with
// local variables that redirect to boot.wim instead of the boot media.
// Syntax.........: RunFromRam
// Parameters.....:
// Return values..:
// Author.........: Homes32
// Remarks........: Do not use System,SetLocal here. For this macro to work it must run in the scope of the calling script.
// Related........:
// ===============================================================================================================================
[_PhoenixAPI_RunFromRam]
Set,%TargetPrograms%,"%TargetDir%\Program Files"
Set,%PEPrograms%,"X:\Program Files"
[#_PhoenixAPI_DirDeleteEx#]
// ===============================================================================================================================
// Name...........: DirDeleteEx
// Description....: Delete a directory if it exists. If the DirDelete commands fails, for example if a file or folder is open in another
// application or Explorer then give the user a meaningful error message and a chance to correct the problem.
// if that doesn't work halt the build.
// Syntax.........: DirDeleteEx,<Directory>
// Parameters.....: #1 Directory - The full path to the directory to delete.
// Return values..:
// Author.........: Homes32
// Remarks........:
// Related........:
// ===============================================================================================================================
[_PhoenixAPI_DirDeleteEx]
If,#1,Equal,"",Halt,"Syntax Error: Directory was not specified."
System,ErrorOff
If,ExistDir,#1,DirDelete,#1
// If Dir still exists wait a few more seconds to give async tasks time to complete before we bother the user...
If,ExistDir,#1,Wait,5
While,ExistDir,#1,Begin
If,Question,"Error: The specified folder could not be deleted.#$x#$x#1#$x#$xPlease make sure there are no files open in other applications (eg. Text Editor/vmWare/VirtualBox), registry hives are unloaded, and you do not have the directory open in Explorer.#$x#$xRetry?",Begin
// User clicked 'Yes'
System,ErrorOff
DirDelete,#1
// Wait a few seconds to give async tasks time to complete...
Wait,5
End
Else,Begin
// User clicked 'No'
Halt,"Error: The specified folder could not be deleted."
End
End
[#_PhoenixAPI_FileDeleteEx#]
// ===============================================================================================================================
// Name...........: FileDeleteEx
// Description....: Delete a file if it exists. If the FileDelete commands fails, for example if a file is open in another
// application, then give the user a meaningful error message and a chance to correct the problem.
// if that doesn't work halt the build.
// Syntax.........: DirDeleteEx,<File>
// Parameters.....: #1 File - The full path to the file to delete.
// Return values..:
// Author.........: Homes32
// Remarks........:
// Related........:
// ===============================================================================================================================
[_PhoenixAPI_FileDeleteEx]
If,#1,Equal,"",Halt,"Syntax Error: File was not specified."
System,ErrorOff
If,ExistFile,#1,FileDelete,#1
While,ExistFile,#1,Begin
If,Question,"Error: The specified file could not be deleted.#$x#$x#1#$x#$xPlease make sure the file is not running or in use by another application (eg. Text Editor/vmWare/VirtualBox).#$x#$xRetry?",Begin
// User clicked 'Yes'
Wait,3
System,ErrorOff
If,ExistFile,#1,FileDelete,#1
End
Else,Begin
// User clicked 'No'
Halt,"Error: The specified file could not be deleted."
End
End
[#_PhoenixAPI_InnoCleanup#]
// ===============================================================================================================================
// Name...........: InnoCleanup
// Description....: Cleanup extracted Inno Setup files.
// Syntax.........: InnoCleanup,<Path>,<Filter>[,NOREC]
// Parameters.....: #1 Path - The full path to the extracted InnoSetup Files.
// #2 Filter - Comma delimited list of file types to include. eg. *.dll,*.exe
// #3 NOREC - (Optional) Do not recurse sub-directories.
// Return values..:
// Author.........: Homes32
// Remarks........: An Inno Setup installer may contain several identical files (possibly under different names).
// Inno Setup stores only one copy of such files, so identical files are unpacked with an incremental suffix
// eg. myfile,1.exe myfile,2.exe myfile,3.exe etc.
// If the installer contains files for multiple processor architectures, you will need to determine which suffix
// is used for the architecture you are interested in. This can be accomplished with tools such as exeinfope or CFF Explorer.
// Note that sub-folders may use a different suffix then the parent folder for the same architecture.
//
// You can use the InnoCleanup command to bulk remove files that you have not renamed with the InnoRename command.
// Once this has been accomplished you can then copy the entire directory or groups of files,
// instead of having to copy and rename each file individually.
// Related........: InnoExtract, InnoRename
// ===============================================================================================================================
[_PhoenixAPI_InnoCleanup]
System,SetLocal
GetParam,1,%Path%
GetParam,2,%Filter%
GetParam,3,%Arg3%
If,%Path%,Equal,"",Halt,"InnoCleanup Syntax Error: You must specify the full path to the folder containing the extracted Inno Setup files."
If,%Filter%,Equal,"",Halt,"InnoCleanup Syntax Error: You must specify a file filter."
If,%Arg3%,Equal,"NOREC",Set,%Recurse%,False
Else,Set,%Recurse%,True
StrFormat,Replace,%Filter%," ","",%Filter%
StrFormat,Replace,%Filter%,",","#$c",%Filter%
If,%Recurse%,Equal,True,ShellExecute,Hide,"powershell.exe","-ExecutionPolicy Bypass -Command #$qGet-ChildItem -Path '%Path%' -Include %Filter% -Recurse | Where-Object {$_.Name -Like '*#$c*.*'} | Remove-Item -Force#$q","%Path%"
Else,ShellExecute,Hide,"powershell.exe","-ExecutionPolicy Bypass -Command #$qGet-ChildItem -Path '%Path%\*' -Include %Filter% | Where-Object {$_.Name -Like '*#$c*.*'} | Remove-Item -Force#$q","%Path%"
If,Not,%ExitCode%,Equal,0,Halt,"InnoCleanup Error: Failed to rename files. [%ExitCode%]."
System,EndLocal
[#_PhoenixAPI_InnoRename#]
// ===============================================================================================================================
// Name...........: InnoRename
// Description....: Rename extracted Inno Setup files.
// Syntax.........: InnoRename,<Path>,<Filter>,<Suffix>[,NOREC]
// Parameters.....: #1 Path - The full path to the extracted InnoSetup Files.
// #2 Filter - Comma delimited list of file types to include. eg. *.dll,*.exe
// #3 Suffix - A number representing the group of files to process. eg. 1
// #4 NOREC - (Optional) Do not recurse sub-directories.
// Return values..:
// Author.........: Homes32
// Remarks........: An Inno Setup installer may contain several identical files (possibly under different names).
// Inno Setup stores only one copy of such files, so identical files are unpacked with an incremental suffix
// eg. myfile,1.exe myfile,2.exe myfile,3.exe etc.
// If the installer contains files for multiple processor architectures, you will need to determine which suffix
// is used for the architecture you are interested in. This can be accomplished with tools such as exeinfope or CFF Explorer.
// Note that sub-folders may use a different suffix then the parent folder for the same architecture.
//
// You can use the InnoRename command to bulk rename the files with the suffix you want and remove the others
// with the InnoCleanup command. Once this has been accomplished you can then copy the entire directory or groups
// of files, instead of having to copy and rename each file individually.
//
// Dev Note: We are using `Move-Item -Force` as `Rename-Item -Force` can't overwrite files that already exist. Brilliant M$.
//
// Related........: InnoExtract, InnoCleanup
// ===============================================================================================================================
[_PhoenixAPI_InnoRename]
System,SetLocal
GetParam,1,%Path%
GetParam,2,%Filter%
GetParam,3,%Suffix%
GetParam,4,%Arg4%
If,%Path%,Equal,"",Halt,"InnoRename Syntax Error: You must specify the full path to the folder containing the extracted Inno Setup files."
If,%Filter%,Equal,"",Halt,"InnoRename Syntax Error: You must specify a file filter."
If,%Suffix%,Equal,"",Halt,"InnoRename Syntax Error: You must specify the suffix to process."
If,%Arg4%,Equal,"NOREC",Set,%Recurse%,False
Else,Set,%Recurse%,True
StrFormat,Replace,%Filter%," ","",%Filter%
StrFormat,Replace,%Filter%,",","#$c",%Filter%
If,%Recurse%,Equal,True,ShellExecute,Hide,"powershell.exe","-ExecutionPolicy Bypass -Command #$qGet-ChildItem -Path '%Path%' -Include %Filter% -Recurse | ForEach { $NewName = $_.Name.Replace('#$c%Suffix%.','.'); $Destination = Join-Path -Path $_.Directory.FullName -ChildPath $NewName; Move-Item -Path $_.FullName -Destination $Destination -Force }#$q","%Path%"
Else,ShellExecute,Hide,"powershell.exe","-ExecutionPolicy Bypass -Command #$qGet-ChildItem -Path '%Path%\*' -Include %Filter% | ForEach { Move-Item $_ $_.Name.Replace('#$c%Suffix%.','.') -Force }#$q","%Path%"
If,Not,%ExitCode%,Equal,0,Halt,"InnoRename Error: Failed to cleanup files. [%ExitCode%]."
System,EndLocal
[#_PhoenixAPI_ApplyBitMask#]
// ===============================================================================================================================
// Name...........: ApplyBitMask
// Description....: Apply a bitmask to a hex value in a binary string.
// Syntax.........: ApplyBitMask,<BitArray>,<BitGroup>,<BitMask>[,BitSize]
// Parameters.....: #1 BitArray - A comma separated string of bits in hex format.
// #2 BitGroup - The specific group of bits to manipulate. This is determined by the 1-based index of the bit group
// supplied by <BitArray>. Example: In order to apply a mask to the value 'DB' in
// <BitArray> 01,DB,1A,4C we would specify a <BitGroup> of 2.
// #3 BitMask - The hexadecimal bitmask to apply to the specified <BitGroup>. Ex. 0x000020
// #4 BitSize - (Optional) Specify the bitsize (8,16,32,64) used. Default is 32.
// Return values..: #r - Returns <BitArray> with the specified bitmask applied.
// Author.........: Homes32
// Remarks........:
// Related........:
// ===============================================================================================================================
[_PhoenixAPI_ApplyBitMask]
System,SetLocal
GetParam,1,%BitArray%
GetParam,2,%BitGroup%
GetParam,3,%BitMask%
GetParam,4,%BitSize%
If,%BitArray%,Equal,"",Halt,"ApplyBitMask Syntax Error: You must specify a bit array."
If,%BitGroup%,Equal,"",Halt,"ApplyBitMask Syntax Error: You must specify the bit group in order to apply a mask."
If,%BitMask%,Equal,"",Halt,"ApplyBitMask Syntax Error: You must specify the bitmask to apply."
If,%BitSize%,Equal,"",Begin
Echo,"ApplyBitMask Warning: BitSize was not specified. Assuming it's a 32bit integer.",WARN
Set,%BitSize%,32
End
List,Get,%BitArray%,%BitGroup%,%Bits%,Delim=#$c
Math,BitOr,%Bits%,0x%Bits%,%BitMask%
// Back to Hex for our return value
Math,Hex,%Hex%,%Bits%,%BitSize%
StrFormat,LTRIM,%Hex%,2,%Hex%
List,Set,%BitArray%,%BitGroup%,%Hex%,Delim=#$c
Return,%BitArray%
System,EndLocal
[#_PhoenixAPI_BitClear#]
// ===============================================================================================================================
// Name...........: BitClear
// Description....: Clear a specific bit in a binary string.
// Syntax.........: BitClear,<BitArray>,<BitGroup>,<BitPosition>[,BitSize]
// Parameters.....: #1 BitArray - A comma separated string of bits in hex format.
// #2 BitGroup - The specific group of bits to manipulate. This is determined by the 1-based index of the bit group
// supplied by <BitArray>. Example: In order to clear a bit in the value 'DB' in
// <BitArray> 01,DB,1A,4C we would specify a <BitGroup> of 2.
// #3 BitPosition - The binary position to modify. (0-based Right to Left)
// #4 BitSize - (Optional) Specify the bitsize (8,16,32,64) used. Default is 32.
// Return values..: #r - Returns <BitArray> with the specified bit cleared.
// Author.........: Homes32
// Remarks........: BitGroup &= ~(1 << BitPosition); // Take OR of <BitGroup> and 1 shifted <BitPosition> positions negated
// Related........:
// ===============================================================================================================================
[_PhoenixAPI_BitClear]
System,SetLocal
GetParam,1,%BitArray%
GetParam,2,%BitGroup%
GetParam,3,%BitPosition%
GetParam,4,%BitSize%
If,%BitArray%,Equal,"",Halt,"BitClear Syntax Error: You must specify a bit array."
If,%BitGroup%,Equal,"",Halt,"BitClear Syntax Error: You must specify the bit group in order clear a bit."
If,%BitPosition%,Equal,"",Halt,"BitClear Syntax Error: You must specify the position of the bit to clear."
If,%BitSize%,Equal,"",Begin
Echo,"BitClear Warning: BitSize was not specified. Assuming it's a 32bit integer.",WARN
Set,%BitSize%,32
End
List,Get,%BitArray%,%BitGroup%,%Bits%,Delim=#$c
Math,BitShift,%BitMask%,1,LEFT,%BitPosition%,%BitSize%
Math,BitNot,%BitMask%,%BitMask%,%BitSize%
Math,BitAnd,%Bits%,0x%Bits%,%BitMask%
// Back to Hex for our return value
Math,Hex,%Hex%,%Bits%,%BitSize%
StrFormat,LTRIM,%Hex%,2,%Hex%
List,Set,%BitArray%,%BitGroup%,%Hex%,Delim=#$c
Return,%BitArray%
System,EndLocal
[#_PhoenixAPI_BitSet#]
// ===============================================================================================================================
// Name...........: BitSet
// Description....: Set a specific bit in a binary string.
// Syntax.........: BitSet,<BitArray>,<BitGroup>,<BitPosition>[,BitSize]
// Parameters.....: #1 BitArray - A comma separated string of bits in hex format.
// #2 BitGroup - The specific group of bits to manipulate. This is determined by the 1-based index of the bit group
// supplied by <BitArray>. Example: In order to set a bit in the value 'DB' in
// <BitArray> 01,DB,1A,4C we would specify a <BitGroup> of 2.
// #3 BitPosition - The binary position to modify. (0-based Right to Left)
// #4 BitSize - (Optional) Specify the bitsize (8,16,32,64) used. Default is 32.
// Return values..: #r - Returns <BitArray> with the specified bit set.
// Author.........: Homes32
// Remarks........: BitGroup |= (1 << BitPosition); // Take OR of <BitGroup> and 1 shifted <BitPosition> positions
// Related........:
// ===============================================================================================================================
[_PhoenixAPI_BitSet]
System,SetLocal
GetParam,1,%BitArray%
GetParam,2,%BitGroup%
GetParam,3,%BitPosition%
GetParam,4,%BitSize%
If,%BitArray%,Equal,"",Halt,"BitSet Syntax Error: You must specify a bit array."
If,%BitGroup%,Equal,"",Halt,"BitSet Syntax Error: You must specify the bit group in order to set a bit."
If,%BitPosition%,Equal,"",Halt,"BitSet Syntax Error: You must specify the position of the bit to set."
If,%BitSize%,Equal,"",Begin
Echo,"BitSet Warning: BitSize was not specified. Assuming it's a 32bit integer.",WARN
Set,%BitSize%,32
End
List,Get,%BitArray%,%BitGroup%,%Bits%,Delim=#$c
Math,BitShift,%BitMask%,1,LEFT,%BitPosition%,%BitSize%
Math,BitOr,%Bits%,0x%Bits%,%BitMask%
// Back to Hex for our return value
Math,Hex,%Hex%,%Bits%,%BitSize%
StrFormat,LTRIM,%Hex%,2,%Hex%
List,Set,%BitArray%,%BitGroup%,%Hex%,Delim=#$c
Return,%BitArray%
System,EndLocal
[#_PhoenixAPI_BitToggle#]
// ===============================================================================================================================
// Name...........: BitToggle
// Description....: Set/Clear a specific bit in a binary string.
// Syntax.........: BitToggle,<BitArray>,<BitGroup>,<BitPosition>[,BitSize]
// Parameters.....: #1 BitArray - A comma separated string of bits in hex format.
// #2 BitGroup - The specific group of bits to manipulate. This is determined by the 1-based index of the bit group
// supplied by <BitArray>. Example: In order to toggle a bit in the value 'DB' in
// <BitArray> 01,DB,1A,4C we would specify a <BitGroup> of 2.
// #3 BitPosition - The binary position to modify. (0-based Right to Left)
// #4 BitSize - (Optional) Specify the bitsize (8,16,32,64) used. Default is 32.
// Return values..: #r - Returns <BitArray> with the specified bit flipped.
// Author.........: Homes32
// Remarks........: BitGroup ^= (1 << BitPosition); // Take XOR of <BitGroup> and 1 shifted <BitPosition> positions
// Related........:
// ===============================================================================================================================
[_PhoenixAPI_BitToggle]
System,SetLocal
GetParam,1,%BitArray%
GetParam,2,%BitGroup%
GetParam,3,%BitPosition%
GetParam,4,%BitSize%
If,%BitArray%,Equal,"",Halt,"BitToggle Syntax Error: You must specify a bit array."
If,%BitGroup%,Equal,"",Halt,"BitToggle Syntax Error: You must specify the bit group in order to toggle a bit."
If,%BitPosition%,Equal,"",Halt,"BitToggle Syntax Error: You must specify the position of the bit to toggle."
If,%BitSize%,Equal,"",Begin
Echo,"BitToggle Warning: BitSize was not specified. Assuming it's a 32bit integer.",WARN
Set,%BitSize%,32
End
List,Get,%BitArray%,%BitGroup%,%Bits%,Delim=#$c
Math,BitShift,%BitMask%,1,LEFT,%BitPosition%,%BitSize%
Math,BitXOr,%Bits%,0x%Bits%,%BitMask%
// Back to Hex for our return value
Math,Hex,%Hex%,%Bits%,%BitSize%
StrFormat,LTRIM,%Hex%,2,%Hex%
List,Set,%BitArray%,%BitGroup%,%Hex%,Delim=#$c
Return,%BitArray%
System,EndLocal
[#_PhoenixAPI_JSONCompact#]
// ===============================================================================================================================
// Name...........: JSONCompact
// Description....: Experimental wrapper for jj - Compress the JSON into the fewest characters possible by squashing newlines and spaces.
// Syntax.........: JSONCompact,<JSONFile>
// Parameters.....: #1 JSONFile - Full path to the JSON filed to compact.
// Return values..: #r - Returns
// Author.........: Homes32
// Remarks........: https://github.com/tidwall/jj
// Related........: Depends on %Tools%\%HostArch%\jj.exe
// ===============================================================================================================================
[_PhoenixAPI_JSONCompact]
System,SetLocal
GetParam,1,%JSONFile%
If,Not,ExistFile,%JSONFile%,Halt,"JSONCompact Syntax Error: The file [%JSONFile%] does not exist."
ShellExecute,Hide,"%Tools%\%HostArch%\jj.exe","-u -i #$q%JSONFile%#$q -o #$q%JSONFile%#$q"
If,Not,#r,Equal,0,Halt,"JSONCompact ERROR: Failed to compact [%JSONFile%]."
System,EndLocal
[#_PhoenixAPI_JSONDelete#]
// ===============================================================================================================================
// Name...........: JSONDelete
// Description....: Experimental wrapper for jj - Delete an JSON value.
// Syntax.........: JSONDelete,<JSONFile>,<Path>
// Parameters.....: #1 JSONFile - Full path to the JSON filed to edit.
// #2 Path - GJSON Path notation used to locate the value to delete.
// Return values..: #r - Returns
// Author.........: Homes32
// Remarks........: jj.exe Homepage: https://github.com/tidwall/jj
// Path Syntax Help: https://github.com/tidwall/gjson/blob/master/SYNTAX.md
// Related........: Depends on %Tools%\%HostArch%\jj.exe
// ===============================================================================================================================
[_PhoenixAPI_JSONDelete]
System,SetLocal
GetParam,1,%JSONFile%
GetParam,2,%Path%
If,Not,ExistFile,%JSONFile%,Halt,"JSONDelete Syntax Error: The file [%JSONFile%] does not exist."
If,%Path%,Equal,"",Halt,"JSONDelete Syntax Error: You must specify an JSON Path."
ShellExecute,Hide,"%Tools%\%HostArch%\jj.exe","-D -i #$q%JSONFile%#$q -o #$q%JSONFile%#$q #$q%Path%#$q"
If,Not,#r,Equal,0,Halt,"JSONDelete ERROR: Failed to delete [%Path%] from [%JSONFile%]."
System,EndLocal
[#_PhoenixAPI_JSONPretty#]
// ===============================================================================================================================
// Name...........: JSONPretty
// Description....: Experimental wrapper for jj - Format and indent the JSON file for easy human reading.
// Syntax.........: JSONPretty,<JSONFile>
// Parameters.....: #1 JSONFile - Full path to the JSON filed to compact.
// Return values..: #r - Returns
// Author.........: Homes32
// Remarks........: https://github.com/tidwall/jj
// Related........: Depends on %Tools%\%HostArch%\jj.exe
// ===============================================================================================================================
[_PhoenixAPI_JSONPretty]
System,SetLocal
GetParam,1,%JSONFile%
If,Not,ExistFile,%JSONFile%,Halt,"JSONPretty Syntax Error: The file [%JSONFile%] does not exist."
ShellExecute,Hide,"%Tools%\%HostArch%\jj.exe","-p -i #$q%JSONFile%#$q -o #$q%JSONFile%#$q"
If,Not,#r,Equal,0,Halt,"JSONPretty ERROR: Failed to pretty [%JSONFile%]."
System,EndLocal
[#_PhoenixAPI_JSONRead#]
// ===============================================================================================================================
// Name...........: JSONRead
// Description....: Experimental wrapper for jj - Read an JSON value.
// Syntax.........: JSONRead,<JSONFile>,<Path>
// Parameters.....: #1 JSONFile - Full path to the JSON filed to read.
// #2 Path - GJSON Path notation used to locate the value to read.
// Return values..: #r - Returns the value of <Path>
// Author.........: Homes32
// Remarks........: jj.exe Homepage: https://github.com/tidwall/jj
// Path Syntax Help: https://github.com/tidwall/gjson/blob/master/SYNTAX.md
// Related........: Depends on %Tools%\%HostArch%\jj.exe
// ===============================================================================================================================
[_PhoenixAPI_JSONRead]
System,SetLocal
GetParam,1,%JSONFile%
GetParam,2,%Path%
If,Not,ExistFile,%JSONFile%,Halt,"JSONRead Syntax Error: The file [%JSONFile%] does not exist."
If,%Path%,Equal,"",Halt,"JSONRead Syntax Error: You must specify an JSON Path."
FileDeleteEx,"%ProjectTemp%\PhoenixAPI-JSONRead.txt"
FileDeleteEx,"%ProjectTemp%\PhoenixAPI-JSONRead.ini"
ShellExecute,Hide,"%Tools%\%HostArch%\jj.exe","-i #$q%JSONFile%#$q -o #$q%ProjectTemp%\PhoenixAPI-JSONRead.txt#$q #$q%Path%#$q"
If,Not,#r,Equal,0,Halt,"JSONRead ERROR: Failed to read [%JSONFile%]."
ShellExecute,Hide,"cmd.exe","/c for /f #$qtokens=*#$q %a in (PhoenixAPI-JSONRead.txt) do (echo Value=%a) > #$q%ProjectTemp%\PhoenixAPI-JSONRead.ini#$q",%ProjectTemp%
If,ExistFile,"%ProjectTemp%\PhoenixAPI-JSONRead.ini",Begin
// Value was found in JSON file
TXTAddLine,"%ProjectTemp%\PhoenixAPI-JSONRead.ini","[Read]",PREPEND
IniRead,"%ProjectTemp%\PhoenixAPI-JSONRead.ini","Read","Value",#r
End
Else,Begin
// Value was not found in JSON file
Return,""
End
System,EndLocal
[#_PhoenixAPI_JSONWrite#]
// ===============================================================================================================================
// Name...........: JSONWrite
// Description....: Experimental wrapper for jj - Set/Modify an JSON value.
// Syntax.........: JSONWrite,<JSONFile>,<Path>,<Value>
// Parameters.....: #1 JSONFile - Full path to the JSON filed to edit.
// #2 Path - GJSON Path notation used to locate the value to write.
// #3 Value - The value to write. (Can be empty)
// Return values..: #r - Returns
// Author.........: Homes32
// Remarks........: jj.exe Homepage: https://github.com/tidwall/jj
// Path Syntax Help: https://github.com/tidwall/gjson/blob/master/SYNTAX.md
// Related........: Depends on %Tools%\%HostArch%\jj.exe
// ===============================================================================================================================
[_PhoenixAPI_JSONWrite]
System,SetLocal
GetParam,1,%JSONFile%
GetParam,2,%Path%
GetParam,3,%Value%
If,Not,ExistFile,%JSONFile%,Halt,"JSONWrite Syntax Error: The file [%JSONFile%] does not exist."
If,%Path%,Equal,"",Halt,"JSONWrite Syntax Error: You must specify an JSON Path."
ShellExecute,Hide,"%Tools%\%HostArch%\jj.exe","-v #$q%Value%#$q -i #$q%JSONFile%#$q -o #$q%JSONFile%#$q #$q%Path%#$q"
If,Not,#r,Equal,0,Halt,"JSONWrite ERROR: Failed to write the value of [%Value%] to [%Path%] in [%JSONFile%]."
System,EndLocal
[#_PhoenixAPI_XMLAdd#]
// ===============================================================================================================================
// Name...........: XMLAdd
// Description....: Experimental wrapper for XmlStarlet - Add a new element/text/attribute to an XML file.
// Syntax.........: XMLAdd,<Operation>,<XMLFile>,<XPath>,<Type>,<Name>[,<Value>]
// Parameters.....: #1 Operation - Can be one of:
// Insert - Insert a node at the the beginning of the XPath.
// Append - Append a node to the end of the XPath.
// Subnode - Add a new subnode to each XPath in the document.
// #2 XMLFile - Full path to the .xml filed to edit.
// #3 XPath - XPath (XML Path Language) query used to insert the Attribute/Element.
// #4 Type - XPath type [elem|text|attr]
// #5 Name - Value Name
// #6 Value - (Optional) Value
// Return values..: #r - Returns
// Author.........: Homes32
// Remarks........:
// http://xmlstar.sourceforge.net/doc/UG/xmlstarlet-ug.pdf
// Related........:
// ===============================================================================================================================
[_PhoenixAPI_XMLAdd]
System,SetLocal
GetParam,1,%Operation%
GetParam,2,%XMLFile%
GetParam,3,%XPath%
GetParam,4,%Type%
GetParam,5,%Name%
GetParam,6,%Value%
If,%Operation%,Equal,"",Halt,"XMLAdd Syntax Error: You must specify an operation [insert|append|subnode]."
If,Not,ExistFile,%XMLFile%,Halt,"XMLAdd Syntax Error: The file [%XMLFile%] does not exist."
If,%XPath%,Equal,"",Halt,"XMLAdd Syntax Error: You must specify an XPath."
If,%Type%,Equal,"",Halt,"XMLAdd Syntax Error: You must specify a type [elem|text|attr]."
If,%Name%,Equal,"",Halt,"XMLAdd Syntax Error: You must specify a name."
//ShellExecute,Hide,"%Tools%\x86\xml.exe","select --text --template --value-of #$q%XPath%/@%Name%#$q #$q%XMLFile%#$q"
//If,Not,#r,Equal,0,Halt,"XMLAdd ERROR: Failed to query [%XPath%/@%Name%] from [%XMLFile%]."
If,%Operation%,Equal,"Insert",Begin
ShellExecute,Hide,"%Tools%\x86\xml.exe","edit --inplace --insert #$q%XPath%#$q --type #$q%Type%#$q --name #$q%Name%#$q --value #$q%Value%#$q #$q%XMLFile%#$q"
If,Not,#r,Equal,0,Halt,"XMLAdd ERROR: Failed to insert value [%XPath%/%Name%: %Value%] to [%XMLFile%]."
End
Else,If,%Operation%,Equal,"Append",Begin
ShellExecute,Hide,"%Tools%\x86\xml.exe","edit --inplace --append #$q%XPath%#$q --type #$q%Type%#$q --name #$q%Name%#$q --value #$q%Value%#$q #$q%XMLFile%#$q"
If,Not,#r,Equal,0,Halt,"XMLAdd ERROR: Failed to append value [%XPath%/%Name%: %Value%] to [%XMLFile%]."
End
Else,If,%Operation%,Equal,"Subnode",Begin
ShellExecute,Hide,"%Tools%\x86\xml.exe","edit --inplace --subnode #$q%XPath%#$q --type #$q%Type%#$q --name #$q%Name%#$q --value #$q%Value%#$q #$q%XMLFile%#$q"
If,Not,#r,Equal,0,Halt,"XMLAdd ERROR: Failed to add subnode value [%XPath%/%Name%: %Value%] to [%XMLFile%]."
End
Else,Halt,"XMLAdd Syntax Error: You must specify an valid operation [insert|append|subnode]."
System,EndLocal
[#_PhoenixAPI_XMLDelete#]
// ===============================================================================================================================
// Name...........: XMLDelete
// Description....: Experimental wrapper for XmlStarlet - Delete an XML path/value.
// Syntax.........: XMLDelete,<XMLFile>,<XPath>
// Parameters.....: #1 XMLFile - Full path to the .xml filed to edit.
// #2 XPath - XPath (XML Path Language) query used to locate the Attribute/Element to delete.
// Return values..: #r - Returns
// Author.........: Homes32
// Remarks........: http://xmlstar.sourceforge.net/doc/UG/xmlstarlet-ug.pdf
// Related........:
// ===============================================================================================================================
[_PhoenixAPI_XMLDelete]
System,SetLocal
GetParam,1,%XMLFile%
GetParam,2,%XPath%
If,Not,ExistFile,%XMLFile%,Halt,"XMLDelete Syntax Error: The file [%XMLFile%] does not exist."
If,%XPath%,Equal,"",Halt,"XMLDelete Syntax Error: You must specify an XPath."
//ShellExecute,Hide,"%Tools%\x86\xml.exe","select --text --template --value-of #$q%XPath%#$q #$q%XMLFile%#$q"
//If,Not,#r,Equal,0,Halt,"XMLDelete ERROR: Failed to query [%XPath%] from [%XMLFile%]."
ShellExecute,Hide,"%Tools%\x86\xml.exe","edit --inplace --delete #$q%XPath%#$q #$q%XMLFile%#$q"
If,Not,#r,Equal,0,Halt,"XMLDelete ERROR: Failed to delete [%XPath%] from [%XMLFile%]."
System,EndLocal
[#_PhoenixAPI_XMLRename#]
// ===============================================================================================================================
// Name...........: XMLRename
// Description....: Experimental wrapper for XmlStarlet - Rename a value in an XML file.
// Syntax.........: XMLRename,<XMLFile>,<XPath>,<Value>
// Parameters.....: #1 XMLFile - Full path to the .xml filed to edit.
// #2 XPath - XPath (XML Path Language) query used to locate the Attribute/Element to rename.
// #3 Value - New Value
// Return values..: #r - Returns
// Author.........: Homes32
// Remarks........: The XPath must exist in order for the value to be Renamed.
// http://xmlstar.sourceforge.net/doc/UG/xmlstarlet-ug.pdf
// Related........:
// ===============================================================================================================================
[_PhoenixAPI_XMLRename]
System,SetLocal
GetParam,1,%XMLFile%
GetParam,2,%XPath%
GetParam,3,%Value%
If,Not,ExistFile,%XMLFile%,Halt,"XMLRename Syntax Error: The file [%XMLFile%] does not exist."
If,%XPath%,Equal,"",Halt,"XMLRename Syntax Error: You must specify an XPath."
If,%Value%,Equal,"",Halt,"XMLRename Syntax Error: You must specify a value."
//ShellExecute,Hide,"%Tools%\x86\xml.exe","select --text --template --value-of #$q%XPath%#$q #$q%XMLFile%#$q"
//If,Not,#r,Equal,0,Halt,"XMLRename ERROR: Failed to query [%XPath%] from [%XMLFile%]."
ShellExecute,Hide,"%Tools%\x86\xml.exe","edit --inplace --rename #$q%XPath%#$q --value #$q%Value%#$q #$q%XMLFile%#$q"
If,Not,#r,Equal,0,Halt,"XMLRename ERROR: Failed to write value [%XPath%: %Value%] to [%XMLFile%]."
System,EndLocal
[#_PhoenixAPI_XMLUpdate#]
// ===============================================================================================================================
// Name...........: XMLUpdate
// Description....: Update the value of an existing Attribute/Element
// Syntax.........: XMLUpdate,<XMLFile>,<XPath>,<Value>,[NOERR]
// Parameters.....: #1 XMLFile - Full path to the .xml filed to edit.
// #2 XPath - XPath (XML Path Language) query used to locate the Attribute/Element to update.
// #3 Value - New Value
// #4 NOERR - Don't Halt on errors. (Use if you intend to handle errors yourself).
// Return values..: #r - Returns: 0 - Success
// 1 - Failure
// 2 - Invalid Arguments
// 3 - Invalid XML File
// 4 - Library Exception
// 5 - Internal Error
// -99999999 - XPath does not exist
// Author.........: Homes32
// Remarks........: The XPath must exist in order for the value to be updated.
// http://xmlstar.sourceforge.net/doc/UG/xmlstarlet-ug.pdf
// Related........:
// ===============================================================================================================================
[_PhoenixAPI_XMLUpdate]
System,SetLocal
GetParam,1,%XMLFile%
GetParam,2,%XPath%
GetParam,3,%Value%
GetParam,4,%NOERR%
If,Not,ExistFile,%XMLFile%,Halt,"XMLUpdate Syntax Error: The file [%XMLFile%] does not exist."
If,%XPath%,Equal,"",Halt,"XMLUpdate Syntax Error: You must specify an XPath."
If,%Value%,Equal,"",Halt,"XMLUpdate Syntax Error: You must specify a value."
ShellExecute,Hide,"%Tools%\x86\xml.exe","select --text --template --value-of #$q%XPath%#$q #$q%XMLFile%#$q"
If,Not,#r,Equal,0,Begin
If,Not,%NOERR%,Equal,"NOERR",Halt,"XMLUpdate ERROR: Failed to query [%XPath%] from [%XMLFile%]. The XPath must exist in order for the value to be updated."
Return,-99999999
End
Else,Begin
ShellExecute,Hide,"%Tools%\x86\xml.exe","edit --inplace --update #$q%XPath%#$q --value #$q%Value%#$q #$q%XMLFile%#$q"
If,Not,#r,Equal,0,Halt,"XMLUpdate ERROR: Failed to write value [%XPath%: %Value%] to [%XMLFile%]."
End
System,EndLocal