Jump to content


Recommended Posts

Hi all,

I wanted to be able to quickly and cleanly send commands to a running copy of PowerPro, so here's how it can be done without constructing a god-awful Run() line. Using this code also adds the benefit of having your AutoIt script execution pause while PowerPro processes the passed command/s.

I have no 'expertise' in the area of DLLs and structures so please feel free to offer criticism and improvements to the code. Thanks to Larry for helping me get this far.

Note: Tested with AutoIt v3.1.1.82 and PowerPro v4.3.08.

Edit: The code no longer modifies the WinTitleMatchMode outside its own scope (thanks Valik).

Edit: Simpler command structure preparation (thanks again Larry).

Edit: Added better error checking (won't crash PowerPro if very long commands are sent).

Edit: Function now returns a Boolean value to indicate success.

Local $Cmd = 'Message PowerPro can now receive commands from AutoIt!'
MsgBox(0x40, "PowerProCmdSend()", 'Returned ' & PowerProCmdSend($Cmd) _
    & @CRLF & '@Error was ' & @Error)

Func PowerProCmdSend($Cmd)

; @Error = 0 -> Success
; @Error = 1 -> Command too long
; @Error = 2 -> PowerPro not running
; @Error = 3 -> Structures could not be made

; Assert a safe PowerPro command length
    If StringLen($Cmd) > 530 Then
        Return False

; Assert existence of PowerPro in memory
    Local $PrevOpt = Opt('WinTitleMatchMode', 4)
    Local $PProHandle = WinGetHandle('ClassName=PowerProMain')
    Local $Error = @Error
    Opt('WinTitleMatchMode', $PrevOpt)
    If $Error Then
        Return False

; Prepare command structure
    Local $CmdStruct = DLLStructCreate('Char[' & StringLen($Cmd) + 1 & ']')
    If @Error Then
        Return False
    DLLStructSetData($CmdStruct, 1, $Cmd)

    Local $CDStruct = DLLStructCreate('Ptr;DWord;Ptr')
    If @Error Then
        Return False
    DLLStructSetData($CDStruct, 1, 1)
    DLLStructSetData($CDStruct, 2, StringLen($Cmd) + 1)
    DLLStructSetData($CDStruct, 3, DLLStructGetPtr($CmdStruct))

; Do the call (WM_COPYDATA => 74)
    DLLCall('User32.dll', 'None', 'SendMessage', 'HWnd', $PProHandle, _
        'Int', 74, 'HWnd', WinGetHandle(AutoItWinGetTitle()), _
        'Ptr', DLLStructGetPtr($CDStruct))

; Tidy up

; Indicate success
    Return True

Edited by LxP
Link to post
Share on other sites

Warning: The code sets the WinTitleMatchMode to 4 as it needs to determine the handle of PowerPro's main window by class name. I'd love not to have to do this if anyone can offer a better way (but using window titles is out of the question).

Just set it back to whatever it was when your function ends.

Local $nWinTitleMatchMode = Opt("WinTitleMatchMode", 4)

; Code

Opt("WinTitleMatchMode", $nWinTitleMatchMode)
Link to post
Share on other sites

Thanks Larry,

Your code runs without problems; does it guarantee that the final character will be null though, or would it be wiser to explicitly declare it? --

DLLStructSetData($CmdStruct, 1, $Cmd)
DLLStructSetData($CmdStruct, 1, 0x00, StringLen($Cmd) + 1)
Link to post
Share on other sites

Thanks layer! ;)

Modified the above code to perform better error checking and to return a Boolean value indicating success. It seems that PowerPro will crash if it receives commands longer than 530 characters (while I could sometimes send longer commands during testing, the shortest command length with which I could get PowerPro to crash was 531). The function will now prevent this from occurring and return False and an appropriate @Error code.

Edited by LxP
Link to post
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
  • Recently Browsing   0 members

    No registered users viewing this page.

  • Create New...