by Fenton Webb
Recently, a developer ran into an issue with some LISP code where he was trying to add multiple paths to the PrinterStyleSheetPath property… The code looked something like this:
(defun c:xx()
(vl-load-com)
(setq
acad (vlax-get-acad-object)
prefs (vla-get-preferences *acad)
files (vla-get-files prefs)
)
(vla-put-PrinterStyleSheetPath files "c:\\fenny;c:\\temp")
)
The problem is that behind the scenes, as with other Preference variables, the put-PrinterStyleSheetPath does not handle the semi colon’s and just fails because the path is invalid.
The solution is simply to use getenv and/or setenv.
If you are not familiar with these functions, basically they have a two stage process… First, check the FixedProfile in the registry for the required system setting, and second, if an entry is not found then the Windows System environment is searched.
Here’s the code to set the PrinterStyleSheetPath to multiple paths in LISP…
(setenv "PrinterStyleSheetDir" "c:\\fenton;c:\\temp")
Here’s the code to set the PrinterStyleSheetPath to multiple paths in ARX…
acedSetEnv(_T("PrinterStyleSheetDir"), _T("c:\\fenton;c:\\temp"));
Now for .NET, it seems there is no native way to call acedSetEnv()… I can see why that is actually (it’s because the ObjectARX API’s, which .NET is built around, AcDbHostApplicationServices class only exposes a GetEnvironmentVariable(), not a Set) so you will have to PInvoke acedSetEnv… Not difficult, here’s how…
[DllImport("acad.exe", CallingConvention = CallingConvention.Cdecl,
CharSet = CharSet.Auto, EntryPoint = "acedGetEnv")]
extern static private Int32 acedGetEnv(string var,
[Out] System.Text.StringBuilder val);
[DllImport("acad.exe", CallingConvention = CallingConvention.Cdecl,
CharSet = CharSet.Auto, EntryPoint = "acedSetEnv")]
extern static private Int32 acedSetEnv(string var, string val);
// test acedGet and acedSetEnv by Fenton Webb, DevTech, 05/06/2012
[CommandMethod("testenv")]
static public void testenv()
{
System.Text.StringBuilder buf = new System.Text.StringBuilder("", 1024);
acedGetEnv("PATH", buf);
buf.Append(";"); buf.Append(@"c:\temp");
acedSetEnv("PATH", buf.ToString());
}
To finish off, I personally think that one other great advantage of using getenv/acedGetEnv() and setenv/acedSetEnv() instead of the COM Preferences in .NET is that you reduce the need to bring in the COM Interop reference DLLs into your project references – namely Autodesk.AutoCAD.Interop.dll and/or Autodesk.AutoCAD.Interop.Common.dll. To explain why I’m bringing this up; so when you bring in these DLL’s as references you can no longer rely on the “Any CPU” setting in your project build settings working universally across 32bit and 64bit AutoCAD, thus possibly making you have to consider creating separate 32bit and 64bit versions of your application. Don’t worry too much though, it really all depends on which parts of the COM Interop libraries you are using; my advise is, if you are using these COM Interop libs, and you are compiling as “Any CPU” make sure you test your application on both 32bit and 64bit… If it fails, you know you have to create separate 32bit and 64bit versions. If it works, then great!! Actually, a good first test is to simply set your CPU build type to Win32 and recompile, do the same for x64 – if you get any compiler errors, you know you definitely have a problem…