cancel
Showing results for 
Search instead for 
Did you mean: 

Calling PowerBuilder.NET Assembly From a C# Assembly Always Returns Null or Empty String

Former Member
0 Kudos

I have a C# assembly that is calling a PowerBuilder.NET(12.1 Build 7217) assembly. The PowerBuilder source code is contained below, you can see it is a rather simple true/false evaluation of a string.

When the PB.NET assembly is called by a Window in C#, it returns the expected result of "true". When the same code is called by a C# assembly, the code returns "", or an empty string.

I have managed to narrow the problem down to the DataStore interactions in the PB.NET assembly. If the PB.NET assembly is called from another assembly, the DataStore always has 0 rows and contains only empty strings. Has anyone seen or dealt with this before?

// Create instance of Datastore

ldsExpression = CREATE DataStore 

// Set data object

ldsExpression.DataObject = "d_condition_expression" 

//// Setting datawindow expression

lsExpression = 'condition_expression.expression = ~"' + asConditionExpression + '~"' 


//// Apply Expression

lsError = ldsExpression.Modify(lsExpression) 

IF len(lsError) = 0 THEN ldsExpression.InsertRow(0) 

     //get the result

     lsResult = ldsExpression.GetItemString(1,"condition_expression")

ELSE

     lsResult = lsError

END IF 

// Destroy instance of ldsExpression

DESTROY(ldsExpression) 

RETURN lsResult

Accepted Solutions (0)

Answers (1)

Answers (1)

Former Member
0 Kudos

Hi Jayme.

The dataobject you assign to the datastore is an external dataobject? If yes where is the settrans or settransobject command? If no what does the ldsExpression.InsertRow(0) command returns?

PS: I use assemblies created with pb.net 12.1 wich are referenced through c# service and have no problem.

Andreas.

Former Member
0 Kudos

The datastore is not connecting to the database in any way. It is simply being used to evaluate the expression. I have tried other approaches to evaluating the expression as well. (Describe and Evaluate). They all work correctly when called by a window but fail when called by a library.

The insertrow fails when called by a library (returns -1). When it is called by a regular C# window the code returns "true" as expected. Also, the expression I am passing is a simple "1 = 1".

Former Member
0 Kudos

I actually found a work-around for this. It really looks like a PowerBuilder.NET bug that should be addressed in future versions. Calling the PowerBuilder.NET assembly works when called by a Window or a Service but does not work if called by regular DLL assembly.

I found ONE exception to the rule. A PowerBuilder.NET assembly CAN be called by a C# assembly IF it is called by a Window or Service first within the same application. I'm thinking this is because the object remains in memory after the first call and gets reused from there. 

Luckily my application consists of a Service that launches several threads contained in a C# assembly. I added this call to the Main method of my Service, and all of the subsequent calls to EvaluateExpression work perfectly regardless of where they are called from.

        private static string Evaluate(string expression)

        {

            var blah = new PowerBuilderAssembly();

            return blah.EvaluateExpression(expression);

        }

        /// <summary>

        /// The main entry point for the application.

        /// </summary>

        static void Main(string[] args)

        {

            var result = Evaluate("1 = 1");

Former Member
0 Kudos

Then the problem is that insertrow fails. After that the getitemstring won't return a valid value! The IIS is on the same machine where you run the c# (I guess) winform project to test it?

Andreas.

Former Member
0 Kudos

The problem is that all calls to the PB.NET assembly from a C# assembly do not work if there is a datawindow/datastore in the PB.NET assembly. I have tested it dozens of times and have been able to reproduce the issue consistently in a simple test application. No datawindow/datastore code works in that situation.

I enclosed the 2 main files of the test application. Calling Evaluate via the TestLibraryClass does not work unless the PowerBuilder object is instantiated in the Window code itself. The code in TestLibraryClass should be independent of the code contained in the Window, but it's not.

    public static class TestLibraryClass

    {

        public static string Evaluate(string expression)

        {

            var blah = new PowerBuilderAssembly();

            return blah.EvaluateExpression(expression);

        }

    }

     public partial class frmTest : Form

    {

        public frmTest()

        {

            InitializeComponent();

        }

        //This code can be uncommented in order to make all of the calls to the PB.NET assembly work.

        //As soon as the PowerBuilder object is created here in the window, all calls to the assembly function as intended.

        private void ActuallyWork()

        {

            //var blah = new PowerBuilderAssembly();

            //var resultWindow = blah.EvaluateExpression("(1 = 1)");

            //if (resultWindow == "true")

            //{

            //    lblOutputWindow.Text = resultWindow.ToString(CultureInfo.InvariantCulture);

            //    lblOutputWindow.BackColor = Color.GreenYellow;

            //}

            //else

            //{

            //    lblOutputWindow.Text = resultWindow.ToString(CultureInfo.InvariantCulture);

            //    lblOutputWindow.BackColor = Color.Red;

            //}

        }

        private void btnDoStuff_Click(object sender, EventArgs e)

        {

            var resultFromLibrary = TestLibraryClass.Evaluate("(1 = 1)");

           

            ActuallyWork();

            if(resultFromLibrary == "true")

            {

                lblOutputLibrary.Text = resultFromLibrary.ToString(CultureInfo.InvariantCulture);

                lblOutputLibrary.BackColor = Color.GreenYellow;

            }

            else

            {

                lblOutputLibrary.Text = "Fail";

                lblOutputLibrary.BackColor = Color.Red;

                lblOutputWindow.Text = "Fail";

                lblOutputWindow.BackColor = Color.Red;

            }

        }

    }