Éviter les échecs du géotraitement ArcObjects avec .NET?

14

Il existe de belles fonctionnalités dans ArcToolbox que nous pouvons utiliser, mais pour une raison quelconque, cela ne fonctionne PAS correctement. Cela ne me lance même pas d'erreur.

Mon logiciel s'exécute dans ArcMap, donc pas besoin de AoInitialize à nouveau, corret?

    public void Execute()
    {
        InitializeProduct();
        try
        {
            Geoprocessor gp = new Geoprocessor();
            gp.OverwriteOutput = true;

            FeatureToPoint featureToPoint = new FeatureToPoint();

            string outputPathName = CurrentWorkspace.PathName + "\\teste_centroide";

            featureToPoint.in_features = InputFeatureClass;
            featureToPoint.out_feature_class = outputPathName;
            featureToPoint.point_location = "INSIDE";

            IGeoProcessorResult result = (IGeoProcessorResult)gp.Execute(featureToPoint, null);

            if (result == null)
            {
                for (int i = 0; i <= gp.MessageCount - 1; i++)
                {
                    Console.WriteLine(gp.GetMessage(i));
                }
            }

            IGPUtilities gpUtils = new GPUtilitiesClass();
            this.OutputFeatureClass = gpUtils.OpenFeatureClassFromString(outputPathName);
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message + "\r\n");
        }

Ceci est un exemple de code que j'ai ici. J'ai généré l'assembly d'outils DataManagement, mais je n'ai pas pu trouver le fichier pour le signer.

Ce code me donne juste une erreur. est-ce à cause de la signature?

J'ai également essayé dans l'autre sens, en utilisant IVariantArray et en appelant depuis le nom de l'outil, sans succès. Est-ce juste moi ou ...?

Quelqu'un peut-il me désigner une solution «plus agréable»? J'ai besoin d'exécuter plusieurs processus déjà construits dans ArcToolbox que je ne veux vraiment pas dupliquer.

George Silva
la source
Quelle est l'erreur que vous mentionnez plus tard dans votre question?
Dandy
Bonjour Dandy. Il ne génère pas d'erreurs, il échoue.
George Silva

Réponses:

14

Dans le code ci-dessous, la fonction multi2single fonctionne pour moi dans 10.0. Je n'ai pas pu tester Feature2Point car je n'ai pas de licence ArcInfo, pouvez-vous?.

public class Test
{
    public static void TestGP(IApplication app)
    {
        IMxDocument mxDoc = (IMxDocument)app.Document;
        //Feat2Point((IFeatureLayer)mxDoc.FocusMap.get_Layer(0), @"D:\Projects\AmberGIS\Forums\forumtest.gdb\f2p");
        Multi2Single((IFeatureLayer)mxDoc.FocusMap.get_Layer(0), @"D:\Projects\AmberGIS\Forums\forumtest.gdb\m2s");
    }

    public static void Multi2Single(IFeatureLayer inLayer, string outPath)
    {
        MultipartToSinglepart m2s = new MultipartToSinglepart();
        m2s.in_features = inLayer.FeatureClass;
        m2s.out_feature_class = outPath;
        Execute(m2s);
    }

    public static void Feat2Point(IFeatureLayer inLayer, string outPath)
    {
        FeatureToPoint f2p = new FeatureToPoint();
        f2p.in_features = inLayer.FeatureClass;
        f2p.out_feature_class = outPath;
        Execute(f2p);
    }

    public static void Execute(IGPProcess proc)
    {
        Geoprocessor gp = new Geoprocessor();
        gp.AddOutputsToMap = true;
        gp.OverwriteOutput = true;
        gp.RegisterGeoProcessorEvents((IGeoProcessorEvents)new GPEvents());
        IGeoProcessorResult2 result = gp.Execute(proc, null) as IGeoProcessorResult2;
        IGPMessages msgs = result.GetResultMessages();
        for(int i=0;i<msgs.Count;i++)
            Debug.Print("{0} {1}", msgs.GetMessage(i).Description, msgs.GetMessage(i).Type);            
    }
}
public class GPEvents : IGeoProcessorEvents3, IGeoProcessorEvents 
{
    #region IGeoProcessorEvents3 Members
    public void OnProcessMessages(IGeoProcessorResult result, IGPMessages pMsgs)
    {
        Debug.Print("OnProcessMessages {0}", result.Status);
    }
    public void OnProgressMessage(IGeoProcessorResult result, string message)
    {
        Debug.Print("OnProgressMessages {0}", result.Status);
    }
    public void OnProgressPercentage(IGeoProcessorResult result, double percentage)
    {
        Debug.Print("OnProgressPercentage {0}", result.Status);
    }
    public void OnProgressShow(IGeoProcessorResult result, bool Show)
    {
        Debug.Print("OnProgressShow {0}", result.Status);
    }
    public void PostToolExecute(IGeoProcessorResult result)
    {
        Debug.Print("PostToolExecute {0}", result.Status);
    }
    public void PreToolExecute(IGeoProcessorResult result)
    {
        Debug.Print("PreToolExecute {0}",result.Status);
    }
    #endregion

    #region IGeoProcessorEvents Members

    void IGeoProcessorEvents.OnMessageAdded(IGPMessage message)
    {
        Debug.Print("OnMessageAdded {0} {1}", message.Description, message.Type);
        throw new NotImplementedException();
    }

    void IGeoProcessorEvents.PostToolExecute(IGPTool Tool, ESRI.ArcGIS.esriSystem.IArray Values, int result, IGPMessages Messages)
    {
        Debug.Print("PostToolExecute2 {0}", Tool.Name);
    }

    void IGeoProcessorEvents.PreToolExecute(IGPTool Tool, ESRI.ArcGIS.esriSystem.IArray Values, int processID)
    {
        if (Tool.IsLicensed())
            Debug.Print("PreToolExecute");
        else
            Debug.Print("tool is not licensed to run");
    }

    void IGeoProcessorEvents.ToolboxChange()
    {
        Debug.Print("ToolboxChange");
    }

    #endregion
}

J'obtiens cette sortie en VS:

PreToolExecute
PostToolExecute2 MultipartToSinglepart
Executing: MultipartToSinglepart GPL0 D:\Projects\AmberGIS\Forums\forumtest.gdb\m2s esriGPMessageTypeProcessDefinition
Start Time: Thu Sep 02 11:32:44 2010 esriGPMessageTypeProcessStart
Succeeded at Thu Sep 02 11:32:51 2010 (Elapsed Time: 7.00 seconds) esriGPMessageTypeProcessStop
Kirk Kuykendall
la source
Cette gestion des erreurs est fantastique Kirk. Je n'ai jamais passé assez de temps à utiliser le géoprocesseur pour connaître les interfaces IGeoProcessorEvent. Merci de l'avoir signalé!
BlinkyBill
VOTRE code fonctionne! ArcObjects ne m'aime pas.
George Silva
4

Vous avez raison, car il n'y a pas besoin d'AoInitialize. Comme vous l'avez découvert, le débogage avec l'objet géoprocesseur est une douleur dans le cou.

Ce que vous devez faire, lisez le message, l'avertissement et la file d'attente d'erreurs après chaque appel, pour vérifier les problèmes. Il n'y a pas de chance de s'appuyer sur la gestion des erreurs .NET standard.

Essayez ceci après chaque appel d'exécution (notez GetMessageS, pas GetMessage) ...

Console.WriteLine("Messages: " + gp.GetMessages(1));
Console.WriteLine("Warnings: " + gp.GetMessages(2));
Console.WriteLine("Errors: " + gp.GetMessages(3));
BlinkyBill
la source
Bonjour eldac! J'ai abandonné après quelques heures de coups de tête, mais je vais réessayer bientôt et je terminerai les suivis sur la question. Serait-ce un problème avec la signature de l'assembly lors de sa première génération?
George Silva
Salut George, ce n'est probablement pas un problème de signature. Si vous avez une simple erreur de syntaxe / chemin / type dans les paramètres du FeatureToPoint (ou de tout autre outil de géotraitement), elle échouera sans aucune notification, d'où l'inspection de la file d'attente des erreurs. Je ne m'embête plus guère avec les outils de géotraitement. Cela prend juste si longtemps pour le faire fonctionner dans la plupart des cas, car le débogage est un enfer.
BlinkyBill
C'est une douleur, car j'ai besoin de tester un centroïde, mais je ne sais pas comment pourrais-je lier les modifications que je dois faire sans utiliser un outil de géotraitement. J'ai besoin de modifier une couche polygonale, mais les tests doivent être effectués sous son centre de gravité. J'utilise une requête spatiale pour filtrer mes résultats, donc je perdrais cela.
George Silva