How to get "ProductName" and "ProductVersion" properties for a DLL file?
-
I have to display the "ProductName" and "ProductVersion" properties for two DLL files. The resulting string shall contain (ProductName + " " + ProductVersion), and the code shall work with Qt 5.12.12, 5.15.x and 6.x.
The only example I found on the internet is this one: https://stackoverflow.com/questions/56335697/is-there-a-function-to-get-a-exe-files-product-name. But I can't figure out most parts of the code and can't get it to work for me.Currently, I am only able to display the birthTime of my DLL file. For this, my code is as follows:
#ifdef WIN32 QDir dataPath = QCoreApplication::applicationDirPath(); QFileInfo f1(dataPath.absolutePath() + "/" + "dll1.dll"); QString birthTime1 = f1.birthTime().toString("yyyy-MM-dd hh:mm"); ui_->in_use->setText(QString{"In use: %1"}.arg(birthTime1())); #endifAny help would be appreciated.
-
@Urbi said in How to get "ProductName" and "ProductVersion" properties for a DLL file?:
I have to display the "ProductName" and "ProductVersion" properties for two DLL files.
The "ProductName" and "ProductVersion" of DLLs is a Windows-specific concept, and I don't believe Qt has generic support for it. Basically, you'd have to call Win32 APIs - specifically one of the GetFileVersionInfo*() functions.
Any help would be appreciated.
For some inspiration on how to do this is with Qt, have a look at how Qt does it internally for the "current" app in QCoreApplicationPrivate::appVersion():
QString QCoreApplicationPrivate::appVersion() const { QString applicationVersion; #ifndef QT_BOOTSTRAPPED const QString appFileName = qAppFileName(); QVarLengthArray<wchar_t> buffer(appFileName.size() + 1); buffer[appFileName.toWCharArray(buffer.data())] = 0; DWORD versionInfoSize = GetFileVersionInfoSize(buffer.data(), nullptr); if (versionInfoSize) { QVarLengthArray<BYTE> info(static_cast<int>(versionInfoSize)); if (GetFileVersionInfo(buffer.data(), 0, versionInfoSize, info.data())) { UINT size; DWORD *fi; if (VerQueryValue(info.data(), __TEXT("\\"), reinterpret_cast<void **>(&fi), &size) && size) { const VS_FIXEDFILEINFO *verInfo = reinterpret_cast<const VS_FIXEDFILEINFO *>(fi); applicationVersion = QStringLiteral("%1.%2.%3.%4") .arg(HIWORD(verInfo->dwProductVersionMS)) .arg(LOWORD(verInfo->dwProductVersionMS)) .arg(HIWORD(verInfo->dwProductVersionLS)) .arg(LOWORD(verInfo->dwProductVersionLS)); } } } #endif return applicationVersion; }Basically, you'd want to replace
appFileNamewith the DLL filename, but probably need to adjust other bits too.For additional inspiration, here's an example I implemented years ago - originally for Qt 4, so it's quite old, and I'm sure it could a lot better today, but you get the idea:
https://github.com/pcolby/bipolar/blob/main/src/os/fileversioninfo.cpp
Good luck :)
Cheers.
-
@Urbi said in How to get "ProductName" and "ProductVersion" properties for a DLL file?:
I have to display the "ProductName" and "ProductVersion" properties for two DLL files.
The "ProductName" and "ProductVersion" of DLLs is a Windows-specific concept, and I don't believe Qt has generic support for it. Basically, you'd have to call Win32 APIs - specifically one of the GetFileVersionInfo*() functions.
Any help would be appreciated.
For some inspiration on how to do this is with Qt, have a look at how Qt does it internally for the "current" app in QCoreApplicationPrivate::appVersion():
QString QCoreApplicationPrivate::appVersion() const { QString applicationVersion; #ifndef QT_BOOTSTRAPPED const QString appFileName = qAppFileName(); QVarLengthArray<wchar_t> buffer(appFileName.size() + 1); buffer[appFileName.toWCharArray(buffer.data())] = 0; DWORD versionInfoSize = GetFileVersionInfoSize(buffer.data(), nullptr); if (versionInfoSize) { QVarLengthArray<BYTE> info(static_cast<int>(versionInfoSize)); if (GetFileVersionInfo(buffer.data(), 0, versionInfoSize, info.data())) { UINT size; DWORD *fi; if (VerQueryValue(info.data(), __TEXT("\\"), reinterpret_cast<void **>(&fi), &size) && size) { const VS_FIXEDFILEINFO *verInfo = reinterpret_cast<const VS_FIXEDFILEINFO *>(fi); applicationVersion = QStringLiteral("%1.%2.%3.%4") .arg(HIWORD(verInfo->dwProductVersionMS)) .arg(LOWORD(verInfo->dwProductVersionMS)) .arg(HIWORD(verInfo->dwProductVersionLS)) .arg(LOWORD(verInfo->dwProductVersionLS)); } } } #endif return applicationVersion; }Basically, you'd want to replace
appFileNamewith the DLL filename, but probably need to adjust other bits too.For additional inspiration, here's an example I implemented years ago - originally for Qt 4, so it's quite old, and I'm sure it could a lot better today, but you get the idea:
https://github.com/pcolby/bipolar/blob/main/src/os/fileversioninfo.cpp
Good luck :)
Cheers.
@Paul-Colby Thanks for your reply, Paul. I tried to adopt your code and added it to various places in my Configuration.cpp file. Best seems to be to include it in my existing void Configuration::impl::display_file_information () class:
void Configuration::impl::display_file_information () { #ifdef WIN32 QString applicationVersion1; #ifndef QT_BOOTSTRAPPED const QString appFileName1 = (dataPath.absolutePath() + "/" + "dll1.dll"); QVarLengthArray<wchar_t> buffer(appFileName1.size() + 1); buffer[appFileName1.toWCharArray(buffer.data())] = 0; DWORD versionInfoSize = GetFileVersionInfoSize(buffer.data(), nullptr); if (versionInfoSize) { QVarLengthArray<BYTE> info(static_cast<int>(versionInfoSize)); if (GetFileVersionInfo(buffer.data(), 0, versionInfoSize, info.data())) { UINT size; DWORD *fi; if (VerQueryValue(info.data(), __TEXT("\\"), reinterpret_cast<void **>(&fi), &size) && size) { const VS_FIXEDFILEINFO *verInfo = reinterpret_cast<const VS_FIXEDFILEINFO *>(fi); applicationVersion1 = QStringLiteral("%1.%2.%3.%4") .arg(HIWORD(verInfo->dwProductVersionMS)) .arg(LOWORD(verInfo->dwProductVersionMS)) .arg(HIWORD(verInfo->dwProductVersionLS)) .arg(LOWORD(verInfo->dwProductVersionLS)); // applicationVersion1 = QStringLiteral("%1 %2") // .arg(HIWORD(verInfo->dwProductName)) // .arg(LOWORD(verInfo->dwProductVersion)); } } } #endif return applicationVersion1; ui_->in_use->setText(QString{"In use: %1"}.arg(applicationVersion1)); #endif }However, I am still getting the following compilation errors:
[C:\project1\Configuration.cpp: In member function 'void Configuration::impl::display_file_information()': C:\project1\Configuration.cpp:3352:74: error: cannot convert 'wchar_t*' to 'LPCSTR {aka const char*}' for argument '1' to 'DWORD GetFileVersionInfoSizeA(LPCSTR, LPDWORD)' DWORD versionInfoSize = GetFileVersionInfoSize(buffer.data(), nullptr); ^ C:\project1\Configuration.cpp:3355:78: error: cannot convert 'wchar_t*' to 'LPCSTR {aka const char*}' for argument '1' to 'WINBOOL GetFileVersionInfoA(LPCSTR, DWORD, DWORD, LPVOID)' if (GetFileVersionInfo(buffer.data(), 0, versionInfoSize, info.data())) { ^ C:\project1\Configuration.cpp:3373:12: error: return-statement with a value, in function returning 'void' [-fpermissive] return applicationVersion1; ^~~~~~~~~~~~~~~~~~~](link url)And then I would need to get (ProductName + " " + ProductVersion) instead of the 4-digit version number.
Any further help is appreciated. Thanks!
-
@Paul-Colby Thanks for your reply, Paul. I tried to adopt your code and added it to various places in my Configuration.cpp file. Best seems to be to include it in my existing void Configuration::impl::display_file_information () class:
void Configuration::impl::display_file_information () { #ifdef WIN32 QString applicationVersion1; #ifndef QT_BOOTSTRAPPED const QString appFileName1 = (dataPath.absolutePath() + "/" + "dll1.dll"); QVarLengthArray<wchar_t> buffer(appFileName1.size() + 1); buffer[appFileName1.toWCharArray(buffer.data())] = 0; DWORD versionInfoSize = GetFileVersionInfoSize(buffer.data(), nullptr); if (versionInfoSize) { QVarLengthArray<BYTE> info(static_cast<int>(versionInfoSize)); if (GetFileVersionInfo(buffer.data(), 0, versionInfoSize, info.data())) { UINT size; DWORD *fi; if (VerQueryValue(info.data(), __TEXT("\\"), reinterpret_cast<void **>(&fi), &size) && size) { const VS_FIXEDFILEINFO *verInfo = reinterpret_cast<const VS_FIXEDFILEINFO *>(fi); applicationVersion1 = QStringLiteral("%1.%2.%3.%4") .arg(HIWORD(verInfo->dwProductVersionMS)) .arg(LOWORD(verInfo->dwProductVersionMS)) .arg(HIWORD(verInfo->dwProductVersionLS)) .arg(LOWORD(verInfo->dwProductVersionLS)); // applicationVersion1 = QStringLiteral("%1 %2") // .arg(HIWORD(verInfo->dwProductName)) // .arg(LOWORD(verInfo->dwProductVersion)); } } } #endif return applicationVersion1; ui_->in_use->setText(QString{"In use: %1"}.arg(applicationVersion1)); #endif }However, I am still getting the following compilation errors:
[C:\project1\Configuration.cpp: In member function 'void Configuration::impl::display_file_information()': C:\project1\Configuration.cpp:3352:74: error: cannot convert 'wchar_t*' to 'LPCSTR {aka const char*}' for argument '1' to 'DWORD GetFileVersionInfoSizeA(LPCSTR, LPDWORD)' DWORD versionInfoSize = GetFileVersionInfoSize(buffer.data(), nullptr); ^ C:\project1\Configuration.cpp:3355:78: error: cannot convert 'wchar_t*' to 'LPCSTR {aka const char*}' for argument '1' to 'WINBOOL GetFileVersionInfoA(LPCSTR, DWORD, DWORD, LPVOID)' if (GetFileVersionInfo(buffer.data(), 0, versionInfoSize, info.data())) { ^ C:\project1\Configuration.cpp:3373:12: error: return-statement with a value, in function returning 'void' [-fpermissive] return applicationVersion1; ^~~~~~~~~~~~~~~~~~~](link url)And then I would need to get (ProductName + " " + ProductVersion) instead of the 4-digit version number.
Any further help is appreciated. Thanks!
@Urbi You seem to be running your app as non UNICODE and passing wide character functions to the WinAPI calls.
Either make sure you define UNICODE in your project or explicitly use wide versions of the functions e.g.GetFileVersionInfoSizeWinstead ofGetFileVersionInfoSize.