I am trying to figure out a way to read the file name of a selected file in windows explorer. I tried this but it did not work
run ("C:\WINDOWS\explorer.exe C:\ProgramData\")
WinWaitActive("ProgramData")
Sleep(2000)
;select the 4th file
Send("{down}{down}{down}")
$index=ControlListView ( "ProgramData", "", "SysListView321", "GetSelected")
ConsoleWrite("$index: " & $index & #CRLF)
$text = ControlListView ( "ProgramData", "", "SysListView321", "GetText",$index)
ConsoleWrite("$text: " & $text & #CRLF)
I know that we can do it with Run("explorer.exe /e,/select," & filename) but I want an alternate way to this.
Your above script accesses DirectUIHWND. ControlListView sends a command to a ListView32 control.
DirectUIHWND <> ListView32 and it can not be accesses that easily.
This is a "dirty" way to access it:
;#include <MsgBoxConstants.au3>
;Run("explorer.exe")
;Sleep(2000)
Local $hWin = WinGetHandle("Libraries") ;Change to ProgramData for you
Local $hwnd = ControlGetHandle($hWin, "", "DirectUIHWND3") ;the name of the list on the left is : SysTreeView321. Hence it is a listTREEview
ConsoleWrite("Window handle: " & $hWin & #LF)
ConsoleWrite("Control handle: " & $hwnd & #LF)
WinActivate($hWin)
ControlFocus($hwnd, "", $hwnd)
Send("{down}{down}{down}") ;;;select a random item
ConsoleWrite(SysTreeViewGetText() & #LF)
Func SysTreeViewGetText()
ClipPut("")
ControlSend($hWnd, "", "", "{F2}")
ControlSend($hWnd, "", "", "^c")
ControlSend($hWnd, "", "", "{ESC}")
Return ClipGet()
EndFunc
If you are trying to acces the treeview on the left then check the comments in the example and replace the controlid
You can create a small gui that will list all the files of the folder you want and then make then select from the gui without even having to interact the explorer.exe
Here is an example:
#include <File.au3>
Local $aFileList
Local $hGui = GUICreate("ProgramData", 450, 300)
Local $hButton = GUICtrlCreateButton("File list", 180, 50, 100)
Local $hList = GUICtrlCreateList("", 10, 100, 430, 200)
GUISetState(#SW_SHOW)
While True
$sMsg = GUIGetMsg()
Switch $sMsg
Case -3
Exit
Case $hButton
$aFileList = _FileListToArray(#DesktopDir, "*") ; add your path here
For $i = 0 To UBound($aFileList) -1
GUICtrlSetData($hList, $aFileList[$i])
Next
EndSwitch
Sleep(100)
WEnd
As promised ;)
Here is an simpler example without having to download any udf:
HotKeySet("{ESC}", "_Exit")
Do
Sleep(10)
Until WinExists("[REGEXPCLASS:^(Cabinet|Explore)WClass$]")
Local $hWin = WinGetHandle( "[REGEXPCLASS:^(Cabinet|Explore)WClass$]" )
If Not $hWin Then Exit
Local $hItem = "", $hSelection, $sText
WinActivate($hWin)
; Shell object
$oShell = ObjCreate("Shell.Application")
; Find window
For $oWindow In $oShell.Windows()
If $oWindow.HWND() = $hWin Then ExitLoop
Next
; Selected items
For $oItem In $oWindow.Document.SelectedItems()
$hItem = $oItem.Name()
Next
While WinExists("[REGEXPCLASS:^(Cabinet|Explore)WClass$]")
For $oItem In $oWindow.Document.SelectedItems()
If $oItem.Name() <> $hItem Then
ConsoleWrite("Name: " & $oItem.Name & #CRLF) ;Sets or gets the item's name.
ConsoleWrite("Type: " & $oItem.Type & #CRLF) ;Contains a string representation of the item's type.
ConsoleWrite("Path: " & $oItem.Path & #CRLF) ;Contains the item's full path and name.
ConsoleWrite("IsLink: " & $oItem.IsLink & #CRLF) ;Indicates whether the item is a shortcut.
ConsoleWrite("IsFolder: " & $oItem.IsFolder & #CRLF) ;Indicates whether the item is a folder.
ConsoleWrite("IsFileSystem: " & $oItem.IsFileSystem & #CRLF) ;Indicates if the item is part of the file system.
ConsoleWrite("IsBrowsable : " & $oItem.IsBrowsable & #CRLF) ;Indicates if the item can be hosted inside a browser or Windows Explorer frame.
ConsoleWrite("GetLink : " & $oItem.GetLink & #CRLF) ;Contains the item's ShellLinkObject object, if the item is a shortcut.
ConsoleWrite("GetFolder : " & $oItem.GetFolder & #CRLF) ;Contains the item's Folder object, if the item is a folder.
ConsoleWrite("Application : " & $oItem.Application & #CRLF) ;Contains the Application object of the folder item.
ConsoleWrite("Date: " & $oItem.ModifyDate & #CRLF) ;yy/mm/dd hh/nn/ss
ConsoleWrite("Size: " & $oItem.Size & " bytes"& #CRLF) ;Contains the item's size.
;ConsoleWrite("Type: " & Round($oItem.Size / 1000) & " KB"& #CRLF)
$hItem = $oItem.Name()
EndIf
Next
Sleep(100)
WEnd
ConsoleWrite("Exit" & #LF)
Func _Exit()
Exit
EndFunc ;==>_Exit
In the first for loop you will have all the names. In the second we simply select every item.
If you need more help let me know
Related
I need a VBScript that will check if a process is in use by a specific user:
Agent clicks program icon --> batch file calls for progcheck.vbs -->
progcheck.vbs looks to see is "whatever.exe" is running under that user only -->
if program is running under that user then MsgBox "Program running" --> wscript.quit (this needs to terminate out of the batch file)
else --> return to batch file.
I have tried this with tasklist in a batch file and the script works, but takes forever to run for a domain user. Want to do this in vbscript anyway.
*** UPDATED SCRIPT WITH MODS 10/12 *****
OPTION EXPLICIT
DIM strComputer,strProcess, strUserName,wshShell
Set wshShell = WScript.CreateObject( "WScript.Shell" )
strUserName = wshShell.ExpandEnvironmentStrings( "%USERNAME%" )
strComputer = "." '
strProcess = "notepad.exe"
IF isProcessRunning(strComputer,strProcess,strUserName) THEN
If MsgBox ("Notepad needs to be closed.", 1) = 1 then
wscript.Quit(1)
End If
END IF
FUNCTION isProcessRunning(BYVAL strComputer,BYVAL strProcessName,BYVAL strUserName)
DIM objWMIService, strWMIQuery
strWMIQuery = "Select * from Win32_Process where name like '" & strProcessName & "' AND owner like '" &strUserName& "'"
SET objWMIService = GETOBJECT("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" _
& strComputer & "\root\cimv2")
IF objWMIService.ExecQuery(strWMIQuery).Count > 0 THEN
isProcessRunning = TRUE
ELSE
isProcessRunning = FALSE
END If
End Function
Let me know what you think and where I have it wrong. Thanks in advance.
UPDATED CODE v3: review comments for help
OPTION EXPLICIT
DIM strComputer, strProcess, strUserName, wshShell
Set wshShell = WScript.CreateObject( "WScript.Shell" )
strUserName = wshShell.ExpandEnvironmentStrings( "%USERNAME%" )
strComputer = "."
strProcess = "notepad.exe" 'change this to whatever you are trying to detect
IF isProcessRunning(strComputer, strProcess, strUserName) THEN
If MsgBox ("Notepad needs to be closed.", 1) = 1 then
wscript.Quit(1) 'you need to terminate the process if that's your intention before quitting
End If
Else
msgbox ("Process is not running") 'optional for debug, you can remove this
END IF
FUNCTION isProcessRunning(ByRef strComputer, ByRef strProcess, ByRef strUserName)
DIM objWMIService, strWMIQuery, objProcess, strOwner, Response
strWMIQuery = "SELECT * FROM Win32_Process WHERE NAME = '" & strProcess & "'"
SET objWMIService = GETOBJECT("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2").ExecQuery(strWMIQuery)
IF objWMIService.Count > 0 THEN
msgbox "We have at least ONE instance of Notepad"
For Each objProcess in objWMIService
Response = objProcess.GetOwner(strOwner)
If Response <> 0 Then
'we didn't get any owner information - maybe not permitted by current user to ask for it
Wscript.Echo "Could not get owner info for process [" & objProcess.Name & "]" & VBNewLine & "Error: " & Return
Else
Wscript.Echo "Process [" & objProcess.Name & "] is owned by [" & strOwner & "]" 'for debug you can remove it
if strUserName = strOwner Then
msgbox "we have the user who is running notepad"
isProcessRunning = TRUE
Else
'do nothing as you only want to detect the current user running it
isProcessRunning = FALSE
End If
End If
Next
ELSE
msgbox "We have NO instance of Notepad - Username is Irrelevant"
isProcessRunning = FALSE
END If
End Function
You can use the following function:
FUNCTION isProcessRunning(BYVAL strComputer,BYVAL strProcessName)
DIM objWMIService, strWMIQuery
strWMIQuery = "Select * from Win32_Process where name like '" & strProcessName & "'"
SET objWMIService = GETOBJECT("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" _
& strComputer & "\root\cimv2")
IF objWMIService.ExecQuery(strWMIQuery).Count > 0 THEN
isProcessRunning = TRUE
ELSE
isProcessRunning = FALSE
END IF
END FUNCTION
For local computer you would use "."
For the process name, you would use the executable "notepad.exe"
For the rest of the code, you could can use something simple:
OPTION EXPLICIT
DIM strComputer,strProcess
strComputer = "." ' local computer
strProcess = "notepad.exe" 'whatever is the executable
IF isProcessRunning(strComputer,strProcess) THEN
'do something
ELSE
'do something else or nothing
wscript.echo strProcess & " is NOT running on computer '" & strComputer & "'"
END IF
That should do it.
EXTRA
To show every process running, then just run:
Option Explicit
Dim objWMIService, objProcess, colProcess
Dim strComputer, strList
strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" _
& strComputer & "\root\cimv2")
Set colProcess = objWMIService.ExecQuery _
("Select * from Win32_Process")
For Each objProcess in colProcess
strList = strList & vbCr & _
objProcess.Name
Next
WSCript.Echo strList
WScript.Quit
in terminal server this function can be very slow, all the GetOwner calls are terrible in performance.
A very fast solution i created is to narrow the query using SessionID of the current user (assuming we want only current user's processes) So I added this code:
SessionID can be obtained this way:
Dim oExec, sOutput, iUserPos, iUserLen, iStatePos, SessionID
dim oShell, userName
Set oShell = CreateObject("Wscript.Shell")
userName = oShell.ExpandEnvironmentStrings("%USERNAME%")
Set oExec = oShell.Exec("query session %username%")
sOutput = LCase(oExec.StdOut.ReadAll)
iUserPos = InStr(sOutput, LCase(userName))
iStatePos = InStr(sOutput, "active")
iUserLen = Len(userName)
SessionID = CInt(Trim(Mid(sOutput, iUserPos+iUserLen, iStatePos-iUserPos-iUserLen)))
Changed the function from the previous post:
Function isProcessRunning(ByRef strComputer, ByRef strProcess, ByRef strUserName, byRef sessionID)
DIM objWMIService, strWMIQuery, objProcess, strOwner, Response
strWMIQuery = "SELECT * FROM Win32_Process WHERE SessionId = " & sessionID & " And NAME = '" & strProcess & "'"
SET objWMIService = GETOBJECT("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2").ExecQuery(strWMIQuery)
IF objWMIService.Count > 0 THEN
'msgbox "We have at least ONE instance of Notepad"
For Each objProcess in objWMIService
Response = objProcess.GetOwner(strOwner)
If Response = 0 Then
'Wscript.Echo "Process [" & objProcess.Name & "] is owned by [" & strOwner & "]" 'for debug you can remove it
if strUserName = strOwner Then
'msgbox "we have the user who is running notepad"
isProcessRunning = TRUE
Else
'do nothing as you only want to detect the current user running it
isProcessRunning = FALSE
End If
'else
'we didn't get any owner information - maybe not permitted by current user to ask for it
'Wscript.Echo "Could not get owner info for process [" & objProcess.Name & "]" & VBNewLine & "Error: " & Return
End If
Next
ELSE
'msgbox "We have NO instance of Notepad - Username is Irrelevant"
isProcessRunning = FALSE
END If
End Function
I have huge number of PDF documents, they are being manually checked for watermarks in all pages. Is it possible for this to be automated through scripts. Each page contains only one watermark. It will also be better to return the list of filenames or documents that are not having watermarks in all pages.
Watermarks in a pdf will be stored in the OCG object. So you have to ask acrobat if this object is in the pdf and whether it keeps watermarks.
Attach you will find VBS/VBA code which can do that. The Code you can copy over to Notepad and then save it as "FindWatermarks.vbs" on the desktop. Then drag&drop some pdfs on it and the script will tell you if the pdf include watermarks or not. Good luck, Reinhard
PS.: The script works only with Adobe Acrobat $$$ version, not with only Reader!
'// test dropped files for included watermarks
set WshShell = CreateObject ("Wscript.Shell")
set fs = CreateObject("Scripting.FileSystemObject")
Set objArgs = WScript.Arguments
'// check if files has been dropped on the script
if objArgs.Count < 1 then
msgbox("Please drag a file on the script")
WScript.quit
else
msgbox("Files Count: "& objArgs.Count &vblf &"Start with file: " & ObjArgs(0))
end if
'//contact Acrobat
Set App = CreateObject("AcroExch.App")
App.show 'comment or take out to work in hidden mode
Set AVDoc = CreateObject("AcroExch.AVDoc")
Set AForm = CreateObject("AFormAut.App") 'from AFormAPI
'// write needed js code into vbs variable
js = "var found "&vblf _
& "var ocgArray = this.getOCGs();" &vblf _
& "if (ocgArray == null) { " &vblf _
& " found = 0; " &vblf _
& " }else{ " &vblf _
& " for (var i=0; i < ocgArray.length; i++) { " &vblf _
& " if (ocgArray[i].name == 'Watermark') { " &vblf _
& " found= 1; " &vblf _
& " }else{ " &vblf _
& " found = 0; " &vblf _
& " } " &vblf _
& " } " &vblf _
& " }"
filesWithWm = ""
filesExWm =""
'//open files via Avdoc and check for watermarks
for i=0 to objArgs.Count - 1
FileIn = ObjArgs(i)
If AVDoc.Open(FileIn, "") Then
'msgbox(FileIn)
Set PDDoc = AVDoc.GetPDDoc()
Set jso = PDDoc.GetJSObject
AForm.Fields.ExecuteThisJavaScript js
if jso.found = 1 then
filesWithWm = filesWithWm &FileIn &vblf
else
filesExWm = filesExWm &FileIn &vblf
end if
end if
next
'// report found files
if InStr(filesWithWm,":\")>0 then msgbox("Watermarks found:" &vblf & filesWithWm)
if InStr(filesExWm,":\")>0 then msgbox("No Watermarks found:" &vblf & filesExWm)
'// exit application
App.CloseAllDocs
App.Exit
Set AForm = Nothing
Set JSO = Nothing
Set PDDoc = Nothing
Set AVDoc = Nothing
Set App = Nothing
If you need small code changes let me know.
I'm working on a ASP (Within the payment gateway). The options in the drop down at being pulling in from a database. I can't touch the database so have to attack the matter from the code.
Here is the value name that I need to exclude _01BM(Q)
Here is the code for the drop down.
<select name="programgroup" onchange="onProgramGroup()">
<% Call buildDropDownList(strProgramGroupCode, rsProgramGroup, "ProgramGroupCode", "ProgramGroupDescription", False)%>
</select>
I would really appreciate any help on this guys.
Here is the code for the method:
Sub buildDropDownList(strCurrentSelection, objListData, strCodeName, strDescriptionName, blnIncludeOther)
If Not objListData.BOF Then
objListData.MoveFirst
End If
While Not objListData.EOF
Response.Write "<option value='" & objListData(strCodeName) & "' "
If StrComp(strCurrentSelection, objListData(strCodeName),1) = 0 then
Response.Write "selected"
End If
Response.Write ">" & objListData(strDescriptionName) & "</option>" & VbCrLf
objListData.MoveNext
Wend
if blnIncludeOther then
Response.Write "<option value='<Other>' "
If strCurrentSelection <> "" and InStr(1, "<Other>", strCurrentSelection) = 1 then
Response.Write "selected"
End If
Response.Write ">Other</option>" & VbCrLf
end if
End Sub
You will have to change the method building the drop down. Since you did not provide us with the code for it, I'll give you a skeleton, and can use it to change your actual code.
To make it more generic and less ugly, better pass the value(s) to exclude to the method, as an array, instead of hard coding them in there.
So, the method should look like this:
Sub buildDropDownList(strProgramGroupCode, rsProgramGroup, someParamHere, anotherParam, boolParam, arrValuesToExclude)
Dim excludedValuesMapping, x
Set excludedValuesMapping = Server.CreateObject("Scripting.Dictionary")
For x=0 To UBound(arrValuesToExclude)
excludedValuesMapping.Add(LCase(arrValuesToExclude(x)), True)
Next
'...unknown code here...
Do Until rsProgramGroup.EOF
strCurrentValue = rsProgramGroup(valueFieldName)
If excludedValuesMapping.Exists(LCase(strCurrentValue)) Then
'value should be excluded, you can do something here, but not write it to browser
Else
strCurrentText = rsProgramGroup(textFieldName)
Response.Write("<option value=""" & Replace(strCurrentValue, """", """) & """>" & strCurrentText & "</option>")
End If
rsProgramGroup.MoveNext
Loop
End Sub
And to use it:
<% Call buildDropDownList(strProgramGroupCode, rsProgramGroup, "ProgramGroupCode", "ProgramGroupDescription", False, Array("_01BM(Q)"))%>
Now having your code, and if you don't want to make it generic, you can also ignore specific values by having such code in the buildDropDownList sub:
Dim currentCodeValue
While Not objListData.EOF
currentCodeValue = objListData(strCodeName)
If (UCase(currentCodeValue)<>"_04GIDBM") And _
(UCase(currentCodeValue)<>"_05GIDFM") And _
(UCase(currentCodeValue)<>"_08EXHRM") And _
(UCase(currentCodeValue)<>"_10EXMKT") And _
(UCase(currentCodeValue)<>"_12EXTTH") And _
(UCase(currentCodeValue)<>"_17EXHSC") Then
Response.Write "<option value='" & currentCodeValue & "' "
If StrComp(strCurrentSelection, currentCodeValue, 1) = 0 then
Response.Write "selected"
End If
Response.Write ">" & objListData(strDescriptionName) & "</option>" & VbCrLf
End If
objListData.MoveNext
Wend
This will just skip any records with such values, and will not output a drop down option for them.
I am trying to automate testing of an application. When opening the application it might open a pop-up window or security alert and I want to handle it. So is there a way to get handle or title of the most recently opened window in AutoIt?
Maybe you need to add some options. WinSearchChildren ...
include
Example()
Func Example()
; Retrieve the window title of the active window.
Local $sText = WinGetTitle("[ACTIVE]")
; Display the window title.
MsgBox($MB_SYSTEMMODAL, "", $sText)
EndFunc ;==>Example
I ran into this issue when needing to see a window "flash" every 60 seconds something was grabbing the focus, then changing back to the original window. I was able to write the following and capture the hi-jacker.
;what is the current active window
$Win1 = ""
$Win2 = ""
$Win3 = ""
$Win4 = ""
$Win5 = ""
$Win6 = ""
HotKeySet("{F1}","myExit")
while(1)
$blah = WinGetTitle("[ACTIVE]")
if $blah <> $Win1 Then
$Win6 = $Win5
$Win5 = $Win4
$Win4 = $Win3
$Win3 = $Win2
$Win2 = $Win1
$Win1 = $blah
EndIf
ToolTip("Last Active Windows: [press F1 to quit]" & #CRLF & "-" & $Win1 & #CRLF & "-" & $Win2 & #CRLF & "-" & $Win3 & #CRLF & "-" & $Win4 & #CRLF & "-" & $Win5 & #CRLF & "-" & $Win6)
sleep(100)
WEnd
Func myExit()
msgbox(0,"closing","closing program")
Exit
EndFunc
For a web application, I am creating a SMS module that can send an SMS from the application. My SMS provider has an API that I can call over HTTP.
The API is called via an XmlTextReader who just reads the XML response from the API.
Now my problem is: When I send the SMS from a web page (basically just doing an HTTP request) it takes more than a minute before I receive the SMS.
But when I run the exact same code from a Windows console application, my SMS arrives in less then 5 seconds.
I have done multiple tests with this, and it's not really my SMS provider who is slow.
Somehow, the HTTP request gets delayed from within the ASP.NET engine, and it does not delay directly from an console application. Is there a solution?
This is the way I'm calling the HTTP API:
Dim strPostString As String = Convert.ToString(muriPostUrl) & mstrPostPath
If mblnUseSecureConnection Then
strPostString = Convert.ToString(muriSecurePostUrl) & mstrPostPath
End If
Dim strDataString As String = "username=" & mstrUsername
strDataString += "&" & "password=" & mstrPassword
strDataString += "&" & "originator=" & mstrOriginator
strDataString += "&" & "recipients=" & mstrRecipients
strDataString += "&" & "gateway=" & mstrGateway
strDataString += "&" & "reference=" & mstrReference
strDataString += "&" & "message=" & mstrMessage
If mstrType <> String.Empty Then
strDataString += "&" & "type=" & mstrType
End If
If mstrUDH <> String.Empty Then
strDataString += "&" & "udh=" & mstrUDH
End If
If Not mdtDeliveryDate = Nothing Then
Dim objDeliveryDate As New StringBuilder()
objDeliveryDate.Append(mdtDeliveryDate.Year)
objDeliveryDate.Append(Prefix(mdtDeliveryDate.Month.ToString(), 2))
objDeliveryDate.Append(Prefix(mdtDeliveryDate.Day.ToString(), 2))
objDeliveryDate.Append(Prefix(mdtDeliveryDate.Hour.ToString(), 2))
objDeliveryDate.Append(Prefix(mdtDeliveryDate.Minute.ToString(), 2))
objDeliveryDate.Append(Prefix(mdtDeliveryDate.Second.ToString(), 2))
strDataString += "&" & "deliverydate=" & Convert.ToString(objDeliveryDate)
End If
Dim strReturnValue As String = ""
Dim xmlReader As New XmlTextReader(String.Format("{0}?{1}", strPostString, strDataString))
While xmlReader.Read()
If xmlReader.NodeType = XmlNodeType.Element Then
Select Case xmlReader.LocalName
Case "recipients"
If True Then
mintSuccessCount = Integer.Parse(xmlReader.ReadString())
strReturnValue += "recipients : " & mintSuccessCount.ToString() & vbCr & vbLf
Exit Select
End If
Case "success"
If True Then
mblnSuccess = Boolean.Parse(xmlReader.ReadString())
strReturnValue += "success : " & mblnSuccess.ToString() & vbCr & vbLf
Exit Select
End If
Case "resultcode"
If True Then
mintResultCode = Integer.Parse(xmlReader.ReadString())
strReturnValue += "resultcode : " & mintResultCode.ToString() & vbCr & vbLf
Exit Select
End If
Case "resultmessage"
If True Then
mstrResultMessage = xmlReader.ReadString()
strReturnValue += "resultmessage : " & mstrResultMessage & vbCr & vbLf
Exit Select
End If
End Select
End If
End While
Also, when performing an HTTP request from ASP.NET, it does not appear in Fiddler, while the actual HTTP request happens. How can I track the HTTP fastback from within the ASP.NET engine?
I still don't know what the problem is, but I worked around it by doing the postback via an HttpWebRequest directly. I think the problem was somewhere in the while loop.