VBScript get temp folder - vbscript

fso.GetSpecialFolder(2) correctly returns the temp folder for me, when run from a VBS file. However, when run from within an Autodesk Revit journal file, which has historically been VBS compliant, I get back the proper path and a GUID after Temp. I had never seen this before, and I am unsure if this is perhaps a known issue in newer builds of Windows 10 (it's been about three years since I tested this), or is this more likely an issue with Autodesk's implementation of VBScript support? I suspect the latter.
Which then raises the question, is there another good way to get the full temp path in VBScript?
I could use
Dim strUser : strUser = CreateObject("WScript.Network").UserName
"C:\Users\" & strUser & "\AppData\Local\Temp"
It's just been so long since I played with VBS, I'm not remembering if there is a better answer, or this is the consistently workable way to go. And, more than anything I want to know if .GetSpecialFolder(2) is broken in some way in Windows, or just by Autodesk.

Isn't it logical to have different values on different environments / scripting hosts?
GetSpecialFolder(2) simply returns the process environment variable named TMP. Any change on that variable -which is quite legal-, affects the value that GetSpecialFolder(2) returns.
GetSpecialFolder method
Constant: TemporaryFolder
Value: 2
The Temp folder is used to store temporary files. Its path is found in the TMP environment variable.
Since GetSpecialFolder(2) will always return an existing directory path I probably would use it with the thought that this is intended by the environment; the Autodesk Revit.
Other than that, I'd use something like below if I want the usual temporary path because even they are rare, there are installations where system drive is not C:. Relying on %localappdata% makes more sense in that manner.
Set WshShell = CreateObject("Wscript.Shell")
TempPath = WshShell.ExpandEnvironmentStrings("%localappdata%\Temp")

Related

How to keep the value of a global variable next time the script is run?

I have a VBScript file, that's called from another, which has some global variables defined, something like Dim var="whatever" outside of every function and sub. Those variables might change, maybe an instruction like var="whatever2" and their new values might be used in some calls that the other VBScript file does. But problem is that everytime the file is called their values are reset to the ones that are shown in the place where the global values are defined, so it takes the same values again.
I see two ways to solve this: One to create a text file where all actual correct values are written and then when the script is called read them from that text file, although I guess there has to be a better way. The other is to keep on using parameters for the calls, but this would likely complicate the application a lot, that's precisely the reason to use global variables, so I don't think it's a real option. I also think getting to set the values in a function wouldn't help much as they would be reseted afterwards anyway.
Any idea on how something like what I'm telling could be done?
Global variables only live as long as their process is running. If you need to persist the values of these variables so they're available when the script is run again later on you need to store them elsewhere.
The canonical methods are saving the values to a file:
Set fso = CreateObject("Scripting.FileSystemObject")
Set f = fso.OpenTextFile("C:\path\to\mystate.txt")
f.Write "var1=" & var1
f.Write "var2=" & var2
...
f.Close
or to the registry:
Set sh = CreateObject("WScript.Shell")
sh.RegWrite "HKCU\Software\mystate\var1", var1, "REG_SZ"
sh.RegWrite "HKCU\Software\mystate\var2", var2, "REG_DWORD"
...
However, if you only need them to be available during the current user session, you could also use the volatile environment:
Set sh = CreateObject("WScript.Shell")
Set env = sh.Environment("VOLATILE")
env("mystate_var1") = var1
env("mystate_var2") = var2
...
The volatile environment is only available for the current user and will vanish when the user logs off.
Consider using COM objects as your slave objects.
Script Components make vbscript COM objects. WSF script files hold many scripts in one file and can reference other files.
From Help
Windows® Script Components provide you with an easy way to create powerful, reusable COM components in script. You create script components using any scripting language that supports the Microsoft® ActiveX® Scripting interfaces. Script languages that support these interfaces include JScript, Microsoft® Visual Basic® Scripting Edition (VBScript), PERLScript, PScript, and Python.
COM Support
This new script component technology supports common types of COM components, such as Automation, and is extensible with add-ons such as DHTML behaviors.
Script Components:
Are small and efficient.
Are easy to create, maintain, and deploy.
Provide the ability to create COM components.
Provide access to a broad range of system services.
Using script components, you can create COM components for a variety of tasks, such as performing middle-tier business logic, accessing and manipulating database data, adding transaction processing to applications, and adding interactive effects to a Web page using DHTML Behaviors
and wsf files.
A Windows script (*.wsf) file is a text document containing Extensible Markup Language (XML) code. It incorporates several features that offer you increased scripting flexibility. Because Windows script files are not engine-specific, they can contain script from any Windows Script compatible scripting engine. They act as a container.
Additional Features
.wsf files support You can
Include statements
Incorporate functions from VBScript or JScript files into your Windows Script Host project.
Multiple engines
Use more than one scripting language per file.
Type libraries
Add constants to your code.
Tools
Edit files with any XML editor.
Multiple jobs in one file
Store all of your code in a single location

Set path in Visual Foxpro

I want to set path in Visual Foxpro. In such a way that I want to keep exe file on local machine and data\tables on server. How can I do so?
I personally have never liked using SET PATH, especially if you have many "paths" that your application is expecting to use.. If you have a given table / file in multiple locations that are visible with multiple paths that qualify, you may be getting the wrong table, but you won't necessarily know it since the application just runs as normal, finds a table and continues.
Instead, I would suggest one of a few things. Yes, have your application on each user's local machine, but have the person's shortcut have the "START IN" folder pointing to the path on the server where your data is. This way, your application will BE in the folder where the data resides and processes without issue. If no data is on the local machine, during your startup, you could add a messagebox about ... hey... your shortcut should be set to "Start In" setting to X:\SomeShareOnServer\MyVFPDataPath...
If not that, then another avenue I have used is to have your application during startup, add a property to the "_Screen" object which will NEVER loose scope, and set that property to the path you have the data located such as...
_Screen.AddProperty( "cDataPath" )
_Screen.cDataPath = "X:\SomeShareOnServer\MyVFPDataPath\"
Then, in your code, any of your opening tables or SQL queries, use the path variable PLUS the table... something like
if not used( "SomeTable" )
select 0
use ( _Screen.cDataPath + "SomeTable" )
endif
if doing a query, use similar approach
select ST.* ;
from ( _Screen.cDataPath + "SomeTable" ) ST ;
where ST.SomeID = 123;
into cursor C_TmpResult readwrite
So, although the second option may take more effort, especially on an existing application, the first option to make sure the "Start In" path is where the data is might help.
Again, this is my suggestion as I hate chasing down ambiguous -- sometimes it works, but not others. If I can't find a file, I WANT TO KNOW about it and fail outright.
Your call, your app, your environment. But if you DO use the "SET PATH" command, you might want to make sure you use the ADDITIVE command, just in case there are other settings, such as pointing to the a path for forms, classes, report folders... You run a SET PATH without it, and you kill your other paths...
SET PATH TO "X:\SomeShareOnServer\MyVFPDataPath\" ADDITIVE
Also, if you have any spaces in your path in question, MAKE SURE you use quotes around it, otherwise it will fail finding the path you expect and may cause compile error, such as
SET PATH TO X:\Some Share On Server\MyVFPDataPath\ ADDITIVE
You can use VFP's Set Path command
Set Path To m.lcDataFolder
early in your client startup code, i.e. in your project's "main.PRG".
Where the content of the m.lcDataFolder could for example come from something like a custom "myConfig.XML/INI/TXT" containing the desired string, e.g. \\fileServerNameOrIP\sharedDataFolder
Use 'SET DEFAULT TO' to change the current working directory or use explicit full paths as per the answer by #DRapp.

Running programs from command prompt (PATH environment variable)

I'm having some issues when trying to run some programs from the command prompt after adding their executable file paths to the PATH variable. I respected the syntax (; at the end of every path added). Has this ever happened to anyone?
You have not told us what problem you are seeing, but it you append the path to a program at the end of PATH thus:
set PATH=%PATH%;"c:\somewhere_else"
you can find the new path nevers gets seen, since there's a hard upper limit on path length. See for example this SO post
One option is to prepend the new location, bearing in mind this will drop other things off the end:
set PATH="c:\somewhere_else";%PATH%
There are various workrounds. For example, I tend to have a few set_path.bat files in a few different locations that reset my path to what's required for various different tasks.

Set ComputerName Enviornment Variable

I need to use a VBS script to set the environment variable %computername% to "blah". This seems like a simple enough task but for some reason I'm finding it difficult this morning. I can do this via a command prompt (set computername=blah) and I can get the value of the environment variable via VBS but I cant seem to find the correct syntax to override the environment variable. Any help would be greatly appreciated. Thanks!
How you create it determines its type and lifetime. If you want the variable to be available until the user logs off, you can create it as VOLATILE.
Set objShell = CreateObject("WScript.Shell")
objShell.Environment("VOLATILE")("MyVariable") = "This is some data to share"
And to read it back...
strValue = objShell.Environment("VOLATILE")("MyVariable")
Other options for the variable's type are SYSTEM, USER, and PROCESS. See here for a nice article describing the differences.

Getting safe temp folder in Windows

I need to get a safe temp folder where I could store temporary files for my application, but so far my research has lead me to conclusion that all approaches I've found are flawed.
The first idea was to use GetTempPath function, but that causes two problems:
The folder might not exist, so I would have to truncate folders one by one up to root, and recreate them if they do not exist back to full path (error prone, tedious)
From "Larry Osterman's WebLog" click it seems that GetTempPath might fallback to USERPROFILE or Windows directory and extract whole lot of files right in there, which is SUPER BAD(TM)!
In the same post, there is a suggestion to use GetEnvironmentVariable, but this seems a dangerous function to me (missing TMP & TEMP envvars for instance).
Is there a cleaner function I could use? Seems that SHGetKnownFolderPath has no clue what temp folder is.
Your program is probably not the only one to rely on GetTempPath, so it's reasonable to expect it to return a proper writable path. Especially since Windows automatically initializes the TMP and TEMP environment variables for you; someone would have to go to some trouble to override them, and it would be their responsibility to make sure the change did not mess up their system.
I would go ahead and assume GetTempPath works properly, and worry about failures when you try to create the temporary file - there are other errors that might occur at that time that you need to check for anyway.
An idea would be to get the path where your application is (GetModuleFileNameEx combined with GetModuleHandle(NULL) and GetCurrentProcess) since this directory cannot be deleted under windows as long as your application is running from it (maybe I'm wrong ...some years ago I couldn't do this :) ) and in this directory create a temporary directory.
Your first bullet point is the solution. Wrap it up in a method so that you don't duplicate code.
According to this answer, Boost's Filesystem library can be used for this.

Resources