Hello everyone.
I have a C++ application and I want to invoke Blender in background mode. It all works fine except that I’ve hardcoded the path to where blender is installed.
Is there a way to find where blender is installed on Windows and Linux?
Regards,
Kostadin
On windows you could look at what application is registered for handling .blend
files through AssocQueryString on linux i’m not aware of any functionality like that, but i admit, not my platform.
1 Like
Thank you. At least for windows it works for me, here is what I wrote if anyone else needs it:
#include <Shlwapi.h> // link to Shlwapi.lib
std::string findBlenderExePath()
{
#ifdef WIN32
char blenderPath[MAX_PATH] = {'\0'};
DWORD blenderPathSize = SGE_ARRSZ(blenderPath);
HRESULT hr = AssocQueryStringA(0, ASSOCSTR_EXECUTABLE, ".blend", NULL, blenderPath, &blenderPathSize);
if (S_OK == hr) {
return std::string(blenderPath);
}
// Blender seems to be not assiciated with .blend files so assume it is not installed.
return std::string();
#else
return std::string();
#endif
}
Careful there, you’re calling AssocQueryStringA
which is the ascii version of this API.
This will fail if the registered path has some unicode characters in it (they will get replaced with ‘?’). This happens more often than you’d expect, as some people install to their user folder, which for some countries can regularly contain non-ascii characters.
1 Like
Yeah, I know but this is in the TODO for the near future.
Thanks for the heads up
Alternate solution is to force the narrow api to use UTF-8 using a manifest
that’s what we did for blender for some of the problematic deps that did not use the W
api, just be sure that whatever you feed the filename is aware it contains UTF-8 (fopen won’t like it so needs help, CreateFileA will have no issues as the manifest fixes all A
api calls)
Okey, here it is an UTF-8 path, if someone wants utf-16 they can delete the unnecessary code:
std::string findBlenderExePath()
{
#ifdef WIN32
// The idea came form this thread:
// https://devtalk.blender.org/t/find-where-blender-is-installed-in-code-c/25499
// Basically we find which program is associated to default open .blend files and assume that this program is
// Blender.
WCHAR blenderPath[1024] = {'\0'};
DWORD blenderPathSize = ARRAYSIZE(blenderPath);
const HRESULT hr = AssocQueryStringW(0, ASSOCSTR_EXECUTABLE, L".blend", NULL, blenderPath, &blenderPathSize);
if (hr == S_OK) {
// Convert the wide char string (UTF-16) to UTF-8.
// Caution: we do a bit of a hack to write in the std::string.
const int utf8Size = WideCharToMultiByte(CP_UTF8, 0, blenderPath, int(blenderPathSize), NULL, 0, NULL, NULL);
std::string blenderPathUtf8(utf8Size, 'a'); // Initialize the string with some random character. All these
// characters should get replaced by WideCharToMultiByte.
if (WideCharToMultiByte(
CP_UTF8, 0, blenderPath, int(blenderPathSize), &blenderPathUtf8[0], utf8Size, NULL, NULL)) {
return blenderPathUtf8;
}
}
// Blender seems to be not assiciated with .blend files so assume it is not installed.
return std::string();
#else
return std::string();
#endif
}