Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations derfloh on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Easy Way to Update EXE to all Workstations

dylim

Programmer
Joined
Dec 12, 2001
Messages
195
Location
PH
Hi Guys,

I know this has been discussed. I would just like to get your various methodologies in doing EXE updates across multiple workstations using the app so I can decide on which to adopt.

Thanks in advance.
 
Dear

what I am using

in my main exe file, i wrote code, which i update exe file version to table
then in same main exe file, i find out what is the version of the exe is (running systems)
and compare with running exe version with table version
if not matched , that means server have updated exe
so down load exe file from server

example

Steps
Create table in server or center system ( am using mysql)

main table
fields are (fversion,filestr)

manually update my main exe file and version whenever i compile

now with in main exe file
run the code

First Find what what is the version in main table
and get the version of running exe file

if that not match, then show the message to user
ie get new version file from server
and write the BAT file,
call the loader file from BAT File

if you needed actual code

please reply ,
Thanks and good day
 
I think, happy to be corrected, most people run a 'stub' program on the workstation that compares the full executable
with one in a different location (that no one else runs directly from that location). If it is newer the full executable is downloaded
locally and run, otherwise it is just run locally by the stub program.

In my systems, I have the main program check for the new version, if it's found it runs the stub and quits, the stub downloads
the update to a local temporary location and then copies it over the original .exe and starts that - then the stub quits.
 
I think, happy to be corrected, most people run a 'stub' program on the workstation that compares the full executable
with one in a different location (that no one else runs directly from that location). If it is newer the full executable is downloaded
locally and run, otherwise it is just run locally by the stub program.

In my systems, I have the main program check for the new version, if it's found it runs the stub and quits, the stub downloads
the update to a local temporary location and then copies it over the original .exe and starts that - then the stub quits.

How is the very act of downloading done? Just a simple COPY FILE command? Thanks
 
I have a copy_file function:

Code:
FUNCTION COPY_FILE
    PARAMETERS m.FROMFILE,m.TOFILE
    PRIVATE m.FROMFILE,m.TOFILE
    PRIVATE m.TOPATH
    M.TOPATH = MYPATHABOVE(m.TOFILE)
    IF !DIRECTORY(m.TOPATH)
        MD (m.TOPATH)
    ENDIF
    COPY FILE (m.FROMFILE) TO (m.TOFILE)
    RETURN(MYFILE(m.TOFILE))

The MYFILE() in there is just my own File() to avoid false positives.
MyPathAbove() just returns the folder above the target, there is a vfp function for that too.

This is good for local networks, where you can do a copy.
If I want to check online, I use a westwind module to download the executable after checking a 'signature file'
which has the time and date of the executable.
 
I would suggest an endpoint manager system.

For example : desktop central from Manage engine. (not a sponsor)

You install an agent and you can do ANYTHING on that endpoint.

Including the updating said executable ( via some push on script)

Its free but you cna pay for it.

Let me know what you come up with.

Thanks
 
I have a copy_file function:

Code:
FUNCTION COPY_FILE
    PARAMETERS m.FROMFILE,m.TOFILE
    PRIVATE m.FROMFILE,m.TOFILE
    PRIVATE m.TOPATH
    M.TOPATH = MYPATHABOVE(m.TOFILE)
    IF !DIRECTORY(m.TOPATH)
        MD (m.TOPATH)
    ENDIF
    COPY FILE (m.FROMFILE) TO (m.TOFILE)
    RETURN(MYFILE(m.TOFILE))

The MYFILE() in there is just my own File() to avoid false positives.
MyPathAbove() just returns the folder above the target, there is a vfp function for that too.

This is good for local networks, where you can do a copy.
If I want to check online, I use a westwind module to download the executable after checking a 'signature file'
which has the time and date of the executable.

The "main computer" where the workstation checks against must have a shared folder where the EXE is, right?
 
I would suggest an endpoint manager system.

For example : desktop central from Manage engine. (not a sponsor)

You install an agent and you can do ANYTHING on that endpoint.

Including the updating said executable ( via some push on script)

Its free but you cna pay for it.

Let me know what you come up with.

Thanks

Wow. It's up there in the food chain alright. That's kinda like having a Lamborghini to deliver newspapers in a neighborhood. Thanks for pointing this to me. This is perfect for a company with a sizable IT inventory.

I simply needed a simple way to update EXEs across multiple workstations.
 
One method I particularly like for the scenario where the exe is on a network share and the users run the application over the network is to use a simple launcher methodology:

1. Make the main exe that the user executes from their shortcut (or whatever) a miniscule launcher, the job of the launcher is to determine a local folder on the user's workstation to copy any necessary files (apps, other exes, flls, dlls) from the network location to the local folder, perform the copy and proceed to launch the rest of the application
2. Each time the launcher is executed it will compare the versions of various files on the network against the version in the local folder and copies to local, any files that are missing locally or they are newer on the network are copied. Yep, just doing a COPY FILE for each file.
3. As an example, the local folder on the workstation would be something like: c:\Users\<username>\AppData\Local\<CompanyName>\, the base of that path taken by asking the OS for the path to that AppData\Local special folder path.
4. When the compare/copy job is complete, the launcher then runs the main app (or Exe) specifically by running the local copy, not the networked instance. When run in this mode the local app (or exe) still knows how to access the data on the network, whether that is DBFs on a share or from whatever database server, if applicable.
5. This means that the launcher exe will always ensure that the user has the latest version of everything it needs in the local folder on their workstation and then launches the main application. Users can be sure that they are on the latest version of the application simply by restarting the application because doing so will cause the launcher to do it's job again.

There are some nice advantages of doing this, in this scenario:

a) The network folder becomes a repository for the latest application files rather than somewhere that users are running the application from. In fact, the only exe or anything that anyone actually executes from that folder is the tiny launcher exe.
b) This also means users are putting less load on the network because no matter what size the main application is, a tiny launcher will almost certainly be significantly smaller than any main exe. That might not be a big issue in places where they have small numbers of users or an good/fast network but it's still an advantage, especially if someone is running on a slower network or has a very large number of users.
c) Since the network folder is now only a repository, no user should have your main app (or exe) locked because no user is actually running it from that location, this means you can easily update that main file through whatever means you want or install new versions alongside, it depends on how you want to manage your new versions.

You could then code your main application to know how to download new versions of the application from your website, SFTP, FTP (whatever applies) and download it specifically to the network folder (repo). This means the application can be used to very easily keep itself up to date. When a new version has been downloaded and put in place in the network repo, restarting the application is all that is required for any user to "be on" that new version because the launcher will replay it's logic, copy the new version to the local folder and run the application on the new version.

If your application can keep itself up to date, either automatically or through user intervention, then the only thing you need to factor in is if you have to do database migrations (DB schema updates) and how you do that is very much dependent on what your database is. Anything on a database server (like SQL Server, MySQL and many others) is usually much easier to perform the schema updates than if you are using shared DBFs.

I followed this on a pattern on a 25+ year old application which used a DBF database and it meant updating the application became significantly easier. By doing so I reduced our main exe from being in the 13 to 15 MB file size, to around 100KB and to be honest, the lion's share of that file size was due to the exe icon, the actual code size was laughably small. Obviously that other 13MB got moved to the app (in our case) but that was no longer being "run over the network", it would be copied to each workstation, only once plus on any future updates. After doing that, I just had the headache of the database schema issue. The DBF problem meant that I could never assume that the database wasn't in use by at least one user so I couldn't have the application try to do a DB migration itself, I resigned myself to running DB updates semi-automatically, for peace of mind really. If that application had used a DB server, I would have done auto DB updates but I didn't dare with DBFs, there was too much at stake.

I made my application version number schema know the difference between major version updates and minor version updates. Major updates are those that required a change to the DB schema, minor updates required no schema updates. So I coded my application to be able to do minor updates automatically but major updates had to be more formal. For example, if the user was on version 24.138.4 and version 24.138.32 was available (only the last element had changed) the user can do that themselves, without support from us as the difference between .4 and .32 within the same 24.138.x edition meant no DB schema changes required. Even if 24.139.x versions would be available, the application could request to be updated as high as it can go within the same edition. That kept things simpler for me.

If I then updated that user to, say 24.139.3 and a few weeks or months later 24.139.4 was available, the users could trigger that update themselves. I think the pattern is clear enough. The second element in that version number (the 138, 139 etc) that was the number of my migrations (DB schema update routines) so that made it easy for me to keep track, as well as recording it in the database, which migrations the installation had gone through.

I even coded the launcher to check for new versions of itself, as well as the main application, just in case I needed to update the launcher and didn't want to have to kick users out. The user's shortcuts would always look for the same filename, auction.exe but I could drop a new launcher version, specifically named so the first thing that the launcher did was check for anything matching the specific skeleton and, if found, check which is the latest version so if it found one that was newer, it would "Shell Execute" the newer version and let itself come to a close, the newer version would then take over and do what it needed to do with the application aspect.

I've maybe gone much deeper in my response than just describing the launcher methodology that we settled on but the above gives a lot of detail on how we managed to greatly simplify version updates, given that we still had one major awkwardness by still using DBFs on a file share. In the end we arrived at a place where I could build new versions, manage the version numbers correctly, push the new zip files online and our application would keep the users correct. They could update themselves within their own "edition" or "parent version" and bigger updates required us to help with a more formal update process but that still drastically reduced the amount of time I spent updating users versions. Having the network folder act as a repository rather than the main launch folder (other than for the launcher itself) meant we never had to update individual users within any given company, we'd just put the new version in the central folder and the launcher and application would take care of everything else. If we'd gone through the pain of replacing the database with something that didn't use DBFs then I'm confident that we could have moved to a 100% fully automated way of updating users, it was only the DBFs that were holding us back.
 
Wow. It's up there in the food chain alright. That's kinda like having a Lamborghini to deliver newspapers in a neighborhood. Thanks for pointing this to me. This is perfect for a company with a sizable IT inventory.

I simply needed a simple way to update EXEs across multiple workstations.
Unless. If the pcs are in the same network.

And execute said exe from a shortcut from a network location.

You change at a single position, it changes everything, everywhere.

Think about it
 
Unless. If the pcs are in the same network.

And execute said exe from a shortcut from a network location.

You change at a single position, it changes everything, everywhere.

Think about it

Won't running an EXE from a network drive have problems like latency? Do you practice this sir?
 
One method I particularly like for the scenario where the exe is on a network share and the users run the application over the network is to use a simple launcher methodology:

1. Make the main exe that the user executes from their shortcut (or whatever) a miniscule launcher, the job of the launcher is to determine a local folder on the user's workstation to copy any necessary files (apps, other exes, flls, dlls) from the network location to the local folder, perform the copy and proceed to launch the rest of the application
2. Each time the launcher is executed it will compare the versions of various files on the network against the version in the local folder and copies to local, any files that are missing locally or they are newer on the network are copied. Yep, just doing a COPY FILE for each file.
3. As an example, the local folder on the workstation would be something like: c:\Users\<username>\AppData\Local\<CompanyName>\, the base of that path taken by asking the OS for the path to that AppData\Local special folder path.
4. When the compare/copy job is complete, the launcher then runs the main app (or Exe) specifically by running the local copy, not the networked instance. When run in this mode the local app (or exe) still knows how to access the data on the network, whether that is DBFs on a share or from whatever database server, if applicable.
5. This means that the launcher exe will always ensure that the user has the latest version of everything it needs in the local folder on their workstation and then launches the main application. Users can be sure that they are on the latest version of the application simply by restarting the application because doing so will cause the launcher to do it's job again.

There are some nice advantages of doing this, in this scenario:

a) The network folder becomes a repository for the latest application files rather than somewhere that users are running the application from. In fact, the only exe or anything that anyone actually executes from that folder is the tiny launcher exe.
b) This also means users are putting less load on the network because no matter what size the main application is, a tiny launcher will almost certainly be significantly smaller than any main exe. That might not be a big issue in places where they have small numbers of users or an good/fast network but it's still an advantage, especially if someone is running on a slower network or has a very large number of users.
c) Since the network folder is now only a repository, no user should have your main app (or exe) locked because no user is actually running it from that location, this means you can easily update that main file through whatever means you want or install new versions alongside, it depends on how you want to manage your new versions.

You could then code your main application to know how to download new versions of the application from your website, SFTP, FTP (whatever applies) and download it specifically to the network folder (repo). This means the application can be used to very easily keep itself up to date. When a new version has been downloaded and put in place in the network repo, restarting the application is all that is required for any user to "be on" that new version because the launcher will replay it's logic, copy the new version to the local folder and run the application on the new version.

If your application can keep itself up to date, either automatically or through user intervention, then the only thing you need to factor in is if you have to do database migrations (DB schema updates) and how you do that is very much dependent on what your database is. Anything on a database server (like SQL Server, MySQL and many others) is usually much easier to perform the schema updates than if you are using shared DBFs.

I followed this on a pattern on a 25+ year old application which used a DBF database and it meant updating the application became significantly easier. By doing so I reduced our main exe from being in the 13 to 15 MB file size, to around 100KB and to be honest, the lion's share of that file size was due to the exe icon, the actual code size was laughably small. Obviously that other 13MB got moved to the app (in our case) but that was no longer being "run over the network", it would be copied to each workstation, only once plus on any future updates. After doing that, I just had the headache of the database schema issue. The DBF problem meant that I could never assume that the database wasn't in use by at least one user so I couldn't have the application try to do a DB migration itself, I resigned myself to running DB updates semi-automatically, for peace of mind really. If that application had used a DB server, I would have done auto DB updates but I didn't dare with DBFs, there was too much at stake.

I made my application version number schema know the difference between major version updates and minor version updates. Major updates are those that required a change to the DB schema, minor updates required no schema updates. So I coded my application to be able to do minor updates automatically but major updates had to be more formal. For example, if the user was on version 24.138.4 and version 24.138.32 was available (only the last element had changed) the user can do that themselves, without support from us as the difference between .4 and .32 within the same 24.138.x edition meant no DB schema changes required. Even if 24.139.x versions would be available, the application could request to be updated as high as it can go within the same edition. That kept things simpler for me.

If I then updated that user to, say 24.139.3 and a few weeks or months later 24.139.4 was available, the users could trigger that update themselves. I think the pattern is clear enough. The second element in that version number (the 138, 139 etc) that was the number of my migrations (DB schema update routines) so that made it easy for me to keep track, as well as recording it in the database, which migrations the installation had gone through.

I even coded the launcher to check for new versions of itself, as well as the main application, just in case I needed to update the launcher and didn't want to have to kick users out. The user's shortcuts would always look for the same filename, auction.exe but I could drop a new launcher version, specifically named so the first thing that the launcher did was check for anything matching the specific skeleton and, if found, check which is the latest version so if it found one that was newer, it would "Shell Execute" the newer version and let itself come to a close, the newer version would then take over and do what it needed to do with the application aspect.

I've maybe gone much deeper in my response than just describing the launcher methodology that we settled on but the above gives a lot of detail on how we managed to greatly simplify version updates, given that we still had one major awkwardness by still using DBFs on a file share. In the end we arrived at a place where I could build new versions, manage the version numbers correctly, push the new zip files online and our application would keep the users correct. They could update themselves within their own "edition" or "parent version" and bigger updates required us to help with a more formal update process but that still drastically reduced the amount of time I spent updating users versions. Having the network folder act as a repository rather than the main launch folder (other than for the launcher itself) meant we never had to update individual users within any given company, we'd just put the new version in the central folder and the launcher and application would take care of everything else. If we'd gone through the pain of replacing the database with something that didn't use DBFs then I'm confident that we could have moved to a 100% fully automated way of updating users, it was only the DBFs that were holding us back.

Thank you for taking the time and effort for this rather lengthy reply. I appreciate it.

By "network share", you mean a shared folder on the server and the workstations must map this shared folder to a certain drive letter, right?

I also agree with you that copying the EXE into a local folder and running it way better than running the EXE on a network share. This is so much back and forth eh?
 
Now a days Network speeds are MUCH MUCH faster than FoxPro. SO I assume No you won't have any issues that you didn't already had. ( like opening a BIG table remotely )

BUT every setup is different , best way to make sure is to test it :D
let us know
 
I have the user call the program with a bat fille. When I have an update I increment a number at the end of the exe name. MayProgram1.exe, MyProgram2.exe.
Then I just change the bat file to call the new exe.
 
A little thing about letting 10 users run an executable from the network at the same time... you have to get all 10 to exit the application
in order to update it. Try that a 2pm on a Friday before a public holiday...
 
Hi Guys,

I know this has been discussed. I would just like to get your various methodologies in doing EXE updates across multiple workstations using the app so I can decide on which to adopt.

Thanks in advance.
You should not revive an old thread, even for illustrating you already found one old thread on this, you can link to that in a new thread. Reviving old threads most of the time leads to less participation.

The most often given answer is not even here in this thread, it's using a bat/cmd file with an xcopy or robocopy nowadays (with its mirror option) to copy a centralised application directory(and only files newer than local) that's used for the developer to provide the newest version to copy that to a local directory from where you then start.

This method even has a wikipedia subtopic under XCOPY: https://en.wikipedia.org/wiki/XCOPY#Deployment

There's one or two major problems to address with this:
a) You can't just copy over ActiveX controls from a central share to a local directory and use them.
b) Users pinning an EXE and using that to restart directly circumvent updates through the batch file.

To a)
You can circumvent that with a one time registration of such things that need registration or using the registry free COM feature, which exists since Windows XP as a mode of letting an EXE point out where to find COM Servers or ActiveX controls in an embedded or a separate EXE manifest xml file. You find more about that googling regfree COM.

To b)
To deal with a pinned EXE you can make the EXE create and start the batch file and end with a start using a genuine parameter which changes every start like in a one time password scheme, so you don't get into an endless loop of only starting the batch file, of course. The EXE then first checks, whether a start parameter is a valid one time code and start.

All that's only a valid way of installing within a company. For home end users notice that a setup project you can make for a normal setup of your application allows you to upgrade the project later to not only create setups for first installation but also for upgrade installations. And you can therefore update such setups and provide them. The downsside for company/corporate situations is, that users are not administrators, usually. But for that matter you also have centralized software deployment. Google centralized software deployment and/or ask your customers IT depeartment whether and what they use for that matter. In the usual case such tools work with a setup.exe or MSI package you provide to them. Or the more modern MSIX, or deployment via the ClickOnce feature.

All in all you find most of these things if you google software deployment, especially desktop application deployment, as of course web applications mainly need no deployment, you manage and upgrade the backend software server side and clients have no local installation in that case. Which also applies to applications hosted in some cloud like Microsoft Azure or Googles Cloud Platform. But those are infrastructures you should not just use for deployment but for integration with cloud services and so that only applies to such cloud applications, not to any on premise desktop application. And all regarding Azure mainly applies to .NET applications. But there's a Code Magazine article about Clilck Once deployment that's also still valid: https://www.codemag.com/article/0703072/Welcome-to-the-Future-of-Deployment
 
Well, you very indirectly address a problem I skipped over. Users still executing an old version. Often enough they become a reason you can't update the database with changes necessary for the new version. And that's how I usually detect those and trigger the shutdown of their clients. There are multiple ways to do that, some of which can be integrated into your application itself, too, i.e. you can program something that shuts down all clients when a flag is set on some share, in data, in the form of a setting or anything like that - as long as it's centrally and seen by any running exe - under your control.
 
Last edited:
But unfortunately, You can't get FoxPro from a Running condition ( or someone suck waiting for user input ) to execute something else :D

As far as I know :D OR you can swap over from several check-in procedures. Time wise :D But it will be slow on execution / wasted resources :D ( keep checking the flag IF it happened to change to shutdown the software )

At least this is my idea :D if someone else has an other idea let us know.
 
A Timer can do this. At least as far as I remember I never had a problem. Not with a modal form, not with a report preview (which actually is about the same modal state). So a timer running often enough so you don't need to wait long for clients to be shut down and rare enough it doesn't slow down everything.
 

Part and Inventory Search

Sponsor

Back
Top