 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
animeaime
Joined: 04 Nov 2008 Posts: 1045
|
Posted: Sat Apr 25, 2009 5:18 pm Post subject: [Func] EnvVars - replace Environment Variables in Text |
|
|
Function: EnvVars
Description
- Replace environment variables in text.
- Convert legacy Pre-Vista paths to their Vista equivalent - when on a Vista comptuer.
- Specify user-defined "environment variables" to also replace.
Download
EnvVars.zip
Requirements
None.
I wrote this function because I want to write programs that are truly portable. One annoyance with portability is that Vista uses different paths than the Pre-Vista paths. This causes problems for folders, such as All Users -> My Music. Pre-Vista you would specify "%AllUsersProfile%\Documents\My Music", making use of the AllUsersProfile environment variable. On Vista, the equivalent folder is "C:\Users\Public\Music".
Since I have gotten use to Free Commander which allows navigating using the Pre-Vista paths, even on a Vista computer, I thought I would write a function to expand on this idea, so that I could write programs that would have path portability.
Function
EnvVars(String, ExtraEnvVars = "", CaseSensitive = false)
Replace all Environment variables with their associated value.
Supported environment variables: ALLUSERSPROFILE, APPDATA, COMPUTERNAME, COMMONPROGRAMFILES, COMMONPROGRAMFILES(X86), COMSPEC, PROGRAMFILES, PROGRAMFILES(X86), TMP, TEMP, USERNAME, USERPROFILE, WINDIR, and PUBLIC.
Additionally, converts legacy Pre-Vista paths to their Vista equivalent - when on a Vista computer. This allows for path portability. For example, below are examples of paths that are specified using legacy paths. On a Vista computer, these are converted to their Vista equivalent. This means, regardless if on a Vista computer or not, the paths work as they should.
Parameters
String - String which has evironment variables and paths replaced
ExtraEnvVars - a list of any extra "environment variables" to convert. Must be in this form (one variable per line): Var = Value. All occurrances of "%Var%" in the inputted string would be replaced with "Value". See example at the end, for a demonstration.
CaseSensitive - whether the matching of environment variable names is case-sensitive.
ReturnValue
The inputted string with any environment variables and paths replaced.
Code
| Code: | /*
Function to replace any environment variable references in a String
Additionally, converts from Pre-vista path to the Vista equivalent - when running a Vista computer
This allows using the same Path on a Vista and non-vista computer - path portability
*/
EnvVars(String, ExtraEnvVars = "", CaseSensitive = false)
{
/*
ExtraEnvVars is a list of any extra EnvVar replacements
ex.
ExtraEnvVars =
(LTrim Commments
Var1 = Value1
Var2 = Value2
*/
static EnvVars, VistaSpecific, Vista
if (!EnvVars)
{
;Note: Vista running in compatability mode isn't seen as Vista
Vista := A_OSVersion = "WIN_VISTA"
AllUsersProfile := Vista ? "C:\ProgramData" : "C:\Documents and Settings\All Users"
Public := Vista ? "C:\Users\Public" : ""
EnvGet, ProgramFilesX86, PROGRAMFILES(X86)
UserProfile := (Vista ? "C:\Users\" : "C:\Documents and Settings\") . A_UserName
EnvVars =
(LTrim Comments
ALLUSERSPROFILE = %AllUsersProfile%
APPDATA = %A_AppData%
COMPUTERNAME = %A_ComputerName%
COMMONPROGRAMFILES = C:\Program Files\Common Files
COMMONPROGRAMFILES(X86) = C:\Program Files (x86)\Common Files
COMSPEC = %ComSpec%
;HOMEDRIVE
;HOMEPATH
;PATH
;PATHEXT
PROGRAMFILES = %ProgramFiles%
PROGRAMFILES(X86) = %ProgramFilesX86%
;PROMPT
;SYSTEMDRIVE
;SystemRoot
TMP = %A_Temp%
TEMP = %A_Temp%
USERNAME = %A_UserName%
USERPROFILE = %UserProfile%
WINDIR = %A_WinDir%
PUBLIC = %PUBLIC%
)
;vista modifications for the basic paths
;ex. %USERPROFILE%\Start Menu -> %USERPROFILE%\AppData\Roaming\Microsoft\Windows\Start Menu
;replaced only on a Vista machine
VistaSpecific =
(LTrim Comments
C:\Documents and Settings = C:\Users
C:\Users\All Users = C:\ProgramData
C:\ProgramData\Application Data = C:\ProgramData
C:\ProgramData\Desktop = C:\Users\Public\Desktop
C:\ProgramData\Documents = C:\Users\Public\Documents
C:\ProgramData\Favorites = C:\Users\Public\Favorites
C:\ProgramData\Start Menu = C:\ProgramData\Microsoft\Windows\Start Menu
C:\ProgramData\Templates = C:\ProgramData\Microsoft\Windows\Templates
C:\Users\Default User = C:\Users\Default
)
}
oldStringCaseSense := A_StringCaseSense
if (CaseSensitive)
StringCaseSense, On
else if (A_StringCaseSense = "On")
StringCaseSense, Locale
UsedEnvVars := EnvVars . (ExtraEnvVars ? "`n" . ExtraEnvVars : "")
Loop, Parse, UsedEnvVars, `n
{
CurrentField := A_LoopField
if !RegExMatch(CurrentField, "^(?<Var>.*?)\s*+=\s*+(?<Value>.*)$", Env)
continue
if inStr(String, "%" EnvVar "%", CaseSensitive)
StringReplace, String, String, % "%" EnvVar "%", %EnvValue%, All
}
if (Vista)
{
Loop, Parse, VistaSpecific, `n
{
CurrentField := A_LoopField
if !RegExMatch(CurrentField, "^(?<Find>.*?)\s*+=\s*+(?<Replace>.*)$", Env)
continue
if inStr(String, EnvFind, CaseSensitive)
StringReplace, String, String, %EnvFind%, %EnvReplace%, All
}
;in the below replaces, any "valid" username is allowed
;a "valid" username is [\w ]++
String := RegExReplace(String, "i)C:\\Users\\(?!Public)([\w ]++)\\Application Data"
, "C:\Users\$1\AppData\Roaming", "", -1)
String := RegExReplace(String, "i)C:\\Users\\(?!Public)([\w ]++)\\"
. "(Cookies|Recent|SendTo|Start Menu|Templates)"
, "C:\Users\$1\AppData\Roaming\Microsoft\Windows\$2", "", -1)
String := RegExReplace(String, "i)C:\\Users\\(?!Public)([\w ]++)\\Local Settings"
, "C:\Users\$1\AppData\Local", "", -1)
String := RegExReplace(String, "i)C:\\Users\\(?!Public)([\w ]++)\\My Documents"
, "C:\Users\$1\Documents", "", -1)
String := RegExReplace(String, "i)C:\\Users\\([\w ]++)\\Documents\\"
. "My (Music|Pictures|Videos)"
, "C:\Users\$1\$2", "", -1)
String := RegExReplace(String, "i)C:\\Users\\(?!Public)([\w ]++)\\NetHood"
, "C:\Users\$1\AppData\Roaming\Microsoft\Windows\Network Shortcuts", "", -1)
String := RegExReplace(String, "i)C:\\Users\\(?!Public)([\w ]++)\\PrintHood"
, "C:\Users\$1\AppData\Roaming\Microsoft\Windows\Printer Shortcuts", "", -1)
}
StringCaseSense, %oldStringCaseSense%
return String
} |
Example
| Code: | /*
These examples return the desired path for XP and Vista alike
When running on Vista, the paths are converted
*/
;the my documents folder
MsgBox, % "My Documents folder (1): `n`n"
. EnvVars("%UserProfile%\My Documents")
;another way to get the my documents folder
MsgBox, % "My Documents folder (2): `n`n"
. EnvVars("C:\Documents and Settings\%UserName%\My Documents")
;the All Users -> My Music folder
MsgBox, % "All Users -> My Music (1): `n`n"
. EnvVars("%AllUsersProfile%\Documents\My Music")
;another way to get the All Users -> My Music Folder
MsgBox, % "All Users -> My Music (2): `n`n"
. EnvVars("C:\Documents and Settings\All Users\Documents\My Music")
;Note: the passed string need not be just the directory
;the temp folder
MsgBox, % "Tmp directory: `n`n"
. EnvVars("The temp directory is: ""%TMP%""")
;allows specifying additional "environment variables" to use
SRC := "C:\SomeFolder"
DEST := "E:\A new folder"
File := "ThisFile.txt"
ExtraEnvVars =
(LTrim Comments
SRC = %SRC%
DEST = %DEST%
File = %File%
)
;an example "file transfer" notice
MsgBox, % "Example file transfor notice (1): `n`n"
. EnvVars("Copying ""%SRC%\%File%"" to ""%DEST%"".", ExtraEnvVars)
;a single double quote
quote = "
;or you could only pass the file to EnvVars
MsgBox, % "Example file transfor notice (2): `n`n"
. "Copying " quote . EnvVars("%SRC%\%File%", ExtraEnvVars) . quote
. " to " quote . EnvVars("%DEST%", ExtraEnvVars) . quote "."
;The start menu for a different user
;valid user names consist of letters, numbers, underscores, and spaces
;(I can modify this to allow additional valid characters, if needed)
MsgBox, % "Start Menu directory for SomeNoNamePerson: `n`n"
. EnvVars("C:\Documents and Settings\SomeNoNamePerson\Start Menu") |
How to use
Extract the zip's contents to a library folder for automatic inclusion - StdLib compliant.
A copy of the above example can be found in the "Func Examples" folder.
Things to come
- If AHK is running in compatability mode, Vista won't be seen as Vista - thus, Pre-Vista paths won't be converted. If this is not desired, I can modify this behavior.
- Currently a "valid" username consists of only letters, numbers, underscrores, and spaces - does this need to be expanded? See the last output in the example (the Start Menu), for an example of usage.
Download EnvVars function _________________ As always, if you have any further questions, don't hesitate to ask.
Add OOP to your scripts via the Class Library. Check out my scripts. |
|
| Back to top |
|
 |
DeWild1
Joined: 30 Apr 2006 Posts: 345 Location: Shigle Springs
|
Posted: Tue Jan 12, 2010 5:34 pm Post subject: |
|
|
nice, but, using the user name is not 100%.
Many people, like me, have ones like, S:\Documents and Settings\Administrator.ASP1\Start Menu and c:\Documents and Settings\Dean.Deans\Start Menu because I have reinstalled many times.. (I never format... and when you reinstall, it keeps the old c:\Documents and Settings\Dean and makes a new c:\Documents and Settings\Dean.Deans based upon computer name)
Sadly, I say this before trying your code, I just read it so I hope I do not look sta, sta, STUPID!  _________________ CPULOCK.com
virusSWAT.com
Computer Repair Computer Service.com
911PCFIX.com |
|
| Back to top |
|
 |
Lexikos
Joined: 17 Oct 2006 Posts: 4808 Location: Australia
|
Posted: Thu Jan 14, 2010 9:58 am Post subject: |
|
|
When I read the subject line, I wasn't expecting a limited set of supported variables. FYI, you can retrieve all environment variables for the current process in one go:
| Code: | GetEnvironmentStrings() ; NOTE: AutoHotkeyU not supported.
{
; Get pointer to environment block.
pEnv := p := DllCall("GetEnvironmentStringsA")
; For each substring, append to sEnv and advance to next substring.
; MulDiv is used as a shortcut method to convert address -> string.
; The environment block is terminated by \0\0, i.e. an empty string.
While "" != (s:=DllCall("MulDiv", "int",p, "int",1, "int",1, "str"))
sEnv .= s "`n", p += StrLen(s) + 1
; Free the block as recommended by MSDN.
DllCall("FreeEnvironmentStringsA", "uint", pEnv)
return sEnv
} |
I also found that the "My Documents" example failed on my system: it returns "C:\Users\xxx\Documents" whereas A_MyDocuments returns the correct value, "F:\Documents". Most of these "special folders" can be moved by the user; check the folder's Properties dialog. AutoHotkey uses registry keys to retrieve the locations of special folders, but the correct methods are functions like SHGetSpecialFolderPath. See my post here for a little info.
While the "additional conversion functionality" of EnvVars may seem like a good idea, I think it would be better to not rely on those paths to begin with. |
|
| Back to top |
|
 |
Lexikos
Joined: 17 Oct 2006 Posts: 4808 Location: Australia
|
Posted: Sat Jan 30, 2010 7:02 am Post subject: |
|
|
I just remembered Windows already provides a function for this.
| Code: | EnvVars(str)
{
if sz:=DllCall("ExpandEnvironmentStrings", "uint", &str
, "uint", 0, "uint", 0)
{
VarSetCapacity(dst, A_IsUnicode ? sz*2:sz)
if DllCall("ExpandEnvironmentStrings", "uint", &str
, "str", dst, "uint", sz)
return dst
}
return src
}
MsgBox, % "My Documents folder (1): `n`n"
. EnvVars("%UserProfile%\My Documents")
MsgBox, % "All Users -> My Music (1): `n`n"
. EnvVars("%AllUsersProfile%\Documents\My Music")
MsgBox, % "Tmp directory: `n`n"
. EnvVars("The temp directory is: ""%TMP%""")
EnvSet, SRC, C:\SomeFolder
EnvSet, DEST, E:\A new folder
EnvSet, File, ThisFile.txt
MsgBox, % "Example file transfor notice (1): `n`n"
. EnvVars("Copying ""%SRC%\%File%"" to ""%DEST%"".") | (Tested on v1.0.48.05, AutoHotkey_L and AutoHotkeyU.)
Btw,
| Code: | SRC = C:\SomeFolder
DEST = E:\A new folder
File = ThisFile.txt
notice := "Copying ""%SRC%\%File%"" to ""%DEST%""."
Transform, notice, Deref, %notice%
MsgBox Example file transfer notice: `n`n%notice% |
|
|
| Back to top |
|
 |
|
|
You can post new topics in this forum You can reply to topics in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|