Custom Component Depoloyment (ESRI) – better to use TARGETDIR

I think ESRI may be wrong on how to properly set up a custom installer for your custom dll’s for ArcMap etc.

How to deploy a custom component using a setup project

 

custom install

 

It’s basically implying that you should use:

[ProgramFilesFolder]\[ProductName]\bin\foo.dll

Which translates to soemthing like “C:\Program Files(x86)\MyCompany\bin\foo.dll”

But this may not always be true, what happens when your user wants to install to a custom installation directory?  The ESRIRegAsm.exe tool will always fire against – C:\Program Files(x86)\MyCompany\bin\foo.dll, and not where the user selected to install! – it’s basically hard wired so that means your customers could have problems trying to install your software.  It’s better to use:

[TARGETDIR]foo.dll

Which is basically the value you get back from this stage in the installation process (although it’s not very clear as you don’t see that as a variable in the properties window for this stage!):

install folder

 

This will then run ESRIRegAsm.exe against where the user decided to install your dll’s, properly installing the dlls into ArcMap etc.  This is, I believe more foolproof.  However if I have got this wrong, I’m happy to be proved wrong 🙂

Custom Component Depoloyment (ESRI) – better to use TARGETDIR

Issues with persisting changes to the scale in PageLayout (LayoutView) using ArcObjects

Scenario

Now and again you may find yourself developing an application outside of ArcMap i.e. essentially an ArcEngine app.

I was developing an application that accessed an mxd via the IMapDocument interface and tried to persist a change in the map scale in the Layout View.  Every time I changed the scale and saved the mxd – however the original scale would not change and the programmatic new scale was ignored!

This was very frustrating indeed, I was sure that there must be a way to persist this change as it’s not exactly NASA missile launch code – I’m just trying to change a scale damn it!

ArcMap Scale
Highlight of the scale control in the layoutview of ArcMap

Solution

Anyway, it so happens that there is a fix, but it’s kind of unusual and not exactly intuitive or obvious to the developer coming at this problem cold.

Firstly we have to make use of some win32 API calls and most importantly to call IActiveView.Activate and pass our call to GetDesktopWindow().  This does the trick and is absolutely essential if you want to get this kind of change persisted.  Take a look at the code below to see how it’s done:

  
[DllImport("User32.dll")]
public static extern int GetDesktopWindow();

private void ChangeMyScale()
{
    IMapDocument MapDoc;
    mapDoc = new MapDocumentClass();
    mapDoc.Open(@"C:\Foo\Bar.mxd",null);
    IPageLayout pageLayout = mapDoc.PageLayout;
    IActiveView activeView = (IActiveView)pageLayout;
    activeView = (IActiveView) mapDoc.PageLayout;
    activeView.Activate(GetDesktopWindow()); //Key line!!
    mapDoc.ActiveView.FocusMap.MapScale = 10000; //Now we can change the scale!!
    activeView.Refresh();

    MessageBox.Show(@"We have an mxd called:" + mapDoc.DocumentFilename +
    "\nExtent: 1 to " + mapDoc.ActiveView.FocusMap.MapScale);

    mapDoc.Save(true, false)
    mapDoc.Close();
}

Other things to bear in mind, code such as:

MapDoc.SetActiveView((IActiveView)pageLayout)

only sets the view for the application as PageLayout, in order to get control of the specified window you have to use the Activate method:

<pre>activeView.Activate(GetDesktopWindow())

When working with the IActiveView interface on a MapDocument object, you should always first call IActiveView::Activate() in order to properly initialize the display of the PageLayout or Map object.

The MxDocument, MapServer objects, MapControl and PageLayoutControl all initialise display objects automatically after opening an MXD, but MapDocument DOES NOT DO THIS, so you should call Activate() before working with any other members of IActiveView.

So to summarise, if your application has a user interface, you should call Activate() with the hWnd of the application’s client area.  If your application runs in the background and has no windows, you retrieve a valid hWnd from the GDI GetDesktopWindow() function, part of the Win32 API.

Conclusion

I am hopeful that ESRI will change this so that you don’t have to, what I view totally unnecessary calls to the Windows API etc.  Maybe it will be fixed properly in version 10 or some other update to that, but I wouldn’t hold your breath!

Anyway I hope it’s useful to you and stops you burning lots of valuable dev time!

Issues with persisting changes to the scale in PageLayout (LayoutView) using ArcObjects