Find C4D's directory without C4D
-
Hello PluginCafe
I'm writing a standalone application which will be used for installing my C4D plugins.
I need to find an appropriate way of finding plugins directory.Currently, I'm using a simple expression to define the preferences folder.
Then I'm iterating through each file in the preferences folder and then creating plugins directory with os module.here is the code.
import os from getpass import getuser as user def plugins_path(release_number): if os.name == 'nt': MAXON = r"C:\Users\{}\AppData\Roaming\MAXON".format(user()) #Windows if os.name != 'nt': MAXON = r"/Users/{}/Library/Preferences/MAXON".format(user()) #OSX plugins_path = "" for i in os.listdir(MAXON): if release_number.upper() in i.upper(): plugins_path = os.path.join(MAXON, i, "plugins") if os.path.exists(plugins_path): return plugins_path user_input = "R20" print(plugins_path(user_input))
The problem is that some users are installing C4D in a custom directory and my code is very limited for this task.
Is it possible to find an exact directory of C4D's plugins folder?
-
Hi @merkvilson thanks for reaching us,
Here is a script to retrieves the Cinema 4D preference folder of a specific installation stored in temp folder working from R17 to R20.
""" Copyright: MAXON Computer GmbH Author: Maxime Adam Description: - Retrieves the path of the preference folder according to an installation path without the need to launch Cinema 4D. Note: - From Cinema 4D c4d.storage.GeGetC4DPath(c4d.C4D_PATH_STARTUPWRITE) can be called to retrieves the current installation path. Compatible: - Win / Mac - R17, R18, R19, R20 """ import os import platform def CRC(rawString): # Performs CRC 32 BIT on the input byte crc = 0xffffffff crc32tab_o32 = [ 0x00000000, 0xf26b8303, 0xe13b70f7, 0x1350f3f4, 0xc79a971f, 0x35f1141c, 0x26a1e7e8, 0xd4ca64eb, 0x8ad958cf, 0x78b2dbcc, 0x6be22838, 0x9989ab3b, 0x4d43cfd0, 0xbf284cd3, 0xac78bf27, 0x5e133c24, 0x105ec76f, 0xe235446c, 0xf165b798, 0x030e349b, 0xd7c45070, 0x25afd373, 0x36ff2087, 0xc494a384, 0x9a879fa0, 0x68ec1ca3, 0x7bbcef57, 0x89d76c54, 0x5d1d08bf, 0xaf768bbc, 0xbc267848, 0x4e4dfb4b, 0x20bd8ede, 0xd2d60ddd, 0xc186fe29, 0x33ed7d2a, 0xe72719c1, 0x154c9ac2, 0x061c6936, 0xf477ea35, 0xaa64d611, 0x580f5512, 0x4b5fa6e6, 0xb93425e5, 0x6dfe410e, 0x9f95c20d, 0x8cc531f9, 0x7eaeb2fa, 0x30e349b1, 0xc288cab2, 0xd1d83946, 0x23b3ba45, 0xf779deae, 0x05125dad, 0x1642ae59, 0xe4292d5a, 0xba3a117e, 0x4851927d, 0x5b016189, 0xa96ae28a, 0x7da08661, 0x8fcb0562, 0x9c9bf696, 0x6ef07595, 0x417b1dbc, 0xb3109ebf, 0xa0406d4b, 0x522bee48, 0x86e18aa3, 0x748a09a0, 0x67dafa54, 0x95b17957, 0xcba24573, 0x39c9c670, 0x2a993584, 0xd8f2b687, 0x0c38d26c, 0xfe53516f, 0xed03a29b, 0x1f682198, 0x5125dad3, 0xa34e59d0, 0xb01eaa24, 0x42752927, 0x96bf4dcc, 0x64d4cecf, 0x77843d3b, 0x85efbe38, 0xdbfc821c, 0x2997011f, 0x3ac7f2eb, 0xc8ac71e8, 0x1c661503, 0xee0d9600, 0xfd5d65f4, 0x0f36e6f7, 0x61c69362, 0x93ad1061, 0x80fde395, 0x72966096, 0xa65c047d, 0x5437877e, 0x4767748a, 0xb50cf789, 0xeb1fcbad, 0x197448ae, 0x0a24bb5a, 0xf84f3859, 0x2c855cb2, 0xdeeedfb1, 0xcdbe2c45, 0x3fd5af46, 0x7198540d, 0x83f3d70e, 0x90a324fa, 0x62c8a7f9, 0xb602c312, 0x44694011, 0x5739b3e5, 0xa55230e6, 0xfb410cc2, 0x092a8fc1, 0x1a7a7c35, 0xe811ff36, 0x3cdb9bdd, 0xceb018de, 0xdde0eb2a, 0x2f8b6829, 0x82f63b78, 0x709db87b, 0x63cd4b8f, 0x91a6c88c, 0x456cac67, 0xb7072f64, 0xa457dc90, 0x563c5f93, 0x082f63b7, 0xfa44e0b4, 0xe9141340, 0x1b7f9043, 0xcfb5f4a8, 0x3dde77ab, 0x2e8e845f, 0xdce5075c, 0x92a8fc17, 0x60c37f14, 0x73938ce0, 0x81f80fe3, 0x55326b08, 0xa759e80b, 0xb4091bff, 0x466298fc, 0x1871a4d8, 0xea1a27db, 0xf94ad42f, 0x0b21572c, 0xdfeb33c7, 0x2d80b0c4, 0x3ed04330, 0xccbbc033, 0xa24bb5a6, 0x502036a5, 0x4370c551, 0xb11b4652, 0x65d122b9, 0x97baa1ba, 0x84ea524e, 0x7681d14d, 0x2892ed69, 0xdaf96e6a, 0xc9a99d9e, 0x3bc21e9d, 0xef087a76, 0x1d63f975, 0x0e330a81, 0xfc588982, 0xb21572c9, 0x407ef1ca, 0x532e023e, 0xa145813d, 0x758fe5d6, 0x87e466d5, 0x94b49521, 0x66df1622, 0x38cc2a06, 0xcaa7a905, 0xd9f75af1, 0x2b9cd9f2, 0xff56bd19, 0x0d3d3e1a, 0x1e6dcdee, 0xec064eed, 0xc38d26c4, 0x31e6a5c7, 0x22b65633, 0xd0ddd530, 0x0417b1db, 0xf67c32d8, 0xe52cc12c, 0x1747422f, 0x49547e0b, 0xbb3ffd08, 0xa86f0efc, 0x5a048dff, 0x8ecee914, 0x7ca56a17, 0x6ff599e3, 0x9d9e1ae0, 0xd3d3e1ab, 0x21b862a8, 0x32e8915c, 0xc083125f, 0x144976b4, 0xe622f5b7, 0xf5720643, 0x07198540, 0x590ab964, 0xab613a67, 0xb831c993, 0x4a5a4a90, 0x9e902e7b, 0x6cfbad78, 0x7fab5e8c, 0x8dc0dd8f, 0xe330a81a, 0x115b2b19, 0x020bd8ed, 0xf0605bee, 0x24aa3f05, 0xd6c1bc06, 0xc5914ff2, 0x37faccf1, 0x69e9f0d5, 0x9b8273d6, 0x88d28022, 0x7ab90321, 0xae7367ca, 0x5c18e4c9, 0x4f48173d, 0xbd23943e, 0xf36e6f75, 0x0105ec76, 0x12551f82, 0xe03e9c81, 0x34f4f86a, 0xc69f7b69, 0xd5cf889d, 0x27a40b9e, 0x79b737ba, 0x8bdcb4b9, 0x988c474d, 0x6ae7c44e, 0xbe2da0a5, 0x4c4623a6, 0x5f16d052, 0xad7d5351] for s in rawString: k = ord(s) crc = crc32tab_o32[(crc & 0xff) ^ (k & 0xff)] ^ (crc >> 8) k >>= 8 crc = crc32tab_o32[(crc & 0xff) ^ (k & 0xff)] ^ (crc >> 8) k >>= 8 crc = crc32tab_o32[(crc & 0xff) ^ (k & 0xff)] ^ (crc >> 8) k >>= 8 crc = crc32tab_o32[(crc & 0xff) ^ (k & 0xff)] ^ (crc >> 8) return format(crc ^ 0xffffffff, 'x').upper() def GetTempFolder(instalDir): # Retrieves the temp folder tempFolder = None if platform.system() == "Windows": tempFolder = os.getenv('APPDATA') elif platform.system() == "Darwin": libPath = os.path.expanduser('~/Library') tempFolder = os.path.join(libPath, "Preferences") if not os.path.exists(tempFolder) or tempFolder is None: raise RuntimeError("Failed to retrieves appdata folder.") # Cleanups the input path instalDir = os.path.normpath(instalDir) instalDir = instalDir.replace('\\\\', '\\') parentDirLower = instalDir.lower() # Retrieves only the name of the last folder parentName = os.path.split(instalDir)[1] if not parentName: raise RuntimeError("Failed to retrieves parent Name folder") parentName = parentName.replace(':', '_') # Computes the crc of the dir in lowercase. crc = CRC(parentDirLower) # Builds the final path finalPath = os.path.join(tempFolder, "MAXON", parentName + "_" + crc) return finalPath def main(): # Path must be in unicode, it can be retrieved from c4d with c4d.storage.GeGetStartupPath() winInstallationPath = unicode("C:\Program Files\MAXON\Cinema 4D R20") macInstallationPath = unicode("/Users/m_adam/Application/MAXON/Cinema 4D R20") print "Path:", GetTempFolder(winInstallationPath) if __name__ == '__main__': main()
As a side note in R20 plugins can be installed everywhere as long as the path is set in the preferences.
And finally, there is no reliable way to know where Cinema 4D is installed from outside of Cinema 4D.If you have any question, please let me know.
Cheers,
Maxime. -
Thanks, Maxime!
Can you tell me about Copyright and EULA? How can I use this code in my software?
-
@merkvilson, sorry this code is planned to be part of our github, so like any of our examples, they are under the Apache License.
For more information see Apache License from our Github repository.
Cheers,
Maxime. -
Thanks, Maxime!
I tested the code, and it works.
But this is not what I exactly wanted.As I mentioned, the problem is that some users are installing C4D in a custom directory and I can't find preferences path nor an actual installation path.
I also tried os.walk() Method to find MAXON directory, but it has two significant problems.
- It's too slow
- there are several folders called MAXON
The only thing that users can define is the release number, and I have to find it according to the string, for example, "R20".
Here is how the installer works.
It works on most of the computers but some users already reported that it can't find their directory so they are forced to manually define it but most of them are defining global directory. If you remember, I had to remove symbolcache file and this is one of the reasons why I made this installer.
-
Unfortunately, Cinema 4D does not track this, and there is no way to know it currently since Cinema 4D is almost a portable application (you can copy/paste Cinema 4D folder to anywhere as long as dependencies have been installed once it will work).
In any case, it's a request we already made to our development team, I'll push the topic again and will see .
Cheers,
Maxime. -
Thanks, Maxime! This script is still quite useful.
Is it possible to use it in order to find C4D executable on Windows as well as on mac?Let's assume the directory is
C:\Program Files\MAXON\Cinema 4D R20\
which contains several exe. How to define which one is the Cinema 4D itself?I tried this way but I guess there should be a better option
def MAXON_P(): if os.name == 'nt': MAXON = r"C:\Program Files\MAXON" if os.name != 'nt': MAXON = r"/Applications/MAXON" if os.path.exists(MAXON): return MAXON else: return "" def c4d_executable_path(ver): user_ver = "" versions = os.listdir(MAXON_P()) for i in versions: if ver.upper() in i.upper() and "demo".upper() not in i.upper(): user_ver = i c4d_folder = os.path.join(MAXON_P(), user_ver,) files = os.listdir(c4d_folder) for file in files: if os.name == 'nt' and "CINEMA 4D" in file.upper() and "exe" in file and len(file) < 18: ex = file if os.name != 'nt' and "CINEMA 4D" in file.upper() in file and len(file) < 18: ex = file return os.path.join(c4d_folder, ex) print c4d_executable_path("R20")
-
On Windows, you can use a little trick: To retrieve the currently used Cinema 4D installation, you can query the registry for the program associated with
*.c4d
files.
This gives you only a single installation - probably the most current one.Is it possible to use it in order to find C4D executable on Windows as well as on mac?
On Win+Mac, filenames must be unique. So,
Cinema 4D.exe/app
should be sufficient. -
Thanks, buddy!
But the problem is that the most current one is not a way to go.If the user installed the plugin for R16, then the installer should open R16 itself.
I'm trying to find and open it by the name, but the name is always different. It can be Cinema 4D / Cinema 4D R16 / Cinema 4D R16 Demo / Cinema 4D Demo / etc.
Well. This is considerably easier on windows since I can check if it exists by usingos.path.exists()
function, but I have no Idea how to do this on Mac.