Author Topic: Custom System Variables  (Read 6604 times)

0 Members and 1 Guest are viewing this topic.

MexicanCustard

  • Swamp Rat
  • Posts: 705
Custom System Variables
« on: January 26, 2012, 07:40:23 AM »
At AU 2011, in Bill Adkinson's class on the Undo/Redo system he briefly mentioned creating your own system variables in the registry.  I haven't been able to find anything written on the matter via a few searches on google.  Does anyone have any experience in trying this?

I'm going to experiment today I'll post back my findings.
Revit 2019, AMEP 2019 64bit Win 10

Jeff_M

  • King Gator
  • Posts: 4087
  • C3D user & customizer
Re: Custom System Variables
« Reply #1 on: January 26, 2012, 07:55:09 AM »
Tony T posted an example C# project a few years ago demonstrating how to implement Custom System Variables. Since his site is no longer available, I could send it to you direct if you'd like.  I'm not sure how the laws apply to defunct websites, but the EULA included says
Quote
Further, the intent of this license is to prohibit all forms
of unauthorized distribution of the SOFTWARE for any purpose.
The AUTHOR's sole point of distribution of the SOFTWARE is
at the following interet URL:

   http://www.caddzone.com/CustomSystemVariableExample.zip
So I'm not too wild about posting it here unless Mark says it's OK with him.

Jeff H

  • Needs a day job
  • Posts: 6144
Re: Custom System Variables
« Reply #2 on: January 26, 2012, 10:15:32 AM »
Not much info but the Variable class

Quote
  Variables are created by declaring them in the registry. The following format should be used (elements between {} should be replaced with a legal value for the property or type indicated inside the {}).
[HKEY_LOCAL_MACHINE{ProductRegistryRoot}Variables{AcRxVariable::name()}] @="{some value}" : Required, will be converted to PrimaryDataType "PrimaryType"=dword:{AcRxVariable::primaryType()} : Required "SecondaryType"=dword:{AcRxVariable::seondaryType()} : Optional "TypeFlags"=dword:{AcRxVariable::typeFlags()} : Optional "StorageType"=dword:{AcRxVariable::StorageType} : Required "Owner"="{LogicalAppName|exe}" : Optional "Range"="{lowerbound},{upperbound}" : Optional, applies to RTREAL, RTANG, RTSHORT and RTLONG primary types
Note these variables can be get/set using acedGetVar/acedSetVar functions in AutoCAD. They are also visible to the SETVAR command. 

I have little something that I started once I get a little time will finish it up and post.
 
You can do it manully.
Look at the bottom of this post with a registry file example
http://through-the-interface.typepad.com/through_the_interface/2011/02/creating-the-smallest-possible-circle-around-2d-autocad-geometry-using-net.html
 

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: Custom System Variables
« Reply #3 on: January 26, 2012, 04:35:26 PM »
Hi,

Here's a little example I wrote some times ago.
It defines a sysvar called LAYLOCKSEL wich allows or prevent selection of entities on locked layers.
It's separated in three projects:
  • an AutoCAD ExtensionApplication to define the sysvar behavior (dll),
  • an Installer to write registry keys defining the sysvar properties and autoloading (exe)
  • an Uninstaller to remove registry keys (exe)
As the sysvar definition have to be written in HKeyLocalMachine, a manifest is requiered for the Installer and Uninstaller to set Administrator account.

AutoCAD ExtensionApplication
Code - C#: [Select]
  1. using System.Collections.Generic;
  2. using Autodesk.AutoCAD.ApplicationServices;
  3. using Autodesk.AutoCAD.DatabaseServices;
  4. using Autodesk.AutoCAD.EditorInput;
  5. using Autodesk.AutoCAD.Runtime;
  6. using AcAp = Autodesk.AutoCAD.ApplicationServices.Application;
  7.  
  8. [assembly: ExtensionApplication(typeof(LayLockSel.SysVar))]
  9.  
  10. namespace LayLockSel
  11. {
  12.     public class SysVar : IExtensionApplication
  13.     {
  14.         // Fields
  15.         private DocumentCollection _docMan;
  16.         private Editor _ed;
  17.         private Variable _var;
  18.  
  19.         // Constructor
  20.         public SysVar()
  21.         {
  22.             _docMan = AcAp.DocumentManager;
  23.             _ed = _docMan.MdiActiveDocument.Editor;
  24.             _var = SystemObjects.Variables["LAYLOCKSEL"];
  25.  
  26.         }
  27.  
  28.         // Initialization (register 'DocumentActivated' event)
  29.         void IExtensionApplication.Initialize()
  30.         {
  31.             _docMan.DocumentActivated += new DocumentCollectionEventHandler(onDocumentActivated);
  32.             Activate();
  33.         }
  34.  
  35.         void IExtensionApplication.Terminate()
  36.         {
  37.         }
  38.  
  39.         // 'DocumentActivated' event handler
  40.         void onDocumentActivated(object sender, DocumentCollectionEventArgs e)
  41.         {
  42.             _ed = e.Document.Editor;
  43.             Activate();
  44.         }
  45.  
  46.         // 'Variable.Changed' event handler
  47.         void onVarChanged(object sender, VariableChangedEventArgs e)
  48.         {
  49.             if ((short)e.NewValue == 1)
  50.                 _ed.SelectionAdded += new SelectionAddedEventHandler(onSelectionAdded);
  51.             else
  52.                 _ed.SelectionAdded -= new SelectionAddedEventHandler(onSelectionAdded);
  53.         }
  54.  
  55.         // 'SelectionAdded' event handler
  56.         void onSelectionAdded(object sender, SelectionAddedEventArgs e)
  57.         {
  58.             List<int> toRemove = new List<int>();
  59.             SelectionSet ss = e.AddedObjects;
  60.             Database db = HostApplicationServices.WorkingDatabase;
  61.             using (Transaction tr = db.TransactionManager.StartTransaction())
  62.             {
  63.                 LayerTable lt = (LayerTable)tr.GetObject(db.LayerTableId, OpenMode.ForRead);
  64.                 for (int i = 0; i < ss.Count; i++)
  65.                 {
  66.                     Entity ent = (Entity)tr.GetObject(ss[i].ObjectId, OpenMode.ForRead);
  67.                     LayerTableRecord ltr = (LayerTableRecord)tr.GetObject(lt[ent.Layer], OpenMode.ForRead);
  68.                     if (ltr.IsLocked)
  69.                         toRemove.Add(i);
  70.                 }
  71.                 foreach (int i in toRemove) e.Remove(i);
  72.                 tr.Commit();
  73.             }
  74.         }
  75.  
  76.         // Activate 'LAYLOCKSEL' sysvar
  77.         private void Activate()
  78.         {
  79.             try
  80.             {
  81.                 _ed.SelectionAdded -= new SelectionAddedEventHandler(onSelectionAdded);
  82.                 _var.Changed -= new VariableChangedEventHandler(onVarChanged);
  83.             }
  84.             catch { }
  85.             if ((short)_var.Value == 1)
  86.                 _ed.SelectionAdded += new SelectionAddedEventHandler(onSelectionAdded);
  87.             _var.Changed += new VariableChangedEventHandler(onVarChanged);
  88.         }
  89.     }
  90. }
  91.  

Installer
Code - C#: [Select]
  1. using System.IO;
  2. using System.Linq;
  3. using System.Windows.Forms;
  4. using Microsoft.Win32;
  5.  
  6. namespace LayLockSel_Install
  7. {
  8.     class Program
  9.     {
  10.         static void Main()
  11.         {
  12.             try
  13.             {
  14.                 // Check if 'LayLockSel.dll is in the same folder
  15.                 string filename = Application.StartupPath + "\\LayLockSel.dll";
  16.                 if (!File.Exists(filename))
  17.                 {
  18.                     MessageBox.Show("Can't find 'LayLockSel.dll' file", "LAYLOCKSEL");
  19.                     return;
  20.                 }
  21.  
  22.                 // Get AutoCAD product key path
  23.                 RegistryKey hive = Registry.CurrentUser;
  24.                 string prodk = @"Software\Autodesk\AutoCAD\";
  25.                 string ver = (string)hive.OpenSubKey(prodk).GetValue("CurVer");
  26.                 if (ver.CompareTo("18.1") < 0)
  27.                 {
  28.                     MessageBox.Show("AutoCAD current version is prior to 2011", "LAYLOCKSEL");
  29.                     return;
  30.                 }
  31.                 prodk += "\\" + ver;
  32.                 prodk += "\\" + hive.OpenSubKey(prodk).GetValue("CurVer");
  33.  
  34.                 hive = Registry.LocalMachine;
  35.                 using (RegistryKey ack = hive.OpenSubKey(prodk, true))
  36.                 {
  37.                     // Create the sysvar definition key
  38.                     using (RegistryKey vark = ack.OpenSubKey("Variables", true))
  39.                     {
  40.                         if (vark.GetSubKeyNames().Contains("LAYLOCKSEL"))
  41.                         {
  42.                             MessageBox.Show("LAYLOCKSEL is already installed", "LAYLOCKSEL");
  43.                             return;
  44.                         }
  45.                         else
  46.                         {
  47.                             using (RegistryKey rk = vark.CreateSubKey("LAYLOCKSEL"))
  48.                             {
  49.                                 rk.SetValue("", 0, RegistryValueKind.String);
  50.                                 rk.SetValue("LowerBound", 0, RegistryValueKind.DWord);
  51.                                 rk.SetValue("PrimaryType", 5003, RegistryValueKind.DWord);
  52.                                 rk.SetValue("StorageType", 1, RegistryValueKind.DWord);
  53.                                 rk.SetValue("UpperBound", 1, RegistryValueKind.DWord);
  54.                             }
  55.                         }
  56.                     }
  57.  
  58.                     // Create the autoload key
  59.                     using (RegistryKey appk = ack.OpenSubKey("Applications", true))
  60.                     {
  61.                         if (!appk.GetSubKeyNames().Contains("LAYLOCKSEL"))
  62.                             using (RegistryKey rk = appk.CreateSubKey("LAYLOCKSEL"))
  63.                             {
  64.                                 rk.SetValue("DESCRIPTION", " LAYLOCKSEL System Variable", RegistryValueKind.String);
  65.                                 rk.SetValue("LOADCTRLS", 2, RegistryValueKind.DWord);
  66.                                 rk.SetValue("LOADER", filename, RegistryValueKind.String);
  67.                                 rk.SetValue("MANAGED", 1, RegistryValueKind.DWord);
  68.                             }
  69.                     }
  70.                 }
  71.                 MessageBox.Show("Installation succeded", "LAYLOCKSEL");
  72.             }
  73.             catch (System.Exception ex)
  74.             {
  75.                 MessageBox.Show("Installation failed\n" + ex.Message, "LAYLOCKSEL");
  76.             }
  77.         }
  78.     }
  79. }
  80.  

Uninstaller
Code - C#: [Select]
  1. using System.Text;
  2. using System.Windows.Forms;
  3. using Microsoft.Win32;
  4.  
  5. namespace LayLockSel_Uninstall
  6. {
  7.     class Program
  8.     {
  9.         static void Main()
  10.         {
  11.             try
  12.             {
  13.                 // Deletes sysvar definition and autoload registry keys
  14.                 RegistryKey hive = Registry.LocalMachine;
  15.                 using (RegistryKey rk = hive.OpenSubKey(GetAcadProductKey() + "\\Variables", true))
  16.                 {
  17.                     rk.DeleteSubKey("LAYLOCKSEL", false);
  18.                 }
  19.                 using (RegistryKey rk = hive.OpenSubKey(GetAcadProductKey() + "\\Applications", true))
  20.                 {
  21.                     rk.DeleteSubKey("LAYLOCKSEL", false);
  22.                 }
  23.                 MessageBox.Show("Uninstallation succeded", "LAYLOCKSEL");
  24.             }
  25.             catch (System.Exception ex)
  26.             {
  27.                 MessageBox.Show("Uninstallation failed\n" + ex.Message, "LAYLOCKSEL");
  28.             }
  29.         }
  30.  
  31.         // Return AutoCAD product key path
  32.         private static string GetAcadProductKey()
  33.         {
  34.             StringBuilder sb = new StringBuilder(@"HKEY_CURRENT_USER\Software\Autodesk\AutoCAD\");
  35.             return sb
  36.                 .Append(Registry.GetValue(sb.ToString(), "CurVer", ""))
  37.                 .Append("\\")
  38.                 .Append(Registry.GetValue(sb.ToString(), "CurVer", ""))
  39.                 .Remove(0, 18)
  40.                 .ToString();
  41.         }
  42.     }
  43. }
  44.  

Application manifest
Code - XML: [Select]
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  3.   <assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
  4.   <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
  5.     <security>
  6.       <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
  7.         <requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
  8.       </requestedPrivileges>
  9.     </security>
  10.   </trustInfo>
  11. </asmv1:assembly>
  12.  
« Last Edit: January 26, 2012, 04:48:47 PM by gile »
Speaking English as a French Frog

MexicanCustard

  • Swamp Rat
  • Posts: 705
Re: Custom System Variables
« Reply #4 on: January 27, 2012, 08:26:35 AM »
Thanks for the replies.  I went the Gile route, created the app (DLL) and a .reg file to install registry entries.  Thanks Jeff_M for getting me the Tony T stuff.  That really showed me the how, where, and why of custom system variables.
Revit 2019, AMEP 2019 64bit Win 10