10月15日
Deploying DLLs Over the Network
After initially "installing" my .net app's to users computers via lisp within AutoCAD I ran into the problem of updating a dll. The problem lies with one of my applications that sets reactors in each drawing, as such it needs to be loaded at AutoCAD startup. Obviously if the dll is loaded it cannot be deleted because it is in use. So we have decided to use a vbscript file to install and update dlls, so far so good.
I have created a script file that sits on the network that contains a sub which will install/update a dll file onto the user's local machine and setup registry keys for demand loading. This network script file is then called by a local script file in each user's startup folder.
The local user's file contains:
ExecuteGlobal _
CreateObject("Scripting.FileSystemObject"). _
OpenTextFile("\\SERVER\FILE_PATH\Setup.vbs").ReadAll
WScript.Quit
The network file contains:
SetupApp "APP_NAME", "Application Description", "FILENAME.dll", LOADCTRLS, "COMMAND_NAME", "GROUP_NAME", True
Const APPLICATION_DATA = &H1a&
Const FOR_APPENDING = 8
Const AUTOCAD_SUPPORT = "\Autodesk\AutoCAD 2008\R17.1\enu"
Const LOCAL_DLLS = "\COMPANY_SPECIFIC_SUBFOLDER"
Const NETWORK_DLLS = "NETWORK_PATH_OF_DLLS"
Const AUTOCAD_REGPATH = "HKEY_CURRENT_USER\Software\Autodesk\AutoCAD\R17.1\ACAD-6001:409\Applications"
Const DEBUGGING = False
If DEBUGGING Then WScript.Echo "AutoCAD add-ons installed"
Sub SetupApp(sAppName, sDescription, sFileName, iLoadCtrls, sCommandName, sGroupName, bUpdate)
If bUpdate Then
Set objShell = CreateObject("Shell.Application")
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFolder = objShell.Namespace(APPLICATION_DATA)
Set objFolderItem = objFolder.Self
sDestination = objFolderItem.Path & AUTOCAD_SUPPORT & LOCAL_DLLS
sSource = NETWORK_DLLS
If FileInUse(sDestination & "\" & sFileName) Then
WScript.Echo sFileName & " is in use." & vbcrlf & "Could not setup " & sAppName & "."
Else
'Create directory if it doesn't exist
If not objFSO.FolderExists(sDestination) Then
Set objFolder = objFSO.CreateFolder(sDestination)
If DEBUGGING Then WScript.Echo sDestination & " created."
End If
'Delete file if it exists
If objFSO.FileExists(sDestination & "\" & sFileName) Then
objFSO.DeleteFile sDestination & "\" & sFileName
If DEBUGGING Then WScript.Echo sDestination & "\" & sFileName & " deleted."
End If
'Copy file to replace deleted one
If objFSO.FileExists(sSource & "\" & sFileName) Then
objFSO.CopyFile sSource & "\" & sFileName, sDestination & "\"
If DEBUGGING Then WScript.Echo sDestination & "\" & sFileName & " copied."
End If
sRegPath = AUTOCAD_REGPATH & "\" & sAppName
Set WshShell = CreateObject("WScript.Shell")
WshShell.RegWrite sRegPath & "\DESCRIPTION", sDescription, "REG_SZ"
WshShell.RegWrite sRegPath & "\LOADCTRLS", iLoadCtrls, "REG_DWORD"
WshShell.RegWrite sRegPath & "\MANAGED", 1, "REG_DWORD"
WshShell.RegWrite sRegPath & "\LOADER", sDestination & "\" & sFileName, "REG_SZ"
If Not sCommandName = vbNullString Then
WshShell.RegWrite sRegPath & "\Commands\" & sCommandName, sCommandName, "REG_SZ"
WshShell.RegWrite sRegPath & "\Groups\" & sGroupName, sGroupName, "REG_SZ"
End If
If DEBUGGING Then WScript.Echo "Registry paths written."
If DEBUGGING Then WScript.Echo sAppName & " setup."
End If
Set objShell = Nothing
Set objFSO = Nothing
Set objFolder = Nothing
Set objFolderItem = Nothing
End if
End Sub
Function FileInUse(sFileName)
On Error Resume Next
Set objFSO = CreateObject("Scripting.FileSystemObject")
If objFSO.FileExists(sFileName) Then
Set objFile = objFSO.OpenTextFile(sFileName, FOR_APPENDING, False)
If Err.Number = 70 Then
FileInUse = True
Else
objFile.Close
Set objFile = Nothing
FileInUse = False
End If
Else
FileInUse = False
End If
End Function
Basically what this file does is to copy a central (network) version of the dll to the user's local machine. If the dll already exists it will delete it first and replace it with the new one. It will then write the appropriate keys to the registry to set up the application for demand loading within AutoCAD.
A brief description of the Sub's arguments:
- sAppName: Is the name of the application and will be the key name in the registry.
- sDescription: Is a description of the application and will be the value of DESCRIPTION in the registry.
- sFileName: Is the filename of the dll. It is assumed that you will update the CONST variables to match the appropriate network and local locations.
- iLoadCtrls: Is the value of LOADCTRLS within the registry and will set in what circumstances to demand load the app in AutoCAD.
- sCommandName: Is the command name referred to within the dll and must match exactly or demand loading will not work.
- sGroupName: Is the group name the command belongs to.
- bUpdate: If set to true then the script will attempt to update the dll, otherwise it will skip this application. This is to reduce windows startup times if there becomes a large number of dlls to setup.
If the dll does not contain any commands you will still need to include an argument for sCommandName and sGroupName but they should both be vbNullString.