Automating Maps: Using ArcObjects without ArcMap

Posted by Dave Bouwman | Posted in .NET, ArcMap, ESRI | Posted on 31-01-2007

0

[UPDATE: 1/31/07 I got a note from a member of the ArcMap team who indicated that when using the IActiveView interface on a MapDocument object, you need to call IActiveView.Activate. The sample has been updated to reflect this, and you can read more about this in the ArcObjects documentation for IActiveView.Activate]

Thought Id cook up another simple example application that
shows how you can streamline the creation of repetitive maps. In this sample
Im going to create either a PDF of the map layout, or a JPEG of the map.
This sample also shows another use of the configuration section handlers I
posted recently. It’s written in
VB.NET, and its based on ArcGIS 9.2.

Scenario

You work for a county
GIS
department and every
day people come in, and ask for maps of their property. These are very simple
maps basically just the parcel outline with other base data. Since you are an
industrious person, you always have ArcMap open doing some other work, and its a
pain to close your current map, open the countys standard Parcel Map mxd, zoom
to the parcel and export the map. You want a simpler way to do this.

IMapDocument & MapDocument Class

This is the central point for getting things started. The
MapDocument Class can be instantiated and used to load a map document. Its
worth noting that this happens much faster than opening ArcMap the whole
thing open map, select feature, zoom to it, and export to PDF takes ~ 1
second. Time savings of not watching ArcMap spin up could more than pay for the
effort to customize this sample!

‘Load up a map into an IMapDocument

 Dim mapDoc As IMapDocument = New MapDocument

 mapDoc.Open(myMxdFile)

Once you have the document, the ArcObjects code needed to
zoom to a particular area is very simple. The export to an image is somewhat
complex, but the sample wraps that up in the ExportMapToImage and ExportPDF
methods.

Sample Solution

The sample solution has two projects the MapMaker class
library that contains the configuration handler, and the code that actually
exports the maps, and a simple WinForms app that can drive the class library,
Sample data and a MXD file is included in the zip file. All you need to change
to get this to run is set the path to the mxd file in the app.config of the
MapMakerForm project.

 

MapMaker Class Library

The MapMaker Class library really only has one class of signifigance – the MapMaker itself. Since I like to make things flexible, it also has a configuration section handler, which is
used to define the various map files that the class can work with. These are
referred to as MapMakerServices. The class model is below

A service has a name, an mxd file, the layer the query
will be run on, and the field that the “where clause” in the query will be applied. The following
shows the app.config section for the sample.

  <mapmakerservices tempfolder=G:\temp>

    <service name=ParcelMap mxdfile=G:\SVN\Research\Automation\Data\parcelmap.mxd querylayer=Parcels queryfield=pidn/>

  </mapmakerservices>

By having a config section, you can cook up a simple application that can access a wide array of map files, without having to change the actual implementation at all. Although there is only one service defined in the sample, the list of MapMakerServices is bound to a combo box.

Functionality

Basically, you pass in a whereclause, the height and width
of the map you want, the type of output (JPEG or PDF) and an output file. The
MapMaker will then locate the layer specified in the service, query it for a
matching feature, zoom to it, and create the map.

 

The data that comes with the sample is of parcels. So the
usage in the sample is that the user passed in a PIN, the MapMaker locates and
zooms to the parcel, and then exports a map image. The layout in the sample is
plain as can be, but Ill leave the cartography up to you.

 

Anyhow this is a super simple example of how to automate
ArcMap map creation without actually firing up ArcMap.

Download the source code (2.25Mb includes sample data)

Have fun!

Live Writer Test – AGAIN…

Posted by Dave Bouwman | Posted in Uncategorized | Posted on 27-01-2007

0

Just seeing if I can get images to upload from WLW into dasBlog…

ESRI Citrix Whitepapers

Posted by Dave Bouwman | Posted in ArcGIS Devt, ArcMap | Posted on 26-01-2007

0

I’ve been working on the System Architecture for a Citrix based enterprise GIS system, and in the process have dug up a bunch of ESRI whitepapers on the topic. If you run ArcGIS in a Citrix environment, these are some good reading…

 
System Design Strategies – ESRI Whitepaper (PDF Jan 2007)

This is the mothership for all ESRI system design topics. Check pages 8-8-3 for the WTS/Citrix server sizing models (partially shown below)

According to the model, you can run 45 ArcMap sessions on an Intel Xeon with 2 Dual Core 3Ghz (5160) CPUs and 16GB of RAM. In case your were wondering – you can pick up a Dell PowerEdge 1950 with this configuration for ~$10,000. And if you want to be really cool, you could go with the quad core CPU’s for about ~$2,000 more. RAM starts to get pretty pricy when you go much above 16GB, so while you likely can’t stuff 90 users onto a quad core system, for $2,000 more, your 45 users will have a lot more power at their disposal.

Citrix / WTS Support Overview - Whitepaper (HTML – Feb 2006)

This covers the main topics, including how to configure multiple products (ArcView/ArcEditor) to run on the same server.

Force ArcMap to close when logging off Citrix - ESRI Tech Article

Printing from ArcGIS on Citrix – ESRI Whitepaper (PDF – Oct 2006)

System Architecture to Support Printing on Citrix - Citrix Whitepaper (PDF – Nov 2001)

Metaframe Printing Optimization Techniques - Citrix Whitepaper (PDF – Feb 2004)

 

I’ll update this post as I find more resources.

ESRI Dev Summit Code Challenge

Posted by Dave Bouwman | Posted in ArcGIS Server, Dev Summit, ESRI | Posted on 19-01-2007

0

I was just getting the details for our trip out to the Dev Summit, and I noticed that they added a little something new…

Read all about it on the Code Challenge page, but here’s the basic deal:
  1. Whip up something cool with ArcGIS Server
  2. Post it to ArcScripts
  3. Register for the contest
  4. Win prizes – 1st: Trimble GPS, 2nd: XBox 360, 3rd:a Zune

What’s cool is that the community gets to vote on the entries – so it will be interesting to see what get’s submitted.

Avoiding IP Issues
Before everyone starts submitting code, I’d recommend clearing your submission with whoever you report to. Some organizations can be very concerned about intellectual property, and many times the people who are the most concerned are the least knowlegable about what can be shared vs what is an actual “trade secret”. Best be safe than sorry.

Damn – I just noticed that James posted about this! There is no getting ahead of him! ;-)

Monitoring Remote Servers: Part 2

Posted by Dave Bouwman | Posted in ASP.NET, Web Services | Posted on 17-01-2007

2

I’ve been running my Server Monitor for a few days, and logged serveral thousand data points – more or less getting “perfmon” type data every minute. Pulling this into Excel we can see some interesting patterns…

As the number of running ASP.NET applications increase (blue dots) they top out around 28. At that point the server runs for a while, until something happens, and ASP.NET is effectively killed – all the worker processes are killed off (the running applications drop), RAM is freed up (we see the Mem Usage drop), and the response time is significantly higher than usual – which makes sense since the server is busy re-starting IIS or ASP.

Anyhow – I’m sending this data off to my hosting provider. I’ll let you know how they handle it.

Source Code
Also – as promised – I’ve uploaded the source code for the web service and the viewer/logger. There is no step-by-step how to for using it – I assume that you understand web services, and WinForms. Just grab the code and have at it. You can contact me if you have problems. The logger is using SQL Express, and the SQL for creating the tables and a view (handy for pulling the data int Excel) is also in the zip.

Keeping it simple…

Posted by Dave Bouwman | Posted in Software | Posted on 12-01-2007

2

One challenge to software developers is to keep software simple. As
developers, we are both comfortable with complexity (just look at the Visual
Studio interface) and have a tendency to create applications that are
complex. The thing is that the end users really just want to get their
jobs done
. They want software that they don’t have to think about.
Software that is obvious and easy to use. They want one click not 5, and
short-cut keys are even better. Simple is better.

When a user is given software that helps them get their job done, they will
use it. If it’s also simple and easy to use, they will be happy. And a happy
customer is the simplest way to get more customers.

So – beyond the happy user, why should we want to build simple software? The
world is complex and does not always follow simple cut and dry rules. Shouldn’t
our software handle all the possible corner cases? If the complexity is a
necessary part of the business process, it will need to be addressed in the
software. But we want to avoid unnecessary functions that are
not business critical i.e. an RSS reader a parcel management system.

In the end, the level of simplification you can achieve in your
application does come down to negotiation with your client, but there are some
compelling reasons to avoid complexity. First, as noted above, simple software
is easier to use and more likely to be used. This is a big win right out of the
gate, especially if it is a new technology deployment. If it’s really easy to
use, the organization may also see significant productivity gains – which is a
huge win.

Additionally, designing simple software forces the team to focus
their effort on only the most critical elements of the system and on executing
them in the most effective and efficient manner. Keeping the software simple
makes it easier to write and easier to test. Corner cases and “extra” rarely
used functions tend to eat up a lot of time, add a lot of complexity, and make
maintenance and testing more difficult. Since maintenance of software can be 60% of
it’s total lifetime cost
, keeping it simple can save a lot in the long run.
Finally – if it turns our that some areas of the application must address more
complex aspects of the business process, simple software is easy to extend.

Additional reading on ”Keeping it simple”

Conversation with Ward
Cunningham
  creator of “wiki” - quote: “Simplicity is the shortest path to a
solution”

Agile and Extreme
Programming
, which is focuses on skipping “big design up front” and writing
the simplest thing that can possibly work, and adding in complexity only when it
is absolutely necessary.

37Signals.com – a web company focused
on simple solutions. They build “elegant thoughtful products that do exactly
what you want, and nothing you don’t”. They have written a free e-book about their development
philosophy called “Getting
Real”

Joel Spolsky
(JoelOnSoftware.com)
also has some thoughts on “Simple”

Steve McConnell – author of Code Complete in addition to a number of other great books on software development wrote this article on simplicity as a best practice back in 1996

Monitoring Remote Servers: Part 1

Posted by Dave Bouwman | Posted in .NET, Web Services | Posted on 07-01-2007

1

Recently I’ve been having some problems with the performance of my web sites.
I use Montastic  (free web site
monitoring service) and it is reporting multiple outages almost every day. This
does not jive with the 99.99% uptime that my hosting provider claims. I should
note that I’ve got a shared server hosting package – $10/month for 200GB,
with up to 2GB in SQL Server. Not bad, but I think they overload their servers.

When I contacted them, they say that everything is fine, and that the box I’m
on is not overloaded. But I’m skeptical. The main reason is that my sites
should be fast.

My main site is essentially static
content that only uses ASP.NET for the master page functionality. This blog is
running dasBlog, which uses Xml files for
storage, and caches like crazy. ArcDeveloper.net runs on CommunityServer,
and does use SQL, so there’s a little hit there, but it also has serious
caching. Overall, things are static, or cached – essentially they should not be a lot of “work” for IIS.

This leads me to think that the server is overloaded – but I needed a
way I check what’s happening on a remote server that I do not have desktop
access to (i.e. I cannot connect to it with Perfmon). While I’m sure there are other tools/samples etc that can do this
same thing, I thought this would be an interesting little project to play with over the holidays.

Performance Data + .NET

The key to getting system  performance information in .NET is the  System.Diagnostics.PerformanceCounter class.
Using this, you can basically access any performance counter on the system. Pair
this with a simple web service to collect the data, a windows client to make the
requests and store the data, and I had a quick and dirty server load monitor.

The rest of this post will discuss the web service and the client. A subsequent
post will talk about the results, and contain the source code.

ServerLoad Web Service

It’s hard to make a simpler web service than this – the GetSystemData method simply
returns performance counter information in the form of a MonitorData object. This first method just returns CPU untilization, and Available Memory. While very limited, this could at least tell me if the Montasic service was wrong, of if indeed there were some issues on the server itself.

    [WebMethod]

    public MonitorData GetSystemData() {

        float aveLoad = 0;

        float totalLoad = 0;

        float aveMem = 0;

        float totalMem = 0;

        try

        {

 

            PerformanceCounter cpuCounter =

                    new PerformanceCounter(“Processor”, “% Processor Time”, “_Total”);

            PerformanceCounter theMemCounter =

                    new PerformanceCounter(“Memory”, “Available MBytes”);

            for (int i = 0; i < 10; i++)

            {

                totalLoad = totalLoad + cpuCounter.NextValue();

                totalMem = totalMem + theMemCounter.NextValue();

                System.Threading.Thread.Sleep(100);

            }

 

            return new MonitorData(totalLoad / 10, totalMem/10);

        }

 

        catch (Exception ex) {

            throw new SoapException(“Exception occured in Monitor: “ + ex.Message, null, ex);

        }                 

    }

Windows Client

Instead of storing the data on the server, I chose to have it stored on the client side. The windows client simply calls the web service on a set schedule, reports
the duration of the request, and the performance information in a SQL database.
Since I’m usually working with ArcGIS, it was fun  to write an app that
can use the native .NET data binding. In minutes I had created a database, a
table, a data adapter, and bound it into a datagridview. All from within Visual Studio, and without writing a line of code. Viva DataBinding!

 

Windows Client showing CPU and Memory usage

I after running this for a few days, I was seeing very similar things to what
the Montastic service was reporting. The only difference was that my monitor
would report a very long request when Montastic reported an outage. Which makes
sense since any request that takes longer than 5 seconds should legitimately be
called an outage.

The next step was to add in more counters so I could get a better handle on
what was happening on the server. Specifically I wanted more information on the ASP.NET counters.

For this, I added a second web method – GetASPData, which returns an Array of AspData
objects, instead of a single MonitorData object. This is a nicer model since I
can add as many counters as I want, without having to change the database
schema which stores the data.

Here’s he code for this web method. One change I’ve been thinking of making is to pass the AspData objects into the service. This would allow you to configure what performance counters you want from the client side. Maybe I’ll do this before releasing the source.

    [WebMethod]

    public List<AspData> GetASPNETData()

    {

        List<MonitorCounter> counterList = new List<MonitorCounter>();       

        try

        {

            //Create Counters

            counterList.Add(new MonitorCounter(“Processor”, “% Processor Time”, “_Total”));

            counterList.Add(new MonitorCounter(“Memory”, “Available MBytes”));

            counterList.Add(new MonitorCounter(“ASP.NET”, “Application Restarts”));

            counterList.Add(new MonitorCounter(“ASP.NET”, “Applications Running”));

            counterList.Add(new MonitorCounter(“ASP.NET”, “Worker Process Restarts”));

            counterList.Add(new MonitorCounter(“ASP.NET”, “Worker Processes Running”));

            counterList.Add(new MonitorCounter(“ASP.NET Applications”, “Compilations Total”,“__Total__”));

 

            //Get data every 100ms, for 1 second

            for (int i = 0; i < 10; i++)

            {

                foreach(MonitorCounter m in counterList){

                    m.CheckCounter();

                }

                System.Threading.Thread.Sleep(100);

            }

            List<AspData> aspDataList = new List<AspData>();

            foreach (MonitorCounter m in counterList)

            {

                aspDataList.Add(m.GetData());

            }

            return aspDataList;

        }

 

        catch (Exception ex)

        {

            throw new SoapException(“Exception occured in Monitor: “ + ex.Message, null, ex);

        }

    }

On the client side, I went through the same steps as before, but as I noted above, instead of one record per request, I now have 1 record per counter. I store the counter name so I can run queries to pull out data for specific counters. The data shown below is from my development box, so it’s got a really light load.

I’m going to push this latest version up to my site later today, and capture data for a while and then write up another posting with the results and the (cleaned up) source code.

ESRI Dev Summit Quote…

Posted by Dave Bouwman | Posted in Dev Summit, ESRI | Posted on 02-01-2007

3

Despite my sometimes pointed postings regarding ESRI, here’s a little something from the DevSummit site

And I totally stand by this – the Developer Summit was the best ESRI event that I have ever been to. Why?  Because it was directed at developers. Just developers. Despite the “geoprocessing will save the world” mantra (which even some ESRI people thought was wack), it was an excellent look at what was going on with 9.2, and some very good sessions on developing cross product (ArcMap/ArcEngine/ArcGIS Server) components. I hope that the success of last year does not lead to dumbing down of the content to attract a wider audience. (hope hope hope)

Although the listing of talks is not up yet – looks like a placeholder page – I’m very excited to attend this year. That said, I’d like to see some user papers/sessions so we get some “real-world” insights.

And if they do have the “Birds of a Feather” sessions (need a new name!) I’m going to propose a few – Unit Testing and Code Generation come to mind.

See you in Palm Springs!