Find where blender is installed in code (C++)

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
}