COM-Kommunikation mit Polyworks mithilfe von pywin32

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
polyworks
User
Beiträge: 14
Registriert: Montag 7. April 2014, 08:24

Guten Morgen liebe Community,

um mich kurz vorzustellen: 24 Jahre alt, Student und arbeite momentan an meiner Bachelorarbeit. Hierbei werde ich unter anderem ein Tool in Python (für mich neue Sprache) erstellen, welches über das COM mit einer Software Namens Polyworks kommunizieren soll. Nun habe ich bereits das Programm über die COM starten können, was wie folgt aussieht:

Code: Alles auswählen

from win32com.client import Dispatch
test = Dispatch("Polyworks")
Das Starten über die CLSID funktioniert auch wunderbar.
Ich habe schon sehr viel in Foren gelesen, bin aber am verzweifeln... Das Problem ist nämlich, dass ich bei diesem Programm zusätzlich einen CommandCenter starten muss, um richtig mit den Funktionen des Programms arbeiten zu können. Im Handbuch steht dabei für die Sprachen C++ und VisualBasic folgender Code:

Code: Alles auswählen

#C++
HRESULT CommandCenterCreate( [ out ] IIMCommandCenter **ppIIMCommandCenter_ )
#VB
Sub CommandCenterCreate( ByRef ppIIMCommandCenter_ As IIMCommandCenter )
ppIIMCommandCenter_ ist dabei ein Zeiger um das neue CommandCenter zu empfangen.
Jetzt stellt sich eben für mich die Frage, wie sich das in Python gestaltet, vielleicht kann mir das ja einer hier beantworten, wäre jedenfalls super!




Außerdem verstehe ich folgendes noch nicht bzgl. COM bei z.B. Excel:

Code: Alles auswählen

from win32com.client import Dispatch
test = Dispatch("Excel.Application")

xlBook = test.Workbooks.Add() 
xlSheet = xlBook.Sheets(1) 
xlSheet.Cells(1,1).Value="hello"
Der Code um in Excel ein neues Workbook zu erstellen heißt Workbooks.Add(). Der Code in Python heißt dafür test.Workbooks.Add(). Möchte ich aber in einer Zelle schreiben, heißt es nur xlSheet.Cells(1,1).Value="hello" , ich benenne also kein test (Objekt?) mehr.


Ich wäre Euch unglaublich dankbar, wenn Ihr mir dabei helfen könntet!
BlackJack

Zur zweiten Frage: Vielleicht hilft es ja einen vernünftigeren Namen als `test` zu nehmen. Das wäre zum Beispiel `excel`. Denn das Objekt hinter diesem Namen repräsentiert ja die COM-Schnittstelle zu der Anwendung auf der anderen Seite. Und Excel möchte man ja sagen das ein neues „Workbook” hinzugefügt werden soll. Und dieses „Workbook” wird als Ergebnis zurück gegeben.
Sirius3
User
Beiträge: 18230
Registriert: Sonntag 21. Oktober 2012, 17:20

@polyworks: Da Python keine out-Parameter kennt, werden die soweit ich mich erinnern kann einfach als zusätzliche Rückgabeparameter zurückgegeben, also so ungefähr:

Code: Alles auswählen

from win32com.client import Dispatch
polyworks = Dispatch("Polyworks")
hresult, command_center = polyworks.CommandCenterCreate()
In Excel-VBA wird implizit angenommen, dass es eine Excel-Instanz gibt und deshalb gibt es einige Objekte im globalen Namensraum, unter anderem auch Workbooks.
Wenn Du unbedingt willst, kannst Du auch in Python eine globales Workbooks-Instanz ablegen, würde Dir aber dringend davon abraten:

Code: Alles auswählen

from win32com.client import Dispatch
excel = Dispatch("Excel.Application")
Workbooks = excel.Workbooks # besser nicht ;-)

xlBook = Workbooks.Add()
xlSheet = xlBook.Sheets(1)
xlSheet.Cells(1,1).Value="hello"
polyworks
User
Beiträge: 14
Registriert: Montag 7. April 2014, 08:24

Danke Euch!
polyworks
User
Beiträge: 14
Registriert: Montag 7. April 2014, 08:24

Polyworks lässt sich über "Dispatch" nicht ansprechen... Habe aber mittlerweile eine Lösung erhalten.
Man installiere "pywin32" und "comtypes". Mit folgendem Code hat es dann geklappt bei mir:

Code: Alles auswählen

import comtypes.client
import win32api
import win32con

# Get the CLSID of the current IMInspectFactory
#regIMIKey = win32api.RegOpenKeyEx(win32con.HKEY_CLASSES_ROOT, 'InnovMetric.PolyWorks.IMInspect.12.1', 0, win32con.KEY_READ )
#clsid = win32api.RegQueryValue( regIMIKey, 'CLSID' )
#win32api.RegCloseKey( regIMIKey )

#print (clsid)

# Obtain the path to the current IMInspect server
#regCLSIDKey = win32api.RegOpenKeyEx( win32con.HKEY_CLASSES_ROOT, 'CLSID', 0, win32con.KEY_READ )
#regIMICLSIDKey = win32api.RegOpenKeyEx( regCLSIDKey, clsid, 0, win32con.KEY_READ )
#pathIMI = win32api.RegQueryValue( regIMICLSIDKey, 'LocalServer32' )
#win32api.RegCloseKey( regIMICLSIDKey )
#win32api.RegCloseKey( regCLSIDKey )

clsid = "{15E422F9-2FDD-47AD-8779-ACBED65092B3}"
pathIMI = "C:\Program Files\InnovMetric\PolyWorks 12.1 (64-bit)\\bin\iminspect.exe"

print (pathIMI)

### Load the types information from the IMInspect server
IMInspectLib = comtypes.client.GetModule( pathIMI )

# Create a IIMInspect object
objIUkn = comtypes.client.CreateObject( clsid )
objIMI = objIUkn.QueryInterface( IMInspectLib.IIMInspect )

# Obtain a IIMCommandCenter
objPrj = objIMI.ProjectGetCurrent()
objCC = objPrj.CommandCenterCreate()

# Call a command on it
objCC.CommandExecute( 'ECHO ( "Hello World" )' )
Antworten