{"id":108135,"date":"2023-05-03T07:01:51","date_gmt":"2023-05-03T14:01:51","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=108135"},"modified":"2023-05-03T07:01:51","modified_gmt":"2023-05-03T14:01:51","slug":"20230503-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20230503-51\/?p=108135","title":{"rendered":"What can I do if I don&#8217;t want my file version number to be a sequence of four integers?"},"content":{"rendered":"<p>In the Windows file version resource, the file version number is given as a sequence of four 16-bit integers. Here&#8217;s the prototype file version resource given <a href=\"https:\/\/docs.microsoft.com\/en-us\/windows\/win32\/menurc\/versioninfo-resource\"> on docs.microsoft.com<\/a>:<\/p>\n<pre>#define VER_FILEVERSION             3,10,349,0\r\n#define VER_FILEVERSION_STR         \"3.10.349.0\\0\"\r\n\r\n#define VER_PRODUCTVERSION          3,10,0,0\r\n#define VER_PRODUCTVERSION_STR      \"3.10\\0\"\r\n\r\n#ifndef DEBUG\r\n#define VER_DEBUG                   0\r\n#else\r\n#define VER_DEBUG                   VS_FF_DEBUG\r\n#endif\r\n\r\nVS_VERSION_INFO VERSIONINFO\r\nFILEVERSION     VER_FILEVERSION\r\nPRODUCTVERSION  VER_PRODUCTVERSION\r\nFILEFLAGSMASK   VS_FFI_FILEFLAGSMASK\r\nFILEFLAGS       (VER_PRIVATEBUILD|VER_PRERELEASE|VER_DEBUG)\r\nFILEOS          VOS__WINDOWS32\r\nFILETYPE        VFT_DLL\r\nFILESUBTYPE     VFT2_UNKNOWN\r\nBEGIN\r\n    BLOCK \"StringFileInfo\"\r\n    BEGIN\r\n        BLOCK \"040904E4\"\r\n        BEGIN\r\n            VALUE \"CompanyName\",      VER_COMPANYNAME_STR\r\n            VALUE \"FileDescription\",  VER_FILEDESCRIPTION_STR\r\n            VALUE \"FileVersion\",      VER_FILEVERSION_STR\r\n            VALUE \"InternalName\",     VER_INTERNALNAME_STR\r\n            VALUE \"LegalCopyright\",   VER_LEGALCOPYRIGHT_STR\r\n            VALUE \"LegalTrademarks1\", VER_LEGALTRADEMARKS1_STR\r\n            VALUE \"LegalTrademarks2\", VER_LEGALTRADEMARKS2_STR\r\n            VALUE \"OriginalFilename\", VER_ORIGINALFILENAME_STR\r\n            VALUE \"ProductName\",      VER_PRODUCTNAME_STR\r\n            VALUE \"ProductVersion\",   VER_PRODUCTVERSION_STR\r\n        END\r\n    END\r\n\r\n    BLOCK \"VarFileInfo\"\r\n    BEGIN\r\n        \/* The following line should only be modified for localized versions.     *\/\r\n        \/* It consists of any number of WORD,WORD pairs, with each pair           *\/\r\n        \/* describing a language,codepage combination supported by the file.      *\/\r\n        \/*                                                                        *\/\r\n        \/* For example, a file might have values \"0x409,1252\" indicating that it  *\/\r\n        \/* supports English language (0x409) in the Windows ANSI codepage (1252). *\/\r\n\r\n        VALUE \"Translation\", 0x409, 1252\r\n\r\n    END\r\nEND\r\n<\/pre>\n<p>But what if your file versioning scheme isn&#8217;t major.minor.build.revision? For example, maybe your file versioning sceheme is major.minor.patch? Can you just leave out the fourth value?<\/p>\n<pre>\/\/ Does this work?\r\n#define VER_FILEVERSION             3,10,349\r\n#define VER_FILEVERSION_STR         \"3.10.349\\0\"\r\n<\/pre>\n<p>If you try this, you&#8217;ll find that many tools show the version as <code>3.1.349.0<\/code>. Where is the extra <code>.0<\/code> coming from?<\/p>\n<p>The file version information is recorded in two formats in the version resource. There is a binary machine-parseable version, and there is a string human-readable version. The tools are probably getting the machine-parseable version, which takes the form of <a href=\"https:\/\/docs.microsoft.com\/en-us\/windows\/win32\/api\/VerRsrc\/ns-verrsrc-vs_fixedfileinfo\"> a <code>VS_FIXED\u00adFILE\u00adINFO<\/code> structure<\/a>.<\/p>\n<pre>typedef struct tagVS_FIXEDFILEINFO {\r\n  DWORD dwSignature;\r\n  DWORD dwStrucVersion;\r\n  DWORD dwFileVersionMS;\r\n  DWORD dwFileVersionLS;\r\n  DWORD dwProductVersionMS;\r\n  DWORD dwProductVersionLS;\r\n  DWORD dwFileFlagsMask;\r\n  DWORD dwFileFlags;\r\n  DWORD dwFileOS;\r\n  DWORD dwFileType;\r\n  DWORD dwFileSubtype;\r\n  DWORD dwFileDateMS;\r\n  DWORD dwFileDateLS;\r\n} VS_FIXEDFILEINFO;\r\n<\/pre>\n<p>The file version number is represented in the form of two 32-bit integers <code>dwFileVersionMS<\/code> and <code>dwFileVersionLS<\/code>, and the traditional interpretation of these values is to break it down as follows:<\/p>\n<table class=\"cp3\" style=\"border-collapse: collapse; text-align: center;\" border=\"1\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<td colspan=\"2\"><code>dwFileVersionMS<\/code><\/td>\n<td colspan=\"2\"><code>dwFileVersionLS<\/code><\/td>\n<\/tr>\n<tr>\n<td>\n<table style=\"width: 6em; font-size: 70%;\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td align=\"left\">3<br \/>\n1<\/td>\n<td align=\"right\">1<br \/>\n6<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/td>\n<td>\n<table style=\"width: 6em; font-size: 70%;\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td align=\"left\">1<br \/>\n5<\/td>\n<td align=\"right\">\n0<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/td>\n<td>\n<table style=\"width: 6em; font-size: 70%;\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td align=\"left\">3<br \/>\n1<\/td>\n<td align=\"right\">1<br \/>\n6<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/td>\n<td>\n<table style=\"width: 6em; font-size: 70%;\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td align=\"left\">1<br \/>\n5<\/td>\n<td align=\"right\">\n0<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/td>\n<\/tr>\n<tr>\n<td>major<\/td>\n<td>minor<\/td>\n<td>build<\/td>\n<td>revision<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Technically, it&#8217;s just a 64-bit number, and you could try to get the word out to the entire industry that, &#8220;For my app, please don&#8217;t break it down into four 16-bit integers. Instead, break it down into three 16-bit integers, and ignore the last one. Thanks. Love ya!&#8221;<\/p>\n<p>You may even succeed at convincing some tools vendors to go along with your special rule. But you&#8217;re unlikely to convince all of them.<\/p>\n<p>You can put whatever 64-bit value you like, but you have to accept that tools are going to parse it as if it were four 16-bit integers. You can tell your customers, &#8220;If you try to view the file version information, many tools will show it in four parts rather than three. You can ignore the last part, the one with the trailing <code>.0<\/code>.&#8221;<\/p>\n<p>There&#8217;s a bit of an escape hatch: The <code>VER_FILEVERSION_STR<\/code>. You can set this string to anything you like. By convention, it&#8217;s a human-readable version of the binary file information, but there is no enforcement.<\/p>\n<pre>\/\/ Don't show the final .0 to the user. We don't use it.\r\n#define VER_FILEVERSION_STR         \"3.10.349\\0\"\r\n<\/pre>\n<p>You can even put extra bonus information in there if you like.<\/p>\n<pre>#define VER_FILEVERSION_STR         \"3.10.349 (prerelease)\\0\"\r\n<\/pre>\n<p>Most tools will also show this string to the user, although it carries no formal meaning.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The format is enforced by the Windows file format, but you can present the information in a custom way.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-108135","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>The format is enforced by the Windows file format, but you can present the information in a custom way.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/108135","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=108135"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/108135\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=108135"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=108135"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=108135"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}