Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Cant Log In With XAPI, But COMAPI works fine 1

Status
Not open for further replies.

Adam007

Programmer
Oct 18, 2009
21
0
0
Hey All,

I have an application that i have built and tested on 4 different machines (XP, Vista, Server 2008, Windows 7).
The application is built in C# and i haven't had an issue in my test environments.

Now that we are ready to start testing on the client machines, we are getting an error logging into Accpac using the XAPI, but for some strange reason the COMAPI is logging in fine.

I know what your all thinking, "Just use the COMAPI and be done with it". This isn't going to work for me, i need to use the CS0120 view to execute custom queries in Accpac and the COMAPI doesn't support this view.

I even went as far as building a test application that logs in with both the XAPI and COMAPI, and that shows that the COMAPI can log in fine but not the XAPI.

Here is the code for the log in test app;
Code:
class Program
{
    static string UserName = string.Empty;
    static string Password = string.Empty;
    static string DB = string.Empty;

    static void Main(string[] args)
    {
        Console.Write("Enter the User Name:");
        UserName = Console.ReadLine();

        Console.Write("Enter the Password:");
        Password = Console.ReadLine();

        Console.Write("Enter the Database:");
        DB = Console.ReadLine();

        Console.Write("Attempting to log in with the XAPI:");
        LogInWithXAPI();
        Console.WriteLine();
        Console.Write("Attempting to log in with the COMAPI:");
        LogInWithCOMAPI();
        Console.WriteLine();
        Console.Write("Press Enter To Close");
        Console.ReadLine();
    }

    private static void LogInWithXAPI()
    {
        ACCPACXAPILib.xapiSession pSession = new ACCPACXAPILib.xapiSession();
        try
        {
            pSession.Open(UserName, Password, DB, DateTime.Today, 0);
            Console.Write("Sucessful");
            pSession.Close();
        }
        catch(Exception ex)
        {
            Console.Write("Failed" + Environment.NewLine);
            string xapiErr = GetXAPIError(pSession);

            if (!string.IsNullOrEmpty(xapiErr))
                Console.WriteLine(xapiErr);
            else
                Console.WriteLine(ex.Message);
        }
    }

    private static void LogInWithCOMAPI()
    {
        AccpacCOMAPI.AccpacSession pSession = new AccpacCOMAPI.AccpacSession();
        AccpacCOMAPI.AccpacDBLink pDBLink;

        try
        {
            pSession.Init("", "XX", "XX1000", "55A");
            pSession.Open(UserName, Password, DB, DateTime.Today, 0, "");
            Console.Write("Sucessful");
            pDBLink = pSession.OpenDBLink(AccpacCOMAPI.tagDBLinkTypeEnum.DBLINK_COMPANY, AccpacCOMAPI.tagDBLinkFlagsEnum.DBLINK_FLG_READWRITE);
            pDBLink.Close();
            pSession.Close();
            
        }
        catch(Exception ex)
        {
            Console.Write("Failed" + Environment.NewLine);
            string comErr = GetCOMAPIError(pSession);

            if (!string.IsNullOrEmpty(comErr))
                Console.WriteLine(comErr);
            else
                Console.WriteLine(ex.Message);
        }

    }

    /// <summary>
    /// Gets any XAPI errors and clears them from the XAPI
    /// </summary>
    /// <returns></returns>
    private static string GetXAPIError(ACCPACXAPILib.xapiSession sess)
    {
        long lCount;
        int iIndex;
        string ret = string.Empty;

        try
        {
            if (sess.Errors != null)
            {
                lCount = sess.Errors.Count;

                if (lCount != 0)
                {
                    for (iIndex = 0; iIndex < lCount; iIndex++)
                    {
                        ret += sess.Errors.Item(iIndex).Description;
                    }
                    sess.Errors.Clear();
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }

        return ret;
    }

    private static string GetCOMAPIError(AccpacCOMAPI.AccpacSession sess)
    {
        long lCount;
        int iIndex;
        string ret = string.Empty;

        try{
            if (sess.Errors != null)
            {
                lCount = sess.Errors.Count;

                if (lCount != 0)
                {
                    for (iIndex = 0; iIndex < lCount; iIndex++)
                    {
                        ret += sess.Errors.Item(iIndex);
                    }
                    sess.Errors.Clear();
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        } 

        return ret;
    }
}

Any help would be greatly appreciated, the client machines are all running XP SP3 with all the latest updates.
 
Yeah, thats the first thing i checked.

Thx for the idea though.
 
I'm using CS0120 with COMAPI and it works fine, I can't think of any reason why you cannot use it.
XAPI has not changed in years and the COMAPI encapsulates the XAPI, so whatever you can do in XAPI you can do in COMAPI.
 
The issue with using the CS0120 view from the COMPAI is as follows,

If i run this query using the CS0120 view;
Code:
SELECT CRDUNIQ, OEINVH.SHINUMBER, OECRDH.CRDDATE, OECRDH.LOCATION, OECRDH.CUSTOMER, OECRDH.PONUMBER, OECRDH.SHPCONTACT, CRDUNIQ
FROM OECRDH
	INNER JOIN ARCUS ON ARCUS.IDCUST = OECRDH.CUSTOMER AND ARCUS.IDACCTSET = '12'  
	INNER JOIN OEINVH ON OEINVH.INVNUMBER = OECRDH.INVNUMBER
WHERE OECRDH.SHIPTRACK = '' AND OECRDH.CRDDATE > 20090901
ORDER BY CUSTOMER

when i try to access the fields using the following code, i get an error about not being able to find the field.
Code:
CreditNotes.Browse(sql, 1);

while (Convert.ToBoolean(CreditNotes.Fetch()))
{
    string tempDate = CreditNotes.Fields.get_FieldByName("CRDDATE").get_Value().ToString().Trim();
    DateTime tempDateTime = new DateTime(Convert.ToInt32(tempDate.Substring(0, 4)),
                                        Convert.ToInt32(tempDate.Substring(4, 2)),
                                        Convert.ToInt32(tempDate.Substring(6, 2)), 0, 0, 0);

    OECRDH temp = new OECRDH(CreditNotes.Fields.get_FieldByName("SHINUMBER").get_Value().ToString().Trim(),
                            tempDateTime,
                            CreditNotes.Fields.get_FieldByName("LOCATION").get_Value().ToString().Trim(),
                            CreditNotes.Fields.get_FieldByName("CUSTOMER").get_Value().ToString().Trim(),
                            CreditNotes.Fields.get_FieldByName("PONUMBER").get_Value().ToString().Trim(),
                            CreditNotes.Fields.get_FieldByName("SHPCONTACT").get_Value().ToString().Trim(),
                            CreditNotes.Fields.get_FieldByName("CRDUNIQ").get_Value().ToString().Trim());

    temp.Details = GetOECreditNoteDetails(CreditNotes.Fields.get_FieldByName("CRDUNIQ").get_Value().ToString());

    ret.Add(temp);
}

OECRDH is a struct i built, but it fails with the following error
Field 'CRDDATE' is not a valid field name.

I know CRDDATE should be in the Fields, but if i watch it in Visual Studio Debugger CreditNotes.Fields.Count is 0
 
I just thought I would post the entire function so you can see the whole thing and run a test if you need / want to.

Structs
Code:
/// <summary>
/// Represents the relavent data from the OECRDH table
/// </summary>
public struct OECRDH
{
    public string ORDNUMBER;
    public DateTime ORDDATE;
    public string SHIPVIA;
    public string CUSTOMER;
    public string PONUMBER;
    public string BILNAME;
    public string CRDUNIQ;

    public Collection<OECRDD> Details;

    public OECRDH(string ordnumber, DateTime orddate, string shipvia, string customer, string ponumber, string bilname, string crduniq)
    {
        ORDNUMBER = ordnumber;
        ORDDATE = orddate;
        SHIPVIA = shipvia;
        CUSTOMER = customer;
        PONUMBER = ponumber;
        BILNAME = bilname;
        CRDUNIQ = crduniq;
        Details = new Collection<OECRDD>();
    }
}

/// <summary>
/// Represents the relavent data from the OECRDD table
/// </summary>
public struct OECRDD
{
    public string CRDUNIQ;
    public double QTYRETURN;
    public string ITEM;
    public string LOCATION;

    public OECRDD(string crduniq, double qtyreturn, string item, string location)
    {
        CRDUNIQ = crduniq;
        QTYRETURN = qtyreturn;
        ITEM = item;
        LOCATION = location;
    }
}

Function Sample
Code:
/// <summary>
/// Opens an accpac view
/// </summary>
private void OpenView(string ViewID, out AccpacView view)
{
    pDBLink.OpenView(ViewID, out view);
}


public Collection<OECRDH> GetOECreditNotes()
{
    Collection<OECRDH> ret = new Collection<OECRDH>();
    AccpacView CreditNotes = null;

    try
    {
        OpenView("CS0120", out CreditNotes);
        string sql = "SELECT CRDUNIQ, OEINVH.SHINUMBER, OECRDH.CRDDATE, OECRDH.LOCATION, OECRDH.CUSTOMER, OECRDH.PONUMBER, OECRDH.SHPCONTACT, CRDUNIQ  " +
                        "FROM OECRDH " +
                        "INNER JOIN ARCUS ON ARCUS.IDCUST = OECRDH.CUSTOMER " +
                            "AND (ARCUS.IDACCTSET = '12' " +
                        "INNER JOIN OEINVH ON OEINVH.INVNUMBER = OECRDH.INVNUMBER " + 
                        "WHERE OECRDH.SHIPTRACK = '' AND OECRDH.CRDDATE > 20090901 " + 
                        "ORDER BY CUSTOMER";
        
        CreditNotes.Browse(sql, false);

        while (Convert.ToBoolean(CreditNotes.Fetch()))
        {
            string tempDate = CreditNotes.Fields.get_FieldByName("CRDDATE").get_Value().ToString().Trim();
            DateTime tempDateTime = new DateTime(Convert.ToInt32(tempDate.Substring(0, 4)),
                                                Convert.ToInt32(tempDate.Substring(4, 2)),
                                                Convert.ToInt32(tempDate.Substring(6, 2)), 0, 0, 0);
    
            OECRDH temp = new OECRDH(CreditNotes.Fields.get_FieldByName("SHINUMBER").get_Value().ToString().Trim(),
                                    tempDateTime,
                                    CreditNotes.Fields.get_FieldByName("LOCATION").get_Value().ToString().Trim(),
                                    CreditNotes.Fields.get_FieldByName("CUSTOMER").get_Value().ToString().Trim(),
                                    CreditNotes.Fields.get_FieldByName("PONUMBER").get_Value().ToString().Trim(),
                                    CreditNotes.Fields.get_FieldByName("SHPCONTACT").get_Value().ToString().Trim(),
                                    CreditNotes.Fields.get_FieldByName("CRDUNIQ").get_Value().ToString().Trim());
    
            temp.Details = GetOECreditNoteDetails(CreditNotes.Fields.get_FieldByName("CRDUNIQ").get_Value().ToString());
    
            ret.Add(temp);
        }
        
    }
    catch
    {
        string xapiErr = GetXAPIError();

        if (!string.IsNullOrEmpty(xapiErr))
            throw new Exception(xapiErr);
        else
            throw;
    }
    finally
    {
        if (CreditNotes != null)
        {
            CreditNotes.Close();
            CreditNotes = null;
        }
    }

    return ret;
}

I removed some irrelevant code but that is the core functionality that is not working with that view.
 
Right after you call Browse, call .InternalSet with 256

VBA/VB Coding:
Code:
CSQry.Browse sSql, True
CSQry.InternalSet (256)


 
@DjangMan

OMG, thank you soooo much.
Now i just have one more relatively simple question, from what i can infer AccpacView.InternalSet is setting the max amount of records returned from the query.

Now i have checked all the Docs installed in the Pluswdev directory installed with the SDK but i can't find anything explaining this function call to me in more detail.

So basically what i'm asking is either
where can i find more details on this function?
or
What are the Max / Min values that can be passed in?

That is of course if i'm right in assuming that it is indeed setting the maximum records returned from the query.
 
Ok,

well after doing some testing, i can now say for sure that it is NOT limiting the number of records returned from the database.

So that being said i guess my problem is resolved and i would like to thank you guys for helping me out on this one.

One thing tho, if you could point me in the right direction of where to find this information and well all the information on the COMAPI that would be great. I do have access to the Sage DPP site so if it's just something i missed when downloading the docs a link would be great.

Thx again
 
There aren't many documents at all. We've all learned by recording macros and asking questions and experimenting.

There's even less documenation on CS0120. It was added to support dashboards and it targets the database layer directly. The nice thing is that your macro will work on any Accpac database without needing to create a new database connection (assuming you don't use DB specific syntax). The only other thing I know about CS0120 is that when I use it and then want to run another query I have to create a whole new instance of CS0120 instead of recycling the existing one.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top