[GIS] Getting “Failed to open tool” message when trying to run geoprocessing tool from C# code

arcgis-runtimearctoolboxcgeoprocessing

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

Best Answer

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);
    }
}