 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
Samlii Guest
|
Posted: Tue Jul 13, 2004 8:23 pm Post subject: Variable Expansion |
|
|
I am trying to do some things with the Environment, and so when I set up an enviroment variable (like comspec) that points to other env variables (comspec = %SystemRoot%\cmd.exe)
When I try to Run, %comspec% it fails saying it can't find the file (Its looking for %SystemRoot%\cmd.exe, literally)
Any way to tel the string to expand? Will StringRepl Replace the string when it transfers to the secondVariable?
Sam |
|
| Back to top |
|
 |
PenP
Joined: 14 May 2004 Posts: 10 Location: The Netherlands
|
Posted: Tue Jul 13, 2004 8:52 pm Post subject: |
|
|
Hi,
%SystemRoot%\cmd.exe is not the same as %COMSPEC%, try this:
| Code: | | MsgBox, COMSPEC = %COMSPEC%`nSystemRoot = %SystemRoot%\cmd.exe |
This is my result:
COMSPEC = C:\WINDOWS\system32\cmd.exe
SystemRoot = C:\WINDOWS\cmd.exe
Grtz,
PenP |
|
| Back to top |
|
 |
Chris Site Admin
Joined: 02 Mar 2004 Posts: 10480
|
Posted: Tue Jul 13, 2004 9:00 pm Post subject: |
|
|
(to add a little detail to the above reply)
The problem is that cmd.exe is in the system32 folder (at least on my system). Thus, the following works:
comspec = %SystemRoot%\system32\cmd.exe
run %comspec%
But are you sure you need to set the comspec variable? It is typically already defined, so you can omit the first line and just do:
Run %comspec% |
|
| Back to top |
|
 |
samlii Guest
|
Posted: Tue Jul 13, 2004 10:05 pm Post subject: |
|
|
I know its normally defined, and yes you are correct I missed the system32,
However that is not the problem.
What I am doing is resetting my Environment:
#+t::
MsgBox, 0, , "Comspec is %comspec%"
MsgBox, 0, , "SystemRoot is %SystemRoot%"
Run, %comspec% /k
return
#+r::
MsgBox, 0, , "Your environment settings are:"
Loop, HKEY_LOCAL_MACHINE, SYSTEM\CurrentControlSet\Control\Session Manager\Environment, 0, 0
{
RegRead, value
if ErrorLevel <> 0
value = *error*
EnvSet %a_LoopRegName%, ""
}
Loop, HKEY_LOCAL_MACHINE, SYSTEM\CurrentControlSet\Control\Session Manager\Environment, 0, 0
{
RegRead, value
if ErrorLevel <> 0
value = *error*
MsgBox, 0, , Setting %a_LoopRegName% to %value%
EnvSet %a_LoopRegName%, %value%
lm%a_LoopRegName% = %value%
}
The problem is when I try to run comspec again (which is defined as %SystemRoot%\system32\cmd.exe) it says it can't find the file specified.
%SystemRoot% is defined as c:\Winnt (on my win2k machine)
Could it be something in how they are being set? (ie escaping the %'s without my knowledge?) |
|
| Back to top |
|
 |
Chris Site Admin
Joined: 02 Mar 2004 Posts: 10480
|
Posted: Tue Jul 13, 2004 11:52 pm Post subject: |
|
|
A few things that might help:
1) When a script changes environment variables, the changes are not seen by other scripts and applications (except for processes created via Run/RunWait by a compiled script, I think). You would probably have to use System Properties -> Advanced -> Environment variables to make them take effect globally.
2) If a script variable of the same name as an environment variable is assigned a value, it will "hide" the environment variable from the script. In other word's, the script's own variable will take precedence.
3) If you open the script's main window via the tray icon, you can select View > Variables to find out what's in the script's variables (not the environment variables). Or you can add a MsgBox at a critical section in the script where you're experiencing a problem.
If the above doesn't help, perhaps you can post a specific short script that fails the produce the expected result... something I can run to try to analyze it. |
|
| Back to top |
|
 |
Samlii Guest
|
Posted: Wed Jul 14, 2004 4:38 am Post subject: |
|
|
Chris,
Nothing is getting overwritten. The whole reason I am doing this is so that when I change the system Environment (through the System Properties), the script can pick up that change without having to exit the script (completely) and re start it
Here is a small Script that I think reflects the problem:
sysval = `%Bob`%
systest = %sysval%Test
Bob = Alice
MsgBox, 0, , %systest%
return
I think sysval is an accurate representation of what I get from the RegRead when the value has a %x% in it. |
|
| Back to top |
|
 |
Chris Site Admin
Joined: 02 Mar 2004 Posts: 10480
|
Posted: Wed Jul 14, 2004 10:55 am Post subject: |
|
|
I understand now. The problem is that percent signs are evaluated only when physically present. You can't have percent signs inside a variable and have them evaluated later.
However, you can use any function that takes an input variable, such as StringTrimRight, to dynamically resolve the contents of a variable. For example:
sysval = Bob
Bob = Alice
StringTrimRight, systest, %sysval%, 0 ; This is the key line.
MsgBox, 0, , %systest%
return
But you might be able to avoid all the above by using EnvUpdate described at http://www.autohotkey.com/docs/commands/EnvUpdate.htm |
|
| Back to top |
|
 |
Samlii Guest
|
Posted: Wed Jul 14, 2004 3:15 pm Post subject: |
|
|
Chris,
First, thanks for taking the time with this, and thanks for creating the program, I don't want you to feel like I don't appreciate it.
Second, I started out trying to use Env Update, but it wouldn't retreive new values set from the Environment properties dialog. Maybe I am doing something wrong, does it work this way for you? |
|
| Back to top |
|
 |
Chris Site Admin
Joined: 02 Mar 2004 Posts: 10480
|
Posted: Wed Jul 14, 2004 3:28 pm Post subject: |
|
|
I tried the following script and it didn't work for me either:
msgbox %thing%
pause ; Here I added "thing" as a new environment var. in Sys Properties.
EnvUpdate
msgbox %thing%
Not only didn't it work, but a new cmd prompt I launched didn't see the change either. I think this aspect of the OS just isn't very reliable. Logging off and then on again might be the only sure way to update the variables.
Other than this, I don't know much about EnvUpdate other than what's documented in the help file. Internally, all it does is:
SendMessage(HWND_BROADCAST, WM_SETTINGCHANGE, 0, (LPARAM)"Environment")
You can try to google some of those keywords to see if there is more info. |
|
| Back to top |
|
 |
Guest
|
Posted: Wed Jul 14, 2004 5:46 pm Post subject: |
|
|
Well thanks for trying Chris, according to MSDN the updates are sent to the to level windows, so either the system isn't sending the correct update message, or AHK isn't handling it correctly in the message loop. Maybe I'll look at the code later, if I find time DO you know if it compiles with MingW or only with VC?
Anyways I found a way around it:
#+r::
null = %SystemRoot%
null = %USERPROFILE%
Loop, HKEY_LOCAL_MACHINE, SYSTEM\CurrentControlSet\Control\Session Manager\Environment, 0, 0
{
RegRead, value
if ErrorLevel <> 0
value = *error*
EnvSet %a_LoopRegName%, ""
}
Loop, HKEY_CURRENT_USER, Environment, 0, 0
{
RegRead, value
if ErrorLevel <> 0
value = *error*
EnvSet %a_LoopRegName%, ""
}
Loop, HKEY_LOCAL_MACHINE, SYSTEM\CurrentControlSet\Control\Session Manager\Environment, 0, 0
{
RegRead, value
if ErrorLevel <> 0
value = *error*
EnvSet %a_LoopRegName%, %value%
StringLower, keyLower, a_LoopRegName
lm%keyLower% = %value%
}
Loop, HKEY_CURRENT_USER, Environment, 0, 0
{
RegRead, value
if ErrorLevel <> 0
value = *error*
StringLower, keyLower, a_LoopRegName
IfNotEqual, lm%keyLower%,
{
StringTrimRight, clipboard, lm%keyLower%, 0
EnvSet %a_LoopRegName%, %clipboard%;%value%
}
else
{
EnvSet %a_LoopRegName%, %value%
}
}
expandLeaveUnknown = off
Loop, HKEY_LOCAL_MACHINE, SYSTEM\CurrentControlSet\Control\Session Manager\Environment, 0, 0
{
RegRead, value
if ErrorLevel <> 0
continue
clipboard = %value%
GoSub ExpandInternal
EnvSet %a_LoopRegName%, %clipboard%
}
Loop, HKEY_CURRENT_USER, Environment, 0, 0
{
RegRead, value
if ErrorLevel <> 0
continue
clipboard = %value%
GoSub ExpandInternal
EnvSet %a_LoopRegName%, %clipboard%
}
EnvUpdate
return
ExpandInternal:
percPos = 1
Loop
{
oldpercPos = %percPos%
StringGetPos, startPercent, clipboard, `%, L%percPos%
If errorlevel <> 0
break
percPos++
StringGetPos, endPercent, clipboard, `%, L%percPos%
If errorlevel <> 0
break
percPos++
endPercent -= %startPercent% ; find amount of chars between start and end
endPercent -= 1 ; Take one away since we dont want the last percent
startPercent += 2 ; Because of the fact that start position is specified and getPos starts at zero we add two
StringMid, varName, clipboard, %startPercent%, %endPercent%
StringTrimLeft, varValue, %varName%, 0
IfEqual, varValue,
{
IfEqual, expandLeaveUnknown, on
Continue
}
MsgBox, 0, , Replacing %varname% with %varValue%
StringReplace, clipboard, clipboard, `%%varName%`%, %varValue%, All
percPos = %oldpercPos%
}
return |
|
| Back to top |
|
 |
Samlii Guest
|
Posted: Wed Jul 14, 2004 5:49 pm Post subject: |
|
|
One other thing,
The two nulls up at the top (null = %SystemRoot%) had to be done so that when the varValue was found for the replace it would find them, otherwise they came back as empty values, any ideas as to why?
Also is there a way to either 1) make real functions, or 2) give a Sub args, otherthan how I did it? (Without modifying the actual cpp source?) |
|
| Back to top |
|
 |
Chris Site Admin
Joined: 02 Mar 2004 Posts: 10480
|
Posted: Wed Jul 14, 2004 6:33 pm Post subject: |
|
|
| Quote: | | AHK isn't handling it correctly in the message loop |
When I tested it with System Properties, I couldn't get the env. vars to update at all, even when AHK wasn't involved at all. That's what led me to think that the OS is unreliable when it comes to globally updating environment variables (short of logging off then on again). Though it's possible this is a quirk of my particular XP configuration.
| Quote: | | DO you know if it compiles with MingW or only with VC. |
It would probably take a lot of work to get it to compile under Mingw just from the sheer number of missing includes and capabilties, though it should be possible.
| Quote: | | The two nulls up at the top (null = %SystemRoot%) had to be done so that when the varValue was found for the replace it would find them, otherwise they came back as empty values, any ideas as to why? |
I don't see how those lines would have any effect on the behavior of the script. Maybe you can provide a short script -- something I can understand more easily and run safely on my own system -- that produces behavior you think is questionable or incorrect.
| Quote: | | Also is there a way to either 1) make real functions, or 2) give a Sub args, otherthan how I did it? (Without modifying the actual cpp source?) |
No, though it is planned to examine this type of capability in the future (probably at least several months from now). In the meantime, you're welcome to study and change it as you see fit. |
|
| Back to top |
|
 |
Samlii Guest
|
Posted: Wed Jul 14, 2004 7:12 pm Post subject: |
|
|
| Code: | #+p::
clipboard = Test `%SystemRoot`% `%this`%
this = bob
expandLeaveUnknown = off
GoSub ExpandInternal
MsgBox, 0, , Final string is "%clipboard%"
return
ExpandInternal:
percPos = 1
Loop
{
oldpercPos = %percPos%
StringGetPos, startPercent, clipboard, `%, L%percPos%
If errorlevel <> 0
break
percPos++
StringGetPos, endPercent, clipboard, `%, L%percPos%
If errorlevel <> 0
break
percPos++
endPercent -= %startPercent% ; find amount of chars between start and end
endPercent -= 1 ; Take one away since we dont want the last percent
startPercent += 2 ; Because of the fact that start position is specified and getPos starts at zero we add two
StringMid, varName, clipboard, %startPercent%, %endPercent%
StringTrimLeft, varValue, %varName%, 0
IfEqual, varValue,
{
IfEqual, expandLeaveUnknown, on
Continue
}
StringReplace, clipboard, clipboard, `%%varName%`%, %varValue%, All
percPos = %oldpercPos%
}
return |
If you load that script and hit #+p it will say Final String is "Test Bob".
Now if you add the null=%SystemRoot% before the clipboard = line it should say Final String is "Test C:\WINNT Bob" (or if you are on XP or 95/98 "Test C:\WINDOWS Bob")
Hopefully that helps you see the problem [/code] |
|
| Back to top |
|
 |
Chris Site Admin
Joined: 02 Mar 2004 Posts: 10480
|
Posted: Thu Jul 15, 2004 12:24 am Post subject: |
|
|
I see it now, thanks a lot. In tomorrow's release, the following change will appear:
Fixed InputVars that dynamically resolve to the names of environment variables. Sometimes the value was not being fetched from the environment [thanks Samlii]. Example:
EnvVar = SystemRoot
StringTrimLeft, OutputVar, %EnvVar%, 0 |
|
| 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
|