View Single Post
Old 20th April 2016, 17:06   #10
Anders
Moderator
 
Anders's Avatar
 
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 5,275
All of this just goes to show how hard it is to do UI automation. My old example might be a bit broken because some versions of Calculator seems to interpret space as some operation.

Here is a better version (NSIS v3):
PHP Code:
!include LogicLib.nsh
!include Win\COM.nsh
!include Win\PropKey.nsh
!define /IfNDef CLSID_WshShell {72c24dd5-d70a-438b-8a42-98424b88afb8}
!
define /IfNDef IID_IWshShell2 {24BE5A30-EDFE-11d2-B933-00104B365C9F}
${
NSISCOMIFACEDECL}IWshShell2 AppActivate 17 (p,p,*i); (VARIANT*titlebeginswith,VARIANT*wait,VARIANT_BOOL*success)
${
NSISCOMIFACEDECL}IWshShell2 SendKeys 18 (p,p); (BSTR,VARIANT*wait//technet.microsoft.com/en-us/library/ee156592.aspx#Sending Keystrokes to a Program

Function SendKeysToApp
System
::Store S
Pop $R1 
Keys
Pop $R2 
App
!insertmacro ComHlpr_CreateInProcInstance "${CLSID_WshShell}" "${IID_IWshShell2}r0 ""
${If} $0 P<> 0
    System
::Call 'OLEAUT32::SysAllocString(w R2)i.r9'
    
System::Call '*${SYSSTRUCT_PROPVARIANT}(${VT_BSTR},,ir9)i.r1' 
    
System::Call '*${SYSSTRUCT_PROPVARIANT}(${VT_BOOL},,${VARIANT_TRUE})i.r2'
    
${IWshShell2::AppActivate} $'(r1,r2,${VARIANT_FALSE}r3)i.r4'
    
System::Call 'OLEAUT32::SysFreeString(ir9)'
    
DetailPrint "DEBUG: AppActivate($R2): hr=$4 success=$3"
    
${If} $>= 0
    
${AndIf} $<> ${VARIANT_FALSE}
        
System::Call 'OLEAUT32::SysAllocString(w R1)i.r9'
        
${IWshShell2::SendKeys} $'(r9,r2)i.r4'
        
System::Call 'OLEAUT32::SysFreeString(ir9)'
        
DetailPrint "DEBUG: SendKeys($R1) hr=$4"
    
${EndIf}
    
System::Free $2
    System
::Free $1
    
${IUnknown::Release} $""
${EndIf}
System::Store L
FunctionEnd

Function ActivateOrStart
System
::Store S
Pop $R1 
Cmd
Pop $R2 
App
!insertmacro ComHlpr_CreateInProcInstance "${CLSID_WshShell}" "${IID_IWshShell2}r0 ""
${If} $0 P<> 0
retryFind
:
    
System::Call 'OLEAUT32::SysAllocString(w R2)i.r9'
    
System::Call '*${SYSSTRUCT_PROPVARIANT}(${VT_BSTR},,ir9)i.r1' 
    
System::Call '*${SYSSTRUCT_PROPVARIANT}(${VT_BOOL},,${VARIANT_FALSE})i.r2'
    
${IWshShell2::AppActivate} $'(r1,r2,${VARIANT_FALSE}r3)i.r4'
    
System::Call 'OLEAUT32::SysFreeString(ir9)'
    
System::Free $2
    System
::Free $1
    
${If} $>= 0
    
${AndIf} $= ${VARIANT_FALSE}
        ${If} 
$R1 != ""
            
Exec '$R1'
            
StrCpy $R1 ""
        
${EndIf}
        
Sleep 1000
        
Goto retryFind TODOIt might be a good idea to give up after 20 seconds or so?
    ${EndIf}
    ${
IUnknown::Release} $""
${EndIf}
System::Store L
FunctionEnd


Section
Push 
"Calculator"
Push '"Calc.exe"'
Call ActivateOrStart

Push 
"Calculator"
Push "1{+}2="
Call SendKeysToApp

Sleep 1555
Push 
"Calculator"
Push "{DEL}"
Call SendKeysToApp Send DEL to reset the Calculator is not really required but I'm doing it anyway here

Sleep 1555
Push "Calculator"
Push "4*4="
Call SendKeysToApp
SectionEnd 
Using keybd_event or SendInput is a bit more complicated and I'm not going to even try before you tell us what you are actually trying to do. Performing calculations in Calculator is OK as a example but it is clearly not your real goal!

IntOp $PostCount $PostCount + 1
Anders is offline   Reply With Quote