Is there any "standard method" of ensuring program files on workstations are kept up to date with the current server version?

I am guessing a user login could compare version numbers of exe and dll files with a register on the server, a process I imagine could get very messy. I am sure there must be other proven methods I have not thought of.
I would welcome any suggestions.

A perfect Ai LLM question.

Api’s used.

GetFileVersionInfoA
GetFileVersionInfoSizeA
VerQueryValueA

Prompt:

Give me some Clarion code that NEW's a string for the window's API GetFileVersionInfoA and then extracts the values using the windows api VerQueryValueA before disposing of the NEW'ed string.

Output

 MAP
   MODULE('VERSION.DLL')
      GetFileVersionInfoSizeA(*CSTRING FileName,*LONG Handle),ULONG,PASCAL,RAW,NAME('GetFileVersionInfoSizeA')
      GetFileVersionInfoA(*CSTRING FileName,ULONG Handle,ULONG Len,LONG Buffer),BOOL,PASCAL,RAW,NAME('GetFileVersionInfoA')
      VerQueryValueA(LONG Block,*CSTRING SubBlock,*LONG Buffer,*ULONG Len),BOOL,PASCAL,RAW,NAME('VerQueryValueA')
   END
 END

FileName        CSTRING(260)
Dummy           LONG
Size            ULONG
VersionBuffer   &CSTRING
ValuePtr        LONG
ValueLen        ULONG
Translation     &GROUP,TYPE
wLanguage       USHORT
wCodePage       USHORT
                END
QueryString     CSTRING(80)
CompanyName     CSTRING(256)

CODE

FileName = 'C:\Windows\System32\kernel32.dll'

Size = GetFileVersionInfoSizeA(FileName,Dummy)

IF Size
    VersionBuffer &= NEW CSTRING(Size)

    IF GetFileVersionInfoA(FileName,0,Size,ADDRESS(VersionBuffer))

        !------------------------------------------
        ! Obtain language/codepage translation
        !------------------------------------------

        IF VerQueryValueA(ADDRESS(VersionBuffer), |
                          '\VarFileInfo\Translation', |
                          ValuePtr, |
                          ValueLen)

            Translation &= (ValuePtr)

            QueryString = '\StringFileInfo\' & |
                          FORMAT(Translation.wLanguage,@n04) & |
                          FORMAT(Translation.wCodePage,@n04) & |
                          '\CompanyName'

            IF VerQueryValueA(ADDRESS(VersionBuffer), |
                              QueryString, |
                              ValuePtr, |
                              ValueLen)

                CompanyName = (CSTRING(ValuePtr))
                MESSAGE('Company = ' & CompanyName)

            END

        END

    END

    DISPOSE(VersionBuffer)
END

Edit.

The other thing I would add, is have a look at the VersionRes.tpl template.

#TEMPLATE( cwVersionRes, 'Version Resource' ), FAMILY('ABC'),FAMILY('CW20'),FAMILY('IPServer')

That template add’s version numbers, company name, copyright to the Version Info part of the Resource section of an exe or dll. This will give you an idea of how the data block store’s all the entries into a variable sized String, because ultimately everything, beit an icon file, jpg, or Version info data block is typically just a variable length string or cstring.

First, I’ve always had an app have a version number.
If only one DLL changes, the app version number still changes.

Then it’s easy to do a version check against a server-based configuration file on startup.

If you detect a version mismatch, you can either stop with a message to the user saying that the client needs to be updated, or else use SetupBuilder or some other installation tool to do the update. (Depending on the size of the network, the user may not have permissions that are required to update an app.)

On @Jane’s point if a windows network is using group policy, supported in Windows Pro and above, not Home, then this explains how software can be blocked from running, which can prevent apps from automatically updating itself. It might not even be able to use the network & internet to detect a new version if the firewall locks down network traffic on a per app basis.

One other point. Some times, the need to run two different versions at the same time can exist for final testing & shakedown implementation purposes.

With database apps, adding new fields to the end of the record in SQL server databases, can help with this situation.

eg
Version 1.00.01 SQL Server Record layout

[FileID][FirstName][Surname]

Version 1.01.00 SQL Server Record layout

[FileID][FirstName][Surname][Title][PhoneNumber]

So the database gets updated to version 1.01.00 record layout from the earlier version, but because the [Title][PhoneNumber] is added onto the end of the record layout, the version 1.00.01 software doesnt care about the [Title][PhoneNumber], it cant see it.

So thats how two different versions can coexist at the same time.

If you own SetupBuilder and CapeSoft’s SafeUpdate, you can use them to keep the program files in sync.