Writing to File Whose Path Changes

Writing to File Whose Path Changes

I maintain an in-house (mostly) Fortran application that runs on VMS, Windows, and IRIX. At the end of a run the application opens a file and writes information about the date and time it was run, who ran it, and so on. Most of the source code is the same for all three versions; the OS-dependent parts have been pretty well isolated.

The VMS version uses a logical name for the file in the code. I can change the definition of the logical if necessary without having to modify the code.

The Windows version has the file name and path hard coded. A company mandate about security forced the location of the file to change, and now there is an error every time the application tries to open the file. The application still runs, but we're losing our usage information.

Can I replace the hard-coded file name and path in the Windows version with a system environment variable to give that version the same capability to point to a different file like the VMS version does? If not, then is there something else I can do to accomplish this?


15 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

I can suggets two approaches.

1. Don't use a FILE= keyword and define the environment variable FORTn, where n is the unit number, to point to the file.

2. Precede the OPEN with a call to GETENV that retrieves the value of your defined environment variable and use the result in the OPEN call.


Retired 12/31/2016

Certainly, you should be able to use a getenv call to read an environment variable. See the library documentation.

Thanks for those suggestions, guys.

I thought about this a little more and realized that I hadn't considered something. A system logical name on a VMS system will apply to all users of that system unless a user overrides it by defining his own process or job logical with the same name. A Windows environment variable, no matter whether it's a user or system variable, will apply to only the user of one computer.

This next released version of this application will be running on Windows XP computers, and I can create an installation program for it that sets the environment variable to the correct value. If the location of the file changes, though, I don't think that I can change the value of the variable myself. I'll have to do something like send out a message to the users with instructions on how to make the change or distribute a program that they would run to make the change for them. Are there any other alternatives?


One method occurs to me.
I assume all your users will use the same batch file to start your application.
Create a batch file which starts your application and include the latest file+path as an argument on the command line. Put the batch file in the 'system' folder, or some folder that is in everyone's path.
Rewrite your application to use GETARG to get the filename from the command line. Use the filename in your OPEN statement.
Edit the batch file whenever you need to change the file location.
Alternatively, write a small application to do this for you, giving the new file+path to it as an argument. This small aplication could write the batch file for you and copy it to the system folder.
Then all you need do is rerun this small application each time the file location is changed.

Mike, I didn't follow the rest of the thread carefully, but you (the setup program) could place the file in a folder which is supposed to be read/writeable for all users. See ShGetSpecialFolderLocation API -- CSIDL_APPDATA looks like the best candidate. (Usually, on Win2000 that should be C:Documents and SettingsAll UsersApplication Data, but I didn't test it, and the docs are a bit vague.) In this way, there's no need to cope with environment variables.


After reading the most recent replies it seems that I wasn't specific enough in my original posts. The file that all the application users need to access isn't located on their individual computers; it's a single common file located on a network share with permissions that allow anyone to write to it.

Another piece of information is that the application uses a console interface. Users type commands into the console window and press the Enter key after each one to have it executed.

In response to Anthony's post, the application isn't started with a batch file. Users start the application by typing the name of the executable file.

The documentation on the SHGetSpecialFolderLocation routine Jugoslav mentioned states that it has been superseded by SHGetFolderLocation as of Windows 2000. My users will be running this application on Windows XP. All the CSIDL values for the nFolder parameter appear to refer to local files on a single computer, not files on a network share.


It is easy to write a batch file APPLICATION.BAT that runs APPLICATION.EXE
with a command line argument giving the location of the file in question. eg

@echo off
rem function: to start  APPLICATION.EXE with DATAFILENAME as argument
rem fullpathap stands for the full path to the application executable
rem fullpathdat stands for the full path to the data file
fullpathapAPPLICATION.exe fullpathdatDATAFILENAME

IIRC, typing APPLICATION without extension on a command line will
run the BAT file with the name APPLICATION before trying APPLICATION.EXE.
Your users therefore only need have the .BAT file in
their path so that it is found when they type APPLICATION
then hit . You can keep the executable in another
place of your choice, along with your file. Just supply
the full [network] path with the application and the
data file name on the command line in the batch file
you distribute to all your users.
The above .BAT file contains only one important command,
to run the application.
This can just as easily be programmed as another
executable that issues the system command using the
command SYSTEMQQ to send a command string to the command

Thank you to everyone for all your suggestions on what has turned out to be much more of an OS question than a Fortran one.

I still see a problem that I'll have to work out. A VMS system allows a change to a logical name that will affect multiple users sharing the same computer without the need to modify the Fortran code. Windows computers are fundamentally different because the vast majority of them are single-user systems. I can use the suggestions given above to isolate the name of a file from the Fortran code, but I don't see an easy way to push down a changed file name to all the individual computers if that becomes necessary. I can send messages to the users with instructions on how to manually do it, or I can send them an application that they could run to make the changes, but I can't do it independently from a central location. I guess I'll have to live with that.


The closest equivalent to a VMS system logical name for Windows would be an entry in the registry, which is easy to change and straightforward to access from Fortran.

But typically for Windows users, you're dealing with multiple separate PCs connected to a network. In such cases, a network shared folder could be the best solution - if you need to change the location, you just redefine the share. The downside of this is that the server name has to remain fixed and you can point to a folder, not an individual file.


Retired 12/31/2016


First, VMS logical names when it comes to filenames are more like environment variables than registry settings. In fact a while back I proposed to Steve that the Fortran RTL would be well served to automatically expand environment strings as the command interpreter does, however I don't know if that would ever become reality.

Next, it is important to know if you are targeting just the NT family or also 9X. Depending on how your network is arranged, it is actually quite simple to do the equivalent of a system-wide environment setting. How you actually do this depends NT vs 9X family and the security scheme (domain, workgroup) you are using.


It's pretty easy to call the Win32 API routine ExpandEnvironmentStrings yourself. I'll let you in on a little secret - I did manage to sneak in to the compiler a call to ExpandEnvironmentStrings for INCLUDE filespecs - look for this in Intel Visual Fortran.

Note also that the CVF RTL will already expand environment variables of the form FORTn, where n is the unit number, if you omit FILE=.


Retired 12/31/2016

Yes it is easy to call the Win32 routine, however if you have a lot of different OPENs in your code then either you end up with a bunch of

if OS is WIN32
call ExpandEnvironmentStrings (...)
expanded_filename = unexpanded_name
end if

OPEN (file=expanded_name, ...)


OPEN (file=TRIM(EXPAND_ROUTINE(unexpanded_name)), ...)

It would just be so pretty if we could have just a regular OPEN without the extras.

As for the INCLUDE filespect that is progress, thanks.

FORTn as a system environment variable seems a reasonable solution to the present case.


I think I have all the raw input I need to craft a good solution. It's time for me to digest it and experiment with some of these suggestions.

I never fail to be impressed with the willingness to help and the quality of the suggestions that one can find in this forum. I am so glad that the world is filled with a lot of smart people who take the time to share their knowledge with others. Thanks a bunch.



I don't know if this is what you are looking for, but I always read in from what I call a "control file" the names of all input/output filenames into character variables. I then use these variables in the OPEN statements. This allows great flexibility in the specification of I/O filenames as well as compatability across all operating systems. You can also put in the option of interactively entering I/O filenames. Hope this helps.


Leave a Comment

Please sign in to add a comment. Not a member? Join today