Jump to content

DllCallbackRegister


JohnOne
 Share

Recommended Posts

What exactly is the nature of this function?

The help file does not say much about it execept you use it with the other Dll* functions.

In my head it sounds like it makes a regular DllCall but returns immediately and a function

is called when the DllCall actually returns.

Is this right? :) and if not, can someone explain it for a layman?

AutoIt Absolute Beginners    Require a serial    Pause Script    Video Tutorials by Morthawt   ipify 

Monkey's are, like, natures humans.

Link to comment
Share on other sites

  • Moderators

JohnOne,

This is my hobbyist coder attempt to explain it - no doubt a guru will be along in a while and blind you with all sorts of wondeful pixie-dust. ;)

I have only used DLLCallBackRegister when I an subclassing controls - that means to replace the procedure that they execute when actioned. It works like this:

- 1. You write a new procedure for the control so that it does something different when actioned, An example is my NoFocusLines UDF where I tell the controls not to honour the $WM_SETFOCUS message so as not to get the dotted lines - look at the _NoFocusLines_Proc function within the UDF.

- 2. You now register the procedure by using DllCallbackRegister like this:

$hNoFocusLines_Proc = DllCallbackRegister("_NoFocusLines_Proc", "int", "hwnd;uint;wparam;lparam")

This reserves a chunk of memory that contains the code you want Windows to run later and returns a handle to the procedure you have now registered. You also need a pointer so Windows know where to find it:

$pNew_WindowProc= DllCallbackGetPtr($hNoFocusLines_Proc)

- 3. Now we can tell Windows to replace the current procedure for a control with the one we have registered:

$aRet = _WinAPI_SetWindowLong($hWnd, -4, $pNew_WindowProc)

- 4. And when that control is now actioned it will use our procedure and not the default one. In the case of my UDF I wanted to pass on all other messages to the default Windows procedure for the control - the handle to which is returned by the WinAPI call we made earlier. So I can do this by using a call to _WinAPI_CallWindowProc(The_Returned_Handle, $hWnd, $iMsg, $wParam, $lParam) as the final line of my replacement procedure.

- 5. And then when you have done and want to exit, you have to do the reverse - reset the control to the normal procedure by using _WinAPI_SetWindowLong again and finally clear the memory you reserved with the original DllCallbackRegister call by using DllCallbackFree.

Head hurting yet? ;)

M23

P.S. Do not use the Beta if you want to play with this function (or the UDF I mentioned above) as it is not working correctly - it is fine with 3.3.8.1. :)

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

Cheers M23, I get it a lot more than I have previously when trying to get my head around it.

Thank you very glad.

I was hoping for what I thought it was to be correct though :)

I'm after a way to call a function in a dll but not wait for its return as it has a rather lengthy procedure

and I don't need a return value.

I don't suppose you know of such a spell do you?

AutoIt Absolute Beginners    Require a serial    Pause Script    Video Tutorials by Morthawt   ipify 

Monkey's are, like, natures humans.

Link to comment
Share on other sites

  • Moderators

JohnOne,

I do not believe you can call a DLL asynchronously - but you will need a guru to confirm that. :)

Try posting in the "Developer Chat" section - but I am not moving this thread there as my ears would burn all evening from the laughter when they saw my post above! ;)

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

You are most likely correct, I doubt there is a way to do this.

I'll go away and do a little more research on how I can achieve my goal from

the dll side of the relationship before I go next door for an autoit solution.

I'm thinking maybe create a new thread for the procedure and return from dll function.

Wish me luck :)

AutoIt Absolute Beginners    Require a serial    Pause Script    Video Tutorials by Morthawt   ipify 

Monkey's are, like, natures humans.

Link to comment
Share on other sites

  • Moderators

JohnOne,

I think that would be the way to do it. :)

Which inter-script communication solution will you use? ;)

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

JohnOne,

I think that would be the way to do it. :)

Which inter-script communication solution will you use? ;)

M23

Well currently I'm reading the stdout from the dll module, of course this means (69255) that I already have to

run another exe from an autoit script to be able to do this via a PID.

But that is where my problem lies, no matter where I call the dll from, it will still take too much time to return

and the stdout is not being fully read (for some reason) plus the calling exe seems to use too much cpu.

I imagine that is because it's sitting there waiting for a return from the dll.

In the end, I will probably use my favourite interprocess communication created by GreenCan (cant think of the link)

which is via memory

AutoIt Absolute Beginners    Require a serial    Pause Script    Video Tutorials by Morthawt   ipify 

Monkey's are, like, natures humans.

Link to comment
Share on other sites

I'm after a way to call a function in a dll but not wait for its return as it has a rather lengthy procedure

Why dont you just create a thread on it then? (see msdn: CreateThread).

As for dllcallbackregister, it provides an "standardized" or binary interface for other programs to communicate with yours, so that autoit funcs may be called from other languages. this is usefull with DLLs and callbacks, and COM

Ever wanted to call functions in another process? ProcessCall UDFConsole stuff: Console UDFC Preprocessor for AutoIt OMG

Link to comment
Share on other sites

Talking about DllCallbackRegister..

I've always wondered if it's possible to register a callback for cases when a process is created/terminated, I've searched far and beyond to no avail, is this possible?

Yeah, either through hooking or some lower level driver stuff (pssetcreateprocessnotifyroutine). You can also use wmi to do it, here's an example (in c#): http://weblogs.asp.net/whaggard/archive/2006/02/11/438006.aspx

here's some of the relevant wmi documentation: http://msdn.microsoft.com/en-us/library/aa392727#_hmm_processes

Ever wanted to call functions in another process? ProcessCall UDFConsole stuff: Console UDFC Preprocessor for AutoIt OMG

Link to comment
Share on other sites

Yeah, either through hooking or some lower level driver stuff (pssetcreateprocessnotifyroutine). You can also use wmi to do it, here's an example (in c#): http://weblogs.asp.net/whaggard/archive/2006/02/11/438006.aspx

here's some of the relevant wmi documentation: http://msdn.microsoft.com/en-us/library/aa392727#_hmm_processes

Oh, well, that's a bummer, I was hoping there would be something better than this.

Local $Obj = ObjGet("winmgmts:{impersonationLevel=impersonate}!" & @ComputerName & "rootcimv2")
Local $hObj = ObjCreate("WbemScripting.SWbemSink")
If IsObj($Obj) And IsObj($hObj) Then
  ObjEvent($hObj, "SINK_"); Set up a callback to populate the list view when a process dies or is spawned
  $Obj.ExecNotificationQueryAsync($hObj, "SELECT * FROM __InstanceOperationEvent WITHIN 0.1 WHERE TargetInstance ISA 'Win32_Process'")
EndIf
Link to comment
Share on other sites

Oh, well, that's a bummer, I was hoping there would be something better than this.

Local $Obj = ObjGet("winmgmts:{impersonationLevel=impersonate}!" & @ComputerName & "rootcimv2")
Local $hObj = ObjCreate("WbemScripting.SWbemSink")
If IsObj($Obj) And IsObj($hObj) Then
  ObjEvent($hObj, "SINK_"); Set up a callback to populate the list view when a process dies or is spawned
  $Obj.ExecNotificationQueryAsync($hObj, "SELECT * FROM __InstanceOperationEvent WITHIN 0.1 WHERE TargetInstance ISA 'Win32_Process'")
EndIf
Why so?

Ever wanted to call functions in another process? ProcessCall UDFConsole stuff: Console UDFC Preprocessor for AutoIt OMG

Link to comment
Share on other sites

Why so?

Because in comparison to a call back, the call back will only operate while it was called, the object event works in intervals "WITHIN 0.1 WHERE" I found out that the object event will use a lot of CPU resources if I don't set it to something a little higher than "0.1", which "0.8" seems to be ok for me, I had a hard time finding out that that was what was causing 10-20% cpu usage by my application.

Link to comment
Share on other sites

Because in comparison to a call back, the call back will only operate while it was called, the object event works in intervals "WITHIN 0.1 WHERE" I found out that the object event will use a lot of CPU resources if I don't set it to something a little higher than "0.1", which "0.8" seems to be ok for me, I had a hard time finding out that that was what was causing 10-20% cpu usage by my application.

What was causing it then? I mean what was causing it?

...In your words.

♡♡♡

.

eMyvnE

Link to comment
Share on other sites

What was causing it then? I mean what was causing it?

...In your words.

After being on these forums for quite a while now, getting to know you little by little through your posts that usually contain the most cryptic indecipherable code and knowing that you are personally involved in the development of AutoIt and seeing that I have caught your attention enough so that you quoted me means I must have said something that made you a little unsettled...

Long story short, I'm wrong aren't I?

To answer your question directly, in my words, I can not really know what ​was causing it, but I know you are more eligible to conceive a more accurate explanation.

Link to comment
Share on other sites

  • 1 month later...

What was causing it then? I mean what was causing it?

...In your words.

I hate to resurrect a diseased thread but I just felt the need to correct myself after discovering the true reason for the high CPU usage due to using the WMI callback on event function, the reason was that I was getting results for __InstanceOperationEvent when I should have only been requesting

$Obj.ExecNotificationQueryAsync($hObj, "SELECT * FROM __InstanceCreationEvent WITHIN 0.5 WHERE TargetInstance ISA 'Win32_Process'")
  $Obj.ExecNotificationQueryAsync($hObj, "SELECT * FROM __InstanceDeletionEvent WITHIN 0.5 WHERE TargetInstance ISA 'Win32_Process'")

in order to avoid being bombarded with unwanted information involving modification events which you will receive a F*** load of them if you do.

Link to comment
Share on other sites

  • 1 year later...

@CaptainClucks ( and any other expert )

Have you found a lower level method for monitoring process creation / destruction? The wmi method causes 5% cpu usage for me on polling just every 3 seconds,

which is definitly to much for a background task. Would be nice to hear any proposals.

HotKeySet("{ESC}","ESC")
Func ESC()
    Exit(0)
EndFunc


Local $Obj    = ObjGet(    "winmgmts:{impersonationLevel=impersonate}!\\" & @ComputerName & "\root\cimv2")
Local $hObj   = ObjCreate( "WbemScripting.SWbemSink" )

If IsObj($Obj) And IsObj($hObj) Then
    ObjEvent( $hObj , "SINK_" )
    $Obj.ExecNotificationQueryAsync( $hObj , "SELECT * FROM __InstanceCreationEvent WITHIN 3.0 WHERE TargetInstance ISA 'Win32_Process'")
    $Obj.ExecNotificationQueryAsync( $hObj , "SELECT * FROM __InstanceDeletionEvent WITHIN 3.0 WHERE TargetInstance ISA 'Win32_Process'")
EndIf

Sleep(100000)

Func SINK_OnObjectReady($OB)

    if $OB.Path_.Class =  "__InstanceCreationEvent"  Then  ;  $ob.TargetInstance.ProcessID,  $ob.targetinstance.parentprocessid

        consolewrite( "start " &  $ob.targetinstance.name  & @LF )
    else
        consolewrite( "end "   &  $ob.targetinstance.name & @LF )
    EndIf

EndFunc

Best regards

Blues

Edited by Bluesmaster

My UDF: [topic='156155']_shellExecuteHidden[/topic]

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...