DOS – Still Relevant
Not only is DOS still relevant, its often one of the quickest ways to get some things done.
On XtraCAD.com, someone recently asked how to get the system Date and Time in an Autodesk Fabrication COD script. I provided a solution that uses DOS commands inside a COD script. That solution is explained in more detail here.
DOS’s “Date” Command
Using DOS, we can use the “DATE” command with the “/T” Switch to output the current date to a DOS prompt.
The information given by this simple command is all we need. A script can easily read the data if the output is redirected to a data file.
We’ll get a little more ambitious and get particular on the formatting. We’ll remove the “Tue” and format the date in the format “yyyy.mm.dd”.
To do this, we can use the “FOR” command in DOS.
for /F "tokens=2-4 delims=/- " %A in ('date /T') do echo %C.%A.%B
The Red circled area is the command. It takes the data from the Date command and breaks it apart by the delimiters (DELIMS) which is spaces ( ), forward slashes (/) and dashes (-). You’ll note that the Date doesn’t actually contain any dashes so it’s just ignored.
The TOKENS specifies we want the 2nd thru 4th items of data. They will be assigned sequentially to variables starting with “%A”. The Green circled area is the resulting output ECHO’d to the DOS Window in the format we want.
- %A = 2nd piece of data (month)
- %B = 3rd piece of data (day)
- %C = 4th piece of data (year)
Sending Data to a File
Now that have our DOS command, the next step is to send the output to a file on disk. Doing this will allow the COD script to read it back later.
For this purpose, we use a re-director to pump the data to a file. We simply append a suffix like this…
for /F "tokens=2-4 delims=/- " %A in ('date /T') do echo %C.%A.%B>"C:\Temp\COD Data.Txt"
A few notes about redirecting data to a file….
- We use double quotes around the file path and name in case it contains spaces. This way, DOS doesn’t interpret the space as a separator between commands.
- The Greater-Than (>) symbol is used to redirect output to a file. If the file already exists, it will be overwritten.
- Double Greater-Than (>>) symbols can be used to “append” to the end of an existing file. This is handy if you want to add more data to the same file. If the file doesn’t already exist, it will be created.
We Have DOS, Now for the COD Script
Now that we have our DOS syntax down, we can start writing out COD Script. To start, I typically generate a few variables that help me format things.
REM ------------------------------ REM DQ = Double Quote Character REM CR = Carriage Return Character REM ST = Single Tab Character REM WF = Working File REM ------------------------------ DIM DQ = ascii(34) DIM CR = ascii(10) DIM ST = ascii(9) DIM WF = "C:\Temp\COD Data.Txt"
Because some of our syntax contains double quotes, and because strings (text) in a COD script also contain double quotes, having multiple double quotes in a row can be confusing. Additionally, sometimes the script has trouble understanding where one string ends vs what’s a string containing a double quote.
To handle this, I set a variable (DQ) that will represent any double quote within a COD Script string. I also use a Carriage Return (CR) variable and a Single Tab (ST) variable for formatting purposes that you’ll see later.
Lastly, I also set a variable for the data file. It’s at the beginning, it’s easy to find and change without having to get in the middle of a lot of confusing formatted string data later.
Executing DOS From the Script
To execute an external command from a script, we can use the EXEC function.
EXEC(<“command”>, <execution mode>, <“command data/arguments”>)
Here’s the 3 pieces of data we’ll need…
- <command> = “CMD.EXE”
This is the DOS Command Interpreter
- <execution mode> = exec_wait + exec_show_min
These are a couple variables that tell the external program to “Wait” until finished before proceeding with the rest of the script and to minimize the Window.
- <command/arguments> = The Prior DOS Syntax (with modifications) goes here.
The CMD.EXE program takes an argument of “/C” followed by the command it’s going to execute which is our DOS Syntax. Pay close attention, because here’s where we’re going to have to break up the DOS commands and embed our variables for the embedded double quotes.
The below is a single “String” with double quotes on each end. It also has a lot of double quotes inside the text which will confuse you and your script. This below syntax is WRONG and needs to be corrected….
"/C for /F "tokens=2-4 delims=/- " %A in ('date /T') do echo %C.%A.%B>"C:\Temp\COD Data.Txt""
To do this, it’s easier to illustrate in color. We’re going to take one very long complicated string, and break it into several smaller strings when there’s double quotes within the string.
That is, where ever there’s a double quote within the string, we’re going to make a smaller string before and after, and piece them back together and use our DQ variable to embed the double quote between them.
This works for the first two double quotes. But at the end of the string, we’re going to do something a little different. Here, we want to remove file name and use the WF variable we set earlier to store the file name. And because the filename may have a path, we surround it with DQ variables to embed it in double quotes.
The next piece of code should look like this when we’re done. This will run our DOS command and dump the date to a file,
REM --------------------- REM Get Date (yyyy.mm.dd) REM --------------------- Exec("cmd.exe", exec_wait + exec_show_min, "/C for /F " + DQ + "tokens=2-4 delims=/- " + DQ + " %A in ('date /T') do echo %C.%A.%B>" + DQ + WF + DQ
Reading Our Data File
Now that we’ve dumped the data file to disk, we can read it back in from the COD script using the following code…
DIM myDate Object myFile as File (WF, forinput+istext) myDate = myFile.Readline() myFile.Close()
This code opens the file and reads its data and saves it to a variable. You’ll also note that this code doesn’t add extra double quotes around the WF “Working File” variable. That’s because they aren’t needed here, and will in fact cause problems. The COD Script language is actually better at handling files with and without spaces because it uses a comma (,) as it’s data separator between the file name and file read modes.
Displaying Our Data
Last, we can display the data in a simple debug dialog. Here, you’ll see I make use of the ST variable to place a single tab between the data purely for formatting purposes.
Debug "Date:" + ST + myDate
The Bigger Picture
The following code takes all the above principals and goes a little further. With everything you’ve learned, you should be able to figure out what it’s doing and how. It’s doing all the same things plus a little extra…
- Also writing TIME and the USERNAME of the currently logged in Windows User to the data file.
- It’s “Appending” the TIME and USERNAME using “>>” instead of “>” that DATE uses.
- It’s reading 3 lines of our data file
- The data file is deleted after it’s read leaving our system clean of temporary files.
- The data is displayed by also using the CR (Carriage Return) variable to start new lines for the additional pieces of data.
REM ------------------------------ REM DQ = Double Quote Character REM CR = Carriage Return Character REM ST = Single Tab Character REM WF = Working File REM ------------------------------ DIM DQ = ascii(34) DIM CR = ascii(10) DIM ST = ascii(9) DIM WF = "C:\Temp\COD Data.Txt" REM --------------------- REM Get Date (yyyy.mm.dd) REM Get Time (hh:mm) REM Get User (login name) REM --------------------- Exec("cmd.exe", exec_wait + exec_show_min, "/C for /F " + DQ + "tokens=2-4 delims=/- " + DQ + " %A in ('date /T') do echo %C.%A.%B>" + DQ + WF + DQ) Exec("cmd.exe", exec_wait + exec_show_min, "/C for /F " + DQ + "tokens=1-2 delims=: " + DQ + " %A in ('time /T') do echo %A:%B>>" + DQ + WF + DQ) Exec("cmd.exe", exec_wait + exec_show_min, "/C echo %username%>>" + DQ + WF + DQ) REM --------- REM Read Data REM --------- DIM myDate DIM myTime DIM myUser Object myFile as File (WF, forinput+istext) myDate = myFile.Readline() myTime = myFile.Readline() myUser = myFile.Readline() myFile.Close() REM ---------------- REM Delete Data File REM ---------------- Exec("cmd.exe", exec_default + exec_show_min, "/C DEL " + DQ + WF + DQ) REM ------------ REM Display Data REM ------------ Debug "Date:" + ST + myDate + CR + "Time:" + ST + mytime + CR + "User:" + ST + myUser
Whole program can be downloaded here…