You are here

To Team: A clear coding convention is needed

5 posts / 0 new
Last post
Last seen: 2 years 1 month ago
Joined: 2021-05-23 05:26
To Team: A clear coding convention is needed

I have been using apps from for a few years, and recently I started trying to make my own portable apps with PAL, but when I explored it in depth, I became more confused. I have a certain programming knowledge. It is not difficult for me to deal with a simple programming language like NSIS, but the absence of standard coding conventions often makes my development process tangled. To this end, I collected the problems encountered in my development and organized it into the following list.
Live Mode (Run Local)

  1. Should I consider RunLocally option if I writing my own PAF Launcher?
    Sometimes in order to achieve something that official build PAL cannot achieve, for example Unicode support, or to launcher for the software's secondary applications, developer are forced to write their own launcher. If do so, does developer need to consider the RunLocally option that still supported by PAL? (Same question for AdditionalParameters and DisableSplashScreen options)


  1. The order of the icons
    [Control] section indicates to the platform how many icons a given app should have and how the app should be started. Generally, all apps should have a single icon, then [Control]:Icons will set to be 1 and [Control]:Start will set to the EXE of main application that should be run to start the app.
    Sometimes, an application will have multiple icons, as is the case with Portable. In this case, StartN and NameN will be used in the [Control] section of the appinfo.ini file.
    But the manual and actual practice are handled differently in the order of the icons:

    • In the manual, the first icon (Start1 and Name1) is the main application.
    • For the only application with multiple icons in, LibreOffice Portable and OpenOffice Portable, the main application is the last icon instead of the first icon.


  2. Does the icon of the portable launcher need to be updated together if the icon of the base program is updated?
    Some Icons of's official portable apps are outdated.
    For example, the icons used by the latest Calibre Portable is the icon of calibre after version 0.7.0. calibre has modified their icons in version 0.7.3, 2.66.0 and the latest icons is updated in version 2.69.0.
    The same includes IObit Uninstaller Portable etc.
    Should icon of launcher updated if base program had updated their icon?
  3. The difference between [Details]:Description in appinfo.ini, "catchy tag line" in help.html and "DESCRIPTION OF APP FUNCTION" in help.html
    In Template, the examples of [Details]:Description given by are "Web browser", "Email client", etc.
    Although it named "Description", it is different from "file description" in the file metadata (in most cases, "file description" in file metadata is long description, and does not correspond to the desired value of [Details]:Description in appinfo.ini).
    In my opinion, [Details]:Description in appinfo.ini corresponds more to the GenericName in desktop file of the Linux app, e.g. Typora is considered as a Markdown Editor, Aegisub is considered as a Subtitle Editor, etc.
    In other hand, "catchy tag line" is more like a slogan of the application, sometimes it is correspond to the Description in desktop file of the Linux app, or the "file description" in file metadata we just mentioned, e.g. Atom: "A hackable text editor for the 21st Century", Typora: "A minimal Markdown reading and writing app", etc.
    Nevertheless, I hope that will give us more detailed guidelines to deal with them.
  4. Guideline for AppName, [Details]:AppName, [Details]:AppId
    Sometimes a app has difference app name. We can find how official naming their name from following places:

    • The Windows' uninstall registry key. Sometimes a app will store their app information in registry entries HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall to help Windows to uninstall the program, we can use the information in registry key to complete the information in appinfo.ini and help.html such as DisplayName, Publisher, DisplayVersion, and URLInfoAbout.
    • The file metadata of the program executable.
    • The original subdirectory name used in %APPDATA%, %LOCALAPPDATA%, %ALLUSERSPROFILE% directories to store the configuration.
    • The desktop file of the application in Linux.

    In my opinion, app name used AppId is better to refer the subdirectory name the apps used to store their local files, e.g. If the app creates the local folder %APPDATA%\Publisher\AppName, then AppNamePortable will be used as AppId. The advantage of this method is can make sure the AppId does not contain illegal the characters in folder naming, since the AppId will later used as the base name of the launcher file and the name of the portable app folder.
    The DisplayName in uninstall registry will then used to fill the value of [Details]:AppName in appinfo.ini

Data Directory

  1. App config, how should we name it?
    In Template, it give two example to dealing with [DirectoriesMove]:

    • The first example demonstrates how to deal with the folder of configuration files placed in %APPDATA% directories, in that example it save the contents of %APPDATA%\Publisher\AppName\ to %PAL:DataDir%\AppNameConfig\
    • The second example demonstrates how to deal with folder of configuration files placed in program directory, in that example it save the contents of %PAL:AppDir%\AppName\Config\ to %PAL:DataDir%\AppNamePortableConfig\

    In other hand, in PAL manuals, the example given is saving the contents of %APPDATA%\Publisher\AppName\ to %PAL:DataDir%\config\
    However, NONE of the portable app follow the above examples to naming the folder to save their configuration (well, in fact there are apps that follow them, but only a small portion). Where the settings will be saved is determined by the contributor/developer’s habits.
    The following is my summary of the folder names that have been used in applications:

    • Most of them are simply move the folder without change the folder name i.e. AppName.
    • .AppName, most of them are Linux apps. e.g. Cornice Portable, FontForge Portable, GIMP Portable, Links Portable, Mp3splt-gtk Portable, Qmmp Portable. There is also a variant dotAppName which is used by Mnemosyne Portable.
    • Some of them move the contents in %APPDATA%\Publisher\AppName\ one by one to %PAL:DataDir% instead %APPDATA%\Publisher\AppName\ it self.
    • Since some of the app have multiples folder with same folder name in different directories, to distinguish them, the word APPDATA , Local, LOCALAPPDATA, USERPROFILE are used as the prefix or postfix of the folder name, e.g. AppNameAPPDATA, AppNameLOCALAPPDATA, AppNameLocal, AppNameUSERPROFILE, UserProfileConfig.
    • Some of them had used the %PAL:DataDir%\settings\ directory to save the configuration, which also the path to saving the settings from PAL itself.
    • etc.

    The absence of a unified naming convention makes the files in the Data directory very messy. For users who are computer idiots, every time they want to deal with the setting file from's portable app, they have to pay a learning cost again, I don’t think it is a user-friendly result.
    My suggestion is instead backup the %APPDATA%\Publisher\AppName\, we handle the contents of the directory separately like below:


    The benefit of above suggestion is that the path of configuration saved will be as close as possible to the root directory, to avoid the file path being too long.
    Sometime the app uses the same subdirectory name to save the app configuration in %APPDATA%, %LOCALAPPDATA% and %ALLUSERSPROFILE% at the same time, but because they are created to save files for different purpose, the probability of a directory with the same name in them is actually very small, and the name duplication is avoided.
    In addition, even the configuration files saved in same subdirectory, not all of them are necessary (e.g. cache files). This method is convenient for users to "turn off" the function of saving some files/folders (by replacing the key at left hand side with -) according to their preferences.
    One disadvantage is that it may increase the barriers for newbie to getting started with PAL to make portable app.
    Of course, if the official of the base application has a default folder naming, then official naming of the base application will take precedence.

  2. Should the settings subdirectory be used to store app configuration files other than PAL settings and registry entry files?
    Although using settings as the key in [DirectoriesMove] section is not desirable, but contributor/developer still can use subdirectory of settings (e.g. settings\ExampleFolder) as the key in [DirectoriesMove] section or use settings subdirectory to save the file in FilesMove section.
  3. How can developers and contributors who take over the maintenance of portable software change the folder structure of the Data directory?
    This is a thorny issue.
    After first dev-test app is release, the folder structure of Data directory will be decided by its first contributor/developer, and this portable app had to use it all its lifetime, any modification on Data directory may cause some configuration file cannot be found if user bring his app data from old version of portable app to new version of portable app.
    This brings a lot of historical problems, here is my real example, I plan to use the calibre official's default folder name to name the configuration folder and library folder (Calibre Settings and Calibre Library) (see source code here) in the next release of calibre Portable to replace old paths used by (settings and library), but I realize that data from old portable app will not compatible with the calibre Portable that has modified the paths.
    I see app such as Gramps Portable will pop up a message box stating that the old data cannot be used in new version of the app, which realize with custom.nsh, would a similar feature would included in new version of Launcher?
    I hope would explore a way to deal with this problem.
  4. How can we update the portable app that its base application is no longer updated?
    Just curious how will handle this problem, since the version of official release of portable app is equal to its base app. If we fix the portable app when the base app still the same version, the Platform will not receive the update. Does have a solution to deal with this problem?
  5. DefaultData or Custom.nsh
    Sometime the portability of a app is determined by the existence or content of some files. To make the launcher always launch the app in portable, the launcher should always make sure that file is exist before run the app.
    In most of the time, realize it by include that file into DefaultData, sometime it only a empty file to be copied to Data directory at the first run of the program. There is no doubt that the use of DefaultData does lower the barrier to getting started with PAL, but there is a blind spot, if user delete those file but remain the settings of PAL after first run, the launcher can't guarantee that the file will be regenerated if the file doesn't exist and continue to execute the application in non-portable mode.
    Should we contain empty files/folders in DefaultData directory or make launcher create them?
  6. Should the default files in DefaultData be included into the repo?
    Since most of time the files in DefaultData portable app is necessary to make the portable app work properly, should we consider to include them into Team's GitHub repo etc.?
  7. Placeholder in default files
    Sometime, the placeholders is used in default files in DefaultData directory, these placeholders will then used in [FileWriteN] to replace it with the value base on current status of the portable apps (mostly are the paths base on current directory of the portable app).
    However, there is no standard to naming those placeholders in It is determined by the contributor/developer’s habits. The following is my summary on placeholder name that had been used by

    • One of above, but with parentheses(( and )), e.g. INITIALAPPNAMEDATADIRECTORY, (INITIALPORTABLEAPPSDIRECTORY)

    In fact, in NSIS documentation there are several examples of dealing with placeholders.
    In documentation of ReplaceInFile, the placeholder are in �PLACEHOLDER_SOMETHING format.
    In this, and this NSIS docs etc., the placeholder are wrapped with one or two At sign (@), e.g. @something@, @@something@@ etc.
    How should we name these placeholders?

  8. Replace or INI/XML attribute/XML text/ConfigWrite
    Although PAL provide several method to edit the configuration files, but in my view, there is only two method to dealing with configuration files, the first is directly (dealing it as INI, XML attribute/text or ConfigWrite) the second is indirectly (by replacing the placeholder in default files)
    Let's talk about indirectly, which is by replacing the placeholders in default files.
    In this case, it only processes the file during the first run.
    In order to ensure that the application can still work properly after the application path is changed, it needs to be accompanied by the update of the disk letter, relative path and full path as below.


    The advantage of this method is that the user can modify the value according to his preferences in the future without being forced to reset the value to the default value.
    In the case of edit directly, the value will be reset back to the default value every time the application is opened, and the value change during user use the app will not be saved in next execution.
    There is no good or bad between them, it's just that there are suitable methods for different situations.
    If the value to be dealt with is related to portability of the app, e.g. the path of cache or configuration folder, then write directly would be the best choice.
    If the value to be dealt with is less related to the portability of the app, e.g. the path of documents/pictures/videos/plugins folder, then write indirectly would be the best choice.

  9. What data should consider as "Garbage Data"?
    Cache, blob_storage, log, crashdumps etc., do we need to save these data to Data directory?
  10. Lettercase
    Even Windows system is case insensitive, which mean %APPDATA% and %AppData% are both acceptable, but all Windows's environment variables have their own case (and even a sort order).
    CommonProgramFiles, CommonProgramFiles(x86), CommonProgramW6432, ComSpec, DriveData, Path, ProgramData, ProgramFiles, ProgramFiles(x86), ProgramW6432, SystemDrive, SystemRoot are upper camel case.
    windir are all lowercase.
    For details, you can refer to this article from Microsoft's documentation.
    It is better if the case of environment variables in launcher file of the following app can be standardized, e.g. MusicBrainz Picard Portable, SpeedyFox Portable etc.
  1. Should we ban [RegistryValueWrite]?
    As John T. Haller reply in this forum the modification on registry entry should doing with [FileWriteN] instead using [RegistryValueWrite]. Although John T. Haller states that there might some app need this feature (well, although I don't think it exists), but should we consider to ban [RegistryValueWrite] if the value can handle with [FileWriteN].


  1. Indentation - TABs or SPACEs?
    I found that neither NSIS Team and Team had a standardized indentation rules.
    In's PAL manuals of, the 4 SPACEs are used to indent NSIS code. See here.
    In NSIS's documentation, the 2 SPACEs are used to indent NSIS code. See here.
    However, in real practice, many NSIS codes in NSIS has different indent style based on the habit of their contributor/developer. (See NSIS's source codes at SourceForge or GitHub (mirrored by Szekely)
    The situation on look okay. Most of time tab is used. In PAL templates given by, TABs is used in the AppName.nsi, the source code of the example stubs.
    In HM NIS Edit (a NSIS IDE included in, by default one tab will converted into 8 SPACEs indentation.
    Well, actually I'm a member of the "SPACEism Party" *biggrin*, I prefer using SPACEs rather than TABs in NSIS code since I use VSCode and HM NIS Edit as my IDE, also spacing always make my indention work properly across any editors.
    However, it's okay if prefers to use TABs. Since most of the code in is indented with TABs, remaining it and standardized other code into same indentation method a will facilitate the maintenance work of
    Also, do the following situations need to be indented?

    • Line after !macro SomeMacro and Function SomeFunc
    • Line after a label, i.e. Label:


  2. Lettercase
    In other word,
    label:, Label:, or LABEL: ?
    $variable , $Variable or $VARIABLE?
    !macro macro, !macro Macro or !macro MACRO
    Function func, Function Func or Function FUNC
    Custom.nsh or custom.nsh
  3. Should we prefix functions, variables or even label in Custom.nsh with "Custom"?
    I found that most of the functions, variables in Custom.nsh, and sometimes including the labels, are named in the form of CustomSomething.
    Can I think this is the coding standard from
  4. Where should the plug-in DLLs and NSIS scripts used by Custom.nsh be placed?
    In the case that Custom.nsh uses other plug-ins or NSIS scripts, the directory of that plug-ins or scripts had to specify in Custom.nsh with !addplugindir and !addincludedir.
    Well, actually there is not much dissent on this issue, in general the plugins is put at ${PACKAGE}\Other\Source\Plugins and the include directory ${PACKAGE}\App\AppInfo\Launcher is added.
    Just some apps didn't placed plugins in folder stated above and may need to be corrected, e.g. Iron Portable, OpenShot Portable etc.
  5. The guideline for self-written PAF launcher
    As we mentioned before, sometimes we are forced to write our own launcher for our PAF app instead use the PAL. However we don't have a specification on that program.
    Although I had request for the source of non-PAL launcher in the forum before, but I also think about whether it should be open source. The use of universal PAL launcher in some case had force the users to open their source to people, since most of the time the sources are the launcher INI configuration file that are necessary during run of the universal launcher.
    So may be can give a template of non-PAL launcher that just remain the labels and comments but leave blank to the inner code. The purpose is to specific the flow of the launcher handle the app that developers should comply with. For example, should splash screen display before READINI or after, should launcher test the bits of current OS before READINI or after, etc.

Other related with PAL

  1. JSON support
    I found that many application start to use JSON to replace XML to save app configuration, e.g. HandBrake etc.
    PAL can no longer to access configuration files properly with [FileWriteN] and [LanguageFile] sections. Although a compromise is to treat it as ConfigWrite/Read, but the prerequisite is that the JSON is formatted and make sure the target key it always not the last key (Some apps doesn't accept trailing comma in JSON).
    Does plan to add JSON features to Launcher?
  2. Handle garbage files
    In [DirectoriesMove] section, the source directory can set to - if the directory no need to save.
    In [FilesMove] section, we can't do the same thing to remove the file since the left hand side is compulsory to specify the files to move.
    Will add this feature to Launcher in its future version?
  3. Dealing with latest Qt applications Launcher implement [QtKeysCleanup] section to deal with cleaning up keys like HKCU\Software\Throlltech\QrganizationDefaults\Something.
    But these segment will become less and less applicable in the future, this is because Qt had change its publisher subkey from Throlltech to QtProject.
    Will update the feature of [QtKeysCleanup] so that it can deal with cleaning up keys created from newest Qt applications?
  4. Run 32 bit executable file if 64 bit executable file is absent.
    In 64 bit operating system, for the portable app with both 32 bit and 64 bit exe, e.g. 7-Zip Portable, If you delete the 7-Zip64\7zFM.exe (the 64 bit executable file of 7-Zip), You will receive a ERROR message "7-Zip Portable cannot be started. You may wish to re-install to fix this issue. (ERROR: App\7-Zip64\7zFM.exe could not be found)", this is because PAL will set the execute path to the path of 64-bit exe if it is stated in [Launch]:ProgramExecutable64 of the launcher file, but it didn't test whether the file in ProgramExecutable64 exist or not.
    The solution is insert the file test before setting the string as the executable path of the program.
    The following is the part of Core.nsh that had been modified to fix this problem.

    	${GetParameters} $0
    	StrCpy $ProgramExecutable ""
    	${If} $Bits = 64
    		${If} $0 != ""
    			${ReadLauncherConfig} $1 Launch ProgramExecutableWhenParameters64
    			${If} ${FileExists} $1
    				StrCpy $ProgramExecutable $1
    		${If} $ProgramExecutable == ""
    			${ReadLauncherConfig} $1 Launch ProgramExecutable64
    			${If} ${FileExists} $1
    				StrCpy $ProgramExecutable $1
    	${If} $0 != ""
    	${AndIf} $ProgramExecutable == ""
    		${ReadLauncherConfig} $1 Launch ProgramExecutableWhenParameters
    		${If} ${FileExists} $1
    			StrCpy $ProgramExecutable $1
    	${If} $ProgramExecutable == ""
    		${ReadLauncherConfig} $1 Launch ProgramExecutable
            ${If} ${FileExists} $1
    			StrCpy $ProgramExecutable $1
    	${If} $ProgramExecutable == ""
    		; Launcher file missing or missing crucial details (what am I to launch?)
    		MessageBox MB_OK|MB_ICONSTOP `$EXEDIR\App\AppInfo\Launcher\$BaseName.ini is missing [Launch]:ProgramExecutable - what am I to launch?`

    In addition, this means that the environment variable FullAppDir handled by the Custom.nsh in some applications needs to be modified and fixed, e.g. 7-Zip Portable, AkelPad Portable, Avidemux Portable etc. The following is my fix:

    	${If} $Bits = 64
    	${AndIf} ${FileExists} "$EXEDIR\App\AppName64\AppName.exe"
    		${SetEnvironmentVariablesPath} FullAppDir "$EXEDIR\App\AppName64"
    		${SetEnvironmentVariablesPath} FullAppDir "$EXEDIR\App\AppName"


I have used the translator to assist me when I was writing this article. Some sentences may not be fluent, but I hope that all words can convey my intentions correctly. Hope that a reply from the Team can be obtained.

John T. Haller
John T. Haller's picture
Last seen: 2 hours 34 min ago
Joined: 2005-11-28 22:21
Quick Answers

Most of the minor inconsistencies don't matter. Users don't see them (nor do they care). You asked a ton of questions and didn't organize them easily by number and number.number, so I'll just pull out the major bits.

Live Mode - Mostly deprecated. New and existing apps are not tested with it. Should remove.

AppInfo Icon Order - It doesn't really matter. We discourage apps with more than a single icon unless absolutely necessary. It is a bit more complicated with apps that move multiple directories back and forth to save space. I just updated OpenShot which moves 15 directories back and forth between the 32-bit and 64-bit instances which saves 115MB in installed size, for example.

AppInfo Icon Updates - I generally update icons when the app's icon is updated, but I don't usually notice unless it's mentioned somewhere.

AppInfo Tag and Description - Way back when it was a catchy tag line. For new apps, both should match and just be a few words that will show in the PA.c Menu ("web browser", etc).

AppInfo AppName and AppID - No changes will be made. It should always be AppNamePortable and the full AppName should be the app's name plus the word Portable. AppName is created manually. Don't use illegal characters.

Data Settings is for registry and settings files only

Updates to existing apps without a new release are done as Revisions. So, if we have to fix something in Firefox 91.0 before 91.0.1 is released (a major bug is found in our launcher, for example), it'll be Firefox Portable 91.0 Rev 2 with a PackageVersion off

The Gramps Portable notification is due to Gramps itself doing a major update and not supporting older files. It's a rare occurence, but we may eventually build this into PAL.

Generally, there's no need to change Data folder structures.

DefaultData and custom.nsh - If a user is manually deleting files in their Data directory, it's on them to make sure they don't do it wrong.

Placeholders - We should probably switch to @PLACEHOLDER_PLACEHOLDERNAME@ convention. I just need to ensure this won't affect anything else.

We update paths indirectly except where specific requirements have to be done or where there is only a single value that should be there (an app whose plugin directory is always within the App folder, or an app where the profile.ini is within the App folder but must be updated to point to something in Data at each location)

I prefer TABs and each developer can set whether they appear as 2, 4, etc spaces in their editor. Spaces lock in to whatever the developer thinks every other developer should see.

Lettercase, I don't particularly care.

custom.nsh functions and variables should be prefixed with custom to ensure they don't collide with variables used in PAL, PAI or NSIS

Other\Source\plugins should generally be used as the plugins directory

We do not recommend or support new custom coded NSIS launchers

JSON support is custom coded for now. We may add it to PAL later. Generally, using indirect relative updates is sufficient.

Qt needs an update

Eventually we will support leaving out the 32-bit or 64-bit version and have the launcher fallback gracefully.

Sometimes, the impossible can become possible, if you're awesome!

Last seen: 2 years 1 month ago
Joined: 2021-05-23 05:26
Thanks. It help me a lot.

Thanks. It help me a lot.

John T. Haller
John T. Haller's picture
Last seen: 2 hours 34 min ago
Joined: 2005-11-28 22:21
Questions or Clarifications?

You have any additional questions or clarifications or anything I missed for now while it's fresh in our minds? I was thinking about standardizing on camelCase, btw.

Also, realized I left something out of the last point. Gracefully allowing 32-bit or 64-bit only will be complicated by apps that move directories. Openshot Portable, for instance, moves 15 directories back and forth between the two bit-depth versions to save 115MB in install space.

Sometimes, the impossible can become possible, if you're awesome!

Last seen: 2 years 1 month ago
Joined: 2021-05-23 05:26
No at this moment

No at this moment, but it will better if PA.c create a new webpage or forum post to describe these things. All the best! **thumb**

Log in or register to post comments