4

I've been experimenting with the Military Aspects of Terrain Template, which has a toolbox associated with it. I've been using the following WPF Runtime code, which should open a tool in the associated toolbox . . .

private void RunToolButton_Click(object sender, RoutedEventArgs e)
{
        ESRI.ArcGIS.RuntimeManager.Bind(ESRI.ArcGIS.ProductCode.Desktop);
        //Set a reference to the IGPCommandHelper interface.
        IGPToolCommandHelper pToolHelper = new GPToolCommandHelperClass() as IGPToolCommandHelper;

        //Set the tool you want to invoke.
        string toolboxName = @"C:\ArcGISForDefense\Intelligence\MilitaryAspectsOfTerrainTemplate\Maps\Toolbox\Military Aspects of Terrain Toolbox.tbx";
        pToolHelper.SetToolByName(toolboxName, "CoverFromFlatTrajectoryWeapons");

        // Generate the array of parameters.
        IArray parameters = new ArrayClass();
        parameters.Add(@"C:\ArcGISForDefense\Intelligence\MilitaryAspectsOfTerrainTemplate\Maps\OperationGDB.gdb\BrigadeAOI");
        parameters.Add(@"C:\ArcGISForDefense\Intelligence\Operational_Environment\Data\MAoT\MAoT.gdb\CombinedVegetationCoverage");
        parameters.Add(@"C:\ArcGISForDefense\Intelligence\MilitaryAspectsOfTerrainTemplate\Maps\OperationGDB.gdb\CoverAreas");

        //Invoke the tool. 
        pToolHelper.Invoke(parameters);
}

When I try to run the code, I get the following error message, then it crashes at the "invoke" method . . . "Failed to open tool CoverFromFlatTrajectoryWeapons (Military Aspects of Terrain Toolbox.tbx)" Am I using the right syntax for opening a tool that is in the "Cover and Concealment" toolset, which is in the "Military Aspects of Terrain Toolbox.tbx" toolbox? Am I doing anything wrong that would prompt this error message? I would appreciate any help.

I also wrote the following routine as an alternative, but this also bombs when it gets to the last line of the routine . . .

 public void Run_CoverFromFlatTrajectoryWeapons_Tool()
    {
        // Initialize the geoprocessor.
        //Insert this line before invoking any ArcObjects to bind Engine runtime. 
        ESRI.ArcGIS.RuntimeManager.Bind(ESRI.ArcGIS.ProductCode.Engine);
        GeoProcessor gp = new GeoProcessor();

        // Add the toolbox.
        gp.AddToolbox(@"C:\ArcGISForDefense\Intelligence\MilitaryAspectsOfTerrainTemplate\Maps\Toolbox\Military Aspects of Terrain Toolbox.tbx");           

        // Generate the array of parameters.
        IVariantArray parameters = new VarArrayClass();
        parameters.Add(@"C:\ArcGISForDefense\Intelligence\MilitaryAspectsOfTerrainTemplate\Maps\OperationGDB.gdb\BrigadeAOI");
        parameters.Add(@"C:\ArcGISForDefense\Intelligence\Operational_Environment\Data\MAoT\MAoT.gdb\CombinedVegetationCoverage");
        parameters.Add(@"C:\ArcGISForDefense\Intelligence\MilitaryAspectsOfTerrainTemplate\Maps\OperationGDB.gdb\CoverAreas");
        // Execute the model tool by name.
        gp.Execute("CoverFromFlatTrajectoryWeapons", parameters, null);
    }

By the way, the above mentioned tool does run well with the specified parameters when running it in ArcMap.

Thanks, Renee

10
  • What version of ArcGIS? Commented May 1, 2013 at 22:04
  • @KirkKuykendall Version 10.1 Commented May 2, 2013 at 12:05
  • I suspect something to do with licensing ... did you try creating a new project using the template ArcGIS>Extending ArcObjects>ConsoleApplication(Desktop) ... then take all the license template code and copy it into your wpf project? Commented May 2, 2013 at 14:53
  • I wasn't able to find that template. It wasn't part of my "installed templates". Commented May 2, 2013 at 15:29
  • Try this one: ambergis.com/DesktopConsoleApplication1.zip Commented May 2, 2013 at 17:55

2 Answers 2

3

I would try registering an eventlistener, to help debug what's going on inside of the gp tool.

public static void Test()
{
    InvokeTool(@"C:\Program Files (x86)\ArcGIS\Desktop10.1\ArcToolbox\Toolboxes\3D Analyst Tools.tbx",
        "AddSurfaceInformation");
}

public static void InvokeTool(string tbxPath, string toolName)
{
    var gp = new GeoProcessorClass() as IGeoProcessor2;
    // Add the toolbox.
    gp.AddToolbox(tbxPath);

    //// Generate the array of parameters.
    IVariantArray parameters = new VarArrayClass();
    parameters.Add(@"a bad parameter");
    // Execute the model tool by name.
    var evts = new GpEvents();
    gp.RegisterGeoProcessorEvents3(evts);
    var result = gp.Execute(toolName, parameters,null);
}

Simple callback to see what the tool is experiencing ...

public class GpEvents : IGeoProcessorEvents3, IGeoProcessorEvents2, IGeoProcessorEvents 
{
    private void ListMsgs(IGPMessages msgs)
    {
        for (int i = 0; i < msgs.Count; i++)
        {
            var msg = msgs.GetMessage(i) as IGPMessage;
            Console.WriteLine("{0} {1}", msg.ErrorCode,msg.Description);
        }
    }
    public void OnProcessMessages(IGeoProcessorResult result, IGPMessages pMsgs)
    {
        Console.WriteLine("OnProcessMessages");
        ListMsgs(pMsgs);
    }
    public void OnProgressMessage(IGeoProcessorResult result, string message)
    {
        Console.WriteLine("OnProgressMessage");
    }
    public void OnProgressPercentage(IGeoProcessorResult result, double percentage)
    {
        Console.WriteLine("OnProgressPercentage");
    }
    public void OnProgressShow(IGeoProcessorResult result, bool Show)
    {
        Console.WriteLine("OnProgressShow");
    }
    public void PostToolExecute(IGeoProcessorResult result)
    {
        Console.WriteLine("PostToolExecute");
    }
    public void PreToolExecute(IGeoProcessorResult result)
    {
        Console.WriteLine("PreToolExecute");
    }
    public void OnMessageAdded(IGPMessage message)
    {
        Console.WriteLine("OnMessageAdded {0} {1}",message.ErrorCode, message.Description);
    }
    public void PostToolExecute(int result, IMdProcess Process)
    {
        Console.WriteLine("PostToolExecute");
    }
    public void PreToolExecute(IMdProcess Process)
    {
        Console.WriteLine("PreToolExecute");
    }
    public void ToolboxChange()
    {
        Console.WriteLine("ToolboxChange");
    }
    public void PostToolExecute(IGPTool Tool, IArray Values, int result, IGPMessages Messages)
    {
        Console.WriteLine("PostToolExecute");
        ListMsgs(Messages);
    }
    public void PreToolExecute(IGPTool Tool, IArray Values, int processID)
    {
        Console.WriteLine("PreToolExecute");
    }
}

The method above won't tell you when the toolname is not valid, so this can be used to list toolnames in a toolbox:

public static void ListTools(string tbxPath)
{
    var t = Type.GetTypeFromProgID("esriGeoprocessing.ToolboxWorkspaceFactory");
    var twf = Activator.CreateInstance(t) as IWorkspaceFactory;
    var fi = new System.IO.FileInfo(tbxPath);
    if (!fi.Exists)
        throw new System.IO.FileNotFoundException(tbxPath);
    var ws = twf.OpenFromFile(fi.DirectoryName, 0) as IToolboxWorkspace;
    var tbx = ws.OpenToolbox(fi.Name);
    var enumName = tbx.ToolNames;
    enumName.Reset();
    IGPToolName name;
    while ((name = enumName.Next()) != null)
    {
        Console.WriteLine("{0} : {1}", ((IDatasetName)name).Name, name.DisplayName);
    }
}
7
  • Unfortunately, I got the same error message when it hit the last line of the InvokeTool method. I also tried putting it inside a Try-Catch, but didn't get any descriptive error. Just "COMException". Commented May 6, 2013 at 14:20
  • When I run the tool from ArcMap, a GUI comes up that accepts as inputs the BrigadeAOI and CombinedVegetationCoverage layers, and indicates as output the CoverAreas layer. Is there a certain order in which I should be populating the parameter array? This is the way that I populate the parameters object . . . Commented May 6, 2013 at 14:34
  • parameters.Add(@"C:\ArcGISForDefense\Intelligence\MilitaryAspectsOfTerrainTemplate\Maps\OperationGDB.gdb\BrigadeAOI"); parameters.Add(@"C:\ArcGISForDefense\Intelligence\Operational_Environment\Data\MAoT\MAoT.gdb\CombinedVegetationCoverage"); parameters.Add(@"C:\ArcGISForDefense\Intelligence\MilitaryAspectsOfTerrainTemplate\Maps\OperationGDB.gdb\CoverAreas"); Commented May 6, 2013 at 14:35
  • Do any of the methods on GpEvents get called? Commented May 6, 2013 at 15:04
  • No, it just returns the error "Error HRESULT E_FAIL has been returned from a call to a COM component." Commented May 6, 2013 at 17:45
0

I realize this question is old but maybe someone will benefit from my contribution. I encountered same problem while working on Add-In for ArcMap 10.0. There is documented bug for 10.0 regarding IGPToolCommandHelper2 described here.

I found workaround how to open tool's dialog and avoid "Failed to open tool SomeTool (SomeToolbox.tbx)" error.

Here is the code:

public static IGPTool FindGPTool(string toolboxPath, string toolboxName, string toolName)
{
  var t = Type.GetTypeFromProgID("esriGeoprocessing.ToolboxWorkspaceFactory");
  IWorkspaceFactory iwf = Activator.CreateInstance(t) as IWorkspaceFactory;

  IToolboxWorkspace itw = (IToolboxWorkspace)iwf.OpenFromFile(toolboxPath, 0);
  IGPToolbox tbox = (IGPToolbox)itw.OpenToolbox(toolboxName);

  //return tbox.OpenTool(toolName); // Doesn't work. Produces error.
  IEnumGPTool tools = tbox.Tools;
  IGPTool gpTool = tools.Next();

  if (gpTool.Name.Equals(toolName, StringComparison.OrdinalIgnoreCase))
    return gpTool;

  while (gpTool != null)
  {
    gpTool = tools.Next();
    if (gpTool.Name.Equals(toolName, StringComparison.OrdinalIgnoreCase))
      return gpTool;
  }

  return null;
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.