AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Variable Expansion

 
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Ask for Help
View previous topic :: View next topic  
Author Message
Samlii
Guest





PostPosted: Tue Jul 13, 2004 8:23 pm    Post subject: Variable Expansion Reply with quote

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

PostPosted: Tue Jul 13, 2004 8:52 pm    Post subject: Reply with quote

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
View user's profile Send private message
Chris
Site Admin


Joined: 02 Mar 2004
Posts: 10480

PostPosted: Tue Jul 13, 2004 9:00 pm    Post subject: Reply with quote

(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
View user's profile Send private message Send e-mail
samlii
Guest





PostPosted: Tue Jul 13, 2004 10:05 pm    Post subject: Reply with quote

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

PostPosted: Tue Jul 13, 2004 11:52 pm    Post subject: Reply with quote

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
View user's profile Send private message Send e-mail
Samlii
Guest





PostPosted: Wed Jul 14, 2004 4:38 am    Post subject: Reply with quote

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

PostPosted: Wed Jul 14, 2004 10:55 am    Post subject: Reply with quote

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
View user's profile Send private message Send e-mail
Samlii
Guest





PostPosted: Wed Jul 14, 2004 3:15 pm    Post subject: Reply with quote

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

PostPosted: Wed Jul 14, 2004 3:28 pm    Post subject: Reply with quote

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
View user's profile Send private message Send e-mail
Guest






PostPosted: Wed Jul 14, 2004 5:46 pm    Post subject: Reply with quote

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 Wink 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





PostPosted: Wed Jul 14, 2004 5:49 pm    Post subject: Reply with quote

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

PostPosted: Wed Jul 14, 2004 6:33 pm    Post subject: Reply with quote

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
View user's profile Send private message Send e-mail
Samlii
Guest





PostPosted: Wed Jul 14, 2004 7:12 pm    Post subject: Reply with quote

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

PostPosted: Thu Jul 15, 2004 12:24 am    Post subject: Reply with quote

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
View user's profile Send private message Send e-mail
Display posts from previous:   
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Ask for Help All times are GMT
Page 1 of 1

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group