forums.silverfrost.com Forum Index forums.silverfrost.com
Welcome to the Silverfrost forums
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Setting environment variables within Clearwin code
Goto page 1, 2  Next
 
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> ClearWin+
View previous topic :: View next topic  
Author Message
ljfarrugia



Joined: 06 Jun 2016
Posts: 19

PostPosted: Sat Jun 11, 2016 4:50 pm    Post subject: Setting environment variables within Clearwin code Reply with quote

It has always been possible to obtain the value of a system or user-set environment variable using dosparam@, but is it possible to SET environment variables within a Clearwin program?
Back to top
View user's profile Send private message
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 4698
Location: Salford, UK

PostPosted: Sat Jun 11, 2016 5:01 pm    Post subject: Reply with quote

In theory all API functions are available and SetEnvironmentVariable is already provided in win32api.ins.
Back to top
View user's profile Send private message
ljfarrugia



Joined: 06 Jun 2016
Posts: 19

PostPosted: Sat Jun 11, 2016 11:38 pm    Post subject: Reply with quote

Yes but SetEnvironmentVariable only sets a variable within same process

I wanted to set a permanent one. Is the only way to use RegGreateKeyEx
to create a new key in HKEY_CURRENT_USER Environment ?
Back to top
View user's profile Send private message
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 4698
Location: Salford, UK

PostPosted: Sun Jun 12, 2016 7:18 am    Post subject: Reply with quote

You could try changing the registry via the key HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment or it will probably be easier launch cmd.exe from your program and call SETX. Maybe use StartProcess@ or CISSUE@ etc.
Back to top
View user's profile Send private message
ljfarrugia



Joined: 06 Jun 2016
Posts: 19

PostPosted: Sun Jun 12, 2016 9:50 am    Post subject: Reply with quote

with HKEY_CURRENT_USER,'Environment' I think that you just need to add a value, and changing just the user variable would do

The code below doesnt work (always returns 0). Is there an obvious changeto make this work?



Program main
character(len=255) :: var,buf
var = 'TEMP1'
buf = 'anything'
call Setenv(var,buf)
end
C
C----------------------------------------------------------------------C
C
subroutine SetEnv(var,val)

include <windows.ins>
character(*) :: var,val
integer :: handle
integer :: type,l1,i

type = 0
l1 = len_trim(var)
var(l1+1:l1+1) = char(0)
l1 = len_trim(val)
val(l1+1:l1+1) = char(0)
l1 = l1 +1
i = 0
if(RegOpenKeyEx(HKEY_CURRENT_USER,'Environment',0,
& KEY_READ,handle) /= ERROR_SUCCESS) return

if(RegSetValueEx(handle,var,type,REG_SZ,val,l1)
& == ERROR_SUCCESS) i = 1
write(*,*) i
i = RegCloseKey(handle)
end
Back to top
View user's profile Send private message
JohnCampbell



Joined: 16 Feb 2006
Posts: 1709
Location: Sydney

PostPosted: Sun Jun 12, 2016 10:17 am    Post subject: Reply with quote

What do the updated strings var and val look like in subroutine SetEnv, and what are their lengths ?

I think that : character(*) :: var,val
should possibly be : character*(*) :: var,val

John
Back to top
View user's profile Send private message
ljfarrugia



Joined: 06 Jun 2016
Posts: 19

PostPosted: Sun Jun 12, 2016 10:46 am    Post subject: Reply with quote

The Win API functions are supposed to need null terminated strings. I've also tried it without the char(0) and the result is still the same

I think character(*) is shorthand for character(len=*)

While the system command setx works fine on Win 10, it must be a relatively new command. It is unknown in Win XP and I want the program to work on as many versions of Windows as possible.
Back to top
View user's profile Send private message
JohnCampbell



Joined: 16 Feb 2006
Posts: 1709
Location: Sydney

PostPosted: Sun Jun 12, 2016 3:15 pm    Post subject: Reply with quote

"I think character(*) is shorthand for character(len=*) "

It's not. character(*) defines a character*1 array(*) of unknown length, which would not work.
Back to top
View user's profile Send private message
ljfarrugia



Joined: 06 Jun 2016
Posts: 19

PostPosted: Sun Jun 12, 2016 4:32 pm    Post subject: Reply with quote

I don't think that character(*) var
implies a character array var

placing a statement after this

write(*,'(a)') var(1)

results in a compilation error because var is not declared as an array

In any case changing it to character(len=*) var, val
results in the same failure

Inside SetEnv, both variables look just as they should if printed out.
Back to top
View user's profile Send private message
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 4698
Location: Salford, UK

PostPosted: Mon Jun 13, 2016 6:18 am    Post subject: Reply with quote

The main thing is the you need to use KEY_SET_VALUE. Here is the code assuming that "Environment" is the correct key to use.

Code:
program main
character(len=255) :: var,buf
var = 'TMP_FILE'
buf = 'C:\temp\debug.txt'
call SetEnv(var,buf)
end

subroutine SetEnv(var,val)
character*(*) :: var,val
integer, parameter    :: KEY_SET_VALUE = Z'2'
integer(7), parameter :: HKEY_CURRENT_USER = Z'80000001'
integer, parameter    :: REG_SZ = Z'1'
stdcall RegOpenKeyEx  'RegOpenKeyExA'  (VAL,INSTRING,VAL,VAL,REF):integer
stdcall RegSetValueEx 'RegSetValueExA' (VAL,INSTRING,VAL,VAL,INSTRING,VAL):integer
stdcall RegCloseKey   'RegCloseKey'    (VAL):integer
integer ret,len
integer(7) key_handle
character(len=80)::subkey
subkey = "Environment"
len = len_trim(val)+1
ret = RegOpenKeyEx(HKEY_CURRENT_USER,subkey,0,KEY_SET_VALUE,key_handle)
ret = RegSetValueEx(key_handle,var,0,REG_SZ,val,len)
ret = RegCloseKey(key_handle) 
end     
       
Back to top
View user's profile Send private message
JohnCampbell



Joined: 16 Feb 2006
Posts: 1709
Location: Sydney

PostPosted: Mon Jun 13, 2016 9:35 am    Post subject: Reply with quote

"I think character(*) is shorthand for character(len=*) "

You are correct, the following 2 statements are the same
character(*) :: aa
character*(*) :: bb

However, the following 2 statements are different
character :: aa(*)
character :: bb*(*)

I have only ever used the bb*(*) types for declaring an argument of unknown length.
I always use character*n to define the length, which is a non-standard extension.

I find it confusing that the following 2 statements are different
character(*) :: aa
character :: aa(*)

while the following 2 statements imply the same
character*(*) :: bb
character :: bb*(*)

Shows there is always more to learn.


Last edited by JohnCampbell on Mon Jun 13, 2016 9:37 am; edited 1 time in total
Back to top
View user's profile Send private message
ljfarrugia



Joined: 06 Jun 2016
Posts: 19

PostPosted: Mon Jun 13, 2016 9:37 am    Post subject: Reply with quote

Thanks Paul

It seems to work perfectly on every Win installation I tried. But it seems
that this way of setting environment variables requires a Windows reboot
for them to be available for other processes (which is why I guess so many installation programs require just that)
Back to top
View user's profile Send private message
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 4698
Location: Salford, UK

PostPosted: Mon Jun 13, 2016 10:32 am    Post subject: Reply with quote

Maybe you need to set HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment as well.
Back to top
View user's profile Send private message
ljfarrugia



Joined: 06 Jun 2016
Posts: 19

PostPosted: Mon Jun 13, 2016 1:57 pm    Post subject: Reply with quote

I think that is where the system wide environment variables are stored. I presume a user would have to have administrator privileges to make changes there?

In any case, I did edit one entry there, for one of my own system variables using regedit and saved the change. It still seems to need a Windows reboot
to make the change available to a user.

After editing and saving the change, I opened a new DOS box and typed "set" to see the available variables and the change had not been updated.
Back to top
View user's profile Send private message
ljfarrugia



Joined: 06 Jun 2016
Posts: 19

PostPosted: Tue Jun 14, 2016 11:29 am    Post subject: Reply with quote

I just noticed that if an environment variable is set by using Win API function SetEnvironmentVariable in a program and then that program spawns another program by start_process@, then the value of the environment variable is also available for the spawned process.

Can this behaviour be relied on for all versions of Windows? (I checked it on Win 10). It is very useful
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> ClearWin+ All times are GMT + 1 Hour
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group