Using python with the BOI

SOLVED

We have a python (3.10) application that we want to use to create a sales order in Sage 100.

I have installed pywin32 so the python script can access win32/COM.

This code works up to the point where I try to call a method on the SY_Session object:

import win32com.client as win32
oScript = win32.dynamic.Dispatch("ProvideX.Script") #dynamic = late binding
print( oScript.State )
print( oScript.Instance ) 
oScript.Init("C:\Sage100_v2021\MAS90\Home")
print( oScript.State ) 
oSS = oScript.NewObject("SY_Session") 
r = oSS.nLogon() 

As expected the code outputs the following:

0
{A587B8B2-210E-4BF7-BC88-427744952D5F}
1

but when it tries to call the nLogon method on the session object it throws an error:

TypeError: 'int' object is not callable

The same program as VBS runs successfully on the workstation:

Set oScript = CreateObject ("ProvideX.Script")
MsgBox oScript.State
oScript.Init("C:\Sage100_v2021\MAS90\Home")
MsgBox oScript.State
Set oSS = oScript.NewObject("SY_Session")
retVal = oSS.nLogon()
If retVal=0 Then
	retVal = oss.nSetUser("craig","password") 
End If
MsgBox oSS.sUserName

Has anyone had any success using python and the BOI? 

Parents
  • 0

    It may be that Python requires escaping your back slashes on your init call.

    oScript.Init("C:\\Sage100_v2021\\MAS90\\Home")

  • 0 in reply to scmember

    I tried your suggestion - I'm getting the same result.

    Interestingly both oScript.Init("C:\\Sage100_v2021\\MAS90\\Home") and oScript.Init("C:\Sage100_v2021\MAS90\Home") produce the same results, so to test it I put in a bad path and ran it and did receive an error "The specified path does not exist", so python sees \ and \\ as the same inside the ""s.

  • 0 in reply to CraigJ

    Have you tried a simple non-Sage COM/OLE example in Python to make sure COM works? I got PHP COM to work a couple years ago but unable to get it to work in the current release. Python and PHP are mostly used with Linux and Windows seems not as well supported., Good luck with your effort.

  • 0 in reply to scmember

    It's partially working - I can interact with the ProvideX.Script object just fine - I can get the state, init it, ect.

    I've done further investigation and it seems that I can access properties of the SY_Session object.  For example:

    print( "Last Error Message " + oSS.sLastErrorMsg )
    print( "Registered Name " + oSS.sRegisteredName ) 

    Both work as expected.

    It seems that the issue is specifically related to calling a method.  

    retVal = oSS.nLogon()  is causing a TypeError: 'int' object is not callable

  • 0 in reply to CraigJ

    The problem could be passing an object as an argument with Python COM.

  • +1 in reply to CraigJ
    verified answer

    Let me preface this response by saying that my Python skills are very limited. That said, I debugged the OLE server (ProvideX Script) and noticed that no arguments were being passed to the methods, and all calls were flagged as property get's. I was able to get this working by wrapping the session object as a DumbDispatch (no ITypeInfo) and then using _FlagAsMethod for the methods that would be called.

    oSS = oScript.NewObject("SY_Session")
    
    oScript.TraceOn = 1
    
    session = win32.dynamic.DumbDispatch(oSS)
    
    session._FlagAsMethod("nSetUser")
    session._FlagAsMethod("nLogon")
    
    print(session)
    
    ret = session.nLogon()
    ret = session.nSetUser( "all" , "" )
    
    session.FinalDropObject()

    A couple of notes. First, the method names are case sensitive when using _FlagAsMethod, so use the same casing when calling the method. Second, when your done testing you can remove the oScript.TraceOn. I used it to determine what was happening on the backend, but is not needed for final code.  

    Hope this helps.

    Russell

Reply
  • +1 in reply to CraigJ
    verified answer

    Let me preface this response by saying that my Python skills are very limited. That said, I debugged the OLE server (ProvideX Script) and noticed that no arguments were being passed to the methods, and all calls were flagged as property get's. I was able to get this working by wrapping the session object as a DumbDispatch (no ITypeInfo) and then using _FlagAsMethod for the methods that would be called.

    oSS = oScript.NewObject("SY_Session")
    
    oScript.TraceOn = 1
    
    session = win32.dynamic.DumbDispatch(oSS)
    
    session._FlagAsMethod("nSetUser")
    session._FlagAsMethod("nLogon")
    
    print(session)
    
    ret = session.nLogon()
    ret = session.nSetUser( "all" , "" )
    
    session.FinalDropObject()

    A couple of notes. First, the method names are case sensitive when using _FlagAsMethod, so use the same casing when calling the method. Second, when your done testing you can remove the oScript.TraceOn. I used it to determine what was happening on the backend, but is not needed for final code.  

    Hope this helps.

    Russell

Children