| Richie's profileThe Sandpit - "We hack s...BlogLists | Help |
|
April 27 How to create a ROBUST install for ArcGIS Desktop customizations written in .NETESRI's ArcGIS Desktop product is comprised of a number of applications. These include ArcCatalog, ArcMap, ArcScene and ArcGlobe. All of which can be heavily customized by developers using any COM or .NET language. For developers using a COM compatible language like C++ or VB6 deployment is fairly easy. Deployment would consist of running regsvr32.exe against compiled DLLs on target machines. To register a COM DLL: To unregister a COM DLL: For more information on Packing and deployment ArcGIS Desktop components please visit EDN. But now most of us have embraced C# (or VB.NET) and consider VB6 a distant memory. The hardships endured using VB6 are long forgotten. However, whilst .NET development is a joy to use it can be a nightmare to deployment. In this article I will describe the dangers of creating an install (msi) using installer classes and document a robust alternative. The EDN article How to create a custom install program has step by step instructions on how to create a Setup Project for .NET assemblies that contain custom components. This method involves the addition of an installer class in the .NET assembly to correctly register the .NET assembly for COM interop. The installer class is called by the Windows Installer application (at install time) on target computers. Problems arise if:
If the Windows Installer application fails to install you may get an error message like:
This problem can be easily resolved by the user on the target computer by install one or more of the missing components listed above. However, once installed correctly a user may experience problems uninstalling the custom component if one or more of the dependencies is missing. This may arise if the user has uninstalled ArcGIS Desktop or upgraded (or downgraded) to another version. The only workaround is for the user to restore the same environment as during install time. Below are XXX easy steps to create a Setup Project for a .NET assembly that is independent of ArcGIS Desktop environment, that is, easy on and easy off. Step 1: Create a New Project Start Microsoft Visual Studio 2005 and select File > New > Project...
In the New Project dialog, select Class Library (ArcMap) and enter the name of the project (and assembly). In the example, the name of the project is DeveloperSample. Click OK.
Next, the ArcGIS Project Wizard will appear. You can use this dialog to select ESRI references that may be used in your project. Click Finished to accept the default settings.
The template document automatically created a class called Class1. Select the class in the Solution Explorer and delete it (right click and select Delete).
Step 2: Add an ArcMap Command Select the newly created project in the Solution Explorer and from the Project dropdown menu select Add New Item....
Select the Base Command item in the ArcGIS category. Enter the name of the new item and click Add. In this example, the name of the new command class is SampleCommand.cs.
Next, the ArcGIS New Item Wizard Option will appear prompting for the type of command that you would like to create. Select Desktop ArcMap Command and then click OK.
Step 3: Edit the Command Class Your solution should now include a new class, command bitmap and new references to the ESRI assemblies.
Double click on the command class, SampleCommand.cs, to open it in the Visual Studio code editor. Your class should look very similar to the code displayed below. I have made a few minor edits for clarify and edited values of the protected properties like base.m_category. Also, in the overloaded method OnClick I have added a "Hello World" message box. You can do the same in your code, but don't forget to add a reference to the "System.Windows.Forms" assembly in your project. using System; using System.Drawing; using System.Runtime.InteropServices; using System.Windows.Forms; using ESRI.ArcGIS.ADF.BaseClasses; using ESRI.ArcGIS.ADF.CATIDs; using ESRI.ArcGIS.Framework; using ESRI.ArcGIS.ArcMapUI; namespace DeveloperSample { [Guid("5C0CC07D-A04F-4FE3-BF8E-16645DCBDC1D")] [ClassInterface(ClassInterfaceType.None)] [ProgId("DeveloperSample.SampleCommand")] public sealed class SampleCommand : BaseCommand { [ComRegisterFunction()] [ComVisible(false)] private static void RegisterFunction(Type registerType) { string regKey = string.Format("HKEY_CLASSES_ROOT\\CLSID\\{{{0}}}", registerType.GUID); MxCommands.Register(regKey); } [ComUnregisterFunction()] [ComVisible(false)] private static void UnregisterFunction(Type registerType) { string regKey = string.Format("HKEY_CLASSES_ROOT\\CLSID\\{{{0}}}", registerType.GUID); MxCommands.Unregister(regKey); } private IApplication m_application = null; public SampleCommand() { base.m_category = "DeveloperSample"; base.m_caption = "Sample"; base.m_message = "Sample"; base.m_toolTip = "Sample"; base.m_name = "DeveloperSample_SampleCommand"; try { string bitmapResourceName = GetType().Name + ".bmp"; base.m_bitmap = new Bitmap(GetType(), bitmapResourceName); } catch (Exception ex) { System.Diagnostics.Trace.WriteLine(ex.Message, "Invalid Bitmap"); } } public override void OnCreate(object hook) { if (hook == null) { return; } this.m_application = hook as IApplication; base.m_enabled = (hook is IMxApplication); } public override void OnClick() { MessageBox.Show("Hello World"); } } } Step 4: Test the Command in ArcMap Start ArcMap from the Windows Start menu (Start > All Programs > ArcGIS > ArcMap). Display the Customize dialog by clicking Tools > Customize... When the Customize dialog appear click the Commands tab and click on the category name (base.m_category) used by you command. When clicked, all commands that use that category will be listed in the box on the right hand side. Click on the command that you created above, the name of the command comes from the base.m_caption value. Drag the command from the Customize dialog to the any existing toolbar. Click close on the Customize dialog.
Click the command to display the "Hello World" message box.
Step 5: Export Interop Registry Information from the Assembly. The ArcGIS Desktop product was first release in 2000. The desktop applications are written in C++ and reference a large collection of ESRI developed COM components called ArcObjects. Because ArcMap only recognizes COM components we need to make our .NET assembly look like COM DLL with COM classes. This is easier than it sounds! Start Windows Explorer and navigate to your project folder. In my case the project folder is C:\TEST\DeveloperSample. Inside this folder you should see your Visual Studio Project (.csprj) and Solution (.sln). From the Window Explorer main menu select File > New > Text Document. This will create a new empty text document in your project folder. Right click on the text file and select Rename. Type "MAKE.BAT" and then press ENTER. You may be prompted to confirm the renaming, if so click Yes.
Open the BAT file using a text editor like Microsoft Notepad and enter the following text as a single line. C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\regasm.exe C:\TEST\DeveloperSample\bin\Debug\DeveloperSample.dll /codebase /regfile:DeveloperSample.reg Where:
Save the changes to the MAKE.BAT in the text editor. Close the text editor. Return to the Windows Explorer, double click on MAKE.BAT.
Running the BAT file will launch a DOS command window as shown below. Briefly you will see messages from the REGASM command displayed. When the REGASM command is complete the DOS command window will disappear.
In the project folder you will see a new file called DeveloperSample.reg.
Step 6: Edit the Interop Registry Information Open the registry file DeveloperSample.reg in a text editor like Microsoft Notepad. You will see hard-coded references to the location of the .NET assembly. We need to change this pathname so that it reflects the pathname of the installed assembly on target computers.
Search and replace the text in the text editor so that the codebase entry reads: The [TARGETDIR] flag will be substituted by the Windows Installer application at install time for the correct pathname.
The registry information created by REGASM exposes the .NET class to COM. That is, to an application like ArcMap, your command looks, tastes and feels like a COM class. Before we are done we need to add one more piece of information. When ArcMap starts up it scans through the registry looking for COM classes that are commands. The registry contains literally thousands of COM classes but only a new few hundred are ArcMap commands. To identify our class SampleCommand as an ArcMap command we need to add a category component to the registry. The category component for an ArcMap command is: At the end of the registry file, DeveloperSample.reg, add the following line:
Save changes in the text editor and then close the application. In future, you may develop other types of ArcGIS application customizations. Here are a few commonly used category component guids: [ComVisible(false)] public sealed class EsriRegistry { // General public const string COMPONENT_LAYER_PROPERTY_PAGE = "{1476C782-6F57-11D2-A2C6-080009B6F22B}"; public const string COMPONENT_LAYER_FACTORY = "{34C20001-4D3C-11D0-92D8-00805F7C28B0}"; public const string COMPONENT_RENDERER_PROPERTY_PAGE = "{962BD9A9-1EC8-11D3-9F4D-00C04F6BC709}"; // ArcMap public const string COMPONENT_MX_COMMAND = "{B56A7C42-83D4-11D2-A2E9-080009B6F22B}"; public const string COMPONENT_MX_TOOLBAR = "{B56A7C4A-83D4-11D2-A2E9-080009B6F22B}"; public const string COMPONENT_MX_DOCKABLEWINDOW = "{117623B5-F9D1-11D3-A67F-0008C7DF97B9}"; public const string COMPONENT_MX_TOCVIEW = "{089874FC-CC18-11D2-9F39-00C04F6BC78E}"; public const string COMPONENT_MX_JITEXTENSION = "{B8C1C6CD-BE34-4EED-BAE9-8584F7A61B07}"; // ArcGlobe public const string COMPONENT_GMX_COMMAND = "{720E21D4-2199-11D6-B2B3-00508BCDDE28}"; public const string COMPONENT_GMX_TOOLBAR = "{720E21D3-2199-11D6-B2B3-00508BCDDE28}"; public const string COMPONENT_GMX_DOCKABLEWINDOW = "{720E21D8-2199-11D6-B2B3-00508BCDDE28}"; public const string COMPONENT_GMX_JITEXTENSION = "{99A23410-D290-41C8-83D8-123D37A1B67B}"; public const string COMPONENT_GMX_ANIMATION_TYPE = "{350DE633-42A4-458D-B07B-35D3B10E12B6}"; } Step 7: Create a Setup Project From the Microsoft Visual Studio main menu select File > Add > New Project... Select Setup Project from the Other Project Type > Setup and Deployment category and enter a descriptive project name like DeveloperSampleSetup.
The setup project will be created and added to the current solution. If a file system tab is not display as shown below then right click on the setup project in the Solution Explorer and select View > File System.
Select the Application Folder node in the File System tab. Right click and select Add > Project Output...
When the Add Project Output Group dialog appears select Primary output and then press OK.
Select Primary output from DeveloperSample in the Application Folder. In the Properties Windows set the property Register to vsdrpDoNotRegister.
The sample command references a number of ESRI assemblies. By default, Visual Studio assumes that the target computers do not have these installed and bundles them in the setup. To remove these assemblies from the setup select all ESRI .NET assemblies in the Solution Explorer, right click and select Exclude. You can also exclude the type library, DeveloperSample.tlb, this is really only useful if you want your assembly to be referenced by VBA and VB6 projects.
With the Setup Project selected in the Solution Explorer, click on the Registry Editor button on the Solution Explorer toolbar. Alternatively you can select View > Registry from the Setup Project right click menu.
In the Registry Tab, right click on the root node, Registry on Target Machine, and select Import...
A file browser will appear. Navigate to and select the registry file you created (and edited) in the previous steps. Click Open to add the information in the registry file to the Setup Project.
Opening the registry file will add all the registry keys and values to the setup project. In the Registry tab expand ALL nodes as shown below.
We need to give some specific instructions to the Windows Installer application. The first is to remove class and progid nodes at uninstall time. For every child node under the HKEY_CLASS_ROOT/CLSID, select it in the Registry tab and then change the DeleteAtUninstall property from False to True. In this example, we only have one such key {5C0CC....
Similarly for every child node under HKEY_CLASS_ROOT (excluding CLSID), select it in the Registry tab and then change the DeleteAtUninstall property from False to True. In this example, we only have one such key called DeveloperSample.SampleCommand. This keys are called ProgIds. ProgId are non-unique names used to lookup class guids.
Now, for every guid key that is under keys called "Implemented Categories", select it and change the AlwaysCreate attribute in the Properties Window from False to True. In this example we only have one class with two category component keys {62C8FE65... and {B56A7C42.. The later is the category component for an ArcMap command. The reason for this step is that the Windows Installer application will, by default, not create registry keys on target computers if they are empty. Set the AlwaysCreate property to True forces the Install to create the key.
Step 8: Create the Setup File (msi) The last step is to create a setup file (msi) that you can use to deploy your customization on other computers. In the Solution Explorer window select the Setup Project. From the Microsoft Visual Studio main menu select Build > Build < Setup Project Name>.
Congratulations. You have just created a robust setup file that can be easily installed and uninstalled on any computer regardless of dependencies. You will find the msi file in one of the sub folders in the the setup project folder. |
|
|