Dev Space

Customize and extend the power of Alteryx with SDKs, APIs, custom tools, and more.
SOLVED

C# DotNet Tools: Unstable in a Macro

Hiblet
10 - Fireball

I have written a C# DotNet custom plug in tool that spawns a process and pulls the process' output back into the workflow. 

 

It works really well when used as a normal tool in a workflow.

 

If I wrap it in a macro, and work the macro with a simple harness, the tool seems to work, in that I get data out of the macro, but the attached Browse tool errors with...

 

Error: Browse (4): Error creating the file "  ": The system cannot find the path specified.

 

If I try to run the macro harness workflow with Visual Studio attached as the debugger, AlteryxGui.exe crashes with exit code -1073740791 (0xc0000409).

 

What is different about a macro that would cause this, and how can I debug the problem?

10 REPLIES 10
jdunkerley79
ACE Emeritus
ACE Emeritus

Hi @Hiblet,

 

I did a quick test running HostName over and over:

using System;
using System.Diagnostics;
using AlteryxGuiToolkit.Plugins;
using AlteryxRecordInfoNet;
using OmniBus.Framework;
using OmniBus.Framework.Attributes;
using OmniBus.Framework.Interfaces;

namespace OmniBus.XmlTools
{
    [PlugInGroup("Omnibus", "HostName")]
    public class HostName : BaseTool<object, HostName.Engine>, IPlugin
    {
        public class Engine : BaseEngine<object>
        {
            /// <summary>Gets the input stream.</summary>
            public IInputProperty Input { get; }

            /// <summary>Gets or sets the output stream.</summary>
            public IOutputHelper Output { get; set; }

            public Engine()
            {
                this.Input = new InputProperty(this);
                this.Input.InitCalled += (i, s) => this.Output?.Init(new RecordInfoBuilder().AddFields(i.RecordInfo)
                    .AddFields(new FieldDescription("Output", FieldType.E_FT_V_WString, 12000)).Build());
                this.Input.RecordPushed += Input_RecordPushed;
                this.Input.ProgressUpdated += (s, p) => this.Output?.UpdateProgress(p, true);
                this.Input.Closed += (s) => this.Output.Close(true);
            }

            private void Input_RecordPushed(IInputProperty a, AlteryxRecordInfoNet.RecordData data,
                Framework.EventHandlers.SuccessEventArgs success)
            {
                var proc = new System.Diagnostics.Process
                {
                    StartInfo = new ProcessStartInfo(@"C:\Windows\System32\HOSTNAME.EXE")
                    {
                        UseShellExecute = false,
                        RedirectStandardOutput = true,
                        CreateNoWindow = true
                    }
                };
                proc.Start();
                proc.WaitForExit(1000);

                this.Output.Record.Reset();
                this.Input.Copier.Copy(this.Output.Record, data);
                var field = this.Output.RecordInfo.GetFieldByName("Output", false);
                field.SetFromString(this.Output.Record, $"{proc.StandardOutput.ReadToEnd().Trim()} - {DateTime.Now:HH:mm:ss}");
                this.Output.Push(this.Output.Record);
            }
        }
    }
}

This works fine within a macro. Happy to try and solve if you can share code.

 

In terms of debugging as long as the ini file points to the dlls in the debug folder and you launch Alteryx from VS debugger should allow you to add break points.

2018-10-24_22-44-02.png

 

Happy to Skype/Webex if would help

 

James

 

 

 

Hiblet
10 - Fireball

Hi James @jdunkerley79,

 

Thanks immensely for the offer of help!  

 

I have cloned your AddIns repo and am now working through it.  It is a very elegant project, way above my level.  Thank you for sharing it.

 

 

I will try to write an Omnibus pass-through tool, which will effectively do nothing, and try the same thing with the vanilla SDK code, and see if that is OK.  Then I can add output columns, check that works, and gradually roll forward to the whole tool to see where the problem comes in.

 

When the problem tool is in a workflow, it functions nicely.  When I wrap it in a macro, it still seems to work, but the downstream Browse tool errors.  When I attach a debugger during the macro run, Alteryx crashes out.  I will add some breakpoints around the record push to see what is going on.  The strange thing is that the tool does not do any file IO, so I do not understand why the Browse tool would complain about file names.  The only file stuff I know of is the config read-write.

 

Many thanks for the offer of help.  I think I have enough tools and ideas to get some traction on the problem, so I will try a bit harder with it, and then send up a flare if I get into difficulty.


Steve

 

jdunkerley79
ACE Emeritus
ACE Emeritus

Hey @Hiblet

 

Always happy to help.

 

Take the newest 0.6 branch of the repo - I've finally got to a design I like now. 

 

You can just include the framework as nuget packages but often easier to access raw source. The Nuget approach has perk that it will configure VS correctly for working with Alteryx.

 

Any help I can be just shout. 

 

You inspired me to make a new command tool allowing for a handlebar syntax and execution of custom command on each line :)

 

2018-10-25_09-50-31.png

 

J

Hiblet
10 - Fireball

Hi James @jdunkerley79

 

OK, I'm stuck!  I'm just working through the tool tutorial...

  https://github.com/jdunkerley/AlteryxAddIns/wiki/Creating-Your-First-Custom-Tool

 

I went through this yesterday, using 0.5, and it was fine, everything worked as expected.  

 

I am trying now to run through it again, to try to create a transparent pass through tool.  Before attempting to convert it to a pass-through tool, I intended to follow the tutorial exactly, get it working, and then attempt to change it.

 

I am getting a problem when trying to implement PI_PushAllRecords().  The function FieldDescription.CreateRecordInfo() is not being recognised, even though I have using references.  I thought it might have been made private, but checking the framework source code shows that it is still public.

 

Do you have time to Skype?


Steve

jdunkerley79
ACE Emeritus
ACE Emeritus

Sure. Sent you a DM with Skype address

 

That sample was written against 0.5.3. Will be a bit different for 0.6

 

Hiblet
10 - Fireball

Hi James @jdunkerley79

 

Thanks for the Skype session, very interesting.  

 

Using Omnibus 0.6 methods, the tool compiles, but when I debug in Alteryx I get...

 

Error: Transparent (1): Could not load type 'OmniBus.Framework.RecordInfoBuilder' from assembly 'OmniBus.Framework, Version=0.5.5.0, Culture=neutral, PublicKeyToken=null'.
TypeLoadException
at OmnibusTransparent.TransparentEngine.PI_PushAllRecords(Int64 nRecordLimit)
at SRC.Alteryx.GenericNetPluginInterface.PI_PushAllRecords(GenericNetPluginInterface* , Int64 nRecordLimit)

 

 

So, even though I have the compiled 0.6 DLL's in the Debug directory, somehow Alteryx is still trying to use 0.5.5 version DLL's.  Is Alteryx caching the DLL, or is this something to do with the GAC?  I have tried looking in the GAC using gacutil, but cannot see an entry for the Omnibus.Framework library.

 

jdunkerley79
ACE Emeritus
ACE Emeritus

If you have the OmniBus installed you will need to remove it.

 

Only one version of the DLL at a time unfortunately in Alteryx.

 

Easy fix is to build the omnibus locally from 0.6 branch and run the InstallbinDebug.bat which will link to Debug version.

Hiblet
10 - Fireball

Found it!  I had two INI files set up in AdditionalSettings;  One for the 0.5 Omnibus tool (which I called Exercise) and one for the 0.6 tool written today, called Transparent.  Exercise must have been loaded first, pulling in the Omnibus DLL, so Transparent was using the 0.5 version.  I removed the Exercise INI file, and now it's good.

 

Much obliged!

 

 

jdunkerley79
ACE Emeritus
ACE Emeritus

Had a proper go at what we talked over.

 

https://github.com/jdunkerley/AlteryxAddIns/blob/2bea745cfccb666c229a0e773eda229440d31562/OmniBus.Xm...

 

Should completely avoid dead lock issue in process. I tested it generating thousands of lines of output and error streams and both seem completely fine.

 

Stuck in a macro as well and all was happy.

 

Will be part of the 0.6 OmniBus tools (hopefully next week)