/*! This small program adds a directory to the Win32
path variable or removes it from there.
Copyright (c) 2004 by PHaX - all rights reserved.
If you use this code in your software, drop me a note :)
Ask questions by sending a mail to
coding at helger.com
The directory must be specified by the -p command
line parameter.
Example call:
pathmod -a "-pc:\program file\PathModifier"
Adds the path c:\program file\PathModifier to the users
PATH variable.
The call
pathmod -r "-pc:\program file\PathModifier"
removes the pathe from the users PATH
Compiles with Visual C++ 2003
Should work with others too!
ANSI version:
cl -MD pathmod.cxx
Unicode version:
cl -MD pathmod.cxx -D_UNICODE -DUNICODE
*/
#include <crtdbg.h>
#include <windows.h>
#include <tchar.h>
#ifdef _MSC_VER
#pragma comment (lib, "advapi32.lib")
#pragma comment (lib, "user32.lib")
#endif
int _tmain (int argc, TCHAR**argv)
{
bool bAdd = false;
bool bRemove = false;
LPTSTR pPathToAdd = NULL;
bool bChanged = false;
HKEY hRoot = NULL;
LPCTSTR pEnvPath = NULL;
DWORD eType = 0;
for (int i = 1; i < argc; ++i)
{
LPTSTR pArg = argv[i];
if (*pArg == _T ('-'))
{
++pArg;
if (*pArg == _T ('a'))
bAdd = true;
else
if (*pArg == _T ('r'))
bRemove = true;
else
if (*pArg == _T ('p'))
{
pPathToAdd = new TCHAR [_tcslen (pArg + 1) + 1];
_tcscpy (pPathToAdd, pArg + 1);
}
else
if (*pArg == _T ('l'))
{
hRoot = HKEY_LOCAL_MACHINE;
pEnvPath = _T ("SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment");
eType = REG_EXPAND_SZ;
}
else
if (*pArg == _T ('?'))
{
MessageBox (NULL, _T ("Parameters:\n")
_T ("\t-a\tadd to PATH\n")
_T ("\t-r\tremove from PATH\n")
_T ("\t-pDIR\tthe path to add\n")
_T ("\t-l\tapply to local machine\n"),
_T ("Usage"), MB_OK);
return 1;
}
}
}
// if no directory is set, issue an error
if (!pPathToAdd)
{
MessageBox (NULL, _T ("Error: No path was specified. Use -? to show the usage."), _T ("Error"), MB_OK | MB_ICONERROR);
return 1;
}
// add more than one path at once is not allowed
if (_tcschr (pPathToAdd, _T (';')) != NULL)
{
MessageBox (NULL, _T ("Error: Don't try to add pathes that contain a semicolon ';'. Call separately."), _T ("Error"), MB_OK | MB_ICONERROR);
return 1;
}
// uppercase the path (default behaviour)
CharUpperBuff (pPathToAdd, _tcslen (pPathToAdd));
LONG n;
// HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment
// HKEY_CURRENT_USER\Environment
HKEY hKey;
n = RegOpenKeyEx (hRoot ? hRoot : HKEY_CURRENT_USER,
pEnvPath ? pEnvPath : _T ("Environment"),
0,
KEY_QUERY_VALUE | (bAdd || bRemove ? KEY_SET_VALUE : 0),
&hKey);
_ASSERTE (n == ERROR_SUCCESS);
if (n == ERROR_SUCCESS)
{
// query value length
DWORD nType, nBufSize;
n = RegQueryValueEx (hKey, _T ("Path"), NULL, &nType, NULL, &nBufSize);
_ASSERTE (n == ERROR_SUCCESS);
_ASSERTE (nType == (eType ? eType : REG_SZ));
// query value
LPTSTR pPath = new TCHAR [nBufSize / sizeof (TCHAR)];
n = RegQueryValueEx (hKey, _T ("Path"), NULL, &nType, (LPBYTE) pPath, &nBufSize);
_ASSERTE (n == ERROR_SUCCESS);
_ASSERTE ((nBufSize / sizeof (TCHAR)) == (_tcslen (pPath) + 1));
// find position
// make a copy in uppercase for searching
LPTSTR pUCPath = new TCHAR [_tcslen (pPath) + 1];
_tcscpy (pUCPath, pPath);
CharUpperBuff (pUCPath, _tcslen (pUCPath));
LPTSTR pPathToAddPos = _tcsstr (pUCPath, pPathToAdd);
size_t pPathToAddIndex = pPathToAddPos ? pPathToAddPos - pUCPath : 0;
delete [] pUCPath;
if (bAdd)
{
// add path
if (pPathToAddPos != NULL)
{
MessageBox (NULL, _T ("YourPath is already in the path"), _T ("Warning"), MB_OK | MB_ICONWARNING);
}
else
{
// add to path (first or append)
LPTSTR pNewPath = new TCHAR [_tcslen (pPath) + 1 + _tcslen (pPathToAdd) + 1];
_tcscpy (pNewPath, pPath);
if (*pNewPath)
_tcscat (pNewPath, _T (";"));
_tcscat (pNewPath, pPathToAdd);
// set new value
n = RegSetValueEx (hKey, _T ("Path"), 0, (eType ? eType : REG_SZ), (LPBYTE) pNewPath, (_tcslen (pNewPath) + 1) * sizeof (TCHAR));
_ASSERTE (n == ERROR_SUCCESS);
if (n == ERROR_SUCCESS)
{
bChanged = true;
MessageBox (NULL, _T ("YourPath was successfully added to the path"), _T ("Information"), MB_OK | MB_ICONINFORMATION);
}
else
MessageBox (NULL, _T ("Failed to add YourPath to the path"), _T ("Error"), MB_OK | MB_ICONERROR);
delete [] pNewPath;
}
}
else
if (bRemove)
{
// remove path
if (pPathToAddPos != NULL)
{
// remove from path
LPTSTR pNewPath = new TCHAR [_tcslen (pPath) + 1];
_tcscpy (pNewPath, pPath);
// skip the previous ';' too?
size_t nLen = _tcslen (pPathToAdd);
if (pPathToAddIndex > 0 && pNewPath[pPathToAddIndex - 1] == _T (';'))
{
// was append -> remove ';'
--pPathToAddIndex;
++nLen;
}
else
{
// first element! an ';' at the back?
if (pNewPath [pPathToAddIndex + nLen] == _T (';'))
++nLen;
}
// move everything from right to left
memmove (pNewPath + pPathToAddIndex, pNewPath + pPathToAddIndex + nLen, (_tcslen (pNewPath + pPathToAddIndex + nLen) + 1) * sizeof (TCHAR));
// set new value
n = RegSetValueEx (hKey, _T ("Path"), 0, (eType ? eType : REG_SZ), (LPBYTE) pNewPath, (_tcslen (pNewPath) + 1) * sizeof (TCHAR));
_ASSERTE (n == ERROR_SUCCESS);
if (n == ERROR_SUCCESS)
{
bChanged = true;
MessageBox (NULL, _T ("YourPath was successfully removed from the path"), _T ("Information"), MB_OK | MB_ICONINFORMATION);
}
else
MessageBox (NULL, _T ("Failed to remove YourPath from the path"), _T ("Error"), MB_OK | MB_ICONERROR);
delete [] pNewPath;
}
else
{
MessageBox (NULL, _T ("YourPath is not in the path"), _T ("Warning"), MB_OK | MB_ICONWARNING);
}
}
else
{
// info only
if (pPathToAddPos != NULL)
MessageBox (NULL, _T ("YourPath is already in the path"), _T ("Information"), MB_OK | MB_ICONINFORMATION);
else
MessageBox (NULL, _T ("YourPath is not in the path"), _T ("Information"), MB_OK | MB_ICONINFORMATION);
}
delete [] pPath;
// close again
RegCloseKey (hKey);
}
delete [] pPathToAdd;
if (bChanged)
{
DWORD_PTR dwReturnValue;
LRESULT nRet = SendMessageTimeout (HWND_BROADCAST,
WM_SETTINGCHANGE,
0,
(LPARAM) _T ("Environment"),
SMTO_ABORTIFHUNG | SMTO_NOTIMEOUTIFNOTHUNG,
5000,
&dwReturnValue);
_ASSERTE (nRet != 0);
}
return 0;
}