i writing windows form application in .net list running instances of third-party cad/cam software (in case catia) , let user choose 1 of them perform couple of automated tasks. performing automated tasks, need specific instance of com objects - compared getobject() gives me non-specific com instance. there way specific com instance using window handle or other methods?
update: raymond said there no single solution com objects; managed catia com objects using following code (which uses rot fill list catia com instances name):
<dllimport("user32.dll", charset:=charset.auto)> private shared sub getclassname(byval hwnd system.intptr, byval lpclassname system.text.stringbuilder, byval nmaxcount integer) end sub <dllimport("ole32.dll", exactspelling:=true, preservesig:=false)> private shared function getrunningobjecttable(byval reserved int32) irunningobjecttable end function <dllimport("ole32.dll", charset:=charset.unicode, exactspelling:=true, preservesig:=false)> private shared function createitemmoniker(byval lpszdelim string, byval lpszitem string) imoniker end function <dllimport("ole32.dll", exactspelling:=true, preservesig:=false)> private shared function createbindctx(byval reserved integer) ibindctx end function try dim rotobject object = nothing dim runningobjecttable irunningobjecttable dim monikerenumerator ienummoniker = nothing dim monikers(1) imoniker runningobjecttable = getrunningobjecttable(0) runningobjecttable.enumrunning(monikerenumerator) monikerenumerator.reset() dim numfetched intptr = new intptr() while (monikerenumerator.next(1, monikers, numfetched) = 0) dim ctx ibindctx ctx = createbindctx(0) dim runningobjectname string = "" monikers(0).getdisplayname(ctx, nothing, runningobjectname) runningobjectname = runningobjectname.toupper if (not runningobjectname.equals("")) dim runningobjectins object = nothing runningobjecttable.getobject(monikers(0), runningobjectins) 'check if object catia object try dim catiains infitf.application = nothing catiains = directcast(runningobjectins, infitf.application) listcatia.items.add(catiains.windows.count) catch exc exception messagebox.show(exc.tostring()) end try end if end while catch exc exception throw exc end try
however, catia instances refer first catia application loaded. no idea why, anybody?
the "problem" in code calling getobject
always returns first active server finds in running object table (rot). enumerating rot doesn't change behavior , little frustrating because show there more 1 server in rot. note of items returned in enumeration may not running: getobject
returns first active server -- not first 1 returned enumeration.
however, in case of catia in particular is possible specific instance. suspect possible many applications if can particular instance of interest run code, on demand, before pointer com instance.
for catia, rough outline of process use:
1. make dll 2 functions: hresult __stdcall comarshaltofile(iunknown* punk, const char* const filepath) /* uses `::createstreamonhglobal`, `::comarshalinterface`, `::cogetmarshalsizemax`, , `::gethglobalfromstream` marshal iunknown specified file. */ hresult __stdcall comarshalfromfile(iunknown** ppunk, const char* const filepath) /* uses `::createstreamonhglobal` , `::counmarshalinterface` marshal file iunknown pointer. */ 2. in catia: note: needs done on development computer. make new "vba projects" macro library. add "declare" statements for: "loadlibrary" (windows api) "comarshaltofile" (dll specified above) add function public function marshalcatiatofile _ (marshalinstancefilepath string, _ marshaldllfolder string) long marshalcatiatofile calls "loadlibrary" load c++ dll , calls comarshaltofile (in dll) marshal catia instance file. remove macro library catia's list of macro libraries. 3. create file: "c:\temp\catiaontheflycatscripts\ontheflycatscript.catvbs" file can empty. 4. in catia: note: must done *each* user of catia on *each* computer used. may possible make available users without individual setup required: saved in "frameuseraliases.catsettings" may possible reverse engineer settings file , set needed data outside catia. add "c:\temp\catiaontheflycatscripts\" new "directories" macro library. make added library "current" use "tools --> customize --> commands --> macros" assign "user alias:" "ontheflycatscript.catvbs" script file. name alias "executeontheflycatscript". remove macro library catia's list of macro libraries. close catia @ point force changes saved. 5. vb.net / c# program: add dll (from step 1) , catvba macro library (from step 2) "embedded resource" project. during program execution: extract dll , macro library appropriate location. load dll session using "loadlibrary". create file: "c:\temp\catiaontheflycatscripts\ontheflycatscript.catvbs" "ontheflycatscript.catvbs" executed in catia. uses catia.systemservice.executescript execute "marshalcatiatofile" function in catvba macro library. add method of choice file indicate success/failure. use dialog box appropriate title. execute "ontheflycatscript.catvbs": using windows api functions, window handle "power input" box @ bottom right of "desired" catia window. using windows api functions (*not* "sendkeys") send "c:executeontheflycatscript" + {enter} "power input". wait "completion" signal script. if used dialog box, use windows api function close it. assuming script succeeded in marshaling catia instance file, call dll function comarshalfromfile catia instance.
it's lot of work many "moving" parts allow automate multiple catia sessions "simultaneously". works purposes: automated extraction of data set of catia models , automated creation of set of catia models using more 1 catia session @ time. bottleneck application individual catia session -- not cpu resources (using dual processor 4 or 6 core per processor machine); adding more sessions improves throughput.
Comments
Post a Comment