Sign in to follow this  
Followers 0
LxP

PowerProCmdSend()

6 posts in this topic

#1 ·  Posted (edited)

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
        SetError(1)
        Return False
    EndIf

; 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
        SetError(2)
        Return False
    EndIf

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

; Prepare COPYDATASTRUCT
    Local $CDStruct = DLLStructCreate('Ptr;DWord;Ptr')
    If @Error Then
        DLLStructDelete($CmdStruct)
        SetError(3)
        Return False
    EndIf
    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
    DLLStructDelete($CmdStruct)
    DLLStructDelete($CDStruct)

; Indicate success
    Return True

EndFunc
Edited by LxP

Share this post


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)

Share this post


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)

Share this post


Link to post
Share on other sites

Thanks Valik -- updated. I suppose I should read the help file more effectively.

Thanks Larry -- I'll hold you to your word! ;)

Share this post


Link to post
Share on other sites

AutoIt is amazing.

Nice work LxP ;)


FootbaG

Share this post


Link to post
Share on other sites

#6 ·  Posted (edited)

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

Share this post


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
Sign in to follow this  
Followers 0