FileVersionInfo.GetVersionInfo
is what we’ve been using to view the file properties of an executable or DLL.
We have come across an .exe
where we could see the file properties in the properties section, but GetVersionInfo()
was unable to read them.
Pyinstaller was used in the construction of this .exe
.
eg
VSVersionInfo(
ffi=FixedFileInfo(
filevers=(1, 2, 3, 4),
prodvers=(1, 2, 3, 4),
mask=0x3f,
flags=0x0,
OS=0x40004,
fileType=0x1,
subtype=0x0,
date=(0, 0)
),
kids=[
StringFileInfo(
[
StringTable(
u'040904B0',
[StringStruct(u'CompanyName', u'Your Company Name'),
StringStruct(u'FileDescription', u'Description of your program'),
StringStruct(u'FileVersion', u'1.2.3.4'),
StringStruct(u'InternalName', u'yourprogram'),
StringStruct(u'LegalCopyright', u'© Your Company Name. All rights reserved.'),
StringStruct(u'OriginalFilename', u'yourprogram.exe'),
StringStruct(u'ProductName', u'Your Product Name'),
StringStruct(u'ProductVersion', u'1.2.3.4')])
]),
VarFileInfo([VarStruct(u'Translation', [1033, 1200])])
]
)
Could anyone please assist me in resolving this problem?
We were able to read the file properties, when we used version.dll
‘s GetFileVersionInfo()
and VerQueryValue()
methods.
We are trying to avoid this approach as this not straight forward.
Update 1 – 02/09/2024
-
I am using .Net Framework 4.8
-
I see all the file properties from file explorer
-
I am using GetFileVersionInfo() in the below manner
if (GetFileVersionInfo(filePath, handle, size, buffer))
{
if (VerQueryValue(buffer, @”StringFileInfo40904B0″ + propertyName, out IntPtr ptr, out uint len))
{
string propertyValue = Marshal.PtrToStringAuto(ptr);
}
} -
I am running the code in Windows 10 OS
5
Workaround
Making a version.rc file and utilizing it with a .spec file is how we discovered an alternative method to generate the exe using PyInstaller. and afterwards creating the exe by using this .spec file in the command.
VSVersionInfo(
ffi=FixedFileInfo(
filevers=(1, 2, 3, 4),
prodvers=(1, 2, 3, 4),
mask=0x3f,
flags=0x0,
OS=0x4,
fileType=0x1,
subtype=0x0,
date=(0, 0)),
kids=[StringFileInfo([StringTable(
u'040904B0',
[StringStruct(u'FileDescription', u'xyz'),
StringStruct(u'FileVersion', u'1.0.0.0'),
StringStruct(u'InternalName', u'xyz'),
StringStruct(u'LegalCopyright', u'Copyright'),
StringStruct(u'OriginalFilename', u'xyz'),
StringStruct(u'ProductName', u'productvk'),
StringStruct(u'ProductVersion', u'1.0.0.0'),
StringStruct(u'CompanyName', 'MyCompanyvk'),
StringStruct(u'Language', u'Language Neutral'),
StringStruct(u'LegalTrademarks', u'xyz')])]),
VarFileInfo([VarStruct(u'Translation', [1033, 1200])])]
)
VSVersionInfo(
ffi=FixedFileInfo(
filevers=(1, 2, 3, 4),
prodvers=(1, 2, 3, 4),
mask=0x3f,
flags=0x0,
OS=0x4,
fileType=0x1,
subtype=0x0,
date=(0, 0)),
kids=[StringFileInfo([StringTable(
u'040904B0',
[StringStruct(u'FileDescription', u'xyz'),
StringStruct(u'FileVersion', u'1.0.0.0'),
StringStruct(u'InternalName', u'xyz'),
StringStruct(u'LegalCopyright', u'Copyright'),
StringStruct(u'OriginalFilename', u'xyz'),
StringStruct(u'ProductName', u'productvk'),
StringStruct(u'ProductVersion', u'1.0.0.0'),
StringStruct(u'CompanyName', 'MyCompanyvk'),
StringStruct(u'Language', u'Language Neutral'),
StringStruct(u'LegalTrademarks', u'xyz')])]),
VarFileInfo([VarStruct(u'Translation', [1033, 1200])])]
)
Command – PyInstaller main.spec
After that, FileVersionInfo.GetVersionInfo() could successfully retrieve the properties.
2
I too have had issues with FileVersionInfo
in a full .net application as well. To solve it I referenced the old-school Win32 Library Shell32, a reference to the DLL: Microsoft Shell Controls And Automation – it’s a COM reference
private string GetSpecificFileProperties(string file, params int[] indexes)
{
string fileName = Path.GetFileName(file);
string folderName = Path.GetDirectoryName(file);
Shell32.Shell shell = new Shell32.Shell();
Shell32.Folder objFolder;
objFolder = shell.NameSpace(folderName);
StringBuilder sb = new StringBuilder();
foreach (Shell32.FolderItem2 item in objFolder.Items())
{
if (fileName == item.Name)
{
for (int i = 0; i < indexes.Length; i++)
{
sb.Append(objFolder.GetDetailsOf(item, indexes[i]) + ",");
}
break;
}
}
string result = sb.ToString().Trim();
//Protection for no results causing an exception on the `SubString` method
if (result.Length == 0)
{
return string.Empty;
}
return result.Substring(0, result.Length - 1);
}
Here is some examples of how you call the method:
string Type = GetSpecificFileProperties(filePath, 2);
string ObjectKind = GetSpecificFileProperties(filePath, 11);
DateTime CreatedDate = Convert.ToDateTime(GetSpecificFileProperties(filePath, 4));
DateTime LastModifiedDate = Convert.ToDateTime(GetSpecificFileProperties(filePath, 3));
DateTime LastAccessDate = Convert.ToDateTime(GetSpecificFileProperties(filePath, 5));
string LastUser = GetSpecificFileProperties(filePath, 10);
string ComputerName = GetSpecificFileProperties(filePath, 53);
string FileSize = GetSpecificFileProperties(filePath, 1);
Or get multiple comma separated properties together:
string SizeTypeAndLastModDate = GetSpecificFileProperties(filePath, new int[] {1, 2, 3});
Here is the magical version number you’re after:
string Version = GetSpecificFileProperties(filePath, 166);
Note: This solution has been tested on Windows 7 and Windows 10. It won’t work unless running in a STA as per Exception when using Shell32 to get File extended properties and you will see the following error:
Unable to cast COM object of type ‘Shell32.ShellClass’ to interface type ‘Shell32.IShellDispatch6’