OpenDCL Forums

OpenDCL => Runtime/AutoLISP => Topic started by: johnM on October 16, 2009, 01:13:28 PM

Title: Working with different runtime versions.
Post by: johnM on October 16, 2009, 01:13:28 PM
I just came across a situation that I wanted to share.
If you distribute your programs there could be issues with other programs that are using different runtime versions.

I have always used the load runtime example supplied with the sample files called manualload.lsp and it works great until there is another program that is loaded with different runtime versions.

What I have done is to write a version checker that is called before the ARX load routine

(defun opdc_arx_ck (/ arxnamex proc_arch)
    (setq arxnamex        
       (strcat "opendcl"
       (if
       (and
       (setq proc_arch (getenv "PROCESSOR_ARCHITECTURE"))
       (< 1 (strlen proc_arch))
       (eq "64" (substr proc_arch (1- (strlen proc_arch))))
       )
        ".x64."
        "."
       )
       (substr (getvar "acadver") 1 2)
      ".arx"
       )        
       )
   (if (member arxnamex (arx));_see if a ARX is already loaded
       (progn
   (if (/= (dcl_GETVERSIONEX) "6.0.0.7");_check it with my version
       (progn
   (if (member arxnamex (arx)) (arxunload arxnamex 'nil));_if not my version unload it
       );_progn
       );_if
       );_progn
       );_if
   (princ)
 );_defun

If there is a better idea please post it.
Also if the sample file could be updated to cover this issue it would be extremely helpful to those of use who distribute our programs.

Title: Re: Working with different runtime versions.
Post by: BazzaCAD on October 16, 2009, 01:19:37 PM
If you install the runtime with the runtime.msi & use (command "OPENDCL")
You wont have any issues & wont need to jump through all these hoops.
That's why the samples are setup this way & not with the manual loading technique.
I guess we should add some type of disclaimer and the beginning of the "manualload.lsp" file explaining that it's not the recommended technique to avid confusion.
Title: Re: Working with different runtime versions.
Post by: owenwengerd on October 16, 2009, 02:25:58 PM
The current samples are very poor examples of best practice, and they really need to be fixed.  As Barry said, you should distribute and install the runtime via the runtime MSI (or include the MSM into your own application's MSI) and let Windows Installer take care of installing it on the target system, then use (command "OPENDCL") to load the runtime.  If you do this, your application will not conflict with other OpenDCL applications.  If everyone else does this, their application won't conflict with yours.
Title: Re: Working with different runtime versions.
Post by: BazzaCAD on October 16, 2009, 03:45:14 PM
Quote from: owenwengerd on October 16, 2009, 02:25:58 PM
The current samples are very poor examples of best practice, and they really need to be fixed.

Hi Owen,
I know the samples need some help, but the loading section seams ok to me.
Each sample calls (LoadRunTime) & (LoadRunTime) calls (command "OPENDCL") & ensures demand loading is enabled.

So do you think we should remove (LoadRunTime) in each sample and replace it with (command "OPENDCL")?
Title: Re: Working with different runtime versions.
Post by: Kerry on October 16, 2009, 04:20:52 PM

Most of the hoop jumping code was written before demand loading was available.

Personally I now don't rely on any external lisp files.

I simply put (command "OpenDcl") as the first line of the file so it gets evaluated when the file loads.

and use something like this to load the project
  (or (dcl_project_load "KDUB_BlaBla" )
      (prompt "\n Unable to load KDUB_BlaBla Dialog")
      (exit)
  )

... but that's just me
Title: Re: Working with different runtime versions.
Post by: BazzaCAD on October 16, 2009, 04:41:53 PM
That sounds good to me, my only concern is what if they have demand loading disabled...
Then they get "unknown command OPENDCL"
Title: Re: Working with different runtime versions.
Post by: johnM on October 16, 2009, 06:30:44 PM
Please correct me if I am wrong, but I think I’m lost

You can query the system variable “Demandload” to see if it is on or off

Runtime MSI will install the runtime files located at c:\program files\common files\openDCL\.
Runtime MSM will install the runtime files located at c:\program files\common files\<my software>\.

Now if demand load is enabled and from my program I call (command “opendcl”)
My program will be linked to those runtime arx files installed from the MSM  and even if someone else has a programmed that loaded a ARX file into AutoCAD that arx file will not be linked.

Also if the above is correct I assume the demand load knows which runtime arx to load
(.Arx.16-arx.17-arx.18 ect….) for the correct acad version


Title: Re: Working with different runtime versions.
Post by: owenwengerd on October 16, 2009, 07:35:33 PM
Quote from: BazzaCAD on October 16, 2009, 04:41:53 PM
That sounds good to me, my only concern is what if they have demand loading disabled...
Then they get "unknown command OPENDCL"

My opinion is that if DEMANDLOAD is set to zero, then software should assume it was set that way purposely to prevent stuff from loading (i.e. while testing someting, or debugging a problem).  If a developer wants to do that sort of checking in their own code, fine, but such code shouldn't be in the samples.
Title: Re: Working with different runtime versions.
Post by: owenwengerd on October 16, 2009, 07:38:34 PM
Quote from: johnM on October 16, 2009, 06:30:44 PM
Runtime MSM will install the runtime files located at c:\program files\common files\<my software>\.

If it does, it's a bug.  The MSM should install the runtime files in the Common Files folder same as the MSI.  You're correct about filenames; the installer writes everything into the registry to set up the demand loading for every supported AutoCAD and Bricscad installation on the system so that application code does not need to worry about it.
Title: Re: Working with different runtime versions.
Post by: BazzaCAD on October 16, 2009, 07:54:09 PM
Quote from: owenwengerd on October 16, 2009, 07:35:33 PM
Quote from: BazzaCAD on October 16, 2009, 04:41:53 PM
That sounds good to me, my only concern is what if they have demand loading disabled...
Then they get "unknown command OPENDCL"

My opinion is that if DEMANDLOAD is set to zero, then software should assume it was set that way purposely to prevent stuff from loading (i.e. while testing someting, or debugging a problem).  If a developer wants to do that sort of checking in their own code, fine, but such code shouldn't be in the samples.

OK then I try to start updating the samples when I get some time.
Title: Re: Working with different runtime versions.
Post by: Kerry on October 17, 2009, 12:15:36 AM
Quote from: BazzaCAD on October 16, 2009, 04:41:53 PM
That sounds good to me, my only concern is what if they have demand loading disabled...
Then they get "unknown command OPENDCL"

Perhaps that could be covered by a section in the help " ERROR Messages , and what they mean"

Barry I can spare a couple of hours in the morning so I'll start the sample updates if you like.
Title: Re: Working with different runtime versions.
Post by: BazzaCAD on October 17, 2009, 08:07:50 AM
ok sounds good
Title: Re: Working with different runtime versions.
Post by: johnM on October 17, 2009, 10:03:29 AM
I believe there should be a section on runtime conflicts and how to avoid them.
There should be a standard set and a good sample on how to implement the load.
A lot of the users like myself learn by example and if we are started off in the right direction it is better for all. Of course there always be exceptions.
I would be happy to contribute to the writing of this topic but I don’t know what the hell I’m talking about at this stage, but I will figure it out soon.
For now could someone explain or show an examples of:
How does the MSM work?

I use INNO setup: what files should I include MSI , MSM
Are there any parameter switches?

I’m just trying to wrap my brain around this so please bear with me.


Title: Re: Working with different runtime versions.
Post by: owenwengerd on October 17, 2009, 10:30:40 AM
There is an Inno Setup tutorial here:
http://opendcl.com/wordpress/?page_id=10 (http://opendcl.com/wordpress/?page_id=10)
Title: Re: Working with different runtime versions.
Post by: johnM on October 17, 2009, 10:51:25 AM
Thanks for the link
I read through it and it covers the MSI install but nothing about MSM

The MSI install will install the runtime files at C:\Program Files\Common Files\OpenDCL

Unless I missed something this doesn’t solve any problems. What a user installs my program that uses runtime 4.1.1.x and then a week later installs a different program containing runtime 6.0.0.8. that install would overwrite the files in C:\Program Files\Common Files\OpenDCL and now my program will have issues.
Is this correct?

Title: Re: Working with different runtime versions.
Post by: owenwengerd on October 17, 2009, 10:59:07 AM
The runtime versions are backward compatible, so if another program installs a newer version of the runtime, your program will still work (at least in theory -- there could of course be cases where your code takes advantage of some undocumented or unintended behavior that changes in a newer version).
Title: Re: Working with different runtime versions.
Post by: johnM on October 17, 2009, 11:59:47 AM
That’s what I’m getting at.
I have a package that works great with runtime 4.1.1.2 but it has errors with 6.0.0.8
I don’t want to repackage and submit updates to everybody using it every time there is a change in new runtimes that causes errors in older runtimes.

I personally can work around this issue with the code in my original post but I will have to fix my 4.1.1.2 package with the code and updated my users one time. I was just thinking about my learning curve and how could I make life easer for others like me.
Please don’t get me wrong I really appreciate all the help and advice here
Title: Re: Working with different runtime versions.
Post by: owenwengerd on October 17, 2009, 12:10:18 PM
There were breaking changes from OpenDCL 4 to 5, but that was a special case because OpenDCL 4 applications could not safely coexist with other OpenDCL applications in any case.
Title: Re: Working with different runtime versions.
Post by: Kerry on October 17, 2009, 06:20:52 PM

Regarding updating samples:

I've had a fresh look at the samples.
Unfortunately they are all designed to be run with the "_MasterDemo.lsp" loaded and with the "_OpendclUtils.LSP" loaded.

If any of the samples are loaded and run independently the LoadODCLProj function is not available.
As you know, the LoadODCLProj function's primary purpose is to ensure the  .ODCL files can be found in the  ..\SamplesFolder.

In this regard, the Samples are not really completely simple generic samples.





Title: Re: Working with different runtime versions.
Post by: BazzaCAD on October 17, 2009, 07:09:51 PM
If the samples folder is in the acad support path they should run on there own.
We should try to get them to run from masterdemo & on there own as much as possable.
Title: Re: Working with different runtime versions.
Post by: owenwengerd on October 17, 2009, 07:26:55 PM
I envision adding a prolog like the following (for e.g. the TreeView sample):
Code (autolisp) Select

;;;######################################################################
;;;######################################################################
;;;######################################################################
;;;
;;; OpenDCL Sample
;;;
;;; The code in this prolog is designed to allow this sample project
;;; to work with the other sample projects that are installed with
;;; OpenDCL Studio, and is not intended for nor needed in your own
;;; OpenDCL projects.
;;;
(or
  OpenDCL::Samples::#Prefix
  (setq OpenDCL::Samples::#Prefix (vl-registry-read "HKEY_CURRENT_USER\\SOFTWARE\\OpenDCL" "SamplesFolder"))
  (setq OpenDCL::Samples::#Prefix (vl-registry-read "HKEY_LOCAL_MACHINE\\SOFTWARE\\OpenDCL" "SamplesFolder"))
  (setq OpenDCL::Samples::#Prefix (vl-registry-read "HKEY_CURRENT_USER\\SOFTWARE\\Wow6432Node\\OpenDCL" "SamplesFolder"))
  (setq OpenDCL::Samples::#Prefix (vl-registry-read "HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\OpenDCL" "SamplesFolder"))
)
(and (not OpenDCL::Samples::#findfile)
  (setq OpenDCL::Samples::#findfile findfile)
  (defun findfile (file / path)
    (if OpenDCL::Samples::#Prefix
      (setq path (OpenDCL::Samples::#findfile (strcat OpenDCL::Samples::#Prefix file)))
    )
    (if path path (OpenDCL::Samples::#findfile file))
  )
)
(and (not OpenDCL::Samples::#dcl_project_load)
  (command "_OPENDCL")
  (setq OpenDCL::Samples::#dcl_project_load dcl_project_load)
  (defun dcl_project_load (file)
    (OpenDCL::Samples::#dcl_project_load (findfile file))
  )
)
(if (not *MasterDemo*) ;; print a banner, unless masterdemo is active
  (princ "\nOpenDCL sample loaded. Enter \"TREE\" to run the sample.\n")
)
;;;
;;;
;;;######################################################################
;;;######################################################################
;;;######################################################################
;;;######################################################################
;;;
;;;
;;; TREE Sample
;;;
;;; This sample demonstrates the tree control and all its events.
;;;


;; this function loads the project & shows the form
(defun c:TREE (/)
  (command "_OPENDCL") ;; ensure OpenDCL Runtime is loaded
  (dcl_Project_Load "TreeView.odcl")
  (dcl_Form_Show TreeView_Main)
  ;; The event handlers manage the form until it is dismissed
  (PRINC)
)
Title: Re: Working with different runtime versions.
Post by: Kerry on October 17, 2009, 07:41:11 PM
Redefining findfile is probably not ideal ...

added : ditto redefining dcl_project_load
Title: Re: Working with different runtime versions.
Post by: owenwengerd on October 17, 2009, 08:19:55 PM
The goal of course was to be able to make the sample code work with or without the prolog. The (findfile) redefinition doesn't bother me, but (dcl_project_load) is a problem because it can accept optional arguments (and being in lisp, the replacement can't). Another idea is to use a hybrid approach that requires a call to a custom findfile function for loading sample files. This isn't so bad; it means the sample code can't be used exactly as-is, but it's reasonable to expect most end user applications to require something exactly like the custom findfile function anyway, so here they just have to plug in their version of the function:

Code (autolisp) Select

;;;######################################################################
;;;######################################################################
;;;######################################################################
;;;
;;; OpenDCL Sample
;;;
;;; This function retrieves the full path to files in the samples
;;; folder by prefixing the filename with the path prefix that was
;;; saved in the registry by the OpenDCL Studio installer.
;;;
(defun ODCL::Samples::FindFile (file / prefix path)
  (setq prefix
(cond
((vl-registry-read "HKEY_CURRENT_USER\\SOFTWARE\\OpenDCL" "SamplesFolder"))
((vl-registry-read "HKEY_LOCAL_MACHINE\\SOFTWARE\\OpenDCL" "SamplesFolder"))
((vl-registry-read "HKEY_CURRENT_USER\\SOFTWARE\\Wow6432Node\\OpenDCL" "SamplesFolder"))
((vl-registry-read "HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\OpenDCL" "SamplesFolder"))
)
  )
  (if prefix (setq path (findfile (strcat prefix file))))
  (if path path (findfile file))
)
(if (not *MasterDemo*) ;; print a banner, unless masterdemo is active
  (princ "\nOpenDCL sample loaded. Enter \"TREE\" to run the sample.\n")
)
;;;
;;;
;;;######################################################################
;;;######################################################################
;;;######################################################################
;;;######################################################################
;;;
;;;
;;; TREE Sample
;;;
;;; This sample demonstrates the tree control and all its events.
;;;


;; this function loads the project & shows the form
(defun c:TREE (/)
  (command "_OPENDCL") ;; ensure OpenDCL Runtime is loaded
  (dcl_Project_Load (ODCL::Samples::FindFile "TreeView.odcl"))
  (dcl_Form_Show TreeView_Main)
  ;; The event handlers manage the form until it is dismissed
  (PRINC)
)
Title: Re: Working with different runtime versions.
Post by: Kerry on October 17, 2009, 08:20:15 PM
Would an option be to code the dcl_project_load to look in the Samples if the file is not on the path. ?

oops we posted at the same time ... I'll have a look at your post.
Title: Re: Working with different runtime versions.
Post by: Kerry on October 17, 2009, 08:26:35 PM

That should work Owen I think.
I'm comfortable with it because I do a similar thing in some of my production code.

... and as you indicate, it's only one function call to change to become 'conventional' code. 
Title: Re: Working with different runtime versions.
Post by: owenwengerd on October 17, 2009, 08:40:16 PM
Quote from: Kerry Brown on October 17, 2009, 08:20:15 PM
Would an option be to code the dcl_project_load to look in the Samples if the file is not on the path. ?

That occurred to me, but I think it can be ruled out. The first problem with that approach is that it only works with (dcl_project_load). There are several samples that need to load other kinds of dependent files from the samples folder. The second problem is that such a "ghost" path could cause someone a lot of frustration in certain cases (imagine copying an OpenDCL sample into a folder that is incorrectly thought to be in the support path, editing the copy, and being mystified at why the changes aren't effective when the project is reloaded).
Title: Re: Working with different runtime versions.
Post by: Kerry on October 17, 2009, 08:46:16 PM
I came to a similar conclusion when rethinking the option. :)

Should I wait for a consensus or just plough ahead and make the changes to the samples ?

Title: Re: Working with different runtime versions.
Post by: owenwengerd on October 17, 2009, 08:58:59 PM
I'm all for shooting first and asking questions later. If you're in the mood, have at it.

I'd like to create a set of guidelines for a best practice, then go through each sample line by line and control by control and get everything conforming to the guideline. For now, though, just make identical changes to each sample, in such a way that your changes can easily be revised en masse with the magic of search and replace.

One thought I did have is that the new stuff could go to the end of the file instead of the beginning, thereby giving it less prominence. As a bonus, you could precede the existing event handlers with the "magic" comment (
Code (autolisp) Select
;|«OpenDCL Event Handlers») that signifies where Studio should insert new event handlers.
Title: Re: Working with different runtime versions.
Post by: Kerry on October 17, 2009, 09:32:26 PM
Conforming to a guideLine (and creating a guideline) may be difficult.

for instance :

For modal development I prefer to declare my event handlers local to the main.

This means that my files tend to take this form :

Code (autolisp) Select

(vl-load-com)
(command "_OPENDCL")             ; ensure OpenDCL Runtime is loaded

(defun c:test (/
              ;; vars
              local1 local2 local3
              ;; methods
              *error* _fun1 _fun2 _fun3
               c:event1 c:event2 c:event3)
;;; -------------
;;; LOCAL FUNCTIONS
;;; -------------
 (defun *error* ()
                ;; error trap stuff here
 )
 ;; -------------
 (defun _fun1 ()
              ;; stuff here
 )
 ;; -------------
 (defun _fun2 ()
              ;; stuff here
 )
 ;; -------------
 (defun _fun3 ()
              ;; stuff here
 )
;;; -------------
;;; EVENT HANDLERS
;;; -------------
 (defun c:event1 ()
                 ;; stuff here
 )
 ;; -------------
 (defun c:event2 ()
                 ;; stuff here
 )
 ;; -------------
 (defun c:event3 ()
                 ;; stuff here
 )
;;; -------------
;;; MAIN
;;; -------------
 (dcl_project_load "MySuperDuperSpecial.odcl")
 (setq DialogReturn (dcl_form_show MySuperDuperSpecial_Main))
 ;; The event handlers manage the form until it is dismissed
 ;; Run any post closure routines here
 (error* nil)
 (princ)
)





... but again, this is just me
Title: Re: Working with different runtime versions.
Post by: owenwengerd on October 17, 2009, 09:54:28 PM
I think it's best to leave event handlers global in the samples (for consistency).
Title: Re: Working with different runtime versions.
Post by: Kerry on October 18, 2009, 12:34:42 AM
Yep :)
Have done.


edit
Continuing the topic here :
http://www.opendcl.com/forum/index.php?topic=977.msg4963#msg4963 (http://www.opendcl.com/forum/index.php?topic=977.msg4963#msg4963)