By registering with us, you'll be able to discuss, share and exchange private messages with other members of our community.SignUp Now!
Both "set /v var=" and "unset /v var" work here.It would appear to me that there is no way to delete a volatile variable, i.e., set its value to a null string. "Set /V Variable=" doesn't do it, and while there is a registry function to delete keys, there doesn't seem to be a way to delete values. Am I missing something?
v:\> set /v foo=bar v:\> set /v LOGONSERVER=\\ZZ USERDOMAIN=zz USERNAME=vefatica USERPROFILE=C:\Users\vefatica HOMEPATH=\Users\vefatica HOMEDRIVE=C: APPDATA=C:\Users\vefatica\AppData\Roaming LOCALAPPDATA=C:\Users\vefatica\AppData\Local foo=bar v:\> set /v foo= v:\> set /v LOGONSERVER=\\ZZ USERDOMAIN=zz USERNAME=vefatica USERPROFILE=C:\Users\vefatica HOMEPATH=\Users\vefatica HOMEDRIVE=C: APPDATA=C:\Users\vefatica\AppData\Roaming LOCALAPPDATA=C:\Users\vefatica\AppData\Local v:\> set /v foo=bar v:\> set /v LOGONSERVER=\\ZZ USERDOMAIN=zz USERNAME=vefatica USERPROFILE=C:\Users\vefatica HOMEPATH=\Users\vefatica HOMEDRIVE=C: APPDATA=C:\Users\vefatica\AppData\Roaming LOCALAPPDATA=C:\Users\vefatica\AppData\Local foo=bar v:\> unset /v foo v:\> set /v LOGONSERVER=\\ZZ USERDOMAIN=zz USERNAME=vefatica USERPROFILE=C:\Users\vefatica HOMEPATH=\Users\vefatica HOMEDRIVE=C: APPDATA=C:\Users\vefatica\AppData\Roaming LOCALAPPDATA=C:\Users\vefatica\AppData\Local
As Scott partially said, what you see depends on how/when you are starting the sessions. "SET /V" puts the variable in "HLCU\Volatile Environment" and announces to the system that it has done so. "UNSET /V" removes it and makes a similar announcement. Explorer listens to these messages and adjusts its own environment (which it gives to apps it starts) accordingly. So apps started BY EXPLORER after one of those messages will get the environment you expect. However, most apps do not heed those messages. So what starts what, and when can make a difference. TCC has an option, "Update environment on system change" that may help.Vince, maybe I didn't make this clear. Both of those unset the local environment variable, neither one of them resets the variable in whatever place it is located as a "volatile" variable (which I don't have a clue where it is since it doesn't show up any more in the registry, see below). To be as clear as possible, if I do "Set /V /E ABC=DEF" and then echo %ABC, DEF is displayed as one would expect. And if I then open up a new TCC session and do the same thing I get the same result, as expected. So I close the 2nd TCC session and issue a "Unset /V /E ABC', and "Echo %ABC" yields "Echo is OFF" as expected. However, if I then open a 2nd TCC session and issue the same command, I still get DEF as the result. However, if I go into RegEdit, ABC no longer shows up in the "volatile" variable list despite the result in the 2nd TCC session above. I truly don't understand this even in principle, but what I want is for it to now show up without a value of any kind (much less DEF), i.e. the variable should no longer even exist. (The ultimate purpose of this that is I have a variable whose very existence should inform a batch file one thing and non-existence another. What I have to do is test either for existence or some value that I use as a alias for non-existence. Doable, but ugly.)
Check the setting of "Update environment on system change" in both TCC and TCMD. When TCMD starts TCC, the TCC gets TCMD's current environment. So you want TCMD's environment to react to those changes. But there does seem to be somethine unexpected. With "Update environment on system change" checked in both, the following experiment did not work as desired. All in a single TCMD ...First off, Vince that's good to know. But I have to ask: The primary reason I'm using a volatile variable is because it "disappears" on reboot, and that is the primary reason for the variable-in-question's very existence. If it does not exist, no TCC instance has been started since the last reboot, if it exists this is the 2nd or later TCC instance created after the last reboot. Secondly, a correction to my previous posing which makes absolutely no real difference whatsoever. If I start the 2nd TCC instance in the same Take Command instance as the first TCC instance, things are as above. However (and I just tested this again to make sure) if I start the 2nd TCC instance any other way (start menu, start command, whatever) the variable no longer exists as expected. However, since my normal, deeply ingrained habit, is to start TCC instances in the Take Command instance that I am currently in, that really doesn't have much relevancy to me.
I know what's in "HKCU\Volatile Environment" and aside from the OS itself, I know of no app other than TCC which gives you access to it (or uses it). Using the volatile environment for anything app-specific is certainly not mainstream. I doubt that key was intended for proprietary use by apps. The volatile environment could help with your original issue but don't expect too much of it.Vince, "Update Environment on System Change" is (and was) checked in both options dialogs. And, yes, I can see where the time it takes to check if a variable is no longer defined in the registry could take a (short) while, but the bottom line is that if the registry is always consulted when starting a new TCC instance (even in the same Take Command session) the problem would go away (and I really wouldn't expect an environment variable in a TCC session to become undefined when the registry entry that created it is deleted), and I don't find it significantly slower to start a stand-alone TCC session (which has some distinct disadvantages re my partial blindness) or a new Take Command instance. And finally I'll note that there's a bunch of other stuff defined in that registry key (take a look at it yourself, you might be surprised) so I am hardly doing anything "out of the mainstream".
iff "%@execstr[set /v foo]" == "" then Echo do first time stuff Set /v foo=bar Endiff
If you use "HKCU\Volatile Environment" and broadcast WM_SETTINGSCHANGE, every app that Explorer starts afterward and every app that processes that message (few) will get your change. That hardly seems proprietary. For your purpose, I'll change my tune and suggest unchecking "notify system". That way you won't be messing with anyone else's environment (or even your own unless you use "/E"). Anyone interested (namely you) can look directly at the key. You can do that as Scott suggested, or with @REGQUERY, or most easily with 4UTILS's @GEV[name,v]Certainly that would help, Vince. (And I meant that using it for that purpose is mainstream in my opinion, which I will stand behind given that there is no other way (that I'm aware of, at least) of getting that functionality in Windows. It seems to me that that is precisely what that registry key is for, and the fact that no other apps (that we are aware of, at least) use if for that purpose indicates either a lack of need for that functionality or a lack of awareness that it even exists, but most likely the former.)
set /v > %scrfile :: Do some stuff to select variables from %scrfile and write %scrfile%a set /r %scrfile%a
Oh, and Scott when doing an "Echo %@ExecStr[Set /V foo]", for instance, you get the error message `TCC: Not in environment "foo"` and there appears to be no way to intercept that error message (>&>NUL: doesn't do it). Frankly, I consider that to be unacceptable. (Code that I write absolutely never generates an error message when no "error" exists!)
( echo %@execstr[set /v foo] ) >& nul:
@Echo Off If Exist E:\Temp\RecordedRebootTime.txt %= GoTo NotFirstTime Echo %@ExecStr[SystemInfo >&>NUL: | Find "System Boot Time"] >E:\Temp\RecordedRebootTime.txt Quit 4 :NotFirstTime Set RecordedBootTime=%@ExecStr[Type E:\Temp\RecordedRebootTime.txt] Set LastBootTime=%@ExecStr[SystemInfo >&> NUL: | Find "System Boot Time"] If "%RecordedBootTime" != "%LastBootTime" %= Quit 4 Quit 0
v:\> echo %@WMI[.,"SELECT LastBootUpTime FROM Win32_OperatingSystem"] 20130114112047.802672-300 v:\> echo %@left[14,%@WMI[.,"SELECT LastBootUpTime FROM Win32_OperatingSystem"]] 20130114112047
TCC /C DEL %temp\BootUpTask or TCC /C TOUCH /C %temp\BootUpTask
Your example (using @EXECSTR) definitely won't work in CMD.Viince, that is a much faster way of doing exactly what I was looking for. And I don't really care what time the system was last rebooted, I just want to know that it was rebooted since the last recorded time of a reboot, which is why I compare the current reboot time to the reboot time stored in a file. (There are a couple of reasons I really don't want to use a plugin, one of the main ones being that I want the code to execute properly in cmd.exe.)
@Echo Off If Not Exist E:\Temp\SavedBootUpTime.txt Goto End If Exist E:\Temp\LastBootUpTime.txt Del E:\Temp\LastBootUpTime.txt >NUL: WMic OS Get LastBootUpTime >E:\Temp\LastBootUpTime.txt FC /b E:\Temp\LastBootUpTime.txt E:\TEMP\SavedBootUpTime.txt >NUL: Set EL=%ErrorLevel% If %EL%==0 Exit /B 0 REM This should really never happen, but being safe.. If %EL%==2 Goto End Del E:\Temp\SavedBootUpTime.txt >NUL: Ren E:\Temp\LastBootUpTime.txt SavedBootUpTime.txt >NUL: Exit /B 1 :End WMic OS Get LastBootUpTime >E:\Temp\SavedBootUpTime.txt Exit /B 1
v:\> echo %@regquery[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run\Chores] cmd.exe /c del h:\temp\ChoresSentinel v:\> type chores.bat @echo off if exist h:\temp\ChoresSentinel goto choresdone echo Doing chores REM do chores here :choresdone echo %DATE% %TIME% > h:\temp\ChoresSentinel