Wednesday, November 22, 2006

Building an NSIS installer for deploying a LISP or DVB file

Yesterday, I posted about using NSIS to deploy to AutoCAD. Today, we will see how nice it is to create a simple installer. Not just any basic file copy one either, we will actually update the startup suite.

What we want to do:
We'll have to pretend a little for this. In this case, we'll pretend we have a simple HelloWorld.lsp file and a HelloWorld.dwg file. They need to be installed to the user machine, and ready to use the next time the user launches AutoCAD.

Solution:
As the title to this wonderful blog post reads, we'll be building an NSIS installer. This will focus around a fictitious LISP program, but this technique works for DVB files or even ARX files. So, first things first, you'll need to have NSIS itself installed. Visit the nullsoft nsis homepage over at sourceforge and download the latest version.

Go ahead and look through the examples for building installers. The base installation of NSIS comes with several examples and several pages of topics.

To begin, we'll create a new text document, and rename it to HelloWorldInstaller.nsi. Inside, we'll write a couple lines to define the installer and version number. These will come in handy later:



!define VER_NUMBER "1.0.0"
!define PRODUCT_NAME "HelloWorld"
!define PRODUCT_PUBLISHER "InstallandDemand.blogspot.com"

Var "strRegistryAcad"
Var "strRegistryLoad"
Var "newAppKey"



These !define tags are creating defined constants for us to use later, and the var are creating variable that we can modify for finding the startup suite location.

Next, we'll need to create a few more settings that tell the installer things like what the product name is, and what to save the compiled installer as. In a sense, we are just setting the project properties.



; set project properties using the defined constants above
Name "${PRODUCT_NAME}"
BrandingText "${PRODUCT_PUBLISHER}"

; The file to write
OutFile "${PRODUCT_NAME}_${VER_NUMBER}.exe"

; The default installation directory
InstallDir "$PROGRAMFILES\${PRODUCT_PUBLISHER}\${PRODUCT_NAME}"
InstallDirRegKey HKLM "SOFTWARE\${PRODUCT_PUBLISHER}\${PRODUCT_NAME}" "ApplicationPath"
DirText "Choose a directory to install in to:"



The InstallDir and InstallDirRegKey tell the installer where to set our target directory on the target computer. It will try to read the InstallDirRegKey value in case the application has already been installed. Also notice, we used ${PRODUCT_NAME} constants to define some of the project properties and target directory.

Finally, we are going to get to the meat of our installer. We will tell it what files need to be installed and where to install them. We will also search the registry to find the startup suite and make our new lisp program load on startup.

NSIS installs files in sections. It does this to allow multiple processes to be done and chosen by the person installing the software. In essence, we can create different sections, and based on options the user selects, different sections will be deployed. Our sample here is much to simple for this. We only need one section.



Section "Application (required)"
; install files
SetOutPath $INSTDIR

; -- write prog dir
File "HelloWorld.lsp"
File "HelloWorld.dwg"



SetOutPath tells the installer where to copy the following files to. In this case, $INSTDIR is an NSIS defined variable that is set by the InstallDir function above. File "HelloWorld.lsp" supplies the installer with the file to copy.

Now before we finish this section off, we need to find the startup suite. AutoCAD stores its startup suite under a registry setting that is under HKEY_CURRENT_USER. Here, there is a NumCount string value that stores the count of items, followed by the paths to each of these items. We will read what the count of items installed is, increment that count, add ours to the registry and finally save the new count back.



; Location in registry where AutoCAD Appload loads files...
; This is hard location and will vary based onInstalled versions of AutoCAD
; This is Registry string is for base AutoCAD 2007 English and default profile
StrCpy $strRegistryAcad "Software\Autodesk\AutoCAD\R17.0\ACAD-5001:409\Profiles\<<Unnamed Profile>>\Dialogs\Appload\Startup"


; This is the matching path to let Appload know to load programs
StrCpy $strRegistryLoad "Software\Autodesk\AutoCAD\R17.0\ACAD-5001:409\Applications\AcadAppload"

; Change the switch to force loading new program with Appload
WriteRegDWORD HKLM $strRegistryLoad "LOADCTRLS" 0x0000000f


; Read the number of loaded Applications in the Startup Suite
ReadRegStr $R0 HKCU $strRegistryAcad "NumStartup"

; Increment the Count
IntOp $R0 $R0 + 1

; Build new key name
StrCpy $newAppKey "$R0Startup"

; Tell the registry which file
WriteRegStr HKCU $strRegistryAcad $newAppKey "$INSTDIR\HelloWorld.lsp"

; Increment the NumStartup key in the registry
WriteRegStr HKCU $strRegistryAcad "NumStartup" $R0

SectionEnd



Now, it looks a little cumbersome the way values are copied around, but its all good in the end. All that is needed now is a quick compile, which can be done by right clicking on the HelloWorld.nsi file and choosing "Compile NSIS Script".

So what did we do here? The installer, copies the files, reads the registry for startup suite information, updates said information, and finishes. The next time the user runs AutoCAD, your command or macro is now available.

This is a very simple look into building an NSIS installer, but with some more time and a little elbow grease, you can whip it into shape, make it so you can choose the profile to install to, add more files, update dialogs, and have lots of fun in the process.

Tuesday, November 21, 2006

Installer Profile - NSIS

NSIS or the nullsoft scriptable installer system is a great little installer. As it's name points out, it is scriptable and has as much functionality as any installer program you can imagine. How does it rate for AutoCAD? Great!

Since a lot of custom AutoCAD or Inventor applications are small scripts in and of themselves, NSIS lends a lot of speed to a quick little app that needs to be deployed. Why? Well, first and foremost, the scripts can be edited right in notepad. They can easily be reused, allowing you to create a template script and modify it as needed. Other third parties have also created NSIS editors that have build in wizards!

Ok, so just how powerful is NSIS when it comes to deploying to AutoCAD or Inventor? Here are a few examples:


  • Registry reading and writing - so you can set up your application to demand load. You can also work out a script that enumerates all installed version of AutoCAD and allows the user to select.

  • Full dialog editing and creating. So you can create a dialog with said enumerated versions of AutoCAD

  • It's free!

  • It has a library of scripts and examples on the homepage

  • Simple and easy to use



  • Ok, now that I have drooled all over NSIS, what is wrong with it? Well, sometimes the scriping can get a little cumbersome. Especially when trying to enumerate values from the registry or do anything more than just a simple file copy type installer. While not impossible to create these things, sometimes, a nice wizard or GUI would be very helpful.

    In the end, NSIS is a great tool to have! If you find yourself deploying a lot of applications to AutoCAD or Inventor and they are all simple file copy type deployments, NSIS is priceless! Especially if you create a few templates to modify!

    Monday, November 20, 2006

    A little LISP to tie things together: Part 1


    What? LISP!?!? You have to be kidding me! Ok, nope, not kidding. Sometimes, LISP still comes in handy when deploying your applications. Seriously! Especially if you are going to try and get your project done really quick. Rapid application development? Anyone?

    Ok, here is a good example. You need to fire off a command at the startup of AutoCAD. What do you do? Sure you can program an initialize function in your .NET DLL, but we are talking about LISP here.

    Try this:



    (defun-q Autorun()
    (command "mycommand")
    (princ)
    )
    (setq S::STARTUP (append S::STARTUP Autorun))



    It will have you firing commands at startup in just a few lines of code! Ok, now you need to deploy this to another machine. Hmm... Sounds like a job for NSIS, and another post.

    Friday, November 17, 2006

    Copy Local, or not?


    When creating installers that deploy to AutoCAD, one little question almost always comes up. Do these files need to be deployed? Will there be problems during deployment if the files are included?

    To answer these questions, let's look into what copy local does with a little more detailed. According to Microsoft (via), Copy Local is:

    The Copy Local property (corresponding to CopyLocal) determines whether a reference is copied to the local bin path. At run time, a reference must exist in either the Global Assembly Cache (GAC) or the output path of the project. If this property is set to true, the reference is copied to the output path of the project at run time.


    So what does this mean to us developing in the AutoCAD world? Since our applications are loaded into AutoCAD's AppDomain, the required DLLs are already loaded. Setting copy local equal to true, will cause AutoCAD to try and reload the acmgd.dll and acdbmgd.dll. This could cause your command not to work.

    So, the answer is, Copy Local needs to be FALSE!