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 

Transform, DerefEnv

 
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Wish List
View previous topic :: View next topic  
Author Message
Tekl



Joined: 24 Sep 2004
Posts: 813
Location: Germany

PostPosted: Tue May 30, 2006 11:12 am    Post subject: Transform, DerefEnv Reply with quote

Hi,

I'm now missing that Transform, Deref does not expand environment variables anymore (due tue #NoEnv). Maybe there could be added a new command DerefEnv to Transform which also expands environment variables. Another solution could be EnvGet, *All.
_________________
Tekl
Back to top
View user's profile Send private message Visit poster's website
Chris
Site Admin


Joined: 02 Mar 2004
Posts: 10467

PostPosted: Tue May 30, 2006 12:59 pm    Post subject: Reply with quote

Since #NoEnv operates at a low level, adding the ability to expand environment variables is somewhat difficult. In addition, I wouldn't expect such a feature to be used by very many people. For these reasons, perhaps some non-built-in solution can be found such as:

EnvGet, MyEnv1, MyEnv1
; ...etc.
Transform, OutputVar, Deref, ...

In other words, by fetching all your environment variables into identically-named normal variables (assuming you know all the names), you could then use Transform Deref as though #NoEnv weren't present.

Alternatively, perhaps you could use DllCall and GetEnvironmentStrings() to get the complete list of environment variables, then parse the list and use EnvGet on each one.
Back to top
View user's profile Send private message Send e-mail
Tekl



Joined: 24 Sep 2004
Posts: 813
Location: Germany

PostPosted: Tue May 30, 2006 5:14 pm    Post subject: Reply with quote

Hi Chris,

thanks for the idea with parsing the list of all envvars. I'll try that.
_________________
Tekl
Back to top
View user's profile Send private message Visit poster's website
Tekl



Joined: 24 Sep 2004
Posts: 813
Location: Germany

PostPosted: Wed May 31, 2006 8:15 am    Post subject: Reply with quote

Hi,

GetEnvironmentStrings just returns a numeric value. It's a pointer to the environment block, but how to read this environment block?
_________________
Tekl
Back to top
View user's profile Send private message Visit poster's website
corrupt



Joined: 29 Dec 2004
Posts: 2397

PostPosted: Wed May 31, 2006 8:35 am    Post subject: Reply with quote

You could use the CMDret function (no external .exe or .dll needed in this version) to retrieve the variables, values. Then, parse the output.

Code:
MsgBox, % CMDret_RunReturn(comspec " /c set")
Return


CMDret_RunReturn(CMDin)
{
  Global cmdretPID
  idltm := A_TickCount + 20
  CMsize = 1
  VarSetCapacity(CMDout, 1, 32)
  VarSetCapacity(sui,68, 0)
  VarSetCapacity(pi, 16, 0)
  VarSetCapacity(pa, 12, 0)
  Loop, 4 {
    DllCall("RtlFillMemory", UInt,&pa+A_Index-1, UInt,1, UChar,12 >> 8*A_Index-8)
    DllCall("RtlFillMemory", UInt,&pa+8+A_Index-1, UInt,1, UChar,1 >> 8*A_Index-8)
  }
  IF (DllCall("CreatePipe", "UInt*",hRead, "UInt*",hWrite, "UInt",&pa, "Int",0) <> 0) {
    Loop, 4
      DllCall("RtlFillMemory", UInt,&sui+A_Index-1, UInt,1, UChar,68 >> 8*A_Index-8)
    DllCall("GetStartupInfo", "UInt", &sui)
    Loop, 4 {
      DllCall("RtlFillMemory", UInt,&sui+44+A_Index-1, UInt,1, UChar,257 >> 8*A_Index-8)
      DllCall("RtlFillMemory", UInt,&sui+60+A_Index-1, UInt,1, UChar,hWrite >> 8*A_Index-8)
      DllCall("RtlFillMemory", UInt,&sui+64+A_Index-1, UInt,1, UChar,hWrite >> 8*A_Index-8)
      DllCall("RtlFillMemory", UInt,&sui+48+A_Index-1, UInt,1, UChar,0 >> 8*A_Index-8)
    }
    IF (DllCall("CreateProcess", Int,0, Str,CMDin, Int,0, Int,0, Int,1, "UInt",0, Int,0, Int,0, UInt,&sui, UInt,&pi) <> 0) {
      Loop, 4
        cmdretPID += *(&pi+8+A_Index-1) << 8*A_Index-8
      Loop {
        idltm2 := A_TickCount - idltm
        If (idltm2 < 10) {
          DllCall("Sleep", Int, 10)
          Continue
        }
        IF (DllCall("PeekNamedPipe", "uint", hRead, "uint", 0, "uint", 0, "uint", 0, "uint*", bSize, "uint", 0 ) <> 0 ) {
          Process, Exist, %cmdretPID%
          IF (ErrorLevel OR bSize > 0) {
            IF (bSize > 0) {
              VarSetCapacity(lpBuffer, bSize+1)
              IF (DllCall("ReadFile", "UInt",hRead, "Str", lpBuffer, "Int",bSize, "UInt*",bRead, "Int",0) > 0) {
                IF (bRead > 0) {
                  TRead += bRead
                  VarSetCapacity(CMcpy, (bRead+CMsize+1), 0)
                  CMcpy = a
                  DllCall("RtlMoveMemory", "UInt", &CMcpy, "UInt", &CMDout, "Int", CMsize)
                  DllCall("RtlMoveMemory", "UInt", &CMcpy+CMsize, "UInt", &lpBuffer, "Int", bRead)
                  CMsize += bRead
                  VarSetCapacity(CMDout, (CMsize + 1), 0)
                  CMDout=a   
                  DllCall("RtlMoveMemory", "UInt", &CMDout, "UInt", &CMcpy, "Int", CMsize)
                }
              }
            }
          }
          ELSE
            break
        }
        ELSE
          break
        idltm := A_TickCount
      }
    }
    cmdretPID=
    DllCall("CloseHandle", UInt, hWrite)
    DllCall("CloseHandle", UInt, hRead)
  }
  IF (StrLen(CMDout) < TRead) {
    VarSetCapacity(CMcpy, TRead, 32)
    TRead2 = %TRead%
    Loop {
      DllCall("RtlZeroMemory", "UInt", &CMcpy, Int, TRead)
      NULLptr := StrLen(CMDout)
      cpsize := Tread - NULLptr
      DllCall("RtlMoveMemory", "UInt", &CMcpy, "UInt", (&CMDout + NULLptr + 2), "Int", (cpsize - 1))
      DllCall("RtlZeroMemory", "UInt", (&CMDout + NULLptr), Int, cpsize)
      DllCall("RtlMoveMemory", "UInt", (&CMDout + NULLptr), "UInt", &CMcpy, "Int", cpsize)
      TRead2 --
      IF (StrLen(CMDout) > TRead2)
        break
    }
  }
  StringTrimLeft, CMDout, CMDout, 1
  Return, CMDout
}

Back to top
View user's profile Send private message Visit poster's website
Tekl



Joined: 24 Sep 2004
Posts: 813
Location: Germany

PostPosted: Wed May 31, 2006 9:02 am    Post subject: Reply with quote

Thanks,

well not the fastest way, but it works. Strange that Envget, %uh_EnvVar1%, %uh_EnvVar1% does not work.

Code:

uh_EnvVars := CMDret_RunReturn(comspec " /c set")

Loop, Parse, uh_EnvVars, `n, `r
{
   StringSplit, uh_EnvVar, A_LoopField, =
   If uh_EnvVar1 not in ComSpec,ProgramFiles
      %uh_EnvVar1% = %uh_EnvVar2%%uh_EnvVar3%%uh_EnvVar4%%uh_EnvVar5%%uh_EnvVar6%%uh_EnvVar7%%uh_EnvVar8%%uh_EnvVar9%
}

_________________
Tekl
Back to top
View user's profile Send private message Visit poster's website
PhiLho



Joined: 27 Dec 2005
Posts: 6721
Location: France (near Paris)

PostPosted: Wed May 31, 2006 10:06 am    Post subject: Reply with quote

Without using an external DLL:
Code:
blockAddr := DllCall("GetEnvironmentStrings")
p := blockAddr
bGetVar := true
Loop
{
   l := DllCall("lstrlen", "UInt", p)
   ; Skip first value
   If (A_Index = 1)
   {
      p += l + 1
      Continue   ; Strange value...: "=::=::\"
   }
   VarSetCapacity(buffer, l+1, 0)
   DllCall("lstrcpy", "Str", buffer, "UInt", p)
   ; Here, we have in buffer something like "var=value"
   StringSplit v, buffer, =
   ; Avoid an error because these variables exist and are read-only
   If (v1 != "ComSpec" && v1 != "ProgramFiles")
   {
      %v1% = %v2%
   }
   Tooltip (%A_Index%) %buffer% (%l% -> %p%)
   Sleep 500
;~    result = %result%`n%buffer%
   p += l + 1
   If (*p = 0)
      Break
}
Tooltip
DllCall("FreeEnvironmentStrings", "UInt", blockAddr)

MsgBox %windir%

Escape::ExitApp

_________________
vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2")
Back to top
View user's profile Send private message Visit poster's website
Tekl



Joined: 24 Sep 2004
Posts: 813
Location: Germany

PostPosted: Wed May 31, 2006 12:33 pm    Post subject: Reply with quote

Hey! Thanks! That's great and quite faster.
_________________
Tekl
Back to top
View user's profile Send private message Visit poster's website
Androgen



Joined: 21 Feb 2006
Posts: 11
Location: Russia, Samara

PostPosted: Sun Aug 06, 2006 4:30 am    Post subject: Reply with quote

Sometimes this strange variable (=::=::\) is present, sometimes - is not present.
But such way always passes the first variable (even if it another)

Code:
If (A_Index = 1)
{
  p += l + 1
  Continue   ; Strange value...: "=::=::\"
}


Therefore I have made in another way:

Code:
Block_Pointer := DllCall( "GetEnvironmentStrings" )
String_Pointer := Block_Pointer
Loop
{
   String_Length := DllCall( "lstrlen", UInt, String_Pointer )
   If String_Length = 0
      Break
   VarSetCapacity( Cur_String, String_Length + 1, 0 )
   DllCall( "lstrcpy", Str, Cur_String, UInt, String_Pointer )
   String_Pointer := String_Pointer + String_Length + 1
   If Cur_String = =S:=S:\
      Continue
   If NOT Env_List
      Env_List = %Cur_String%
   Else
      Env_List = %Env_List%`n%Cur_String%
}
DllCall( "FreeEnvironmentStrings", UInt, Block_Pointer )
MsgBox, %Env_List%

And I have not understood, what error we try to avoid? You could not explain me, PhiLho?

Code:
; Avoid an error because these variables exist and are read-only
If (v1 != "ComSpec" && v1 != "ProgramFiles")
{
  %v1% = %v2%
}
Back to top
View user's profile Send private message
Tekl



Joined: 24 Sep 2004
Posts: 813
Location: Germany

PostPosted: Tue Aug 08, 2006 11:39 am    Post subject: Reply with quote

Hello,

btw. the routine crashes on systems which have environment-variables with characters, which arent allowed in autohotkey. Users reported they have variables like {32134:34234:32234:34324}.
_________________
Tekl
Back to top
View user's profile Send private message Visit poster's website
Androgen



Joined: 21 Feb 2006
Posts: 11
Location: Russia, Samara

PostPosted: Wed Aug 09, 2006 5:40 am    Post subject: Reply with quote

Tekl wrote:
Hello,

btw. the routine crashes on systems which have environment-variables with characters, which arent allowed in autohotkey. Users reported they have variables like {32134:34234:32234:34324}.


I add this environment variable and no crashes. Both the name and value of a variable - does not cause problems. Or I have not understood something?
Code:
EnvSet, {32134:34234:32234:34324}, {32134:34234:32234:34324} ; ==> Test
Block_Pointer := DllCall( "GetEnvironmentStrings" )
String_Pointer := Block_Pointer
Loop
{
   String_Length := DllCall( "lstrlen", UInt, String_Pointer )
   If String_Length = 0
      Break
   VarSetCapacity( Cur_String, String_Length + 1, 0 )
   DllCall( "lstrcpy", Str, Cur_String, UInt, String_Pointer )
   String_Pointer := String_Pointer + String_Length + 1
   If Cur_String = =S:=S:\
      Continue
   If NOT Env_List
      Env_List = %Cur_String%
   Else
      Env_List = %Env_List%`n%Cur_String%
}
DllCall( "FreeEnvironmentStrings", UInt, Block_Pointer )
MsgBox, %Env_List%
Back to top
View user's profile Send private message
Tekl



Joined: 24 Sep 2004
Posts: 813
Location: Germany

PostPosted: Wed Aug 09, 2006 7:40 am    Post subject: Reply with quote

Hi,

the variable is set from outside and not inside a script. { and : are illegal characters for AutoHotkey but not for Windows.
_________________
Tekl
Back to top
View user's profile Send private message Visit poster's website
Androgen



Joined: 21 Feb 2006
Posts: 11
Location: Russia, Samara

PostPosted: Wed Aug 09, 2006 8:33 am    Post subject: Reply with quote

I do not see a difference between the set of a variable inside or outside of script. But well. I set this variable via standard applet, and script works well and in this case too.
(Windows XP with Service Pack 2)
Back to top
View user's profile Send private message
Tekl



Joined: 24 Sep 2004
Posts: 813
Location: Germany

PostPosted: Wed Aug 09, 2006 10:01 am    Post subject: Reply with quote

Ok, you're just listing the variables. But if you try to set them in AutoHotkey you'll get the error because it's not allowed to use:

{32134:34234:32234:34324} = anystring
_________________
Tekl
Back to top
View user's profile Send private message Visit poster's website
Display posts from previous:   
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Wish List 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