Check install drive format - visual-studio-2017

I want to make sure that the drive I'm currently installing to is a certain format (e.g. NTFS, exFAT, FAT32, etc.). I was thinking there might be a condition I can check or something before installing.
Since I can't check the install format with conditions, is there some other approach I can take in order to get this?

There isn't a standard property that denotes this, in the list here:
https://learn.microsoft.com/en-us/windows/desktop/msi/property-reference
The difficulty is that there might be a variety of drive formats on the system and the check can't be made until the user browses for an install location which might be one type or another. Visual Studio setups don't support running code when that install location has been chosen.
Is there an underlying problem (perhaps with the app) that this is attempting to solve?

Related

Where to store resources for C++ program on linux

This question says the best place to store settings in linux is in ~/.config/appname
The program I'm writing needs to use a 99MB .dat file for recognizing facial landmarks, embedding it in the binary doesn't seem like a good idea.
Is there some default place to store resources on linux? currently it's just in the directory next to the executable, but this requires that the program is run with the current directory being the directory it's located in.
What's the best way to deal with resources like this on linux? (that could potentially be cross platform with at least OSX)
You should take a look at the Filesystem Hierarchy Standards. Depending on the data (will it change, is it constant across all installations, etc) the path where it gets placed will change based on the standards.
In general:
/usr/lib/program: includes object files, libraries, and internal binaries for an application
/usr/share/program: for all read-only architecture independent data files
/var/lib/program: holds state information pertaining to an application or the system
Those seem like pretty good places to start, and you can check the documentation to see if your app falls into one of those categories.
If the file is specific to the user running the app, it should be in a subdir of ~/ but AFAIK there's no standard, and the best choice depends much on the file type/usage. If it should be visible to the user via GUI, you could use ~/Desktop or ~/Downloads. If it's temporary, you can use ~/tmp or ~/var/tmp.
If it's not specific, you should place it in a subdir of /var. Again, the exact subdir may depend on its kind and other factors.

Design approaches to read/write different version of same config file

In our project we got an application that uses an external configuration file (say server.xml). Now we need to design a setup tool GUI in C++/QT to read/edit such configuration file and it should be able to handle all the different versions of such file. The user will choose the file version and then proceed with the editing. From one version to another doesn't change too much, maybe there is a new xml tag, a tag with a different name or in a different position.
What's the best design approach to do so? We are planning to go for a standard MVC design pattern but how to deal with all the different configuration versions without rewriting the same GUI code again n again?
Here the sample config file:
<?xml version="1.0" encoding="utf-8"?>
<Server_configuration ver="11">
<core>
<enable-tms>true</enable-tms>
<enable-gui-messages>true</enable-gui-messages>
<waiting-for-config-timeout>10000</waiting-for-config-timeout>
<remoting>
<port>50000</port>
<join-timeout>5000</join-timeout>
<ismultithread>true</ismultithread>
<maxconcurrentrequests>20</maxconcurrentrequests>
</remoting>
</core>
<content>
<ftp>
<ip>192.168.0.227</ip>
<port>21</port>
<userid>******</userid>
<passwd>******</passwd>
</ftp>
<library>
<ip>192.168.0.227</ip>
<port>50023</port>
</library>
<local>
<asset-root>/assetroot</asset-root>
<kdm-expiration-warning>172800000</kdm-expiration-warning>
</local>
<hula-store-daemon>
<ip>127.0.0.1</ip>
<port>5567</port>
</hula-store-daemon>
</content>
</Server_configuration>
This is no means a drop in solution but I here are some things to do/consider. Every situation will differ.
Have an explicit version identifier in your config files. Fingerprinting them is a real (error prone) pain.
Consider having a tool that will update from version to version. It will be easier than reading old versions and trying to apply them.
I may be easier to do every version step individually but this can make the conversions less "lossless". A happy hybrid is to do minor updates from version to version but have "checkpoint" major upgrades that will jump right to the latest (or the latest "checkpoint"). This is kinda like incremental backups with full backup snapshots every once and a while.
Keep the user informed. A sysadmin won't be happy if you are changing his settings. You might want to make the process interactive or put comments into the file of every added/moved/removed setting. I would also recommend keeping removed settings in some section of the file for user reference. (Put a note why they are there as well).
Backup the old file. Your script will crash and it will eat data. Do something like naming the current file ${oldname}.old-${ver}~. Saving the settings in a different section of the file won't always be enough and this will save your users a lot of heartache.
Versioning should always be designed as robust and as simple as possible. It is crucial for you to determine whether each version of your application must be compatible with each version of the setup tool (which is rare), or whether you can, for example, meet your needs if any newer setup tool works with any same or older application, but not vice versa.
One way compatibility
One possibility to design for the latter is to add a version attribute to the XML file but try to keep it at the same fixed value forever by always only changing the structure and semantics of the XML file in backward compatible ways. For example, adding an element is backward compatible as long as the setup tool can interpret its absence the same way both the old setup tool and the application would behave. It does not hurt that the new setup tool always writes an (equivalent) value to the new element, because two-way compatibility with the old application is not required.
Once the day comes when you cannot maintain backward compatibility on input, you just change the value of the version attribute and start special casing it in the setup tool.
If you validate the XML against an XSD, notice that XSD can actually do one frequently useful thing for you: assign default attribute values. This way, your setup tool's source code may not even actually notice that the underlying document was missing a recently added attribute!
Two way compatibility
Strict versioning is needed. A schema definition (XSD, RelayNG,...) should be defined for each version of the XML file and the file should be validated against it both when it is read by the setup tool, written by the setup tool, or read by the application. The schema definition may be identical for several consecutive versions, if the interpretation of the same XML has changed, so when in doubt, always increase the version number.
Do what you can educating everyone that they cannot just edit the latest schema and do away with that. Unreliable versioning is worse than no versioning.

The Best way of storing/retrieving config data in Modern Windows

I've not done much coding for Windows lately, and I find myself sitting at Visual Studio right now, making a small program for Windows 7 in C++. I need some configuration data to be read/written.
In the old days, (being a Borland kind of guy) I'd just use a TIniFile and keep the .ini beside my exe Obviously this is just not the done thing any more. The MS docs tell me that Get/WritePrivateProfileString are for compatibility only, and I doubt that I'd get away with writing to Program Files these days. Gosh I feel old.
I'd like the resulting file to be easily editable - open in notepad sort of thing, and easily findable. This is a small app, I don't want to have to write a setup screen when I can just edit the config file.
So, what is the modern way of doing this?
Often people use XML files for storing preferences, but they are often overkill (and they aren't actually all that readable for humans).
If your needs would be easily satisfied with an INI file, you may want to use Boost.Program_options using the configuration file parser backend, which actually writes INI-like files without going through deprecated (and slow!) APIs, while exposing a nice C++ interface.
The key thing to get right is where to write such configuration file. The right place is usually a subdirectory (named e.g. as your application) of the user's application data directory; please, please, please, don't harcode its path in your executable, I've seen enough broken apps failing to understand that the user profile may not be in c:\Documents and settings\Username.
Instead, you can retrieve the application data path using the SHGetFolderPath function with CSIDL_APPDATA (or SHGetKnownFolderPath with FOLDERID_RoamingAppData if you don't mind to lose the compatibility with pre-Vista Windows versions, or even just expanding the %APPDATA% environment variable).
In this way, each user will be able to store its preferences and you won't get any security-related errors when writing your preferences.
This is my opinion (which I think most of the answers you get will be opinion), but it seems that the standard way of doing things these days is to store config files like these in C:\Users\<Username>. Moreover, it is generally good to not clutter this directory itself, but to use a subdirectory for the purpose of storing your application's data, such as C:\Users\<Username>\AppData\Roaming\<YourApplicationName>. It might be overkill for a single config file, but that will give you the opportunity to have all of your application data in one place, should you add even more.

How can I find the user's home dir in a cross platform manner, using C++?

How can I find the user's home directory in a cross platform manner in C++? i.e. /home/user in Linux, C:\Users\user\ on Windows Vista, C:\Documents And Settings\user\ on Windows XP, and whatever it is that Macs use. (I think it's /User/user)
Basically, what I'm looking for is a C++ way of doing this (example in python)
os.path.expanduser("~")
I don't think it's possible to completely hide the Windows/Unix divide with this one (unless, maybe, Boost has something).
The most portable way would have to be getenv("HOME") on Unix and concatenating the results of getenv("HOMEDRIVE") and getenv("HOMEPATH") on Windows.
This is possible, and the best way to find it is to study the source code of os.path.expanduser("~"), it is really easy to replicate the same functionality in C.
You'll have to add some #ifdef directives to cover different systems.
Here are the rules that will provide you the HOME directory
Windows: env USERPROFILE or if this fails, concatenate HOMEDRIVE+HOMEPATH
Linux, Unix and OS X: env HOME or if this fails, use getpwuid() (example code)
Important remark: many people are assuming that HOME environment variable is always available on Unix but this is not true, one good example would be OS X.
On OS X when you run an application from GUI (not console) this will not have this variable set so you need to use the getpwuid().
The home directory isn't really a cross-platform concept. Your suggestion of the root of the profile directory (%USERPROFILE%) is a fair analogy, but depending what you want to do once you have the directory, you might want one of the Application Data directories, or the user's My Documents. On UNIX, you might create a hidden ".myapp" in the home directory to keep your files in, but that's not right on Windows.
Your best bet is to write specific code for each platform, to get at the directory you want in each case. Depending how correct you want to be, it might be enough to use env vars: HOME on UNIX, USERPROFILE or APPDATA (depending what you need) on Windows.
On UNIX at least (any Windows folks care to comment?), it's usually good practice to use the HOME environment variable if it's set, even if it disagrees with the directory specific in the password file. Then, on the odd occasion when users want all apps to read their data from a different directory, it will still work.

Algorithm to determine vista/windows 7 OS edition from product key

We have to automatically create the XML file for an unattended vista/windows 7 installation in which we do write the product key (MAK type). Unfortunately the windows image contains multiple editions (home, home premium, professional, ultimate) so we need to decide which version we should use and write that info to the XML as well. And we would love beeing able to decide dynamically which edition to use.
Is there any public algorithm/way to determine the OS edition from the product key like windows setup does? Preferrably in C/C++.
EDIT:
The question is not to determine which editions a certain images supports - this can be done simply by looking at the catalog files sources\install_*.clg
EDIT2:
I found some (strange) tools like Microsoft PIDX Check and Windows 7 Product Key Checker. These use the same pidgenx.dll. pkeyconfig.xrm-msof as the windows system itself. It can be used to determine, among others:
The edition of the Windows.
The features to unlock and activate.
The distribution channel of the license.
The license type.
Ways to activate the operating system.
Unique identifier to determine if activation should be accepted.
But the evaluation of a key takes awfully long.
They probably don't want anyone to know the format to make it harder for the keygen writers.
Some ISO's have a ei.cfg file, you could check there