├── .gitattributes ├── LICENSE ├── PathMan.ico ├── PathMan.iss ├── PathMan.md ├── PathMan.pp ├── PathMan.rc ├── PathMgr.pp ├── PathMgr.ps1 ├── PathMgr.rc ├── README.md ├── WindowsPath.pp └── history.md /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | 3 | Version 3, 29 June 2007 4 | 5 | Copyright (C) 2007 Free Software Foundation, Inc. https://fsf.org/ 6 | 7 | Everyone is permitted to copy and distribute verbatim copies of this license 8 | document, but changing it is not allowed. 9 | 10 | This version of the GNU Lesser General Public License incorporates the terms 11 | and conditions of version 3 of the GNU General Public License, supplemented by 12 | the additional permissions listed below. 13 | 14 | 0. Additional Definitions. 15 | 16 | As used herein, "this License" refers to version 3 of the GNU Lesser General 17 | Public License, and the "GNU GPL" refers to version 3 of the GNU General Public 18 | License. 19 | 20 | "The Library" refers to a covered work governed by this License, other than an 21 | Application or a Combined Work as defined below. 22 | 23 | An "Application" is any work that makes use of an interface provided by the 24 | Library, but which is not otherwise based on the Library. Defining a subclass 25 | of a class defined by the Library is deemed a mode of using an interface 26 | provided by the Library. 27 | 28 | A "Combined Work" is a work produced by combining or linking an Application 29 | with the Library. The particular version of the Library with which the Combined 30 | Work was made is also called the "Linked Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the Corresponding 33 | Source for the Combined Work, excluding any source code for portions of the 34 | Combined Work that, considered in isolation, are based on the Application, and 35 | not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the object code 38 | and/or source code for the Application, including any data and utility programs 39 | needed for reproducing the Combined Work from the Application, but excluding 40 | the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License without 45 | being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a facility 50 | refers to a function or data to be supplied by an Application that uses the 51 | facility (other than as an argument passed when the facility is invoked), then 52 | you may convey a copy of the modified version: 53 | 54 | a) under this License, provided that you make a good faith effort to ensure 55 | that, in the event an Application does not supply the function or data, the 56 | facility still operates, and performs whatever part of its purpose remains 57 | meaningful, or 58 | 59 | b) under the GNU GPL, with none of the additional permissions of this License 60 | applicable to that copy. 61 | 62 | 3. Object Code Incorporating Material from Library Header Files. 63 | 64 | The object code form of an Application may incorporate material from a header 65 | file that is part of the Library. You may convey such object code under terms 66 | of your choice, provided that, if the incorporated material is not limited to 67 | numerical parameters, data structure layouts and accessors, or small macros, 68 | inline functions and templates (ten or fewer lines in length), you do both of 69 | the following: 70 | 71 | a) Give prominent notice with each copy of the object code that the Library is 72 | used in it and that the Library and its use are covered by this License. 73 | 74 | b) Accompany the object code with a copy of the GNU GPL and this license 75 | document. 76 | 77 | 4. Combined Works. 78 | 79 | You may convey a Combined Work under terms of your choice that, taken together, 80 | effectively do not restrict modification of the portions of the Library 81 | contained in the Combined Work and reverse engineering for debugging such 82 | modifications, if you also do each of the following: 83 | 84 | a) Give prominent notice with each copy of the Combined Work that the Library 85 | is used in it and that the Library and its use are covered by this License. 86 | 87 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 88 | document. 89 | 90 | c) For a Combined Work that displays copyright notices during execution, 91 | include the copyright notice for the Library among these notices, as well as a 92 | reference directing the user to the copies of the GNU GPL and this license 93 | document. 94 | 95 | d) Do one of the following: 96 | 97 | 0) Convey the Minimal Corresponding Source under the terms of this License, 98 | and the Corresponding Application Code in a form suitable for, and under 99 | terms that permit, the user to recombine or relink the Application with a 100 | modified version of the Linked Version to produce a modified Combined Work, 101 | in the manner specified by section 6 of the GNU GPL for conveying 102 | Corresponding Source. 103 | 104 | 1) Use a suitable shared library mechanism for linking with the Library. A 105 | suitable mechanism is one that (a) uses at run time a copy of the Library 106 | already present on the user's computer system, and (b) will operate properly 107 | with a modified version of the Library that is interface-compatible with the 108 | Linked Version. 109 | 110 | e) Provide Installation Information, but only if you would otherwise be 111 | required to provide such information under section 6 of the GNU GPL, and only 112 | to the extent that such information is necessary to install and execute a 113 | modified version of the Combined Work produced by recombining or relinking the 114 | Application with a modified version of the Linked Version. (If you use option 115 | 4d0, the Installation Information must accompany the Minimal Corresponding 116 | Source and Corresponding Application Code. If you use option 4d1, you must 117 | provide the Installation Information in the manner specified by section 6 of 118 | the GNU GPL for conveying Corresponding Source.) 119 | 120 | 5. Combined Libraries. 121 | 122 | You may place library facilities that are a work based on the Library side by 123 | side in a single library together with other library facilities that are not 124 | Applications and are not covered by this License, and convey such a combined 125 | library under terms of your choice, if you do both of the following: 126 | 127 | a) Accompany the combined library with a copy of the same work based on the 128 | Library, uncombined with any other library facilities, conveyed under the terms 129 | of this License. 130 | 131 | b) Give prominent notice with the combined library that part of it is a work 132 | based on the Library, and explaining where to find the accompanying uncombined 133 | form of the same work. 134 | 135 | 6. Revised Versions of the GNU Lesser General Public License. 136 | 137 | The Free Software Foundation may publish revised and/or new versions of the GNU 138 | Lesser General Public License from time to time. Such new versions will be 139 | similar in spirit to the present version, but may differ in detail to address 140 | new problems or concerns. 141 | 142 | Each version is given a distinguishing version number. If the Library as you 143 | received it specifies that a certain numbered version of the GNU Lesser General 144 | Public License "or any later version" applies to it, you have the option of 145 | following the terms and conditions either of that published version or of any 146 | later version published by the Free Software Foundation. If the Library as you 147 | received it does not specify a version number of the GNU Lesser General Public 148 | License, you may choose any version of the GNU Lesser General Public License 149 | ever published by the Free Software Foundation. 150 | 151 | If the Library as you received it specifies that a proxy can decide whether 152 | future versions of the GNU Lesser General Public License shall apply, that 153 | proxy's public statement of acceptance of any version is permanent 154 | authorization for you to choose that version for the Library. 155 | -------------------------------------------------------------------------------- /PathMan.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bill-Stewart/PathMgr/2659334340430c01d8a7d13e4d8a9d5d8973e839/PathMan.ico -------------------------------------------------------------------------------- /PathMan.iss: -------------------------------------------------------------------------------- 1 | ; Copyright (C) 2021-2024 by Bill Stewart (bstewart at iname.com) 2 | ; 3 | ; This program is free software; you can redistribute it and/or modify it under 4 | ; the terms of the GNU Lesser General Public License as published by the Free 5 | ; Software Foundation; either version 3 of the License, or (at your option) any 6 | ; later version. 7 | ; 8 | ; This program is distributed in the hope that it will be useful, but WITHOUT 9 | ; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 10 | ; FOR A PARTICULAR PURPOSE. See the GNU General Lesser Public License for more 11 | ; details. 12 | ; 13 | ; You should have received a copy of the GNU Lesser General Public License 14 | ; along with this program. If not, see https://www.gnu.org/licenses/. 15 | 16 | ; Sample Inno Setup (https://www.jrsoftware.org/isinfo.php) script 17 | ; demonstrating use of PathMgr.dll. 18 | ; 19 | ; This script uses PathMgr.dll in the following ways: 20 | ; * Copies PathMgr.dll to the target machine (required for uninstall) 21 | ; * Defines a task in [Tasks] that should modify the Path 22 | ; * Imports the AddDirToPath() DLL function at setup time 23 | ; * Imports the RemoveDirFromPath() DLL function at uninstall time 24 | ; * Stores task state as custom setting using RegisterPreviousData() 25 | ; * Retrieves task state custom setting during setup and uninstall initialize 26 | ; * At post install, adds app dir to Path if task selected 27 | ; * At uninstall, removes dir from Path if custom setting present 28 | ; * Unloads and deletes DLL and removes app dir at uninstall deinitialize 29 | 30 | #if Ver < EncodeVer(6,0,0,0) 31 | #error This script requires Inno Setup 6 or later 32 | #endif 33 | 34 | [Setup] 35 | AppId={{82425B5C-8B45-4F8C-9830-3D8E2DB64581} 36 | AppName=PathMan 37 | AppVersion=2.0.0.0 38 | UsePreviousAppDir=false 39 | DefaultDirName={autopf}\PathMan 40 | ChangesEnvironment=yes 41 | Uninstallable=true 42 | OutputDir=. 43 | OutputBaseFilename=PathMan-Setup 44 | ArchitecturesInstallIn64BitMode=x64 45 | PrivilegesRequired=none 46 | PrivilegesRequiredOverridesAllowed=dialog 47 | 48 | [Files] 49 | ; Install PathMgr.dll for use with both setup and uninstall; use 50 | ; uninsneveruninstall flag because DeinitializeSetup() will delete after 51 | ; unloading the DLL; install the 32-bit version of PathMgr.dll because both 52 | ; setup and uninstall executables are 32-bit 53 | Source: "i386\PathMgr.dll"; DestDir: "{app}"; Flags: uninsneveruninstall 54 | 55 | ; Other files to install on target system 56 | Source: "i386\PathMan.exe"; DestDir: "{app}"; Check: not Is64BitInstallMode() 57 | Source: "x86_64\PathMan.exe"; DestDir: "{app}"; Check: Is64BitInstallMode() 58 | Source: "PathMan.md"; DestDir: "{app}" 59 | 60 | [Tasks] 61 | Name: modifypath; Description: "&Add to Path" 62 | 63 | [Code] 64 | const 65 | MODIFY_PATH_TASK_NAME = 'modifypath'; // Specify name of task 66 | 67 | var 68 | PathIsModified: Boolean; // Cache task selection from previous installs 69 | ApplicationUninstalled: Boolean; // Has application been uninstalled? 70 | 71 | // Import AddDirToPath() at setup time ('files:' prefix) 72 | function DLLAddDirToPath(DirName: string; PathType, AddType: DWORD): DWORD; 73 | external 'AddDirToPath@files:PathMgr.dll stdcall setuponly'; 74 | 75 | // Import RemoveDirFromPath() at uninstall time ('{app}\' prefix) 76 | function DLLRemoveDirFromPath(DirName: string; PathType: DWORD): DWORD; 77 | external 'RemoveDirFromPath@{app}\PathMgr.dll stdcall uninstallonly'; 78 | 79 | // Wrapper for AddDirToPath() DLL function 80 | function AddDirToPath(const DirName: string): DWORD; 81 | var 82 | PathType, AddType: DWORD; 83 | begin 84 | // PathType = 0 - use system Path 85 | // PathType = 1 - use user Path 86 | // AddType = 0 - add to end of Path 87 | // AddType = 1 - add to beginning of Path 88 | if IsAdminInstallMode() then 89 | PathType := 0 90 | else 91 | PathType := 1; 92 | AddType := 0; 93 | result := DLLAddDirToPath(DirName, PathType, AddType); 94 | end; 95 | 96 | // Wrapper for RemoveDirFromPath() DLL function 97 | function RemoveDirFromPath(const DirName: string): DWORD; 98 | var 99 | PathType: DWORD; 100 | begin 101 | // PathType = 0 - use system Path 102 | // PathType = 1 - use user Path 103 | if IsAdminInstallMode() then 104 | PathType := 0 105 | else 106 | PathType := 1; 107 | result := DLLRemoveDirFromPath(DirName, PathType); 108 | end; 109 | 110 | procedure RegisterPreviousData(PreviousDataKey: Integer); 111 | begin 112 | // Store previous or current task selection as custom user setting 113 | if PathIsModified or WizardIsTaskSelected(MODIFY_PATH_TASK_NAME) then 114 | SetPreviousData(PreviousDataKey, MODIFY_PATH_TASK_NAME, 'true'); 115 | end; 116 | 117 | function InitializeSetup(): Boolean; 118 | begin 119 | result := true; 120 | // Was task selected during a previous install? 121 | PathIsModified := GetPreviousData(MODIFY_PATH_TASK_NAME, '') = 'true'; 122 | end; 123 | 124 | function InitializeUninstall(): Boolean; 125 | begin 126 | result := true; 127 | // Was task selected during a previous install? 128 | PathIsModified := GetPreviousData(MODIFY_PATH_TASK_NAME, '') = 'true'; 129 | ApplicationUninstalled := false; 130 | end; 131 | 132 | procedure CurStepChanged(CurStep: TSetupStep); 133 | begin 134 | if CurStep = ssPostInstall then 135 | begin 136 | // Add app directory to Path at post-install step if task selected 137 | if PathIsModified or WizardIsTaskSelected(MODIFY_PATH_TASK_NAME) then 138 | AddDirToPath(ExpandConstant('{app}')); 139 | end; 140 | end; 141 | 142 | procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep); 143 | begin 144 | if CurUninstallStep = usUninstall then 145 | begin 146 | // Remove app directory from path during uninstall if task was selected; 147 | // use variable because we can't use WizardIsTaskSelected() at uninstall 148 | if PathIsModified then 149 | RemoveDirFromPath(ExpandConstant('{app}')); 150 | end 151 | else if CurUninstallStep = usPostUninstall then 152 | begin 153 | ApplicationUninstalled := true; 154 | end; 155 | end; 156 | 157 | procedure DeinitializeUninstall(); 158 | begin 159 | if ApplicationUninstalled then 160 | begin 161 | // Unload and delete PathMgr.dll and remove app dir when uninstalling 162 | UnloadDLL(ExpandConstant('{app}\PathMgr.dll')); 163 | DeleteFile(ExpandConstant('{app}\PathMgr.dll')); 164 | RemoveDir(ExpandConstant('{app}')); 165 | end; 166 | end; 167 | -------------------------------------------------------------------------------- /PathMan.md: -------------------------------------------------------------------------------- 1 | # PathMan 2 | 3 | PathMan is a Windows console (text-based, command-line) program for managing the system Path and user Path. 4 | 5 | # Author 6 | 7 | Bill Stewart - bstewart at iname dot com 8 | 9 | # License 10 | 11 | PathMan.exe is covered by the GNU Lesser Public License (LPGL). See the file `LICENSE` for details. 12 | 13 | # Download 14 | 15 | https://github.com/Bill-Stewart/PathMgr/releases/ 16 | 17 | # Background 18 | 19 | The system Path is found in the following location in the Windows registry: 20 | 21 | Root: `HKEY_LOCAL_MACHINE` 22 | Subkey: `SYSTEM\CurrentControlSet\Control\Session Manager\Environment` 23 | Value name: `Path` 24 | Value type: `REG_EXPAND_SZ` 25 | 26 | The current user Path is found in the following location in the registry: 27 | 28 | Root: `HKEY_CURRENT_USER` 29 | Subkey: `Environment` 30 | Value name: `Path` 31 | Value type: `REG_EXPAND_SZ` 32 | 33 | The registry value type `REG_EXPAND_SZ` means the string caan contain values surrounded by `%` characters that Windows will automatically expand to environment variable values. (For example, `%SystemRoot%` will be expanded to `C:\Windows` on most systems.) 34 | 35 | The `Path` value contains a `;`-delimited list of directory names that the operating system should search for executables, library files, scripts, etc. Windows appends the content of the current user Path to the system Path, and expands the environment variable references, and sets the resulting string as the `Path` environment variable for new processes. 36 | 37 | PathMan provides a command-line interface for managing the `Path` value in the system location (in `HKEY_LOCAL_MACHINE`) and the current user location (in `HKEY_CURRENT_USER`). 38 | 39 | # Usage 40 | 41 | The following describes the command-line usage for the program. Parameters are case-sensitive. 42 | 43 | **PathMan** _scope_ _action_ [_option_ [...]] 44 | 45 | You must specify only one of the following _scope_ parameters: 46 | 47 | | _scope_ | Abbreviation | Description 48 | | ------- | ------------ | ----------- 49 | | **--system** | **-s** | Specifies the system Path 50 | | **--user** | **-u** | Specifies the current user Path 51 | 52 | You must specify only one of the following _action_ parameters: 53 | 54 | | _action_ | Abbreviation | Description 55 | | -------- | ------------ | ----------- 56 | | **--list** | **-l** | Lists directories in Path 57 | | **--test "**_dirname_**"** | **-t "**_dirname_**"** | Tests if directory is in Path 58 | | **--add "**_dirname_**"** | **-a "**_dirname_**"** | Adds directory to Path 59 | | **--remove "**_dirname_**"** | **-r "**_dirname_**"** | Removes directory from Path 60 | 61 | The following parameters are optional: 62 | 63 | | _option_ | Abbreviation | Description 64 | | --------- | ------------ | ----------- 65 | | **--expand** | **-x** | Expands environment variables (**--list** only) 66 | | **--beginning** | **-b** | Adds to beginning of Path (**--add** only) 67 | | **--quiet** | **-q** | Suppresses result and error messages 68 | 69 | # Exit Codes 70 | 71 | The following table lists typical exit codes when not using **--test** (**-t**): 72 | 73 | | Exit Code | Description 74 | | --------- | ----------- 75 | | 0 | No errors 76 | | 2 | The Path value is missing from the registry 77 | | 3 | The specified directory does not exist in the Path 78 | | 5 | Access is denied 79 | | 87 | Incorrect parameter(s) 80 | | 183 | The specified directory already exists in the Path 81 | 82 | The following table lists typical exit codes when using **--test** (**-t**): 83 | 84 | | Exit Code | Description 85 | | --------- | ----------- 86 | | 1 | The specified directory exists in the unexpanded Path 87 | | 2 | The specified directory exists in the expanded Path 88 | | 3 | The specified directory does not exist in the Path 89 | 90 | # Remarks 91 | 92 | * "Unexpanded" vs. "expanded" refers to whether PathMan expands environment variable references (i.e., names between `%` characters) after retrieving the Path value from the registry. For example, `%SystemRoot%` is unexpanded but `C:\Windows` is expanded. 93 | 94 | * The **--add** (**-a**) parameter checks whether the specified directory exists in both the unexpanded and expanded copies of the Path before adding the directory. For example, if the environment variable `TESTAPP` is set to `C:\TestApp` and `%TESTAPP%` is in the Path, specifying `--add C:\TestApp` will return exit code 183 (i.e., the directory already exists in the Path) because `%TESTAPP%` expands to `C:\TestApp`. 95 | 96 | * The **--remove** (**-r**) parameter does not expand environment variable references. For example, if the environment variable `TESTAPP` is set to `C:\TestApp` and `%TESTAPP%` is in the Path, specifying `--remove "C:\TestApp"` will return exit code 3 (i.e., the directory does not exist in the Path) because **--remove** does not expand `%TESTAPP%` to `C:\TestApp`. For the command to succeed, you would have to specify `--remove "%TESTAPP%"` instead. 97 | 98 | * The program will exit with error code 87 if a parameter (or an argument to a parameter) is missing or not valid, if mutually exclusive parameters are specified, etc. 99 | 100 | * The program will exit with error code 5 if the current user does not have permission to update the Path value in the registry (for example, if you try to update the system Path using a standard user account or an unelevated administrator account). 101 | 102 | * Working with environment variable strings at the cmd.exe command prompt can be tricky because cmd.exe always expands environment variable references. One way to work around this is to set a temporary environment variable using the `^` character to escape each `%` character, then use the temporary environment variable in the PathMan command. See **Examples**, below, for an example. This issue doesn't occur in PowerShell because PowerShell doesn't expand environment variables names enclosed in `%` characters. 103 | 104 | * If a directory name contains the `;` character, PathMan will add it to the Path in the registry with surrounding quote characters (`"`). The quotes around the directory name are required to inform the operating system that the enclosed string is a single directory name. For example, consider the following Path string: 105 | 106 | C:\dir 1;"C:\dir;2";C:\dir3 107 | 108 | Without the quote marks enclosing the `C:\dir;2` directory, the system would incorrectly "split" the path name into the following directory names: 109 | 110 | C:\dir 1 111 | C:\dir 112 | 2 113 | C:\dir3 114 | 115 | In other words, the `"` characters around the `C:\dir;2` directory "protect" the `;` character and inform the system that `C:\dir;2` is a single directory name. (The `"` marks themselves are not part of the directory name.) 116 | 117 | # Examples 118 | 119 | 1. List directories in the system Path, expanding all environment varable references: 120 | 121 | PathMan --system --list --expand 122 | 123 | You can also write this command as `PathMan -s -l -x`. 124 | 125 | 2. Add a directory to the current user from the cmd.exe command line: 126 | 127 | set _T=^%LOCALAPPDATA^% 128 | PathMan --user --add "%_T%\Programs\My App" 129 | set _T= 130 | 131 | This sequence of commands adds the directory `%LOCALAPPDATA%\Programs\My App` to the current user Path. The first command sets a temporary environment variable to the literal string `%LOCALAPPDATA%` (the `^` characters "escape" the `%` characters). The second command adds the directory to the current user Path (cmd.exe expands `%_T%` to the literal string `%LOCALAPPDATA%`), and the third command removes the temporary variable from the environment. 132 | 133 | 3. Remove a directory from the system Path: 134 | 135 | PathMan -s -r "C:\Program Files\MyApp\bin" 136 | 137 | 4. Tests if a directory is in the path: 138 | 139 | PathMan -s --test "C:\Program Files (x86)\MyApp\bin" 140 | 141 | This command returns an exit code of 3 if the specified directory is not in the system Path, 1 if the specified directory is in the unexpanded copy of the system Path, or 2 if the specified directory is in the expanded copy of the system Path. 142 | -------------------------------------------------------------------------------- /PathMan.pp: -------------------------------------------------------------------------------- 1 | { Copyright (C) 2024 by Bill Stewart (bstewart at iname.com) 2 | 3 | This program is free software; you can redistribute it and/or modify it under 4 | the terms of the GNU Lesser General Public License as published by the Free 5 | Software Foundation; either version 3 of the License, or (at your option) any 6 | later version. 7 | 8 | This program is distributed in the hope that it will be useful, but WITHOUT 9 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 10 | FOR A PARTICULAR PURPOSE. See the GNU General Lesser Public License for more 11 | details. 12 | 13 | You should have received a copy of the GNU Lesser General Public License 14 | along with this program. If not, see https://www.gnu.org/licenses/. 15 | 16 | } 17 | 18 | program PathMan; 19 | 20 | {$MODE OBJFPC} 21 | {$MODESWITCH UNICODESTRINGS} 22 | {$R *.res} 23 | 24 | // wargcv and wgetopts: https://github.com/Bill-Stewart/wargcv 25 | uses 26 | windows, 27 | wargcv, 28 | wgetopts, 29 | WindowsMessages, 30 | WindowsPath; 31 | 32 | const 33 | PROGRAM_NAME = 'PathMan'; 34 | PROGRAM_COPYRIGHT = 'Copyright (C) 2024 by Bill Stewart'; 35 | 36 | type 37 | // Must specify only one action param, 38 | TActionParamGroup = ( 39 | ActionParamAdd, 40 | ActionParamHelp, 41 | ActionParamList, 42 | ActionParamRemove, 43 | ActionParamTest); 44 | TActionParamSet = set of TActionParamGroup; 45 | // ...and only one scope param 46 | TScopeParamGroup = ( 47 | ScopeParamSystem, 48 | ScopeParamUser); 49 | TScopeParamSet = set of TScopeParamGroup; 50 | TCommandLine = object 51 | ActionParamSet: TActionParamSet; 52 | ScopeParamSet: TScopeParamSet; 53 | Error: DWORD; 54 | AddBeginning: Boolean; 55 | Expand: Boolean; 56 | Quiet: Boolean; 57 | DirName: string; 58 | procedure Parse(); 59 | end; 60 | 61 | function IntToStr(const I: Integer): string; 62 | begin 63 | Str(I, result); 64 | end; 65 | 66 | function GetFileVersion(const FileName: string): string; 67 | var 68 | VerInfoSize, Handle: DWORD; 69 | pBuffer: Pointer; 70 | pFileInfo: ^VS_FIXEDFILEINFO; 71 | Len: UINT; 72 | begin 73 | result := ''; 74 | VerInfoSize := GetFileVersionInfoSizeW(PChar(FileName), // LPCWSTR lptstrFilename 75 | Handle); // LPDWORD lpdwHandle 76 | if VerInfoSize > 0 then 77 | begin 78 | GetMem(pBuffer, VerInfoSize); 79 | if GetFileVersionInfoW(PChar(FileName), // LPCWSTR lptstrFilename 80 | Handle, // DWORD dwHandle 81 | VerInfoSize, // DWORD dwLen 82 | pBuffer) then // LPVOID lpData 83 | begin 84 | if VerQueryValueW(pBuffer, // LPCVOID pBlock 85 | '\', // LPCWSTR lpSubBlock 86 | pFileInfo, // LPVOID *lplpBuffer 87 | Len) then // PUINT puLen 88 | begin 89 | with pFileInfo^ do 90 | begin 91 | result := IntToStr(HiWord(dwFileVersionMS)) + '.' + 92 | IntToStr(LoWord(dwFileVersionMS)) + '.' + 93 | IntToStr(HiWord(dwFileVersionLS)); 94 | // LoWord(dwFileVersionLS) intentionally omitted 95 | end; 96 | end; 97 | end; 98 | FreeMem(pBuffer); 99 | end; 100 | end; 101 | 102 | procedure Usage(); 103 | begin 104 | WriteLn(PROGRAM_NAME, ' ', GetFileVersion(ParamStr(0)), ' - ', PROGRAM_COPYRIGHT); 105 | WriteLn('This is free software and comes with ABSOLUTELY NO WARRANTY.'); 106 | WriteLn(); 107 | WriteLn('SYNOPSIS'); 108 | WriteLn(); 109 | WriteLn('Provides tools for management of the Path environment variable.'); 110 | WriteLn(); 111 | WriteLn('USAGE'); 112 | WriteLn(); 113 | WriteLn(PROGRAM_NAME, '