How to debug compiled components?

Hi all,

i tried to compile a c# script in visiual studio to get a grasshopper component. The script works as a c# script component but not as a compiled component but it throughs also no error and compile successful.
The problem is that the compiled component does nothing and the question is how can i debug or find the error so that the component do what it should do ?.

using System;
using System.Collections;
using System.Collections.Generic;

using Rhino;
using Rhino.Geometry;

using Grasshopper;
using Grasshopper.Kernel;
using Grasshopper.Kernel.Data;
using Grasshopper.Kernel.Types;

using System.IO;
using NPOI.XSSF.UserModel;
using NPOI.XSSF.Model;
using NPOI.HSSF.Model;
using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using ICSharpCode.SharpZipLib;
using NPOI.SS.Util;


/// <summary>
/// This class will be instantiated on demand by the Script component.
/// </summary>
public class Script_Instance : GH_ScriptInstance
{
#region Utility functions
  /// <summary>Print a String to the [Out] Parameter of the Script component.</summary>
  /// <param name="text">String to print.</param>
  private void Print(string text) { /* Implementation hidden. */ }
  /// <summary>Print a formatted String to the [Out] Parameter of the Script component.</summary>
  /// <param name="format">String format.</param>
  /// <param name="args">Formatting parameters.</param>
  private void Print(string format, params object[] args) { /* Implementation hidden. */ }
  /// <summary>Print useful information about an object instance to the [Out] Parameter of the Script component. </summary>
  /// <param name="obj">Object instance to parse.</param>
  private void Reflect(object obj) { /* Implementation hidden. */ }
  /// <summary>Print the signatures of all the overloads of a specific method to the [Out] Parameter of the Script component. </summary>
  /// <param name="obj">Object instance to parse.</param>
  private void Reflect(object obj, string method_name) { /* Implementation hidden. */ }
#endregion

#region Members
  /// <summary>Gets the current Rhino document.</summary>
  private readonly RhinoDoc RhinoDocument;
  /// <summary>Gets the Grasshopper document that owns this script.</summary>
  private readonly GH_Document GrasshopperDocument;
  /// <summary>Gets the Grasshopper script component that owns this script.</summary>
  private readonly IGH_Component Component;
  /// <summary>
  /// Gets the current iteration count. The first call to RunScript() is associated with Iteration==0.
  /// Any subsequent call within the same solution will increment the Iteration count.
  /// </summary>
  private readonly int Iteration;
#endregion

  /// <summary>
  /// This procedure contains the user code. Input parameters are provided as regular arguments,
  /// Output parameters as ref arguments. You don't have to assign output parameters,
  /// they will have a default value.
  /// </summary>
  private void RunScript(bool Execute, string PathOpen, string PathSave, string Sheet, string RowColStart, DataTree<object> Table)
  {
    if (Execute)
    {
      HSSFWorkbook wb;
      using (FileStream fs = new FileStream(PathOpen, FileMode.Open, FileAccess.Read))
      {
        wb = new HSSFWorkbook(fs);
      }

      ISheet sheet = wb.GetSheet(Sheet);
      CellReference c = new CellReference(RowColStart);
      int columnC = (int) Table.Branches.Count;
      int rowC = (int) Table.Branch(0).Count;
      Print(c.Row.ToString());


      for (int i = c.Row   ; i <= c.Row + rowC - 1 ; i++)
      {
        IRow row = sheet.GetRow(i);
        if (row == null)
        {
          IRow rowCr = sheet.CreateRow(i);
          for (int r = c.Col  ; r <= c.Col + columnC - 1  ; r++)
          {
            var x = Table.Branch(r - c.Col)[i - c.Row];
            string B = Convert.ToString(x);
            if (string.IsNullOrEmpty(B))
            {
              rowCr.CreateCell(r).SetCellType(CellType.Blank);
            }
            else
            {
              double dob;
              if (double.TryParse(B, out dob))
              {
                rowCr.CreateCell(r).SetCellValue(dob);
              }
              else
              {
                rowCr.CreateCell(r).SetCellValue(0);
              }
            }
          }
        }
        else
        {
          for (int r = c.Col  ; r <= c.Col + columnC - 1 ; r++)
          {
            ICell cell = row.GetCell(r, MissingCellPolicy.RETURN_NULL_AND_BLANK);
            if (cell == null)
            {

              var x = Table.Branch(r - c.Col)[i - c.Row];
              string B = Convert.ToString(x);
              if (string.IsNullOrEmpty(B))
              {
                row.CreateCell(r).SetCellValue(0);
              }
              else
              {
                double dob;
                if (double.TryParse(B, out dob))
                {
                  row.CreateCell(r).SetCellValue(dob);
                }
                else
                {
                  row.CreateCell(r).SetCellValue(0);
                }
              }
            }
            else
            {
              var x = Table.Branch(r - c.Col)[i - c.Row];
              string B = Convert.ToString(x);
              if (string.IsNullOrEmpty(B))
              {
                cell.SetCellValue(0);
              }
              else
              {
                double dob;
                if (double.TryParse(B, out dob))
                {
                  cell.SetCellValue(dob);
                }
                else
                {
                  cell.SetCellValue(B);
                }
              }
            }
          }
        }
      }
      wb.ForceFormulaRecalculation = true;
      using (FileStream fs = new FileStream(PathSave, FileMode.Create, FileAccess.Write))
      {
        wb.Write(fs);
      }
      wb.Close();

    }
  }

  // <Custom additional code> 




  // </Custom additional code> 
}

The code in visual studio.

using System;
using System.IO;
using System.Collections.Generic;
using NPOI.XSSF.UserModel;
using NPOI.XSSF.Model;
using NPOI.HSSF.Model;
using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using ICSharpCode.SharpZipLib;
using NPOI.SS.Util;
using Grasshopper.Kernel;
using Grasshopper.Kernel.Data;
using Grasshopper.Kernel.Types;
using Rhino.Geometry;

// In order to load the result of this wizard, you will also need to
// add the output bin/ folder of this project to the list of loaded
// folder in Grasshopper.
// You can use the _GrasshopperDeveloperSettings Rhino command for that.

namespace XLS_Writer
{
    public class XLSWriterComponent : GH_Component
    {
        /// <summary>
        /// Each implementation of GH_Component must provide a public 
        /// constructor without any arguments.
        /// Category represents the Tab in which the component will appear, 
        /// Subcategory the panel. If you use non-existing tab or panel names, 
        /// new tabs/panels will automatically be created.
        /// </summary>
        public XLSWriterComponent()
          : base("XLS_Writer", "Nickname",
              "Description",
              "Category", "Subcategory")
        {
        }

        /// <summary>
        /// Registers all the input parameters for this component.
        /// </summary>
        protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
        {
            pManager.AddBooleanParameter("Execute", "Execute", "run the component", GH_ParamAccess.item, false);
            pManager.AddTextParameter("PathOpen", "PathOpen", "path for existing xls file", GH_ParamAccess.item, "None");
            pManager.AddTextParameter("PathSave", "PathSave", "path for modified xls file", GH_ParamAccess.item, "None");
            pManager.AddTextParameter("Sheet", "Sheet", "xls sheet name", GH_ParamAccess.item, "None");
            pManager.AddTextParameter("RowColStart", "RowColStart", "", GH_ParamAccess.item, "None");      
            pManager.AddGenericParameter("Table", "Table", "data table", GH_ParamAccess.tree);
            
        }

        /// <summary>
        /// Registers all the output parameters for this component.
        /// </summary>
        protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager)
        {         
        }

        /// <summary>
        /// This is the method that actually does the work.
        /// </summary>
        /// <param name="DA">The DA object can be used to retrieve data from input parameters and 
        /// to store data in output parameters.</param>
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            bool execute = false;
            string PathOpen = "None";
            string PathSave = "None";
            string Sheet = "None";
            string RowColStart = "None";
            string Table = "None";


            if (!DA.GetData(0, ref execute)) return;
            if (!DA.GetData(1, ref PathOpen)) return;
            if (!DA.GetData(2, ref PathSave)) return;
            if (!DA.GetData(3, ref Sheet)) return;
            if (!DA.GetData(4, ref RowColStart)) return;
            if (!DA.GetData(4, ref Table)) return;
        }

        private void XLSWrite(bool execute, string PathOpen, string PathSave,string Sheet, string RowColStart, Grasshopper.DataTree<object> Table)
        {
            if (execute)
            {
                HSSFWorkbook wb;
                using (FileStream fs = new FileStream(PathOpen, FileMode.Open, FileAccess.Read))
                {
                    wb = new HSSFWorkbook(fs);
                }

                ISheet sheet = wb.GetSheet(Sheet);
                CellReference c = new CellReference(RowColStart);
                int columnC = (int)Table.Branches.Count;
                int rowC = (int)Table.Branch(0).Count;
                //Print(c.Row.ToString());


                for (int i = c.Row; i <= c.Row + rowC - 1; i++)
                {
                    IRow row = sheet.GetRow(i);
                    if (row == null)
                    {
                        IRow rowCr = sheet.CreateRow(i);
                        for (int r = c.Col; r <= c.Col + columnC - 1; r++)
                        {
                            var x = Table.Branch(r - c.Col)[i - c.Row];
                            string B = Convert.ToString(x);
                            if (string.IsNullOrEmpty(B))
                            {
                                rowCr.CreateCell(r).SetCellType(CellType.Blank);
                            }
                            else
                            {
                                if (double.TryParse(B, out double dob))
                                {
                                    rowCr.CreateCell(r).SetCellValue(dob);
                                }
                                else
                                {
                                    rowCr.CreateCell(r).SetCellValue(0);
                                }
                            }
                        }
                    }
                    else
                    {
                        for (int r = c.Col; r <= c.Col + columnC - 1; r++)
                        {
                            ICell cell = row.GetCell(r, MissingCellPolicy.RETURN_NULL_AND_BLANK);
                            if (cell == null)
                            {

                                var x = Table.Branch(r - c.Col)[i - c.Row];
                                string B = Convert.ToString(x);
                                if (string.IsNullOrEmpty(B))
                                {
                                    row.CreateCell(r).SetCellValue(0);
                                }
                                else
                                {
                                    if (double.TryParse(B, out double dob))
                                    {
                                        row.CreateCell(r).SetCellValue(dob);
                                    }
                                    else
                                    {
                                        row.CreateCell(r).SetCellValue(0);
                                    }
                                }
                            }
                            else
                            {
                                var x = Table.Branch(r - c.Col)[i - c.Row];
                                string B = Convert.ToString(x);
                                if (string.IsNullOrEmpty(B))
                                {
                                    cell.SetCellValue(0);
                                }
                                else
                                {
                                    if (double.TryParse(B, out double dob))
                                    {
                                        cell.SetCellValue(dob);
                                    }
                                    else
                                    {
                                        cell.SetCellValue(B);
                                    }
                                }
                            }
                        }
                    }
                }
                wb.ForceFormulaRecalculation = true;
                using (FileStream fs = new FileStream(PathSave, FileMode.Create, FileAccess.Write))
                {
                    wb.Write(fs);
                }
                wb.Close();

            }
        }

        /// <summary>
        /// Provides an Icon for every component that will be visible in the User Interface.
        /// Icons need to be 24x24 pixels.
        /// </summary>
        protected override System.Drawing.Bitmap Icon
        {
            get
            {
                // You can add image files to your project resources and access them like this:
                //return Resources.IconForThisComponent;
                return null;
            }
        }

        /// <summary>
        /// Each component must have a unique Guid to identify it. 
        /// It is vital this Guid doesn't change otherwise old ghx files 
        /// that use the old ID will partially fail during loading.
        /// </summary>
        public override Guid ComponentGuid
        {
            get { return new Guid("80160204-7edf-44eb-afbe-053fe0c7b5ea"); }
        }
    }
}

Any tips what the problem could be is welcome.

Simply set some breakpoints In Visual Studio just to step through. Debugger -> ‘Attach to Process’ -> ‘Rhino’ (once your plugin is loaded in Rhino).

Hi @flokart,

First of all I would change the

    if(Execute) {...

into

    if (!Execute) return; // done.

… to avoid having endless long {curly} blocks. :slight_smile:

In the script component I would also use messages with info about the state, and a return to test, before or after a suspected line.

RhinoApp.WriteLine("Message with value {0}", your_variable);
return;

or if something crashes, insert return; early in the code and see if it crashes, and if not, move the “return;” to the next line, and so on until you know which row is bombing.

Aso. :slight_smile:

// Rolf

Use Tom’s suggestion. Setting breakpoints and stepping through executing code is the best way to understand what is happening.

You should also run GrasshopperDeveloperSettings and disable coff loading.