COMate - control COM objects via automation - OBSOLETE!

Developed or developing a new product in PureBasic? Tell the world about it.
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

No problem, just remember that you pass a single 'command string' to methods / properties etc. and so you just need to use the regular PB string functions to construct this string.

There are problems with your use of single quotes and escape codes as well. Use :

Code: Select all

colAdapters = objWMIService\CreateEnumeration("ExecQuery('Select * from Win32_NetworkAdapter Where Index= $0027" + index_nic$ +"$0027')")
I have added an extra single quote with an extra $0027 escape sequence.
I may look like a mule, but I'm not a complete ass.
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Post by SFSxOI »

Thank you srod, this is great. I'm having a lot of fun with it now that i'm getting used to it.

Heres a couple more things that work great with this. These are a Windows Vista only (seriously, Vista only) thing. Enable and Disable an adapter;

First, the Enable method:

Code: Select all

; Windows Vista only - per MSDN
; http://msdn.microsoft.com/en-us/library/aa390385(VS.85).aspx
; http://msdn.microsoft.com/en-us/library/aa390364(VS.85).aspx
;
; the adapter index used here is the one stored in the registry not the connection index for the adapter - NetLuidIndex
; HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002bE10318}\<0000 thru how ever many sub keys - the one that contains your physical NIC adapter"
; its the value of NetLuidIndex for your adapter entry


XIncludeFile "COMate.pbi"

Procedure Enable_Adapter(NetLuidIndex.l) 

Define.COMateObject objWMIService, Adapter 
colAdapters.COMateEnumObject 

strComputer.s = "." 
Net_Luid_Index$ = Str(NetLuidIndex)

objWMIService = COMate_GetObject("winmgmts:\\" + strComputer + "\root\cimv2", "") 
If objWMIService 
  colAdapters = objWMIService\CreateEnumeration("ExecQuery('Select * from Win32_NetworkAdapter Where Index= $0027" + Net_Luid_Index$ +"$0027')")
  If colAdapters 
    Adapter= colAdapters\GetNextObject() 
    While Adapter
      result.l = Adapter\Invoke("Enable()")  
      Adapter\Release() 
      Adapter = colAdapters\GetNextObject()
    Wend
    colAdapters\Release() 
  EndIf
  objWMIService\Release()  
EndIf
ProcedureReturn result ; if completed OK result returns 0
EndProcedure
Next, the Disable method:

Code: Select all

; Windows Vista only - per MSDN
; http://msdn.microsoft.com/en-us/library/aa390385(VS.85).aspx
; http://msdn.microsoft.com/en-us/library/aa390364(VS.85).aspx
;
; the adapter index used here is the one stored in the registry not the connection index for the adapter - NetLuidIndex
; HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002bE10318}\<0000 thru how ever many sub keys - the one that contains your physical NIC adapter"
; its the value of NetLuidIndex for your adapter entry


XIncludeFile "COMate.pbi"

Procedure Disable_Adapter(NetLuidIndex.l) 

Define.COMateObject objWMIService, Adapter
colAdapters.COMateEnumObject 

strComputer.s = "." 
Net_Luid_Index$ = Str(NetLuidIndex)

objWMIService = COMate_GetObject("winmgmts:\\" + strComputer + "\root\cimv2", "") 
If objWMIService 
  colAdapters = objWMIService\CreateEnumeration("ExecQuery('Select * from Win32_NetworkAdapter Where Index= $0027" + Net_Luid_Index$ +"$0027')")
  If colAdapters 
    Adapter= colAdapters\GetNextObject() 
    While Adapter
      result.l = Adapter\Invoke("Disable()")  
      Adapter\Release() 
      Adapter = colAdapters\GetNextObject()
    Wend
    colAdapters\Release() 
  EndIf
  objWMIService\Release()  
EndIf
ProcedureReturn result ; if completed OK result returns 0
EndProcedure
Last edited by SFSxOI on Thu Sep 04, 2008 10:37 pm, edited 1 time in total.
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

SFSxOI wrote:Thank you srod, this is great. I'm having a lot of fun with it now that i'm getting used to it.
:) You're welcome.

With the shear number of automation controller's written in VB and VBS code, there's no shortage of examples which we can use - and abuse!

The ActiveX stuff is now done (apart from the 'event sinks') which I will not add until later. I just need to update the help manual and then I will spend a few hours looking at the command parser to see if I can speed it up somewhat. When done I'll start collecting these examples of yours together and add them to the download - with full credit to yourself of course. Assuming you don't mind me making use of your code that is?
I may look like a mule, but I'm not a complete ass.
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

PDF example (Acrobat reader required) by Stefan Schnell : http://www.purebasic.fr/english/viewtop ... hlight=pdf

Code: Select all

XIncludeFile "COMate.pbi"

Define.COMateObject PDFObject

If OpenWindow(0, 0, 0, 640, 480, "COMate PDF-Demo") And CreateGadgetList(WindowID(0))

  pdfObject = Comate_CreateObject("AcroPDF.PDF.1", WindowID(0)) 
  If pdfObject
    pdfObject\SetProperty("src = 'C:\test.pdf'") 
    pdfObject\Invoke("setShowToolbar(#True)") 
    pdfObject\Invoke("setView('FitH')") 
    pdfObject\Invoke("setPageMode('none')") 
    pdfObject\Invoke("setLayoutMode('SinglePage')") 
    While WaitWindowEvent() <> #PB_Event_CloseWindow : Wend 
    CloseWindow(0)
    pdfObject\Release()
  Else
    MessageRequester("COMate -Acrobat PDF demo", "Couldn't create the ActiveX object!")
  EndIf
EndIf
I may look like a mule, but I'm not a complete ass.
Little John
Addict
Addict
Posts: 4775
Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany

Post by Little John »

That's what the doctor has prescribed me! :D
Thanks a lot, srod ( and all other involved enterprises ;) ).

Regards, Little John
X
Enthusiast
Enthusiast
Posts: 311
Joined: Tue Apr 04, 2006 6:27 am

Post by X »

srod wrote:
SFSxOI wrote:Thank you srod, this is great. I'm having a lot of fun with it now that i'm getting used to it.
:) You're welcome.

The ActiveX stuff is now done (apart from the 'event sinks') which I will not add until later. I just need to update the help manual and then I will spend a few hours looking at the command parser to see if I can speed it up somewhat. When done I'll start collecting these examples of yours together and add them to the download - with full credit to yourself of course. Assuming you don't mind me making use of your code that is?
I think thats great news!! Does that mean you will be implementing the event sinks in the future? Or that you will not be implementing them? I think I am confused. This will allow the use of VBScripts calling PB functions?
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Post by SFSxOI »

Great srod. Thanks. Don't mind at all if you want to add the small examples I posted, after all they are more yours then mine anyway as without your guidance to help me get started and on the right path with this I wouldn't have done them.

Yes, by all means, optimize it, speed it up, add to it, just don't stop improving it or making it grow and expand. Eagerly looking forward to the next version. :)

heres another one, having a lot of fun with this thing now:

Code: Select all

XIncludeFile "COMate.pbi"

Procedure.s Monitor_Info()

Define.COMateObject objWMIService, Monitor
colMonitor.COMateEnumObject 

strComputer.s = "." 
Net_I_Index$ = Str(Interface_Index)

objWMIService = COMate_GetObject("winmgmts:\\" + strComputer + "\root\cimv2", "") 
If objWMIService 
  colMonitor = objWMIService\CreateEnumeration("ExecQuery('Select * from Win32_DesktopMonitor')")
  If colMonitor 
    Monitor= colMonitor\GetNextObject() 
    While Monitor
      Debug "Screen Height   =   " + Str(Monitor\GetIntegerProperty("ScreenHeight"))
      Debug "Screen Width   =   " + Str(Monitor\GetIntegerProperty("ScreenWidth"))
      Monitor\Release() 
      Monitor = colMonitor\GetNextObject()
    Wend
    colMonitor\Release() 
  EndIf
  objWMIService\Release()  
EndIf

EndProcedure

Monitor_Info()
Been spending the last several hours in the MSDN WMI section coding a library of snippets for possible use in the future.
Last edited by SFSxOI on Fri Sep 05, 2008 4:36 am, edited 1 time in total.
byo
Enthusiast
Enthusiast
Posts: 635
Joined: Mon Apr 02, 2007 1:43 am
Location: Brazil

Post by byo »

Hi, srod.

I have two questions:

1) Do you think you'll be able to implement COM servers across a network, I mean calling methods from another computer?

2) When creating a COM object and informing the window handle, will I be able to attach the activex object to any windows even external?

Thanks for the wonderful source code. 8)
Proud registered Purebasic user.
Because programming should be fun.
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

@SFSxOI : yes I think that WMI deserves it's own subfolder in the demo section! I have a couple of WMI demos already, but yours will make a great addition!

@X : Including Freak's source for handling Event Sinks shouldn't pose much of a problem. Because of the way COMate works, however, I'll probably need to tinker with the code first.

@byo : 1) Implementing an automation server on even the local machine is complex. Of course, what you mean is controlling an automation server on a remote machine! :wink: All that involves is changing one parameter and adding another to the CoGetClassObject_() function. That can be added at any time.

2) You can already do this. Have a look at the flash demo. Not sure if it would work on an external window; try it! :)
I may look like a mule, but I'm not a complete ass.
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Post by SFSxOI »

OK, just discovered what I think is a bug of some sort. I have a project i'm working on, it uses a data section that looks like this:

Code: Select all

DataSection
Mac_aUnk:
  Data.s "5254AB", "E20C0F", "080089", "080002", "00C0EF", "000150"
  Data.s "00E098", "00E081", "00E07D", "00E018", "004010", "00104B"
  Data.s "00C04F", "00A0CC", "006008", "0040FF", "0019B9", "00067C"
  Data.s "0010A4", "0004AC", "0000E1", "00A04B", "004027", "0006C1"
  Data.s "000214", "0013F7", "001150", "000d88", "000C41", "000086"
  Data.s "525400", "001310", "00045A", "000625", "001839", "009004"
  Data.s "000F66", "001217", "0014BF", "0016B6", "00105A", "002061"
  Data.s "00095B", "000FB5", "00146C", "00184D", "000D88", "00608C"
  Data.s "00173F", "0030BD", "000E3B", "00055D", "00177C", "006094"
  Data.s "000F3D", "001195", "001346", "0015E9", "004001", "006097"
  Data.s "00179A", "0050BA", "0080C8", "001349", "00E08F", "00603E"
  Data.s "00A0C5", "0004E2", "000BC5", "08008A", "08BBCC", "006052"
EndDataSection
Total 72 items ( 0 - 71), and i'm reading them like this:

Code: Select all


#Nb_MacUnk = 71

Dim Mac_aUnk.s(#Nb_MacUnk)
For k=0 To #Nb_MacUnk
  Read Mac_aUnk(k)
Next
and I call them like this to get a random selection from that list:

Code: Select all

Mac_aUnk(Random(#Nb_MacUnk))
If I include the "COMate.pbi":

Code: Select all

XIncludeFile "COMate.pbi"
That data section is no longer read properly and returns what looks like either unicode characters or garbage, sometimes nothing is returned. However, if I comment out the XIncludeFile "COMate.pbi" everything returns to normal and works fine.

So I thought, "OK, i'll compile it in unicode", with the XIncludeFile "COMate.pbi" in place it never compiles and crashes (no error, just a stopped responding) but if I comment out the XIncludeFile "COMate.pbi" it compiles fine.
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

You great dummy! :wink:

COMate has it's own data sections which are getting in the way of yours.

Stick a

Code: Select all

Restore Mac_aUnk
in your code, before reading the data, and you should be fine!
I may look like a mule, but I'm not a complete ass.
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Post by SFSxOI »

Arghhhhhhhhh !!!!

:)

Thanks srod
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

SFSxOI wrote:Arghhhhhhhhh !!!!

:)

Thanks srod
You're welcome! Now, time for me to finish ripping the command parser apart, I'll get this damn thing to run faster if it kills me! :)
I may look like a mule, but I'm not a complete ass.
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Post by SFSxOI »

I just discovered that this is not limited to the W32 classes either, it also works with the CIM classes, which is great for dual function devices.

CIM Classes: http://msdn.microsoft.com/en-us/library ... S.85).aspx

and a little example based on this: http://msdn.microsoft.com/en-us/library ... S.85).aspx

Code: Select all

; network system name

XIncludeFile "COMate.pbi"

Procedure.s CIM_Sys_Name()

Define.COMateObject objWMIService, SysName
colSysNames.COMateEnumObject 
strComputer.s = "." 

objWMIService = COMate_GetObject("winmgmts:\\" + strComputer + "\root\cimv2", "") 
If objWMIService 
  colSysNames = objWMIService\CreateEnumeration("ExecQuery('Select * from CIM_NetworkAdapter')")
  If colSysNames 
    SysName= colSysNames\GetNextObject() 
    While SysName
      System_Name.s = SysName\GetStringProperty("SystemName")
      SysName\Release() 
      SysName = colSysNames\GetNextObject()
    Wend
    colSysNames\Release() 
  EndIf
  objWMIService\Release()  
EndIf
ProcedureReturn System_Name
EndProcedure

Debug CIM_Sys_Name()
User avatar
Michael Vogel
Addict
Addict
Posts: 2797
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Post by Michael Vogel »

Sorry to put this question here between your conversation, I spent now some time to check if there is a possibility to see, if the agent is displayed (or has been hidden by the user) and if the agent is busy (because the given text has not been fully spoken/displayed)...

I found a (Visual Basic?) script somewhere in the internet but have no idea if this can be "translated" for using it with COMate:

Code: Select all

peedy.Get("state", "Showing, Speaking,Moving,Hiding");
The following code tries to show how I will organize my agent help: it should be called by a page reference for displaying the needed help.
It would be great to be able to escape from the procedure by finding a way to check if the state of the agent is "hiding" and to eleminate the fixed timed delays and to check if the state is not "speaking" or "moving"...

Is there any chance to do so?

Code: Select all

; Define

	XIncludeFile "COMate.pbi"

	Global AgentType.s

	Global AgentObject.COMateObject
	Global GenieObject.COMateObject

; EndDefine

If ExamineDesktops()
	cWidth=DesktopWidth(0)/2-50
	cHeight=DesktopHeight(0)/4
EndIf

Procedure.l AgentInit(type.s)

	#Quote$="'"

	AgentType=#Quote$+"Genie"+#Quote$

	AgentObject=COMate_CreateObject("Agent.Control.1")
	AgentObject\SetProperty("Connected = #True")
	AgentObject\Invoke("Characters\Load("+AgentType+")")

	GenieObject=0
	GenieObject=AgentObject\GetObjectProperty("Characters("+AgentType+")")

	ProcedureReturn GenieObject

EndProcedure
Procedure AgentShow(nr)

	Debug "Start "+Str(nr)
			
	If GenieObject
		GenieObject\Invoke("Show")
		Delay(3000)
		Debug "?"

		Select nr

		Case 1
			GenieObject\Invoke("MoveTo("+StrU(300,#Word)+", "+StrU(100,#Word)+", 1000)")
			Delay(2000)
			GenieObject\Invoke("Play('This is the Text for Help Page 1')")
			Delay(2000)
			
		Case 2
			GenieObject\Invoke("Play('Greet')")
			Delay(5000)
Debug COMateClass_GetIntegerProperty(GenieObject,"State")
;Debug GenieObject\Invoke("Get('state')")
			GenieObject\Invoke("Think('Hello, feel the Power!')")
			Delay(5000)
			GenieObject\Invoke("Play('Reading')")
			Delay(2000)
			GenieObject\Invoke("Play('This is the Text for Help Page 2')")
			Delay(5000)
			GenieObject\Invoke("Stop")

		Case 3
			GenieObject\Invoke("Speak('Blah blah.')")
			Delay(2000)
			GenieObject\Invoke("Play('This is the Text for Help Page 3')")
			Debug "!"


		EndSelect

		GenieObject\Invoke("Play('Hide')")
	EndIf


	Debug "Ende "+Str(nr)

EndProcedure
Procedure AgentStop()
	GenieObject\Release()
	AgentObject\Release()
EndProcedure


AgentInit("Genie")
For i=1 To 3
	AgentShow(i)
Next i
AgentStop()
Post Reply