Search code examples
vbscriptqtp

Why does setting a USER environment variable take 12 seconds?


With the following code, I experience horrible runtime:

Option Explicit

Dim ShellEnvironment: Set ShellEnvironment=CreateObject ("WScript.Shell").Environment ("USER")
Dim Name: Name="MyVar"
Dim NewVal: NewVal="This is my value"

Services.StartTransaction "SetEnv"
ShellEnvironment (Name)=NewVal
Services.EndTransaction ("SetEnv")

Note that only the Services.* stuff is QTP-specific. The two statements generate the following run result entry, indicating the runtime for the environment variable assignment:

Transaction "SetEnv" ended with "Pass" status (Total Duration: 12.1970 sec). 

This is on a very fast machine. Of course it is an unacceptable long runtime.

According to Environment.SetEnvironmentVariable takes a long time to set a variable at User or Machine level, this is because all top-level windows are notified with a 1-second timeout. I am not sure if that is C#-specific or not. Well, it obviously is not. But I don´t see how I can control this notification/timeout process under VBScript.

So generally speaking, the question is:

How can I set a USER environment variable in VBScript without getting the horrible runtime?


Solution

  • There seems to be no way to control the timeout that ShellEnvironment uses for the notification broadcast.

    So I decided to build a workaround.

    I call this script:

    Option Explicit
    
    Dim Name
    Dim NewVal
    
    If WScript.Arguments.Count <> 2 then
        WScript.Echo "setUSEREnv.vbs: Pass name and value of USER environment variable to set on the command line"
        WScript.Quit (1)
    End If  
    
    Name=CStr (WScript.Arguments.Item (0))
    NewVal=CStr (WScript.Arguments.Item (1))
    
    Dim ShellEnvironment: Set ShellEnvironment=CreateObject ("WScript.Shell").Environment ("USER")
    If ShellEnvironment (Name) <> NewVal then
        ShellEnvironment (Name)=NewVal
        WScript.Echo "Setting USER env var '" & Name & "'..."
        WScript.Echo "USER env var '" & Name & "' set to '" & NewVal & "'"
    else
        WScript.Echo "USER env var '" & Name & "' already is '" & NewVal & "'"  
    End If
    

    from my setenv function code using Run:

    Dim ShellEnvironment: Set ShellEnvironment=CreateObject ("WScript.Shell").Environment ("USER")
    
    Dim Name: Name=EnvVarName
    If ShellEnvironment (Name) <> NewVal Then
        Dim Shell: Set Shell=CreateObject ("WScript.Shell")
        Shell.Run "cscript.exe ""c:\mydir\setUSERENV.vbs"" " & Name & " " & CStr (NewVal), 0, false
    End If
    

    This still insults me with a long delay for every env var write access, but at least the main script keeps running, and so I don´t have to wait.