Join The Works program to have access to the most current content, and to be able to ask questions and get answers from Revelation staff and the Revelation community

At 08 DEC 2020 01:21:45PM bob carten wrote:

I needed to enumerate the list of printers in OI10 without using OIPI. A WMI query is an easy way to get the collection of printers. WMI is an activex / COM interface. This proved to be a good example of using OpenInsight 10 embedded windows scripting host interface (RTI_AXSH). Read the RTI_AHSH_EQUATES for more information. Code example below.

function example_list_printers(printerList)

     /*

     *  enumerate available printers using WMI plus rti activex scripting host interface (RTI_AXSH)

     * 

     *  printerList (out) = fm delinited list of available printers

     *

     *  returns true on success

     *  may affect set_status in non-eventcontext

     *

     *  12-08-20  rjc  Created

     */



     #pragma format_Indent_Comments



     Declare Function Get_Status, isEventContext

     Declare Subroutine Set_Status



     



     $Insert logical

     $Insert msg_equates

     $Insert rti_text_equates  ; * defines crlf$

     $insert rti_AXSH_Equates  ; * methods for RTI_ASX  ( rti active scripting host interface )

     $Insert rti_ssp_equates   ; * set_status / get_Status equates



     * Build a vbScript to enumerate the printers

     * See geekshangout.com/vbs-script-to-list-the-network-printers-a-user-is-connected-to/



     script = 'Function getNetworkPrinters()'

     script := crlf$:'Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")'

     script := crlf$:'strPrinters = ""'

     script := crlf$: 'Set colPrinters = objWMIService.ExecQuery ("Select * From Win32_Printer")'

     script := crlf$:'If colPrinters.Count <> 0 Then'

     script := crlf$:'    i = 0'

     script := crlf$:''

     script := crlf$:'    For Each objPrinterInstalled In colPrinters '

     script := crlf$:'            i = i+1'

     script := crlf$:''

     script := crlf$:'            If objPrinterInstalled.ServerName <> "" Then'

     script := crlf$:'               strPrinters = strPrinters & objPrinterInstalled.ServerName & "\" & objPrinterInstalled.ShareName'

     script := crlf$:'            else'

     script := crlf$:'               strPrinters = strPrinters & objPrinterInstalled.Name'

     script := crlf$:'            end if'

     script := crlf$:''

     script := crlf$:'            If i < colPrinters.Count Then'

     script := crlf$:'               strPrinters = strPrinters & vbCrlf'

     script := crlf$:'            end if'

     script := crlf$:''

     script := crlf$:'    Next'

     script := crlf$:'End if'

     script := crlf$:''

     script := crlf$:'getNetworkPrinters = strPrinters'

     script := crlf$:''

     script := crlf$:'End Function'



     isOk = true$

     errorText = null$

     printerList = null$

     

     

     * Anything left over in get_status?

     * Assume it can be ignored - we should not have been called it there is already a real error

     hold_err = ""

     hold_status = Get_Status(hold_err)

     Set_Status(SETSTAT_OK$)



     



     * Create an instance of the scripting host, specify vbscript as the language

     createParam = "VBScript":@fm:"0":@FM:"":@FM:"-1"

     handle = rti_AXSH(REVAXSH_MTD_CREATE$, createParam)

     

     * Will set status on error

     If Get_Status(errorText) Then

          isOk = false$

     end



     * Add the script

     If isOk Then

     

          * addcode will return true if script compiles, false on error

          If rti_axsh(REVAXSH_MTD_ADDCODE$, handle, script) Then

               rslt = rti_axsh(REVAXSH_MTD_RUNEX$, handle, 'getNetworkPrinters' ,'')

          End Else

               * retrieve error details using get_status

               isOk = false$

               unused = Get_Status(errorText)

          end



     end



     * release the scripting host instance

     unused = rti_axsh(REVAXSH_MTD_DESTROY$, handle)



     If isOk Then

     

          Swap crlf$ With @fm In rslt

          transfer rslt To printerList

          

     End Else

     

          printerList = ""

          If isEventContext() Then



               Convert @fm To @vm In errorText

               

               def = ''

               def<mCaption$> = 'Error'

               def<mText$> = errorText

               def<mIcon$> = '!'

               Msg(@Window, def)



               Set_Status(setstat_Ok$)

          End

          

     end



Return isOk

At 14 DEC 2020 08:40AM bob carten wrote:

BTW,

The above script is a nice example of using the embedded scripting host in OI10. However, unlike me, some developers are not captivated by puzzling out arcane details of the windows scripting host, WMI queries and so forth. If you just want the answer without worrying about how to get it, you might be interested in using a third party solution. For instance, the free SRPUtilities library will get you the same list if network printers. See

SRP_Get_Printers


At 14 DEC 2020 10:00AM Donald Bakke wrote:

BTW,

The above script is a nice example of using the embedded scripting host in OI10. However, unlike me, some developers are not captivated by puzzling out arcane details of the windows scripting host, WMI queries and so forth. If you just want the answer without worrying about how to get it, you might be interested in using a third party solution. For instance, the free SRPUtilities library will get you the same list if network printers. See

SRP_Get_Printers

Don Bakke

SRP Computer Solutions, Inc.

Thanks for the shout-out, Bob. Just out of curiosity:

  1. In broad strokes, what would it take to implement your solution in OI 9? ( I guess another way to put it is, "How does OI 10 differ from OI 9 when calling scripts?" )
  2. For those who are interested in taking advantage of the Windows scripting host, where's a good place to learn this?

At 14 DEC 2020 02:16PM bob carten wrote:

what would it take to implement your solution in OI 9?

Below is the same function in 9.

It uses the OLECreateInstance to instantiate the windows scripting host, then injects the script and runs it.

How does OI 10 differ from OI 9 when calling scripts?

I think OI10 is a little cleaner. OI10 has a more structured interface, will manage the handles of the scripting host contexts for you. But the underlying capabilities are bounded by the scripting host itself, so 9 and 10 are similar.

For those who are interested in taking advantage of the Windows scripting host, where's a good place to learn this?

There is a lot of information online.

https://www.codeproject.com/articles/1004/windows-script-host-chapter-7-built-in-wshand-vbsc

You can use VbScript or JavaScript in the thing. I tend to search on "do-something javascript", find an example on the web and translate it into a function in I can call from OI. Simple scripts translate directly into OI's OLE syntax, but complex scripts, or scripts involving deeply nested object references are easier to host in the scripting host. You can store the scripting host in a named common, inject a bunch of scripts and use it like a custom OLE dll. That is what I did for RTI_JSON and some of the DSBFS functionality.


Function Example_list_printers(void)



Declare Subroutine Set_Status

Declare Function Get_Status, IsEventContext



$Insert msg_equates

$Insert logical

Equ crlf$ To \0D0A\

Equ setstat_ok$ To 0





script = 'Function getNetworkPrinters()'

script := crlf$:'Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")'

script := crlf$:'strPrinters = ""'

script := crlf$: 'Set colPrinters = objWMIService.ExecQuery ("Select * From Win32_Printer")'

script := crlf$:'If colPrinters.Count <> 0 Then'

script := crlf$:'    i = 0'

script := crlf$:''

script := crlf$:'    For Each objPrinterInstalled In colPrinters '

script := crlf$:'            i = i+1'

script := crlf$:''

script := crlf$:'            If objPrinterInstalled.ServerName <> "" Then'

script := crlf$:'               strPrinters = strPrinters & objPrinterInstalled.ServerName & "\" & objPrinterInstalled.ShareName'

script := crlf$:'            else'

script := crlf$:'               strPrinters = strPrinters & objPrinterInstalled.Name'

script := crlf$:'            end if'

script := crlf$:''

script := crlf$:'            If i < colPrinters.Count Then'

script := crlf$:'               strPrinters = strPrinters & vbCrlf'

script := crlf$:'            end if'

script := crlf$:''

script := crlf$:'    Next'

script := crlf$:'End if'

script := crlf$:''

script := crlf$:'getNetworkPrinters = strPrinters'

script := crlf$:''

script := crlf$:'End Function'



isOk = true$

errorText = null$

printerList = null$





* Anything left over in get_status?

* Assume it can be ignored - we should not have been called it there is already a real error

hold_err = ""

hold_status = Get_Status(hold_err)

Set_Status(SETSTAT_OK$)



/*

** 9.x version of scripting host below.

** I show the longhand and shorthand syntax for each step

*/





* Create an instance of the scripting host

oScript = OLECreateInstance( 'MSScriptControl.ScriptControl')

isOk = ( oleStatus() == 0 )



* specify vbscript as the language

If isOk Then

	

	//OlePutProperty(oScript, 'Language', 'VBScript')

	oScript->Language = 'VBScript'

	isOk = ( oleStatus() == 0 )

end



* Add the script

* This is like using a <script> tag in a webpage

* You can add entire libraries of scripts

* Will set olestatus if there is an error in the script

If isOk Then

	

	//x = OleCallMethod(oScript, 'AddCode', script)

	x = oScript->AddCode( script)

	isOk = ( olestatus() == 0 )

end





* You can run scripts with the Eval method, but you must pass in an expression.

*

* myExpression = "Myfunction(":quote(myparam1):",":quote(myparam2))

* rslt = OleCallMethod(oscript, 'Eval', myExpression)

*

* In practice it is awkward to use Eval, for example to  pass in text which contains quotes, or <idispatch>  





/*

* Instead of Eval, get the handle to the codeObject.

* This is like using scripts in the context of a web page.

* It lets you use syntax like 

* rslt = ocode->myFunction(myparam1,myparam2)

* which in turn allows you to pass parameters directly to the scripts.

*/ 



If isOk Then

	

	//oCode = oleGetProperty(oScript, 'CodeObject')

	oCode = oScript->CodeObject

	

	* Run the script

	//rslt = OleCallMethod(ocode, 'getNetworkPrinters')

	rslt = oCode->getNetworkPrinters()

	

End





If isOk Then

	

	Swap crlf$ With @fm In rslt

	transfer rslt To printerList

	

End Else

	

	printerList = ""

	If isEventContext() Then

		

		Convert @fm To @vm In errorText

		

		def = ''

		def<mCaption$> = 'Error'

		def<mText$> = errorText

		def<mIcon$> = '!'

		Msg(@Window, def)

		

		Set_Status(setstat_Ok$)

	End

	

End



Return printerList

At 14 DEC 2020 02:22PM bshumsky wrote:

BTW,

The above script is a nice example of using the embedded scripting host in OI10. However, unlike me, some developers are not captivated by puzzling out arcane details of the windows scripting host, WMI queries and so forth. If you just want the answer without worrying about how to get it, you might be interested in using a third party solution. For instance, the free SRPUtilities library will get you the same list if network printers. See

SRP_Get_Printers

Point of order - now that the Forum posts can be shown in descending order in a thread, your previous post is no longer necessarily "above".

Your annoyingly literal friend,

- Bryan Shumsky

Revelation Software, Inc.

View this thread on the Works forum...

  • third_party_content/community/commentary/forums_works/f13bbc44e998574691ceabe855a9817b.txt
  • Last modified: 2024/01/04 20:57
  • by 127.0.0.1