Jump to content
VIP

[Solved] Drag and Drop with UAC

Recommended Posts

VIP
#RequireAdmin
#include <WinAPISys.au3>
#include <WindowsConstants.au3>

_WinAPI_ChangeWindowMessageFilterEx ( $hWnd, $iMsg, $iAction )

;_WinAPI_ChangeWindowMessageFilterEx( $hWnd, $WM_DROPFILES, $MSGFLT_ALLOW)
;_WinAPI_ChangeWindowMessageFilterEx( $hWnd, $WM_COPYDATA, $MSGFLT_ALLOW)
;_WinAPI_ChangeWindowMessageFilterEx( $hWnd, $WM_COPYGLOBALDATA, $MSGFLT_ALLOW)

; $WM_COPYDATA = 0x004A - $WM_DROPFILES = 0x0233 - $WM_COPYGLOBALDATA = 0x0049 - $MSGFLT_ALLOW = 1 - $MSGFLT_DISALLOW = 2

Example:

#RequireAdmin
Opt("TrayAutoPause", 0)
#include <WinAPISys.au3>
#include <WindowsConstants.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <ButtonConstants.au3>
Global $AppWindows = GUICreate("Dao Van Trong  - Trong.CF", 320, 50, -1, -1, BitOR($WS_BORDER, $WS_POPUP), BitOR($WS_EX_ACCEPTFILES, $WS_EX_TOPMOST, $WS_EX_WINDOWEDGE))
Global $AppTitle = GUICtrlCreateLabel("=== Drag and drop UAC ===", 56, 0, 210, 25, $SS_CENTERIMAGE, $GUI_WS_EX_PARENTDRAG)
GUICtrlSetState(-1, $GUI_DROPACCEPTED)
GUICtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT)
GUICtrlSetFont(-1, 9, 800)
Global $AppTask = GUICtrlCreateLabel("Drag and drop files here ", 56, 24, 220, 17, $SS_CENTERIMAGE, $GUI_WS_EX_PARENTDRAG)
GUICtrlSetState(-1, $GUI_DROPACCEPTED)
GUICtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT)
GUICtrlSetFont(-1, 9, 500)
Global $xCLOSE = GUICtrlCreateButton("X", 308, 0, 12, 12, BitAND($BS_MULTILINE, $BS_VCENTER, $BS_FLAT))
GUICtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT)
GUICtrlSetState(-1, $GUI_DROPACCEPTED)
GUISetState(@SW_SHOW)
_WinAPI_ChangeWindowMessageFilterEx($AppWindows, $WM_DROPFILES, $MSGFLT_ALLOW)
_WinAPI_ChangeWindowMessageFilterEx($AppWindows, $WM_COPYDATA, $MSGFLT_ALLOW)
_WinAPI_ChangeWindowMessageFilterEx($AppWindows, $WM_COPYGLOBALDATA, $MSGFLT_ALLOW)
Global $__aDropFiles
GUIRegisterMsg($WM_DROPFILES, "WM_DROPFILES")
Local $nMsg
While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_DROPPED
            If $__aDropFiles[0] > 0 Then
                For $i = 1 To $__aDropFiles[0]
                    ConsoleWrite($__aDropFiles[$i] & @CRLF)
                    GUICtrlSetData($AppTask, $__aDropFiles[$i])
                Next
            EndIf
        Case $GUI_EVENT_CLOSE, $xCLOSE
            Exit
    EndSwitch
WEnd
Func WM_DROPFILES($hWnd, $iMsg, $iwParam, $ilParam)
    #forceref $hWnd, $ilParam
    Switch $iMsg
        Case $WM_DROPFILES
            Local $aReturn = _WinAPI_DragQueryFileEx($iwParam)
            If IsArray($aReturn) Then
                $__aDropFiles = $aReturn
            Else
                Local $aError[1] = [0]
                $__aDropFiles = $aError
            EndIf
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_DROPFILES

 

Edited by Trong
Example

Regards,
 

Share this post


Link to post
Share on other sites
AutoBert

An application started with Admin can only get files from apllications which also started with Admin.

Share this post


Link to post
Share on other sites
VIP

Thanks !

Edited by Trong

Regards,
 

Share this post


Link to post
Share on other sites
qwert

@Trong: would you mind restating (in your first post) what the problem is that you've solved?

_WinAPI_ChangeWindowMessageFilterEx appears to be very useful ... but are you working only with AU3 scripts? ... or have you tried it with other applications?  If so, what is your method for doing that?

Thanks for opening this topic.

 

  • Like 1

Share this post


Link to post
Share on other sites
AutoBert

His problem was, he could not drop files on his GUI's ListView. Script requires Admin privileges (#RequireAdmin). I found after @AdmiralAlex post this solution:

;found https://www.autoitscript.com/forum/topic/124406-drag-and-drop-with-uac/
#RequireAdmin
#include <GUIConstantsEx.au3>
#include <ListViewConstants.au3>
#include <WindowsConstants.au3>
Opt("GuiOnEventMode", 1)

Global $DropFilesArr[1]
Global $FilesAllowedMask[4] = [3, ".txt", ".exe", "D"]

$mainFrm = GUICreate("Drop Multiple Files to LV Demo", 500, 400, -1, -1, -1, $WS_EX_ACCEPTFILES+$WS_EX_TOPMOST)
_ChangeWindowMessageFilterEx($mainFrm, 0x233, 1)
_ChangeWindowMessageFilterEx($mainFrm, $WM_COPYDATA, 1)
_ChangeWindowMessageFilterEx($mainFrm, 0x0049, 1)

GUISetOnEvent($GUI_EVENT_CLOSE, "MainEvents")
GUISetOnEvent($GUI_EVENT_DROPPED, "MainEvents")

GUIRegisterMsg(0x233, "WM_DROPFILES_FUNC")

GUICtrlCreateLabel("Drag to the List View some file(s)", 60, 20)

$ListView = GUICtrlCreateListView("Col1", 50, 50, 400, 300, -1, $WS_EX_CLIENTEDGE)
GUICtrlSendMsg(-1, $LVM_SETEXTENDEDLISTVIEWSTYLE, $LVS_EX_HEADERDRAGDROP, $LVS_EX_HEADERDRAGDROP)
GUICtrlSetState(-1, $GUI_DROPACCEPTED)

GUISetState()

While 1
    Sleep(100)
WEnd

Func MainEvents()
    Switch @GUI_CtrlId
        Case $GUI_EVENT_CLOSE
            Exit
        Case $GUI_EVENT_DROPPED
            $NotValidExtPath = ""
            $ValidExtCount = 0
            For $i = 1 To UBound($DropFilesArr)-1
                $ValidExtCount += 1
                GUICtrlCreateListViewItem($DropFilesArr[$i], $ListView)
            Next
            If $ValidExtCount > 0 Then GUICtrlSendMsg($ListView, $LVM_SETCOLUMNWIDTH, 0, -1)
    EndSwitch
EndFunc

Func _IsValidExt($sPath)
    For $i = 1 To $FilesAllowedMask[0]
        If StringRight($sPath, 4) = $FilesAllowedMask[$i] And _
            Not StringInStr(FileGetAttrib($sPath), $FilesAllowedMask[$i]) Then Return True
    Next
    Return False
EndFunc

Func WM_DROPFILES_FUNC($hWnd, $msgID, $wParam, $lParam)
    Local $nSize, $pFileName
    Local $nAmt = DllCall("shell32.dll", "int", "DragQueryFile", "hwnd", $wParam, "int", 0xFFFFFFFF, "ptr", 0, "int", 255)
    For $i = 0 To $nAmt[0] - 1
        $nSize = DllCall("shell32.dll", "int", "DragQueryFile", "hwnd", $wParam, "int", $i, "ptr", 0, "int", 0)
        $nSize = $nSize[0] + 1
        $pFileName = DllStructCreate("char[" & $nSize & "]")
        DllCall("shell32.dll", "int", "DragQueryFile", "hwnd", $wParam, "int", $i, "ptr", _
            DllStructGetPtr($pFileName), "int", $nSize)
        ReDim $DropFilesArr[$i + 2]
        $DropFilesArr[$i+1] = DllStructGetData($pFileName, 1)
        $pFileName = 0
    Next
    $DropFilesArr[0] = UBound($DropFilesArr)-1
EndFunc

Func _ChangeWindowMessageFilterEx($hWnd, $iMsg, $iAction)
    Local $aCall = DllCall("user32.dll", "bool", "ChangeWindowMessageFilterEx", _
            "hwnd", $hWnd, _
            "dword", $iMsg, _
            "dword", $iAction, _
            "ptr", 0)
    If @error Or Not $aCall[0] Then Return SetError(1, 0, 0)
    Return 1
EndFunc

When you remove Lines 12-14 which uses the func _ChangeWindowMessageFilterEx you have the problem similar to @Tong's. When you want to use this func in a other programming language you have to implement the DLL-call for User32.dll.

Share this post


Link to post
Share on other sites
VIP

His problem was, he could not drop files on his GUI's ListView. Script requires Admin privileges (#RequireAdmin). I found after @AdmiralAlex post this solution:

[..]
    Local $aCall = DllCall("user32.dll", "bool", "ChangeWindowMessageFilterEx", _
  [...]

Windows 7 or later Only ChangeWindowMessageFilterEx 

XP and All :

#include <WinAPISys.au3>
_WinAPI_ChangeWindowMessageFilterEx ( $hWnd, $iMsg, $iAction )


 


Regards,
 

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

  • Similar Content

    • griefman
      By griefman
      Hi everyone,
      i am writing to you after a very long struggle i had while trying to figure out how to send a simple click inside a virtual machine running in vmware workstation 14.
      i have an autoit script running on my host machine watching for the UAC prompt to be displayed in a running vm. Both the host and the guest OS are Windows 10. This script worked perfectly with virtual box. It recognized the UAC prompt and clicked inside and the UAC was accepted. Since i switched to VMware Workstation 14, the script no longer clicks inside the VM successfully. It acts as if it clicks, but it doesn't. 
      I tried sending key combinations instead of a click, so that the VM can grab the input, but it also did not work. Every attempt that i made to send clicks or keys from the host inside the VM did not work. I tried using:
      MouseClick
      ControlClick
      MouseMove
      _WinAPI_Mouse_Event
      _WinAPI_Keybd_Event
       
      I also noticed that while the cursor moves to the target which has to be cilcked when my vmware worstation window is not focused, it even doesn't do that when i WinActivate the vmware workstation window first.
       
      Did anyone experience such an issue, or maybe could give me a hint, what else i could use to send a key combination or a mouse click in a vmware workstation 14 pro guest window?
       
      here is my code, which works with virtualbox:
       
      #AutoIt3Wrapper_Icon=".\uac.ico" #include <ImageSearchSubrogated.au3> FileInstall(".\ImageSearchDLL.dll", ".\ImageSearchDLL.dll", 0) FileInstall(".\UAC_ginloSetup.bmp", ".\UAC_ginloSetup.bmp", 0) FileInstall(".\UAC_Yes.bmp", ".\UAC_Yes.bmp", 0) ; set global variables for the coordinates, which should be delivered global $x1 = 0, $y1 = 0 global $x2 = 0, $y2 = 0 global $counter1 = 0 global $counter2 = 0 global $sleep = 10000 global $smallSleep = 5000 ; execute the script in a loop, so that it will hopefully recover from some unexpected errors While $counter1 < 1 checkForImage() WEnd #cs ------------ Functions #ce ------------ Func checkForImage() While $counter2 < 1 ; search for the UAC in the entire screen - 2 screens supported local $searchUac = _ImageSearchArea('UAC_ginloSetup.bmp', 1, -2568, -8, 5136, 1440, $x1, $y1, 0) If $searchUac = 1 Then ; if the UAC was found search for the Yes button in a an area 200 x 200 from the middle of the found UAC image local $searchYes = _ImageSearchArea('UAC_Yes.bmp', 1, $x1, $y1, $x1 + 200, $y1 + 200, $x2, $y2, 0) If $searchYes = 1 Then ; if the Yes button was found click it and pause the script for $sleep seconds MouseClick("left", $x2, $y2, 1,0) Sleep($sleep) Else ; if the Yes button was not found retry from the beginning in $smallSleep seconds MsgBox(0, "UAC found error", "UAC was found but the 'Yes' button was not found. Script will retry in " & $smallSleep & " seconds.", $smallSleep) EndIf ; another way to accept the UAC - via shortcut ;Send("{TAB}{TAB}{TAB}{TAB}{TAB}{TAB}") ;Send("!y") Else ; if UAC was not found try again in $sleep seconds Sleep($sleep) EndIf WEnd ; if some error occured which expired the loop, pause the script for $sleep seconds MsgBox(0, "Error", "Some Error expired the timer and the script could not recover. The script will restart in " & $sleep & " seconds.", $sleep) EndFunc  
    • ur
      By ur
      I saw few UDFs related to IE and Firefox to automate tasks related to these browsers.
       
      But is it possible to automate tasks like drag and drop in the website.?
      Like in the below video.
      If not can you tell me some alternatives, as it is not possible in selenium as I heard.
      drag_and_drop.mp4
    • perlabsrat
      By perlabsrat
       
      Hello,
      I found a good drag and drop example here: https://www.autoitscript.com/forum/topic/28062-drop-multiple-files-on-any-control/
      I have been searching but not finding a way to do a variant of this example.
      I want to have a form with 2 or more list box controls on the form that have $GUI_DROPACCEPTED enabled. I then want to be able to drop separate groups of files on each list box  so that I have 2 separate list of dropped items that I can act upon independently rather than this example which only has one target.
      I have modified the example to add the 2nd list box but I am not sure how to determine which control hwnd got the drop event and then only add the files to that list box. In the current example both controls add the files to $hList1
       
      Apparently $hWnd  in WM_DROPFILES_FUNC() is not the control that triggers the event as I compared its value to the hwnd of each control.
      hwnd from $hList1 = 0x002F0BB8 hwnd from $hList2 = 0x003C06E0 hwnd from WM_DROPFILES_FUNC = 0x002F1180 hwnd from WM_DROPFILES_FUNC = 0x002F1180  
      Any ideas?

       
      ;Example from https://www.autoitscript.com/forum/topic/28062-drop-multiple-files-on-any-control/ #include <GUIConstants.au3> ;~ Global $WM_DROPFILES = 0x233 Global $gaDropFiles[1], $str = "" ### Koda GUI section start ### ;~ $hGUI = GUICreate("Test", 400, 200, 219, 178, -1, BitOR($WS_EX_ACCEPTFILES, $WS_EX_TOPMOST)) ;~ $hList = GUICtrlCreateList("", 5, 5, 390, 190) ;~ GUICtrlSetState (-1, $GUI_DROPACCEPTED) Global $hGUI = GUICreate("Test", 573, 419, 219, 178, -1, BitOR($WS_EX_ACCEPTFILES, $WS_EX_TOPMOST, $WS_EX_WINDOWEDGE)) Global $hList1 = GUICtrlCreateList("", 5, 5, 390, 188) GUICtrlSetState(-1, $GUI_DROPACCEPTED) GUICtrlSetData(-1, "List1") Global $hList2 = GUICtrlCreateList("", 42, 205, 390, 188) GUICtrlSetState(-1, $GUI_DROPACCEPTED) GUICtrlSetData(-1, "List2") ConsoleWrite("hwnd from $hList1 = " & GUICtrlGetHandle($hList1) & @CRLF) ConsoleWrite("hwnd from $hList2 = " & GUICtrlGetHandle($hList2) & @CRLF) GUISetState(@SW_SHOW) ### Koda GUI section end ### GUIRegisterMsg($WM_DROPFILES, "WM_DROPFILES_FUNC") While 1 $nMsg = GUIGetMsg() Switch $nMsg Case $GUI_EVENT_CLOSE Exit Case $GUI_EVENT_DROPPED $str = "" For $i = 0 To UBound($gaDropFiles) - 1 $str &= "|" & $gaDropFiles[$i] Next GUICtrlSetData($hList1, $str) EndSwitch WEnd Func WM_DROPFILES_FUNC($hWnd, $msgID, $wParam, $lParam) ConsoleWrite("hwnd from WM_DROPFILES_FUNC = " & $hGUI & @CRLF) Local $nSize, $pFileName Local $nAmt = DllCall("shell32.dll", "int", "DragQueryFile", "hwnd", $wParam, "int", 0xFFFFFFFF, "ptr", 0, "int", 255) For $i = 0 To $nAmt[0] - 1 $nSize = DllCall("shell32.dll", "int", "DragQueryFile", "hwnd", $wParam, "int", $i, "ptr", 0, "int", 0) $nSize = $nSize[0] + 1 $pFileName = DllStructCreate("char[" & $nSize & "]") DllCall("shell32.dll", "int", "DragQueryFile", "hwnd", $wParam, "int", $i, "ptr", DllStructGetPtr($pFileName), "int", $nSize) ReDim $gaDropFiles[$i + 1] $gaDropFiles[$i] = DllStructGetData($pFileName, 1) $pFileName = 0 Next EndFunc ;==>WM_DROPFILES_FUNC  
       
    • tcurran
      By tcurran
      Here's a short UDF that will, at least in most cases, detect whether a window can be copied from or pasted to programmatically--for example, by Send()ing ctl-c, ctl-v. This is often disabled when programs (like your AutoIt script) run at a lower UAC integrity level than the application they are trying to operate on.
      #include <WinAPI.au3> Func _WindowIsPasteable($handle) ;accepts window handle; returns true or false whether a window will accept Ctl-C, Ctl-V Local $bCanPaste = True Local $hTestWindowPID = 0 Local $hTestWindowTID = _WinAPI_GetWindowThreadProcessId($handle, $hTestWindowPID) _WinAPI_AttachThreadInput(_WinAPI_GetCurrentThreadId(), $hTestWindowTID, True);attach to window we want to paste into $bCanPaste = _WinAPI_GetFocus() ;Test whether window is paste-able--returns False if it is not _WinAPI_AttachThreadInput(_WinAPI_GetCurrentThreadId, $hTestWindowTID, False);detach from window thread Return $bCanPaste EndFunc Pass it a window handle; it returns true or false whether a window will accept programmatic pasting. The function may not work on the CMD window, since it handles the clipboard uniquely.
      This function works by attaching to the program thread of the window whose handle it receives, then attempting to perform a GetFocus on that thread. In most cases, the attempt will fail if the window will not accept programmatic copy-paste.
    • dreivilo47
      By dreivilo47
      When I use the following code I receive an UAC message:
       
      #RequireAdmin RunWait("msiexec /i winzip205-64.msi /quiet") Exit How can I hide (bypass) the UAC message?
×