win32com and IPICalculation secondary interface

212 Views Asked by At

I'm working on an interface to OSISoft's PISDK through win32com. I'm trying to use one of IPICalculation's functions, but since IPICalculation is a secondary interface, I'm having problems getting it to work.

What I have so far is:

from win32com.client import Dispatch, CastTo
from win32com.client.gencache import EnsureModule

tagname = 'sometag'
pisdk = Dispatch('PISDK.PISDK')
pisdk2 = EnsureModule('{0EE075CE-8C31-11D1-BD73-0060B0290178}',
                      0, 1, 1, bForDemand=False)
pi_server = pisdk.Servers.DefaultServer
tag_pipoint = pi_server.PIPoints(tagname)
# Using secondary interface IPIData2 works:
data = CastTo(tag_pipoint.Data, 'IPIData2')
# However, trying to use IPICalculation doesn't work:
server = CastTo(pi_server, 'IPICalculation')
# Traceback (most recent call last):
# ...
#  File "C:\Users\MyUser\AppData\Local\Temp\gen_py\3.7\0EE075CE-8C31-11D1-BD73-0060B0290178x0x1x1\IPICalculation.py", line 49, in <module>
#    win32com.client.CLSIDToClass.RegisterCLSID( "{F293A835-D998-11D3-853F-00C04F45D1DA}", IPICalculation )
# NameError: name 'IPICalculation' is not defined

A quick look at the affected generated files (in %LOCALAPPDATA%\Temp\gen_py) reveals that while the IPIData2.py file declares the IPIData2 class, there is no equivalent in the IPICalculation.py file.

For me, it appears to be a bug in win32com and makepy, but I'm not really sure.

I have also digged through the net and found an alternative way to do this, which also fails:

import pythoncom
iface = pi_server._oleobj_.QueryInterface(pythoncom.IID_IDispatch)
CastTo(iface, 'IPICalculation')  # Fails

Other side-notes:

  • I have also tried running makepy in the type library
  • I have tried EnsureDispatch without success
  • The VBA example for using the IPICalculation interface can be found here

I'm trying this on Python 3.7.3, 64-bit, Anaconda Distribution, Windows 10 64-bit, PISDK 1.3 Type Library, PISDK.dll 64-bit version 1.4.6.494.

1

There are 1 best solutions below

0
On

Caveat: This is not really an answer because it ditches win32com in favor of comtypes, which I don't want to do because my code already does a lot of win32com stuff and I don't want to port everything nor do I want to have both as dependencies.

However, it works and I leave it here for those that want a working solution.

import comtypes
import comtypes.client

ctsdk = comtypes.client.CreateObject("PISDK.PISDK")
ctpisdk2 = comtypes.gen._0EE075CE_8C31_11D1_BD73_0060B0290178_0_1_1
ctserver = ctsdk.Servers.DefaultServer
ctipicalc = ctserver.QueryInterface(ctpisdk2.IPICalculation)  # This works, so I can proceed:
print(ctipicalc.TimedCalculate(['*'], "'%s'" % tagname)[1].Value)