C# Create Sales Invoice From Sales Order; nSetKey() fails, sLastErrorMsg = "The [InvoiceNo] is invalid"

I am on Sage 100c Standard 2016 (Version 5.30.5.0) (yes, I know it is very old, and have plans to upgrade to a supported version).  I am attempting to create a program in C# that creates a sales invoice from a sales order.

When my program executes the this line of code... cmd.InvokeMethod("nSetKey"); ... something terrible must happen.

No matter what I try MessageBox.Show(cmd.GetProperty("sLastErrorMsg").ToString()); pops up "The 0292983 is invalid".  Except, each time that it runs, it obviously increments the invoice# by 1.

If I change "cmd.InvokeMethod("nSetKey");" to "success = (int)cmd.InvokeMethod("nSetKey");" it produces an exception of "System.NullReferenceException: Object reference not set to an instance of an object"

I've been searching this forum for clues, but I've been spinning my wheels for days, and cannot get passed this error.  I am hoping there is someone out here that can help with with this problem.

Thanks.

using (DispatchObject pvx = new DispatchObject("ProvideX.Script"))
{
pvx.InvokeMethod("Init", strsage_path);
using (DispatchObject oSS = new DispatchObject(pvx.InvokeMethod("NewObject", "SY_Session")))
{
success = (int)oSS.InvokeMethod("nSetUser", strusername, strpassword);
if (success == 1)
{
success = (int)oSS.InvokeMethod("nSetCompany", strcompany);
if (success == 1)
{
success = (int)oSS.InvokeMethod("nSetDate", "S/O", DateTime.Today.ToString("MMddyyyy"));
if (success == 1)
{
success = (int)oSS.InvokeMethod("nSetModule", "S/O");
if (success == 1)
{
task_id = (int)oSS.InvokeMethod("nLookupTask", "SO_Invoice_ui");
if (task_id > 0)
{
oSS.InvokeMethod("nSetProgram", task_id);
using (DispatchObject cmd = new DispatchObject(pvx.InvokeMethod("NewObject", "SO_Invoice_bus", oSS.GetObject())))
{
if (new_batch_flag == true)
{
strBatchNo = "";
param = new object[] { strBatchNo, "N", "BOL " + DateTime.Today.ToString("MM/dd/yyyy") };
success = (int)cmd.InvokeMethodByRef("nSelectNewBatch", param);
if (success == 1)
{
strBatchNo = param[0].ToString();
}
else
{
strBatchNo = "";
Cursor.Current = Cursors.Default;
MessageBox.Show(cmd.GetProperty("sLastErrorMsg").ToString());
}
}
if (strBatchNo.Length > 0)
{
success = (int)cmd.InvokeMethod("nSelectBatch", strBatchNo);
if (success == 1)
{
InvoiceNo = new object[] { "" };
success = (int)cmd.InvokeMethodByRef("nGetNextInvoiceNo", InvoiceNo);
if (success == 1)
{
tbxInvoiceNo.Text = InvoiceNo[0].ToString();
param = new object[] { "InvoiceNo$", InvoiceNo[0].ToString() };
success = (int)cmd.InvokeMethod("nSetKeyValue", param);
cmd.InvokeMethod("nSetKey");
MessageBox.Show(cmd.GetProperty("sLastErrorMsg").ToString());

  • That message is a warning not an error but unfortunately, the LastErrorMsg property is used to hold both warnings and errors which is why you need to first and foremost be checking the returned value of the methods you are calling that are critical.  In the case of SetKey, it will return one of the following.

    • 2 if the key is a new record.
    • 1 if it is an existing record.
    • 0 if it failed.

    If you are unsure of the returned values, you can always reference the FLOR.

    Sage 100 File Layouts and Object Reference Documentation - Sage 100 File Layouts and Object Reference

  • in reply to David Speck

    Thank you for responding to my post.

    When this line of code is excuted: cmd.InvokeMethod("nSetKey");  a NULL value is returned.  There is no 0, 1, or 2 returned, whether I try

    success = (int)cmd.InvokeMethod("nSetKey");

    or

    object retval = cmd.InvokeMethod("nSetKey");

    Only a NULL value is returned.  If I ignore the nSetKey NULL result, every line of code after that produces an error and crashes the program.

    If I comment out the the nSetKey line, the lines of code below it seem to execute ok, but I need to set the InvoiceNo for the invoice, so this nSetKey function seems to be critical.

    I have tried referencing the FLOR, but there aren't many that look like the image that you attached.  I have found that most look like this...

    ... and there is no information whatsoever about what the function wants for parameters, or what it will return.

    I am at a full stop on this because I cannot get passed this error.

    I thought it might be because I am on Windows 11, or my anti-virus software, but I installed a copy of Windows 10 from scratch, and nothing else except for Sage and Visual Studio, but it exhibits the exact same behavior.

    I am now working on a solution in Visual Integrator.  The function of it is far less appealing, but Object Interface just doesn't seem to work, and there is very limited documentation for it.

  • in reply to B26354

    Try turning the NE parameter off in your code (example below). When on, any true exceptions won't bubble up to the external client. From what you describe, this is what is occurring, due to everything after that line causing errors / crashing the program.

    using (DispatchObject pvx = new DispatchObject("ProvideX.Script"))
    {
        pvx.InvokeMethod("Init", strsage_path);
        pvx.Execute("SET_PARAM 'NE'=0"); /* Turn the NE parameter off so we get internal exceptions */
        using (DispatchObject oSS = new DispatchObject(pvx.InvokeMethod("NewObject", "SY_Session")))
        {


    Regards,
    Russell

  • in reply to Russell Libby

    Thanks for replying to my post and trying to help me Russell.

    I had to figure out the syntax for your suggestion to work in my program, and this seems to work...

    pvx.InvokeMethod("Execute", "SET_PARAM 'NE'=0");

    ... but unfortunately, it doesn't seem to have any effect on cmd.InvokeMethod("nSetKey") returning a NULL value.

  • in reply to B26354

    You said that if you ignore the nSetKey NULL result, every line of code after that produces an error and crashes the program. It would be helpful to know the exact errors. As to crashing the program, are you wrapping this code with a try/catch in order to determine the exception being thrown after nSetKey fails? If not, you should be. 

    Russell

  • in reply to B26354

    SO_Invoice_Bus inherits SY_Maint so any methods inherited will be better documented at the class it was inherited from.  However, the Library Master module has two different groups of resources.  The ones under Base System are typically documented better than the ones under Library Master.  I got my screenshot from Base System > SY_Maint.

  • in reply to Russell Libby

    If I put the cmd.InvokeMethod("nSetKey"); inside a try/catch, it doesn't throw an exception and fall into the catch block.

    It continues down to success = (int)cmd.InvokeMethod("nSetValue", "ARDivisionNo$", tbxARDivisionNo.Text); and when that line is executed, I get this error message.

    However, if I comment out the nSetKey lines, all the subsequent nSetValue calls for ARDivisionNo, CustomerNo, etc... return success = 1, and there are no errors.

    It is as if executing the cmd.InvokeMethod("nSetKey"); somehow destroys the cmd object, making it NULL, and that's why the subsequent lines produce an error.

    I need to do the SetKeys for the proper creation of the invoice, right?

  • in reply to B26354

    Something abnormal is happening in the call to SetKey() but is not being surfaced; hard to say for sure why, given that I have tested your code on current versions of Sage 100 and it works as expected. And yes, the key needs to be set for the record in order to be able to save it.

    One suggestion I do have is to skip the SetKeyValue and just pass the invoice number to SetKey.

    var InvoiceNo = new object[] { "" };

    success = (int)cmd.InvokeMethodByRef("nGetNextInvoiceNo", InvoiceNo);

    if (success == 1)
    {
    success = (int)cmd.InvokeMethod("nSetKey", InvoiceNo);

    if (success == 2)
    {
    /* Continue on */
    }

  • in reply to Russell Libby

    There's a null reference exception error when I try to pass the InvoiceNo to the nSetKey function.

    I use True Commerce for EDI.  Customer orders come in over EDI, and True Commerce has a service that automagically creates sales orders in Sage from the EDI orders.  I'm told that the True Commerce service uses Object Interface to create the sales orders, but that their program and my program should be able to coexist independently of each other.  Could my program be getting buggered because True Commerce has installed its service?  There are all sorts of UDFs in a number of different tables that seem to serve some unknown purpose.  I wonder if True Commerce installed their own object files and the original Sage files were overwritten.  I'm calling True Commerce tech support to see if I can find out anything.

  • in reply to B26354

    Did you ever find an answer to this?

    Currently troubleshooting the same issue and running in circles trying to resolve the nSetKey call in exactly the same issue scenario.