Jump to content

EnvUpdate() Hangs


Recommended Posts

If I manually edit my environmental variables via the system properties --> advanced tab and then subsequently call "EnvUpdate()" from a script then Autoit hangs (indefinitely as far as I can tell).

Restarting my machine resolves the issue until I manually open the windows environmental variable window again.

Autoit v3.3.8.1

Link to comment
Share on other sites

Hi,

Have you tried with the #RequireAdmin function ? With the latest beta ?

Try this (I don't know at all if it works) :

#include <WindowsConstants.au3>
#include <WinAPIEx.au3>

Local Const $HWND_BROADCAST = 0xFFFF
Local Const $SMTO_ABORTIFHUNG = 0x0002

_WinAPI_SendMessageTimeout($HWND_BROADCAST, $WM_SETTINGCHANGE, 0, "Environment", 0, $SMTO_ABORTIFHUNG)

Br, FireFox.

Link to comment
Share on other sites

Sorry for not responding sooner, I was expecting to get emailed when someone replied!

Thank you for the suggestions!

The script already had #RequireAdmin set and I'm on Win XP so no UAC.

I haven't tried the latest Beta, hopefully I'll get a chance to tomorrow.

Is the snippet you've suggested supposed to be called by another autoit script to knock EnvUpdate() on the head?

(Just downloading the WinAPIEx UDF to test it...)

Link to comment
Share on other sites

Is the snippet you've suggested supposed to be called by another autoit script to knock EnvUpdate() on the head?

No, replace the EnvUpdate function by my snippet in your script.

Br, FireFox.

Link to comment
Share on other sites

Strange that EnvUpdate doesn't work.

UDF List:

 
_AdapterConnections()_AlwaysRun()_AppMon()_AppMonEx()_ArrayFilter/_ArrayReduce_BinaryBin()_CheckMsgBox()_CmdLineRaw()_ContextMenu()_ConvertLHWebColor()/_ConvertSHWebColor()_DesktopDimensions()_DisplayPassword()_DotNet_Load()/_DotNet_Unload()_Fibonacci()_FileCompare()_FileCompareContents()_FileNameByHandle()_FilePrefix/SRE()_FindInFile()_GetBackgroundColor()/_SetBackgroundColor()_GetConrolID()_GetCtrlClass()_GetDirectoryFormat()_GetDriveMediaType()_GetFilename()/_GetFilenameExt()_GetHardwareID()_GetIP()_GetIP_Country()_GetOSLanguage()_GetSavedSource()_GetStringSize()_GetSystemPaths()_GetURLImage()_GIFImage()_GoogleWeather()_GUICtrlCreateGroup()_GUICtrlListBox_CreateArray()_GUICtrlListView_CreateArray()_GUICtrlListView_SaveCSV()_GUICtrlListView_SaveHTML()_GUICtrlListView_SaveTxt()_GUICtrlListView_SaveXML()_GUICtrlMenu_Recent()_GUICtrlMenu_SetItemImage()_GUICtrlTreeView_CreateArray()_GUIDisable()_GUIImageList_SetIconFromHandle()_GUIRegisterMsg()_GUISetIcon()_Icon_Clear()/_Icon_Set()_IdleTime()_InetGet()_InetGetGUI()_InetGetProgress()_IPDetails()_IsFileOlder()_IsGUID()_IsHex()_IsPalindrome()_IsRegKey()_IsStringRegExp()_IsSystemDrive()_IsUPX()_IsValidType()_IsWebColor()_Language()_Log()_MicrosoftInternetConnectivity()_MSDNDataType()_PathFull/GetRelative/Split()_PathSplitEx()_PrintFromArray()_ProgressSetMarquee()_ReDim()_RockPaperScissors()/_RockPaperScissorsLizardSpock()_ScrollingCredits_SelfDelete()_SelfRename()_SelfUpdate()_SendTo()_ShellAll()_ShellFile()_ShellFolder()_SingletonHWID()_SingletonPID()_Startup()_StringCompact()_StringIsValid()_StringRegExpMetaCharacters()_StringReplaceWholeWord()_StringStripChars()_Temperature()_TrialPeriod()_UKToUSDate()/_USToUKDate()_WinAPI_Create_CTL_CODE()_WinAPI_CreateGUID()_WMIDateStringToDate()/_DateToWMIDateString()Au3 script parsingAutoIt SearchAutoIt3 PortableAutoIt3WrapperToPragmaAutoItWinGetTitle()/AutoItWinSetTitle()CodingDirToHTML5FileInstallrFileReadLastChars()GeoIP databaseGUI - Only Close ButtonGUI ExamplesGUICtrlDeleteImage()GUICtrlGetBkColor()GUICtrlGetStyle()GUIEventsGUIGetBkColor()Int_Parse() & Int_TryParse()IsISBN()LockFile()Mapping CtrlIDsOOP in AutoItParseHeadersToSciTE()PasswordValidPasteBinPosts Per DayPreExpandProtect GlobalsQueue()Resource UpdateResourcesExSciTE JumpSettings INISHELLHOOKShunting-YardSignature CreatorStack()Stopwatch()StringAddLF()/StringStripLF()StringEOLToCRLF()VSCROLLWM_COPYDATAMore Examples...

Updated: 22/04/2018

Link to comment
Share on other sites

This is what I just ran:

#include <Array.au3>

Global $HWND_BROADCAST = 0xffff
Global $WM_SETTINGCHANGE = 0x001A
Global $SMTO_ABORTIFHUNG = 0x0002
Global $MSG_TIMEOUT = 5000


EnvSet("TEST", "HELLO")

ShellExecuteWait(@ComSpec)

$iRet2 = DllCall("user32.dll", "lresult", "SendMessageTimeoutW", _
"hwnd", $HWND_BROADCAST, _
"dword", $WM_SETTINGCHANGE, _
"ptr", 0, _
"wstr", "Environment", _
"dword", $SMTO_ABORTIFHUNG, _
"dword", $MSG_TIMEOUT, _
"dword_ptr*", 0)

ConsoleWrite(@CRLF & @error & @CRLF & @extended & @CRLF)

_ArrayDisplay($iRet2)

The variable is set as expected (if I launch @comspec "ECHO %TEST%" I get "HELLO" as expected).

The $iRet2[0] = 1 (i.e. no error as far as I understand). @error = 0 and @extended = 0

All looks good apart from the fact that after the script exits I see no change to my Environment Variables, either through the windows settings or in a fresh command prompt.

Edited by hutchinsfairy
Link to comment
Share on other sites

Here's a function from way back :)...

#include-once
; http://www.autoitscript.com/forum/topic/116484-solved-autoit3-encountered-a-problem-and-needs-to-close/#entry813190
; #INDEX# =======================================================================================================================
; Title .........: Environment Update
; AutoIt Version.: 3.2.12++
; Language.......: English
; Description ...: Refreshes the OS environment.
; Author ........: João Carlos (jscript)
; Support .......: trancexx, PsaltyDS, KaFu
; ===============================================================================================================================

; #CURRENT# =====================================================================================================================
;_EnvUpdate
; ===============================================================================================================================

; #INTERNAL_USE_ONLY# ===========================================================================================================
; ===============================================================================================================================

; #VARIABLES# ===================================================================================================================
Global $MAX_VALUE_NAME = 1024
Global $HWND_BROADCAST = 0xffff
Global $WM_SETTINGCHANGE = 0x001A
Global $SMTO_ABORTIFHUNG = 0x0002
Global $SMTO_NORMAL = 0x0000
Global $MSG_TIMEOUT = 5000

; #Example# =====================================================================================================================
#cs
    _EnvUpdate("VERSION", "7.07.0110.2600")
    MsgBox(4096, @error, EnvGet("VERSION"))
    _EnvUpdate("VERSION", "", True, True)
    MsgBox(4096, @error, EnvGet("VERSION"))
#ce

_EnvUpdate("TEST", "HELLO")
ShellExecuteWait(@ComSpec) ; Try "ECHO %TEST%" => works during runtime of script...
ShellExecute(@ComSpec) ; Try "ECHO %TEST%" => should also work after script has finished :)...

; ===============================================================================================================================

; #FUNCTION# ====================================================================================================================
; Name...........: _EnvUpdate
; Description ...: Refreshes the OS environment.
; Syntax.........: _EnvUpdate( ["envvariable" [, "value" [, CurrentUser [, Machine ]]]] )
; Parameters ....: envvariable  - [optional] Name of the environment variable to set. If no variable, refreshes all variables.
;                  value        - [optional] Value to set the environment variable to. If a value is not used the environment
;                                   variable will be deleted.
;                  CurrentUser  - [optional] Sets the variable in current user environment.
;                  Machine      - [optional] Sets the variable in the machine environment.
; Return values .: Success      - None
;                  Failure      - Sets @error to 1.
; Author ........: João Carlos (jscript)
; Support .......: trancexx, PsaltyDS, KaFu
; Modified.......:
; Remarks .......:
; Related .......:
; Link ..........;
; Example .......; _EnvUpdate("TEMP", @SystemDir & "TEMP", True, True)
; ===============================================================================================================================
Func _EnvUpdate($sEnvVar = "", $vValue = "", $fCurrentUser = True, $fMachine = False)
    Local $sREG_TYPE = "REG_SZ", $iRet1, $iRet2

    If $sEnvVar <> "" Then
        If StringInStr($sEnvVar, "\") Then $sREG_TYPE = "REG_EXPAND_SZ"
        If $vValue <> "" Then
            If $fCurrentUser Then RegWrite("HKCU\Environment", $sEnvVar, $sREG_TYPE, $vValue)
            If $fMachine Then RegWrite("HKLM\System\CurrentControlSet\Control\Session Manager\Environment", $sEnvVar, $sREG_TYPE, $vValue)
        Else
            If $fCurrentUser Then RegDelete("HKCU\Environment", $sEnvVar)
            If $fMachine Then RegDelete("HKLM\System\CurrentControlSet\Control\Session Manager\Environment", $sEnvVar)
        EndIf
        ; http://msdn.microsoft.com/en-us/library/ms686206%28VS.85%29.aspx
        $iRet1 = DllCall("Kernel32.dll", "BOOL", "SetEnvironmentVariable", "str", $sEnvVar, "str", $vValue)
        If $iRet1[0] = 0 Then Return SetError(1)
    EndIf
    ; http://msdn.microsoft.com/en-us/library/ms644952%28VS.85%29.aspx
    $iRet2 = DllCall("user32.dll", "lresult", "SendMessageTimeoutW", _
            "hwnd", $HWND_BROADCAST, _
            "dword", $WM_SETTINGCHANGE, _
            "ptr", 0, _
            "wstr", "Environment", _
            "dword", $SMTO_ABORTIFHUNG, _
            "dword", $MSG_TIMEOUT, _
            "dword_ptr*", 0)

    If $iRet2[0] = 0 Then Return SetError(1)
EndFunc   ;==>_EnvUpdate
Link to comment
Share on other sites

Here's a function from way back :)...

Thank you KaFu. That appears to be the same code that FireFox linked to. I have tested the DLLCALL as in my code above and it doesn't seem to work as expected. When I have a quiet moment at work I'll restart my machine and see what the exact steps are to recreate. Doesn't look likely today though...
Link to comment
Share on other sites

Well, the code works fine for me on this XP machine. What I've noticed is that a process will get the current ENV settings on startup and will not be aware of any intermediate updates.

ShellExecute(@ComSpec) ; Try "ECHO %TEST%" => should also work after script has finished :)...

_EnvUpdate("TEST", "HELLO")

ShellExecute(@ComSpec) ; Try "ECHO %TEST%" => should also work after script has finished :)...

The first cmd.exe will not see the variable, the second will.

Link to comment
Share on other sites

Using the above example the change persists even if the script has ended.

It only seems to me that the default (?) behavior of a process is to load the ENV set only once at startup and that the WM_SETTINGCHANGE broadcast does not trigger a process to reload the env vars... and this seems like an none-AutoIt specific topic to me.

Link to comment
Share on other sites

Using the above example the change persists even if the script has ended.

This is not what happens for me.

It only seems to me that the default (?) behavior of a process is to load the ENV set only once at startup and that the WM_SETTINGCHANGE broadcast does not trigger a process to reload the env vars... and this seems like an none-AutoIt specific topic to me.

I am not trying to get a process to reload the environment. I am trying to get changes made in my script to be available to other, new processes after my script ends. I'm sorry if that was not clear.

There are two presumably related issues here:

  • WM_SETTINGCHANGE does not make ENV VAR changes persist.
  • EnvUpdate() hangs when it tries to do the same.
I have just restarted my machine and EnvUpdate() hangs on a fresh boot. I have also noticed that if I update an existing ENV VAR and call WM_SETTINGCHANGE the ENV VAR appears to be unavailable to new processes. If I then bring up the windows ENV VAR dialog box and immediately click OK it seems to work again (with the original value, not what my script tried to set).

I'm wondering if it could be a group policy or something affecting my registry rights but have limited time to check. If the WM_SETTINGCHANGE call is supposed to work the same as EnvUpdate I might just use that, as at least it doesn't cause the whole script to hang. At best it will work as hoped on most computers and at worst the ENV VAR will remain unset.

Link to comment
Share on other sites

Here's the MSDN documentation:

http://msdn.microsoft.com/en-us/library/windows/desktop/ms682653(v=vs.85).aspx

What OS are you running on?

Maybe give this a try:

_EnvUpdate("TEST", "HELLO", False, True)

This will write variable to HKLM (add #RequireAdmin to top of the script on Vista+).

Also check these registry locations after the test to see whether the keys have been written successfully:

HKCUEnvironment

HKLMSystemCurrentControlSetControlSession ManagerEnvironment

Link to comment
Share on other sites

Windows XP SP3.

After another restart the situation is thus:

I can get my script to update the registry and then run the _EnvUpdate() UDF, and the changes persist beyond the termination of my script. Yay!

However, the shipped function EnvUpdate() still never completes on my machine.

I guess my original problem still stands but I have a workable workaround.

Thank you FireFox and KaFu.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...