Anyone taking plug-in development seriously has to think about plugin versioning. The 3ds Max C++ SDK documentation offers a lot of information on this topic, along with a couple of implementation techniques and some P_VERSION related best practices.
For 3ds Max version querying, the 3ds Max C++ SDK offers (within plugapi.h) some useful macros like:
that can be used to tailor your plugin to different 3ds Max environments and other uses.
However all these tools are updated/adjusted with each major 3ds Max release when the 3ds Max SDK is updated, and not with the service packs, extensions, or updates.
This might look irrelevant for a plugin developer, as the C++ SDK is usually binary compatible for a complete full version and sometimes even across main versions (as was the case of 3ds Max 2015 and 2016). Nevertheless, sometimes there is a need to have more details, be it for logging/diagnostic purposes, or to deal with situations when some of your plugin users are not using the latest SP (and are spread between different SP). For these and other cases it would be nice to have a way of getting some info on client's 3ds Max specific version number or build version number and then if necessary, adjust the behavior of your plugin accordingly.
By inspecting the executable of 3ds Max (3dsmax.exe) we can see that the needed information is included in the file version:
where on the above screenshot:19 is the release number corresponding to 3ds Max 2017, 2 is SP number and 420 is the build number.
To extract this information we could rely on GetFileVersionInfo API (from C++ Windows API) and you can even find some sample code on how to use it (thanks to Kevin Vandecar for pointing this out).
But in MAXScript, there is a simler way. It turns out that among many MAXScript external file methods there is getFileVersion <filename_string> function:
GetFileVersion (getDir #maxRoot + "\\3dsmax.exe")
--> "19,2,420,0 19,2,420,0"
that gives us the very information needed.
The fact that it is just a MAXScript function, should not hold us back, as we can easily call MAXScript from C++:
BOOL ExecuteMAXScriptScript(MCHAR *s, BOOL quietErrors = FALSE, FPValue *fpv = NULL);
and use the extracted information, that in this case will be contained in a FPValue:
// WARNING: for illustration only: assumes SP version is 1 digit, 3rd index
return static_cast<int>(resulted_value.s - '0');
The MAXScript getFileVersion function is in fact using the Windows GetFileVersionInfo API, and this is a very good illustration of how MAXScript is easily inter-operable with the 3ds Max C++ SDK. Either technique frmo the C++ SDK should yeild the same results.
Note that due to the recent transition to a subscription-based model, it seems there will be no future Service Packs or Extensions. Instead they will be called Updates. But, using the above described approach, you will still get the desired details. In this most recent example of the 3ds Max 2017 Update, instead of getting a SP version, it will give you the Update version, that can be used for the same purpose.