-
Posts
28 -
Joined
-
Last visited
Everything posted by eimhym
-
Taming JScript9 aka 'Chakra' with AutoItObject
eimhym replied to eimhym's topic in AutoIt Example Scripts
That's why Chakra is by default inaccessible - it does have CLSID but no ProgID. The hack I mentioned in first post is about assigning ProgID manually, but that require editing the registry. ObjCreateInterface is cool, and if anyone prefer that, please uncomment the first method of obtaining dll path from registry and comment the later (specify it directly). E.g: ; ; Either get DLL path from registry $engine_path = RegRead("HKCR\CLSID\" & $sCLSID_ScriptEngine & "\InprocServer32", "") ; ObjCreateInterface like, autopath ; ; Or bring along the DLL in portable way! ; $engine_path = @ScriptDir & "\JScript9.DLL" ; comment this! ; $engine_path = @ScriptDir & "\JScript.DLL" ; Old JScript For anyone courious, thats what ObjCreateInterface would do anyway; find ProgID/CLSID entry in registry, look for dll path entry. After InprocServer path found, we instantiate class by invoking dll's exported DllGetClassObject and then CreateInstance from the class factory - and I think thats also what _AutoItObject_ObjCreateEx do. I haven't look at AutoItObject source though, trancexx you know better lol To note again, JScript9.dll can be used even without having IE browser installed. This would be extremely usefull in WinPE environment. A portable Windows Scripting Host if I may say. Again, if anyone not sure where the hell the dll is, please uncomment the first method like shown above Updated: now trying to find path in registry automatically when specified dll not found -
Taming JScript9 aka 'Chakra' with AutoItObject
eimhym replied to eimhym's topic in AutoIt Example Scripts
"0" would be an empty string, while the pointer to that string is still not NULL. If AutoIt does convert it to NULL pointer (psz) automatically that would be great (or disaster?) trancexx mentioned about keyword for NULL, IMHO that would be better. -
Taming JScript9 aka 'Chakra' with AutoItObject
eimhym replied to eimhym's topic in AutoIt Example Scripts
Fixed, thank you for the hint! After re-read the doc, EXCEPINFO is indeed not optional. Though it is scriptlet related, not the script parsing error. We still have to watch IActiveScriptSite.OnScriptError for that purpose. Yea, would be awesome if we can pass Null to wstr. I've added comment to ParseScriptText if someone ever need to pass string. If you mean by that is Delphi's like interface and inheritance, oh well you just hit me with an idea PS I have no access to Win x64, so I'd be grateful if someone can confirm that it works in x64 too. The script hasn't tested thoroughly so I believe theres something left here and there. Any feedback welcomed -
Chakra is now reachable, >check it out
-
Since IE9, Microsoft use new JScript engine which powering HTML5 content - JScript9 aka Chakra that is ECMA-262 5th edition compliant and also JIT-ed! Alas, they decide that the powerfull engine to be unreachable through ScriptControl. Though some hacks can re-enable this engine, there's more elegant way - The amazing AutoItObject to the rescue! #include "AutoItObject.au3" _AutoItObject_Startup() $sCLSID_ScriptEngine = "{16D51579-A30B-4C8B-A276-0FF4DC41E755}" ; JScript9 'Chakra' CLSID ; $sCLSID_ScriptEngine = "{F414C260-6AC0-11CF-B6D1-00AA00BBBB58}" ; Old JScript CLSID Global $engine_path ; ; You may specify the DLL path to make it run in portable way! $engine_path = @ScriptDir & "\JScript9.DLL" ; $engine_path = @ScriptDir & "\JScript.DLL" ; Old JScript ; Initialization Script, for other script engine like VBScript or LuaScript the init script would be different. $sInitScript = "AutoIt.SetRootObject(this);function Hello(){AutoIt.MsgBox(0, 'Script Says:', 'Hello World!'); return 'You are running ' + ScriptEngine() + ' ' + [ScriptEngineMajorVersion(), ScriptEngineMinorVersion(), ScriptEngineBuildVersion()].join('.')}" Func GoNuts ( ) ; Execute script's function and fetch return value MsgBox(0, "Script Return Value:", $_Script.Hello()) ; Add new function $_Script.eval("function add(x, y){return x+y}") MsgBox(0, "Script function call", "Awesome," & @CRLF & @CRLF & "1 + 2 = " & $_Script.add(1, 2) & " !") ; etc ... Have Fun! EndFunc #Region >>> ActiveScript Constants Global Const _ ; IActiveScript $sIID_IActiveScript = "{BB1A2AE1-A4F9-11CF-8F20-00805F2CD064}", _ $tagIActiveScript = "QueryInterface hresult(ptr;ptr*);" & _ "AddRef ulong();" & _ "Release ulong();" & _ "SetScriptSite hresult(ptr);" & _ "GetScriptSite hresult(ptr;ptr*);" & _ "SetScriptState hresult(dword);" & _ "GetScriptState hresult(dword*);" & _ "Close hresult();" & _ "AddNamedItem hresult(wstr;dword);" & _ "AddTypeLib hresult(ptr;dword;dword;dword);" & _ "GetScriptDispatch hresult(wstr;ptr);" & _ "GetCurrentScriptThreadID hresult(dword*);" & _ "GetScriptThreadID hresult(dword;dword*);" & _ "GetScriptThreadState hresult(dword;dword*);" & _ "InterruptScriptThread hresult(dword;ptr;dword);" & _ "Clone hresult(int);" ; Credits to trancexx If @AutoItX64 Then ; IActiveScriptParse Global Const $sIID_IActiveScriptParse = "{C7EF7658-E1EE-480E-97EA-D52CB4D76D17}" Else ; 32 bit Global Const $sIID_IActiveScriptParse = "{BB1A2AE2-A4F9-11CF-8F20-00805F2CD064}" EndIf Global Const _ $tIID_IActiveScriptParse = _AutoItObject_CLSIDFromString($sIID_IActiveScriptParse), _ $tagActiveScriptParse = "QueryInterface hresult(ptr;ptr*);" & _ "AddRef ulong();" & _ "Release ulong();" & _ "InitNew long();" & _ "AddScriptlet long(wstr;wstr;wstr;wstr;wstr;wstr;dword*;ulong;dword;ptr;ptr);" & _ "ParseScriptText long(wstr;ptr;ptr;ptr;dword*;ulong;dword;ptr;ptr);" ; NOTE: ; The ptr in ParseScriptText (pstrItemName, pstrDelimiter) is used ; instead of wstr because there's no other way to pass NULL parameter. ; Change it back to wstr if you ever need to pass string. Global Const _ ; IActiveScriptSite $sIID_IActiveScriptSite = "{DB01A1E3-A42B-11CF-8F20-00805F2CD064}", _ $tagActiveScriptSite = "QueryInterface hresult(ptr;ptr*);" & _ "AddRef ulong();" & _ "Release ulong();" & _ "GetLCID hresult(dword*);" & _ "GetItemInfo hresult(wstr;dword;ptr;ptr);" & _ "GetDocVersionString hresult(ptr);" & _ "OnScriptTerminate hresult(ptr;ptr);" & _ "OnStateChange hresult(uint);" & _ "OnScriptError hresult(ptr);" & _ "OnEnterScript hresult();" & _ "OnLeaveScript hresult();" Global Const _ ; IActiveScriptError $sIID_IActiveScriptError = "{EAE1BA61-A4ED-11CF-8F20-00805F2CD064}", _ $tagActiveScriptError = "QueryInterface hresult(ptr;ptr*);" & _ "AddRef ulong();" & _ "Release ulong();" & _ "GetExceptionInfo hresult(ptr);" & _ "GetSourcePosition hresult(ptr;ptr;ptr);" & _ "GetSourceLineText hresult(ptr);", _ $tagEXCEPINFO = "word wCode;" & _ "word wReserved;" & _ "ptr bstrSource;" & _ "ptr bstrDescription;" & _ "ptr bstrHelpFile;" & _ "dword dwHelpContext;" & _ "ptr pvReserved;" & _ "ptr pfnDeferredFillIn;" & _ "long scode;" Enum _ ; SCRIPTSTATE $SCRIPTSTATE_UNINITIALIZED, _ $SCRIPTSTATE_STARTED, _ $SCRIPTSTATE_CONNECTED, _ $SCRIPTSTATE_DISCONNECTED, _ $SCRIPTSTATE_CLOSED, _ $SCRIPTSTATE_INITIALIZED Global Const _ ; SCRIPTITEM $SCRIPTITEM_ISVISIBLE = 0x00000002, _ $SCRIPTITEM_ISSOURCE = 0x00000004, _ $SCRIPTITEM_GLOBALMEMBERS = 0x00000008, _ $SCRIPTITEM_ISPERSISTENT = 0x00000040, _ $SCRIPTITEM_CODEONLY = 0x00000200, _ $SCRIPTITEM_NOCODE = 0x00000400, _ $SCRIPTITEM_ALL = BitOR( $SCRIPTITEM_ISSOURCE, $SCRIPTITEM_ISVISIBLE, $SCRIPTITEM_ISPERSISTENT, $SCRIPTITEM_GLOBALMEMBERS, $SCRIPTITEM_NOCODE, $SCRIPTITEM_CODEONLY ) #EndRegion <<< ActiveScript Constants #Region >>> Scriptable Object Global $_AutoIt = _AutoItObject_Create() Global $pAutoIt = _AutoItObject_IDispatchToPtr($_AutoIt) ; see GetItemInfo handler Global $_Script ; will hold ScriptEngine's root object, where we can access script's global function _AutoItObject_AddMethod($_AutoIt, "SetRootObject", "_AutoIt_SetRootObject") _AutoItObject_AddMethod($_AutoIt, "MsgBox", "_AutoIt_MsgBox") Func _AutoIt_SetRootObject ( $_Self, $_Root ) Dim $_Script = $_Root ; the legit way is through IDispatchEx, but oh well EndFunc ;==> _AutoIt_SetRootObject Func _AutoIt_MsgBox ( $_Self, $iFlags, $sTitle, $sMessage ) Return MsgBox($iFlags, $sTitle, $sMessage) EndFunc ;==> _AutoIt_MsgBox #EndRegion <<< Scriptable Object ; Look in registry if file not found If NOT FileExists($engine_path) Then $engine_path = RegRead("HKCR\CLSID\" & $sCLSID_ScriptEngine & "\InprocServer32", "") If NOT FileExists($engine_path) Then Exit 1 ; Engine's DLL not found EndIf ; Boilerplate Global $_ActiveScript = _AutoItObject_ObjCreateEx($engine_path, $sCLSID_ScriptEngine, $sIID_IActiveScript, $tagIActiveScript, False) If NOT IsObj($_ActiveScript) Then Exit 2 ; Could not instantiate engine, wrong CLSID ? _AutoItObject_IUnknownAddRef($_ActiveScript) $aCall = $_ActiveScript.QueryInterface(DllStructGetPtr($tIID_IActiveScriptParse), 0) Global $_ActiveScriptParse = _AutoItObject_WrapperCreate($aCall[2], $tagActiveScriptParse) If NOT IsObj($_ActiveScriptParse) Then Exit 3 ; Could not acquire ActiveScriptParse, check for 32/64 IID Global $_ActiveScriptSite = _AutoItObject_ObjectFromDtag("_ASS_", $tagActiveScriptSite) If @error Then Exit 4 ; Failed implementing ActiveScriptSite $_ActiveScript.SetScriptSite(Number($_ActiveScriptSite.__ptr__)) $_ActiveScript.AddNamedItem("AutoIt", BitOR($SCRIPTITEM_ISVISIBLE, $SCRIPTITEM_NOCODE)) Global $fScriptInitialized = 0 $_ActiveScriptParse.InitNew() $tActiveScriptParseError = DllStructCreate ($tagEXCEPINFO) $_ActiveScriptParse.ParseScriptText($sInitScript, 0, 0, 0, 0, 0, 0, 0, DllStructGetPtr($tActiveScriptParseError)) $_ActiveScript.SetScriptState($SCRIPTSTATE_CONNECTED) OnAutoItExitRegister("Cleanup") If NOT IsObj($_Script) Then Exit 5 ; Initialization script error GoNuts() Func Cleanup ( ) $_Script = 0 $_ActiveScript.Close() _AutoItObject_IUnknownRelease($_ActiveScript) $_ActiveScriptParse = 0 $_ActiveScript = 0 $_ActiveScriptSite = 0 EndFunc ;==> Cleanup #Region >>> ActiveScriptSite Implementation Func _ASS_QueryInterface ( $_Self, $pRIID, $pObj ) #forceref $_Self, $pRIID, $pObj _Trace("_ASS_QueryInterface") Return 0x80004002 ; E_NOINTERFACE EndFunc ;==> _ASS_QueryInterface Func _ASS_AddRef ( $_Self ) #forceref $_Self Return 1 EndFunc ;==> _ASS_AddRef Func _ASS_Release ( $_Self ) #forceref $_Self Return 1 EndFunc ;==> _ASS_Release Func _ASS_GetLCID ( $_Self, $iLCID ) #forceref $_Self $iLCID = 0x0400 ; LOCALE_USER_DEFAULT _Trace(StringFormat( '_ASS_GetLCID: 0x%X', $iLCID )) Return 0 ; S_OK EndFunc ;==> _ASS_GetLCID Func _ASS_GetItemInfo ( $_Self, $sName, $iMask, $pObj, $pTypeInfo ) #forceref $_Self, $pObj, $pTypeInfo Static Local _ $SCRIPTINFO_IUNKNOWN = 1, _ $SCRIPTINFO_ITYPEINFO = 2 _Trace(StringFormat( '_ASS_GetItemInfo: %s', $sName )) If $sName = "AutoIt" AND BitAND($iMask, $SCRIPTINFO_IUNKNOWN) Then _AutoItObject_IUnknownAddRef($pAutoIt) DllStructSetData(DllStructCreate("ptr", $pObj), 1, $pAutoIt) Return 0 ; S_OK EndIf If BitAND($iMask, $SCRIPTINFO_IUNKNOWN) Then DllStructSetData(DllStructCreate("ptr", $pObj), 1, 0) If BitAND($iMask, $SCRIPTINFO_ITYPEINFO) Then DllStructSetData(DllStructCreate("ptr", $pTypeInfo), 1, 0) Return 0x80004005 ; E_FAIL EndFunc ;==> _ASS_GetItemInfo Func _ASS_GetDocVersionString ( $_Self, $pbstrVersionString ) #forceref $_Self, $pbstrVersionString DllStructSetData(DllStructCreate("byte", $pbstrVersionString), 1, 0) _Trace(StringFormat( '_ASS_GetDocVersionString: %s', "OK" )) Return 0 ; S_OK EndFunc ;==> _ASS_GetDocVersionString Func _ASS_OnScriptTerminate ( $_Self, $pResult, $pExceptionInfo ) #forceref $_Self, $pResult, $pExceptionInfo _Trace(StringFormat( '_ASS_OnScriptTerminate: %s', "OK" )) Return 0 ; S_OK EndFunc ;==> _ASS_OnScriptTerminate Func _ASS_OnStateChange ( $_Self, $iState ) #forceref $_Self _Trace(StringFormat( '_ASS_OnStateChange: State = %d', $iState )) Return 0 ; S_OK EndFunc ;==> _ASS_OnStateChange Func _ASS_OnScriptError ( $_Self, $pActiveScriptError ) #forceref $_Self, $pActiveScriptError Static Local _ $tEXCEPINFO = DllStructCreate ($tagEXCEPINFO), _ $pEXCEPINFO = DllStructGetPtr($tEXCEPINFO) Local $_Error = _AutoItObject_WrapperCreate($pActiveScriptError, $tagActiveScriptError) _AutoItObject_IUnknownAddRef($pActiveScriptError) $aCall = $_Error.GetExceptionInfo($pEXCEPINFO) If NOT $aCall[0] Then MsgBox(16, __Au3Obj_SysReadString(DllStructGetData($tEXCEPINFO, "bstrSource")), StringFormat ( _ "Error 0x%X\r\n\r\n%s", _ DllStructGetData($tEXCEPINFO, "scode"), _ __Au3Obj_SysReadString(DllStructGetData($tEXCEPINFO, "bstrDescription")) _ )) $_Error = 0 Return 0 ; S_OK EndFunc ;==> _ASS_OnScriptError Func _ASS_OnEnterScript ( $_Self ) #forceref $_Self _Trace(StringFormat( '_ASS_OnEnterScript: %s', "OK" )) Return 0 ; S_OK EndFunc ;==> _ASS_OnEnterScript Func _ASS_OnLeaveScript ( $_Self ) #forceref $_Self _Trace(StringFormat( '_ASS_OnLeaveScript: %s', "OK" )) Return 0 ; S_OK EndFunc ;==> _ASS_OnLeaveScript #EndRegion <<< ActiveScriptSite Implementation Func _Trace ( $msg, $ln = @ScriptLineNumber ) ConsoleWrite( @ScriptName & "(" & $ln & "): " & $msg & @CRLF) EndFunc ;==> _Trace Minimum Requirements (JScript9): IE9 (for the JScript9.dll only, can be portable) Win7 (works in WinPE too), x64 still untested NOTE: Through IActiveScriptSite we can host not only JScript engine, but any other ActiveScripting engine like VBScript, LuaScript(JIT), ActivePerl etc. NOTE: If you don't know the DLL path ( Specifiying dll path is now optional ) Please uncomment the first method of specifiying the dll path, ; ; Either get DLL path from registry $engine_path = RegRead("HKCR\CLSID\" & $sCLSID_ScriptEngine & "\InprocServer32", "") ; ObjCreateInterface like ; ; Or bring along the DLL in portable way! ; $engine_path = @ScriptDir & "\JScript9.DLL" ; $engine_path = @ScriptDir & "\JScript.DLL" ; Old JScript Thanks to trancexx for mentioning this Update 23/09/13 Fixed ParseScriptText parameter, credits to trancexx Added x64 support, untested
-
If you refer Mozilla Firefox then we can't use AIO with javascript other than IE. Chakra (used since IE9) is the core JS engine, M$ Active Scripting version of V8. ScriptControl and IE are Active Scripting Hosts, where you can select the engine you like (JS, VB, Python, etc). But Chakra by default is not visible to ScriptControl, only for IE. By implementing IActiveScriptSite you can instantiate it. You can make script host wrapper dll for AutoIt, or implement it directly (yes AutoIt CAN implement Interface ) I'm onto the later but my responsibilities lately hold me from messing with the idea. Try google for 'javascript stacktrace', to get detailed info about exception/error thrown. As for syntax checking you can first pass the code into JSLint or similar. Good luck digging
-
This >old project use ScriptControl, but already has wrapper for AutoIt and JScript to communicate with ease (calling methods, passing variables, arrays etc). The bridge is closure compiled but the unpacked version is included, hopefully readable And FYI Chakra JScript Engine can be used directly without ScriptControl nor IE, see here for hint, use Chakra's GUID instead.
-
Whoa, silly me totally miss that spot! Thank you trancexx! Btw, is there any way to get the object outside autoit? cuz cbi: header is not known and guid not found using the regular GetActiveObject. Edit: OK, found nice example here and in Geez, only a handfull of them in google, these RegisterObject series should get more spotlight, cuz they are the star!
-
Hi, I've made a little test if we can register AutoItObject into ROT. For in-process server it works fine, the AutoItObject returned by _GetActiveObject is the one registered via _RegisterActiveObject. But, invoked via out-of-process, it crash! If you compare the output of inProc vs outProc - with IUnknown debugger turned on - you can see the problem start when external process invoking QueryInterface for IDispatch. A pointer returned, but then it seems OLE stop working, cuz Release never arrived (though successfully invoked). Ain't the default marshaler should handle IDispatch automatically? I hope we can do it proxy-stub-less, if the problem is TypeLib, well I can't find any TLB in AutoItObject.dll Here's the test code, set $OutOfProcessTest and $IUnknownDebugger to alter the test. They are initially set for debugged in-process test: Global Const $OutOfProcessTest = False ; TRUE = out-of-process, FALSE = in-process Global Const $IUnknownDebugger = True ; TRUE = use IUnknown stub, FALSE = pass AutoItObject directly #include "WinAPI.au3" #include "AutoItObject.au3" _AutoItObject_Startup() Global $_ActiveObject, $_pActiveObject, _ $_tActiveObject_Factory = DllStructCreate("ptr;" & _ "ptr QueryInterface;" & _ "ptr AddRef;" & _ "ptr Release" ), _ $_ActiveObject_Factory = DllStructGetPtr($_tActiveObject_Factory), _ $_ActiveObject_QueryInterface = DllCallbackRegister("_ActiveObject_QueryInterface", "INT", "ptr;ptr;ptr"), _ $_ActiveObject_AddRef = DllCallbackRegister("_ActiveObject_AddRef", "ULONG", "ptr"), _ $_ActiveObject_Release = DllCallbackRegister("_ActiveObject_Release", "ULONG", "ptr"), _ $_SizeOfPtr = DllStructGetSize(DllStructCreate('ptr')) DllStructSetData($_tActiveObject_Factory, 1, $_ActiveObject_Factory + $_SizeOfPtr) DllStructSetData($_tActiveObject_Factory, 'QueryInterface', DllCallbackGetPtr($_ActiveObject_QueryInterface)) DllStructSetData($_tActiveObject_Factory, 'AddRef', DllCallbackGetPtr($_ActiveObject_AddRef)) DllStructSetData($_tActiveObject_Factory, 'Release', DllCallbackGetPtr($_ActiveObject_Release)) #Region >>> Win32 ActiveObject API #cs HRESULT CoLockObjectExternal( _In_ LPUNKNOWN pUnk, _In_ BOOL fLock, _In_ BOOL fLastUnlockReleases ); Ole32.dll #ce Func _CoLockObjectExternal ( $pIUnknown, $fLock, $fLastUnlockReleases ) $aCall = DllCall('Ole32.DLL', 'INT', 'CoLockObjectExternal', _ 'ptr', $pIUnknown, _ 'bool', $fLock, _ 'bool', $fLastUnlockReleases ) If @error OR $aCall[0] Then Return SetError(1, $aCall[0], 0) EndFunc #cs HRESULT RegisterActiveObject( IUnknown *punk, REFCLSID rclsid, DWORD dwFlags, // ACTIVEOBJECT_STRONG 0 // ACTIVEOBJECT_WEAK 1 DWORD *pdwRegister ); OleAut32.dll #ce Func _RegisterActiveObject ( ByRef $_IDispatch, $sGUID ) $tGUID = _GuidFromString($sGUID) $tHandle = DllStructCreate('dword') If $IUnknownDebugger Then $pIUnknown = $_ActiveObject_Factory Else $pIUnknown = _AutoItObject_IDispatchToPtr($_IDispatch) EndIf $aCall = DllCall('OleAut32.DLL', 'INT', 'RegisterActiveObject', _ 'ptr', $pIUnknown, _ 'ptr', DllStructGetPtr($tGUID), _ 'dword', 0x0, _ 'ptr', DllStructGetPtr($tHandle) ) If @error OR $aCall[0] Then Return SetError(1, $aCall[0], 0) If NOT $IUnknownDebugger Then _CoLockObjectExternal($pIUnknown, True, True) If @error Then Return SetError(2, @extended, 0) EndIf _Log( "_RegisterActiveObject: " & $pIUnknown & " " & $sGUID ) Return DllStructGetData($tHandle, 1) EndFunc #cs HRESULT GetActiveObject( _In_ REFCLSID rclsid, _Reserved_ void *pvReserved, _Out_ IUnknown **ppunk ); OleAut32.dll #ce Func _GetActiveObject ( $sGUID ) Static Local _ $tagIUnknown = "ptr QueryInterface;" & _ "ptr AddRef;" & _ "ptr Release", _ $IID_IDispatch = _GuidFromString("{00020400-0000-0000-C000-000000000046}"), _ $pIID_IDispatch = DllStructGetPtr($IID_IDispatch), _ $E_NOINTERFACE = 0x80004002, _ $E_POINTER = 0x80004003 $tGUID = _GuidFromString($sGUID) $tIUnknown = DllStructCreate('ptr') $aCall = DllCall('OleAut32.DLL', 'INT', 'GetActiveObject', _ 'ptr', DllStructGetPtr($tGUID), _ 'ptr', 0, _ 'ptr', DllStructGetPtr($tIUnknown) ) If @error OR $aCall[0] Then Return SetError(1, $aCall[0], 0) $pIUnknown = DllStructGetData($tIUnknown, 1) If $IUnknownDebugger Then ; Retreive IUnknown's VTable $tIUnknown = DllStructCreate('ptr', $pIUnknown) $vtIUnknown = DllStructCreate($tagIUnknown, DllStructGetData($tIUnknown, 1)) ; Does MSDN mean the returned IUnknown is not our object because we need ; to QueryInterface for IDispatch? ; How To Attach to a Running Instance of an Office Application ; [http://support.microsoft.com/kb/238975/en-us] ; How to get IDispatch of an Excel or Word document from an OCX ; [http://support.microsoft.com/kb/190985] $aCall = DllCallAddress("INT", DllStructGetData($vtIUnknown, 'QueryInterface'), _ "ptr", $pIUnknown, _ "ptr", $pIID_IDispatch, _ "ptr", DllStructGetPtr($tIUnknown) ) If @error OR $aCall[0] Then If @error Then Return SetError(2, @error, 0) If $aCall[0] = $E_POINTER Then Return SetError(2, 0, 0) ; Invalid IUnknown If $aCall[0] = $E_NOINTERFACE Then Return SetError(3, 0, 0) ; IID not recognized Return SetError(4, $aCall[0], 0) EndIf DllCallAddress("INT", DllStructGetData($vtIUnknown, 'Release'), "ptr", $pIUnknown) ; This call never arrived in out-of-process case (watch the log) ; which is weird because previous AddRef and QueryInterface call ; are arrived safely. (Marshalling failure crash Ole handler?) ; Now we should have the IDispatch right? $pIUnknown = DllStructGetData($tIUnknown, 1) ; Below is required if registered with ACTIVEOBJECT_WEAK flag: ; _AutoItObject_IUnknownAddRef($pIUnknown) EndIf _Log("_GetActiveObject IDispatch acquired " & $pIUnknown & " " & $sGUID) Return _AutoItObject_PtrToIDispatch($pIUnknown) ; Nah, this will crash in out-of-process case EndFunc Func _PtrToIDispatch($pIDispatch) Static Local $PTR_SIZE = DllStructGetSize(DllStructCreate('ptr')) Local $aCall = DllCall('Kernel32.DLL', "none", "RtlMoveMemory", "idispatch*", 0, "ptr*", $pIDispatch, "dword", $PTR_SIZE) If @error Then Return SetError(1, 0, 0) Return $aCall[1] EndFunc #cs HRESULT RevokeActiveObject( _In_ DWORD dwRegister, _Reserved_ void *pvReserved ); OleAut32.dll #ce Func _RevokeActiveObject ( ByRef $_IDispatch, $iHandle ) If NOT $IUnknownDebugger Then $pIDispatch = _AutoItObject_IDispatchToPtr($_IDispatch) _CoLockObjectExternal($pIDispatch, False, True) If @error Then Return SetError(2, @extended, 0) EndIf $aCall = DllCall('OleAut32.DLL', 'INT', 'RevokeActiveObject', _ 'dword', $iHandle, _ 'ptr', 0 ) If @error OR $aCall[0] Then Return SetError(1, $aCall[0], 0) Return 1 EndFunc #EndRegion <<< Win32 ActiveObject API #Region >>> Win32 GUID API (CLSIDFromString may return E_CLASSNOTREG for unregistered ClsId) Func _GuidFromString ( $sUUID, $ptGUID=0 ) Static Local $RPC_S_INVALID_STRING_UUID = 0x6A9 ; Use passed GUID struct by pointer or create new Local $tGUID If $ptGUID = 0 Then $tGUID = DllStructCreate($tagGUID) Else $tGUID = DllStructCreate($tagGUID, $ptGUID) EndIf ; Strip '{}' If StringLeft($sUUID, 1) = '{' Then $sUUID = StringMid($sUUID, 2, StringLen($sUUID) - 2) Local $aCall = DllCall("Rpcrt4.DLL", 'INT', 'UuidFromStringW', 'wstr', $sUUID, 'ptr', DllStructGetPtr($tGUID)) If @error OR $aCall[0] Then If $aCall[0] = $RPC_S_INVALID_STRING_UUID Then Return SetError(2, 0, 0) ; Invalid Uuid String Return SetError(3, @error, 0) ; UuidFromString call failed EndIf Return $tGUID EndFunc ;==> _DllCOM_GuidFromString Func _StringFromGuid ( $tGUID, $fCompat=1 ) If IsPtr($tGUID) Then $tGUID = DllStructCreate($tagGUID, $tGUID) Local $aCall = DllCall("Rpcrt4.DLL", 'INT', 'UuidToStringW', 'ptr', DllStructGetPtr($tGUID), 'wstr*', 0) If @error OR $aCall[0] Then Return SetError(2, $aCall[0], 0) ; UuidToString call failed If $fCompat Then Return "{" & StringUpper($aCall[2]) & "}" Return $aCall[2] EndFunc ;==> _DllCOM_StringFromGuid #EndRegion <<< Win32 GUID API ; AutoItObject test method Func _ActiveObject_Hello ( $_Self, $msg ) MsgBox(0, @AutoItPID, "After all that had happened: " & $msg) EndFunc ; Server & Client Main If $CmdLine[0] Then Opt('TrayIconHide', 1) $sGUID = $CmdLine[1] If $sGUID = EnvGet("ActiveObjectGUID") AND $sGUID = ConsoleRead() Then ; verify GUID _Log("Out-of-process fetching ActiveObject: " & $sGUID) MsgBox(0, @AutoItPID, "Fasten your seatbelt," & @CRLF & "we are going to CRASH!") $_out_proc_object = _Critical( _GetActiveObject($sGUID) ) _Log("Out-of-process object test: " & $_out_proc_object.Data) Else _Log("ActiveObject GUID missmatch!") EndIf ; make sure stdout flushed Sleep(500) Else $_ActiveObject = _AutoItObject_Create() _AutoItObject_AddProperty($_ActiveObject, "Data", $ELSCOPE_PUBLIC, "I'm alive!") _AutoItObject_AddMethod($_ActiveObject, "Hello", "_ActiveObject_Hello") If $IUnknownDebugger Then $_pActiveObject = _AutoItObject_IDispatchToPtr($_ActiveObject) $sGUID = ObjCreate("Scriptlet.TypeLib") $sGUID = $sGUID.GUID $hActiveObject = _Critical( _RegisterActiveObject($_ActiveObject, $sGUID) ) If $OutOfProcessTest Then EnvSet("ActiveObjectGUID", $sGUID) $pid = Run('"' & @AutoItExe & '" "' & @ScriptFullPath & '" ' & $sGUID, @ScriptDir, @SW_HIDE, 0x3) StdInWrite($pid, $sGUID) While ProcessExists($pid) $log = StdoutRead($pid) If @extended Then ConsoleWrite($log) Else Sleep(100) EndIf WEnd Else _Log("In-process fetching ActiveObject: " & $sGUID) $_in_proc_object = _Critical( _GetActiveObject($sGUID) ) _Log("In-process object test: " & $_in_proc_object.Data) EndIf ; Prove that object still valid $_ActiveObject.Hello($_ActiveObject.Data) _Critical( _RevokeActiveObject($_ActiveObject, $hActiveObject) ) EndIf #Region >>> IUnknown Stub Func _ActiveObject_AddRef ( $_Self ) _Log("_ActiveObject_AddRef") Return 0; EndFunc Func _ActiveObject_Release ( $_Self ) _Log("_ActiveObject_Release") Return 0; EndFunc ; IID_IUnknown {00000000-0000-0000-C000-000000000046} ; IID_IMarshal {00000003-0000-0000-C000-000000000046} ; IID_IProxyManager {00000008-0000-0000-C000-000000000046} ; IID_IStdMarshalInfo {00000018-0000-0000-C000-000000000046} ; IID_IExternalConnection {00000019-0000-0000-C000-000000000046} ; ? {0000001B-0000-0000-C000-000000000046} <-- IdentityUnmarshal's GUID ; {4C1E39E1-E3E3-4296-AA86-EC938D896E92} <-- proxy-stub request, handled by default? Func _ActiveObject_QueryInterface ( $_Self, $pIID, $ppObject ) Static Local $E_NOTIMPL = 0x80004001 $sIID = _StringFromGuid($pIID) If $sIID = "{00000000-0000-0000-C000-000000000046}" Then $tOut = DllStructCreate('ptr', $ppObject) DllStructSetData($tOut, 1, $_ActiveObject_Factory) _Log("_ActiveObject_QueryInterface IUnknown Requested") Return 0; ElseIf $sIID = "{00020400-0000-0000-C000-000000000046}" Then $tOut = DllStructCreate('ptr', $ppObject) DllStructSetData($tOut, 1, $_pActiveObject) _Log("_ActiveObject_QueryInterface IDispatch Requested") Return 0; Else _Log("_ActiveObject_QueryInterface Unhandled: " & _StringFromGuid($pIID)) Return $E_NOTIMPL EndIf EndFunc #EndRegion <<< IUnknown Stub #Region >>> Debugging Func _Log ( $msg ) ConsoleWrite($msg & @CRLF) EndFunc Func _Error ( $msg ) ConsoleWriteError($msg & @CRLF) EndFunc Func _Critical ($ret, $rel=0, $msg="Fatal Error", $err=@error, $ext=@extended, $ln = @ScriptLineNumber) If $err Then $ln += $rel Local $LastError = _WinAPI_GetLastError(), _ $LastErrorMsg = _WinAPI_GetLastErrorMessage(), _ $LastErrorHex = Hex($LastError) $LastErrorHex = "0x" & StringMid($LastErrorHex, StringInStr($LastErrorHex, "0", 1, -1)+1) $msg &= @CRLF & "at line " & $ln & @CRLF & @CRLF & "AutoIt Error: " & $err & " (0x" & Hex($err, 8) & ") Extended: " & $ext & " (0x" & Hex($ext, 8) & ")" If $LastError Then $msg &= @CRLF & "WinAPI Error: " & $LastError & " (" & $LastErrorHex & ")" & @CRLF & $LastErrorMsg _Error($msg) ClipPut($msg) MsgBox(270352, "Fatal Error - " & @ScriptName, $msg) Exit EndIf Return $ret EndFunc #EndRegion <<< Debugging Please help to make it work, it would be cool if we can use AutoItObject for IPC!
-
First you need $DEF_BOXEDAPPSDK_OPTION__EMBED_BOXEDAPP_IN_CHILD_PROCESSES option, please refer to my example above. Then call VirtualFLEX_EnableOption: ... MemoryDllCall($VirtualFLEX, "none", "VirtualFLEX_EnableOption", 'dword', $DEF_BOXEDAPPSDK_OPTION__EMBED_BOXEDAPP_IN_CHILD_PROCESSES, 'bool', True) Virtual_DirCreateA(@ScriptDir & '\v') ... Second, try to change l.cmd to @dir c:\windows /s > "%~dp0list.txt" and call it with Run(@ComSpec & ' /c CALL "' & @ScriptDir & '\v\Vl.cmd"', "") The list.txt should be in the same folder as Vl.cmd (in virtual directory) Lets hope prazetto can update the UDF soon.
- 39 replies
-
- Virtual File
- Virtual Registry
-
(and 1 more)
Tagged with:
-
Thank you I think you should add EnableOption too, there are some important options required for attaching sub-process. For example I want to run IE instance that use proxy, but I don't want that proxy settings become permanent (IE re-write options in registry so our virtual registry keys may become permanent). This scenario enable us to launch many IE instances with their own proxy settings. #include <VirtualFlex.Memory.au3> Global Const $DEF_BOXEDAPPSDK_OPTION__ALL_CHANGES_ARE_VIRTUAL = 1 ; default: false Global Const $DEF_BOXEDAPPSDK_OPTION__EMBED_BOXEDAPP_IN_CHILD_PROCESSES = 2 ; default: false Global Const $DEF_BOXEDAPPSDK_OPTION__ENABLE_VIRTUAL_FILE_SYSTEM = 3 ; default: true Global Const $DEF_BOXEDAPPSDK_OPTION__RECREATE_VIRTUAL_FILE_AS_VIRTUAL = 4 ; default: 1 (TRUE) Global Const $DEF_BOXEDAPPSDK_OPTION__ENABLE_VIRTUAL_REGISTRY = 5 ; default: 1 (TRUE) Global Const $DEF_BOXEDAPPSDK_OPTION__HIDE_VIRTUAL_FILES_FROM_FILE_DIALOG = 6 ; default: 0 (FALSE) Global Const $DEF_BOXEDAPPSDK_OPTION__EMULATE_OUT_OF_PROC_COM_SERVERS = 7 ; default: 0 (FALSE) Global Const $DEF_BOXEDAPPSDK_OPTION__INHERIT_OPTIONS = 8 ; default: 0 (FALSE) Local $proxyAddress = InputBox ("IE Launcher", "Enter Proxy Address <address:port>", "177.69.195.4:3128") If @error Then Exit ; To enable IE proxy for Dial-up and VPN see here: ; http://social.technet.microsoft.com/Forums/en-US/winserverGP/thread/d1917135-4655-4e42-8404-33b179136b42/ Virtual_RegWrite("HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings", "MigrateProxy", "REG_DWORD", 1) Virtual_RegWrite("HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings", "ProxyEnable", "REG_DWORD", 1) Virtual_RegWrite("HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings", "ProxyHttp1.1", "REG_DWORD", 1) Virtual_RegWrite("HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings", "ProxyServer", "REG_SZ", $proxyAddress) ; Virtual_RegWrite("HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings", "ProxyOverride", "REG_SZ", "<local>") RunAttached(@ProgramFilesDir & '\Internet Explorer\IEXPLORE.EXE', 'http://www.infobyip.com/detectproxy.php') #include <WinAPI.au3> Func RunAttached ( $sFilename, $sParams=0 ) If $sParams Then $sParams = '"' & $sFilename & '" ' & $sParams Else $sParams = '"' & $sFilename & '"' EndIf Local $hKernel32 = DllOpen("Kernel32.DLL") ; STARTUPINFO Structure Local $tSTARTUPINFO = DllStructCreate("int Size;" & _ "ptr Reserved1;" & _ "ptr Desktop;" & _ "ptr Title;" & _ "int X;" & _ "int Y;" & _ "int XSize;" & _ "int YSize;" & _ "int XCountChars;" & _ "int YCountChars;" & _ "int FillAttribute;" & _ "int Flags;" & _ "short ShowWindow;" & _ "short Reserved2;" & _ "ptr Reserved3;" & _ "int StdInput;" & _ "int StdOutput;" & _ "int StdError") DllStructSetData($tSTARTUPINFO, "Size", DllStructGetSize($tSTARTUPINFO)) ; PROCESS_INFORMATION Structure Local $tPROCESS_INFORMATION = DllStructCreate("ptr Process;" & _ "ptr Thread;" & _ "dword ProcessId;" & _ "dword ThreadId") Local $aCall = DllCall($hKernel32, "INT", "CreateProcess", _ "str", $sFilename, _ "str", $sParams, _ "ptr", 0, _ "ptr", 0, _ "int", 0, _ "dword", 0x4, _ ; CREATE_SUSPENDED "ptr", 0, _ "ptr", 0, _ "ptr", DllStructGetPtr($tSTARTUPINFO), _ "ptr", DllStructGetPtr($tPROCESS_INFORMATION) ) If @error OR NOT $aCall[0] Then Return SetError(1, @error, 0) Local $hProcess = DllStructGetData($tPROCESS_INFORMATION, "Process"), _ $hThread = DllStructGetData($tPROCESS_INFORMATION, "Thread"), _ $PID = DllStructGetData($tPROCESS_INFORMATION, "ProcessId"), _ $TID = DllStructGetData($tPROCESS_INFORMATION, "ThreadId") ; Attach child process MemoryDllCall($VirtualFLEX, "none", "VirtualFLEX_EnableOption", 'dword', $DEF_BOXEDAPPSDK_OPTION__ALL_CHANGES_ARE_VIRTUAL, 'bool', True) MemoryDllCall($VirtualFLEX, "none", "VirtualFLEX_EnableOption", 'dword', $DEF_BOXEDAPPSDK_OPTION__INHERIT_OPTIONS, 'bool', True) Virtual_AttachToProcess($PID) Local $aCall = DllCall($hKernel32, "INT", "ResumeThread", _ "handle", $hThread) If @error OR NOT $aCall[0] Then Return SetError(2, @error, 0) DllCall($hKernel32, 'BOOL', 'CloseHandle', _ 'handle', $hThread) DllCall($hKernel32, 'BOOL', 'CloseHandle', _ 'handle', $hProcess) EndFunc Within RunAttached function, before calling Virtual_AttachToProcess, we need to set Option to keep the virtual registry keys virtual. Running from AutoIt: Running normally:
- 39 replies
-
- Virtual File
- Virtual Registry
-
(and 1 more)
Tagged with:
-
The list doesn't scroll, only display 31 items, and you can't select the file to extract. And the zip component not checked but just get registered everytime script run, and ActiveX for zip? C'mon Search the forum more, there's lots of samples to do it better.
-
Cool Another request please , with BoxedApp you can assign virtual file from protected archive or physical file via BoxedAppSDK_CreateVirtualFileBasedOnIStream. Would you please wrap the IStream handler from inside the DLL, as implementing it via script would be cumbersome. And uh, VirtualDirectory and VirtualRegKey API are nice to have too from within VirtualFlex.Memory.au3
- 39 replies
-
- Virtual File
- Virtual Registry
-
(and 1 more)
Tagged with:
-
Would be nice if other process can see the virtual file too. #Include <Memory.au3> #include <VirtualFlex.Memory.au3> #include <Constants.au3> VirtualFile(@ScriptDir & '\text.txt', 'This file virtually exist!') ConsoleWrite(FileRead(@ScriptDir & '\text.txt') & @LF) ; other process can't find it $pid = Run(@ComSpec & ' /c type ' & @ScriptDir & '\text.txt', @SystemDir, @SW_HIDE, $STDERR_MERGED) $lines = "" While 1 $lines &= StdoutRead($pid) If @error Then ExitLoop WEnd ConsoleWrite($lines) ; The system cannot find the path specified. Terminate() Func Terminate() If Not Opt('TrayIconHide') Then Opt("TrayIconHide", 1) ProcessClose(@AutoItPID) EndFunc
- 39 replies
-
- Virtual File
- Virtual Registry
-
(and 1 more)
Tagged with:
-
Heres another, IE-less, example. Needs libtidy (attached) to clean pages and pass the well-formed html into MSXML ActiveX control (see MSDN documentation here). pros: 1) lightweight, lighting fast. 2) XPath available by default. 3) Script tags won't executed, css or images won't loaded. 4) No problem in deleting SCRIPT tag. cons: 1) does fail with some pages, always check @error after calling _HXmlParser_LoadUrl or _HXmlParser_LoadHtml. 2) libtidy crash on HTML5 pages, you have to reload the dll. 3) Doesn't handle html tags within textarea correctly, suggestion for workaround expected. 4) Can't use JS framework. The sample code do the same as HtmlParser, for comparison. #include-once #include "libtidy.au3" ; Opt("MustDeclareVars", 1) Global Const $_HXmlParser_ScriptName = "HXmlParser.au3" Global $_HXmlParser_DOM = 0 Func _HXmlParser_Startup ( $sConfFilename="tidy-xml-settings.cfg" ) _LibTidy_Startup() If @error Then Return SetError(@error, @extended, 0) _LibTidy_LoadConfig($sConfFilename) If @error Then _LibTidy_Shutdown() Return SetError(@error, @extended, 0) EndIf $_HXmlParser_DOM = ObjCreate("MSXML2.DOMDocument") OnAutoItExitRegister("__HXmlParser_Shutdown") $_HXmlParser_DOM.validateOnParse = False; $_HXmlParser_DOM.resolveExternals = False; Return 1 EndFunc Func __HXmlParser_Shutdown () $_HXmlParser_DOM = 0 OnAutoItExitUnRegister("__HXmlParser_Shutdown") EndFunc Func _HXmlParser_GetErrorString () If IsObj($_HXmlParser_DOM.parseError) AND $_HXmlParser_DOM.parseError.errorCode Then Return "Error loading page " & _ " (" & Hex($_HXmlParser_DOM.parseError.errorCode) & _ ") at line: " & $_HXmlParser_DOM.parseError.line & _ ", position: " & $_HXmlParser_DOM.parseError.linepos & _ ", reason: " & $_HXmlParser_DOM.parseError.reason EndIf Return 0 EndFunc Func _HXmlParser_LoadHtml ( $sHtml ) If NOT $sHtml Then Return SetError(4, 0, 0) _LibTidy_LoadString( $sHtml ) If @error Then Return SetError(@error, @extended, 0) $sHtml = _LibTidy_CleanAndRepair() If @error OR NOT $sHtml Then Return SetError(5, @error, 0) $sHtml = StringRegExp(StringMid($sHtml, StringInStr($sHtml, "<html")), "(?s)^<html[^>]*>[^<]*(<.*)", 1) If @error Then Return SetError(6, @error, 0) $sHtml = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd" [' _ & '<!ENTITY nbsp " "><!ENTITY iexcl "¡"><!ENTITY cent "¢"><!ENTITY pound "£"><!ENTITY curren "¤"><!ENTITY yen "¥"><!ENTITY brvbar "¦"><!ENTITY sect "§"><!ENTITY uml "¨"><!ENTITY copy "©"><!ENTITY ordf "ª"><!ENTITY laquo "«"><!ENTITY not "¬"><!ENTITY shy ""><!ENTITY reg "®"><!ENTITY macr "¯"><!ENTITY deg "°"><!ENTITY plusmn "±"><!ENTITY sup2 "²"><!ENTITY sup3 "³"><!ENTITY acute "´"><!ENTITY micro "µ"><!ENTITY para "¶"><!ENTITY middot "·"><!ENTITY cedil "¸"><!ENTITY sup1 "¹"><!ENTITY ordm "º"><!ENTITY raquo "»"><!ENTITY frac14 "¼"><!ENTITY frac12 "½"><!ENTITY frac34 "¾"><!ENTITY iquest "¿"><!ENTITY times "×"><!ENTITY divide "÷">' _ & '<!ENTITY Agrave "À"><!ENTITY Aacute "Á"><!ENTITY Acirc "Â"><!ENTITY Atilde "Ã"><!ENTITY Auml "Ä"><!ENTITY Aring "Å"><!ENTITY AElig "Æ"><!ENTITY Ccedil "Ç"><!ENTITY Egrave "È"><!ENTITY Eacute "É"><!ENTITY Ecirc "Ê"><!ENTITY Euml "Ë"><!ENTITY Igrave "Ì"><!ENTITY Iacute "Í"><!ENTITY Icirc "Î"><!ENTITY Iuml "Ï"><!ENTITY ETH "Ð"><!ENTITY Ntilde "Ñ"><!ENTITY Ograve "Ò"><!ENTITY Oacute "Ó"><!ENTITY Ocirc "Ô"><!ENTITY Otilde "Õ"><!ENTITY Ouml "Ö"><!ENTITY Oslash "Ø"><!ENTITY Ugrave "Ù"><!ENTITY Uacute "Ú"><!ENTITY Ucirc "Û"><!ENTITY Uuml "Ü"><!ENTITY Yacute "Ý"><!ENTITY THORN "Þ"><!ENTITY szlig "ß"><!ENTITY agrave "à"><!ENTITY aacute "á"><!ENTITY acirc "â"><!ENTITY atilde "ã"><!ENTITY auml "ä"><!ENTITY aring "å"><!ENTITY aelig "æ"><!ENTITY ccedil "ç"><!ENTITY egrave "è"><!ENTITY eacute "é"><!ENTITY ecirc "ê"><!ENTITY euml "ë"><!ENTITY igrave "ì"><!ENTITY iacute "í"><!ENTITY icirc "î"><!ENTITY iuml "ï"><!ENTITY eth "ð"><!ENTITY ntilde "ñ"><!ENTITY ograve "ò"><!ENTITY oacute "ó"><!ENTITY ocirc "ô"><!ENTITY otilde "õ"><!ENTITY ouml "ö"><!ENTITY oslash "ø"><!ENTITY ugrave "ù"><!ENTITY uacute "ú"><!ENTITY ucirc "û"><!ENTITY uuml "ü"><!ENTITY yacute "ý"><!ENTITY thorn "þ"><!ENTITY yuml "ÿ">' _ & ']>' & @CRLF _ & '<html>' & @CRLF _ & $sHtml[0] $_HXmlParser_DOM.loadXML($sHtml); If IsObj($_HXmlParser_DOM.parseError) AND $_HXmlParser_DOM.parseError.errorCode Then SetError(7, $_HXmlParser_DOM.parseError.errorCode, 0) EndIf $_HXmlParser_DOM.setProperty("SelectionLanguage", "XPath"); Return $_HXmlParser_DOM EndFunc Func _HXmlParser_LoadUrl ( $sUrl ) Local $http = ObjCreate("winhttp.winhttprequest.5.1") $http.Open("GET", $sUrl) $http.Send() Local $ret = _HXmlParser_LoadHtml($http.Responsetext) If @error Then Return SetError(@error, @extended, $ret) Return $ret EndFunc #region >> Debugging Func _Alert ($msg, $fDialog=1, $err=@error, $ext=@extended, $ln = @ScriptLineNumber) If $fDialog Then MsgBox(0, @ScriptName, $msg) Else TrayTip(@ScriptName, $msg, 5000) EndIf If $err Then Return SetError($err, $ext, $ln) Return 0 EndFunc Func _Critical ($ret, $rel=0, $msg="Fatal Error", $err=@error, $ext=@extended, $ln = @ScriptLineNumber) If $err Then $ln += $rel Local $LastError = _WinAPI_GetLastError(), _ $LastErrorMsg = _WinAPI_GetLastErrorMessage(), _ $LastErrorHex = Hex($LastError) $LastErrorHex = "0x" & StringMid($LastErrorHex, StringInStr($LastErrorHex, "0", 1, -1)+1) $msg &= @CRLF & "at line " & $ln & @CRLF & @CRLF & "AutoIt Error: " & $err & " (0x" & Hex($err) & ") Extended: " & $ext If $LastError Then $msg &= @CRLF & "WinAPI Error: " & $LastError & " (" & $LastErrorHex & ")" & @CRLF & $LastErrorMsg $msg &= @CRLF & @CRLF & _HXmlParser_GetErrorString() ClipPut($msg) MsgBox(270352, "Fatal Error - " & @ScriptName, $msg) Exit EndIf Return $ret EndFunc #endregion << Debugging Func _HXmlParser_Test () _Critical( _HXmlParser_Startup() ) Local $dom = _Critical( _HXmlParser_LoadUrl("http://www.AutoItScript.com") ) _Alert("Removing all SCRIPT tags") Local $begin = TimerInit() Local $nodes = $dom.selectNodes("//script") If $nodes.length Then For $i = 0 To $nodes.length - 1 Local $node = $nodes.item($i) $node.parentNode.removeChild($node) Next EndIf _Alert("Done in " & TimerDiff($begin) & " ms") _Alert("Collecting all P tags") Local $count = 1, $s = "" $begin = TimerInit() $nodes = $dom.selectNodes("//p") If $nodes.length Then For $i = 0 To $nodes.length - 1 Local $node = $nodes.item($i) $s &= "[" & $count & "] " & $node.text & @CRLF $count += 1 Next EndIf _Alert("Done in " & TimerDiff($begin) & " ms") _Alert($s) $s = "" _Alert("Collecting all feature DIVs") $begin = TimerInit() $nodes = $dom.selectNodes("//div[contains(@class, 'featitem')]") If $nodes.length Then For $i = 0 To $nodes.length - 1 Local $node = $nodes.item($i) $s &= $node.xml & @CRLF Next EndIf _Alert("Done in " & TimerDiff($begin) & " ms") _Alert($s) ClipPut($dom.xml) _Alert("HTML content is in clipboard") EndFunc If @ScriptName = $_HXmlParser_ScriptName Then _HXmlParser_Test() libtidy.7z
-
Finally found a way to "mute" IE -- making it unable to load external resources except the already cached ones -- makes it load page faster. Other IE instances won't be affected, only the one we used as html parser. This simple wrapper functions: _HtmlParser_Startup _HtmlParser_GetDocument ; the IHtmlDocument ref _HtmlParser_LoadHtml ; load plain text, optionally remove all script tags _HtmlParser_LoadUrl _HtmlParser_LoadScript ; to use jquery, xpath, etc. _HtmlParser_ClearScript _HtmlParser_Exec ; execute js and get return value, see sample Save as "HtmlParser.au3" and run, the sample code is included. Clear IE cache first for the best result. Hope it helps #include-once #include <WinAPI.au3> #include <WindowsConstants.au3> #include <GuiConstantsEx.au3> #include <IE.au3> ; Opt("MustDeclareVars", 1) Global $_HtmlParser_Debug = False Global $_HtmlParser_Script = "" Global Const $_HtmlParser_ScriptName = "HtmlParser.au3" Global Const $tagINTERNET_PROXY_INFO = "dword dwAccessType; ptr lpszProxy; ptr lpszProxyBypass"; Global Const $tagCOPYDATA = _ "ULONG_PTR;" & _ ; dwData, The data to be passed to the receiving application "DWORD;" & _ ; cbData, The size, in bytes, of the data pointed to by the lpData member "PTR" ; lpData, The data to be passed to the receiving application. This member can be NULL. Func _HtmlParser_Startup ($iPort=843) If IsDeclared("_HtmlParser_IE") AND IsObj($_HtmlParser_IE) Then Return 1 Global $_HtmlParser_Port = $iPort __HtmlParser_ParseCmdLine() Global $_HtmlParser_HWND = WinWait($_HtmlParser_GUID, "", 5) If NOT $_HtmlParser_HWND Then Return SetError(1, 0, 0) ; Daemon failed to start WinSetTitle($_HtmlParser_HWND, "", "") ; Attach IE Global $_HtmlParser_IE = _IEAttach(WinGetHandle($_HtmlParser_GUID), "embedded") If NOT IsObj(_HtmlParser_GetDocument()) Then Return SetError(2, 0, 0) OnAutoItExitRegister("__HtmlParser_Shutdown") Return 1 EndFunc Func _HtmlParser_GetDocument () If IsObj($_HtmlParser_IE) Then Return _IEDocGetObj($_HtmlParser_IE) Return SetError(1, 0, 0) EndFunc Func _HtmlParser_LoadHtml ( $sHtml, $fRemoveScriptTags=0 ) _IENavigate($_HtmlParser_IE, "about:blank") Local $doc = _HtmlParser_GetDocument() If $fRemoveScriptTags Then $sHtml = StringRegExpReplace($sHtml, "<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>", "") $doc.Write($sHtml & @CRLF & '<script language="javascript">' & @CRLF & $_HtmlParser_Script & @CRLF & 'Array.prototype.set=function(i,v){this[i]=v};Array.prototype.get=function(i){return this[i]};document.scripts[document.scripts.length-1].removeNode(false)</script>') Return $doc EndFunc Func _HtmlParser_LoadUrl ( $sUrl, $fRemoveScriptTags=0 ) Local $http = ObjCreate("winhttp.winhttprequest.5.1") $http.Open("GET", $sUrl) $http.Send() Return _HtmlParser_LoadHtml($http.Responsetext, $fRemoveScriptTags) EndFunc Func _HtmlParser_LoadScript ( $sFilename ) Local $script = "" If FileExists ($sFilename) Then $script = FileRead($sFilename) Else If StringInStr($sFilename, "http://") OR StringInStr($sFilename, "https://") OR StringInStr($sFilename, "ftp://") Then Local $http = ObjCreate("winhttp.winhttprequest.5.1") $http.Open("GET", $sFilename) $http.Send() $script = $http.Responsetext EndIf EndIf If $script Then $_HtmlParser_Script &= @CRLF & @CRLF & $script Return 1 EndIf Return 0 EndFunc Func _HtmlParser_ClearScript ( $sFilename ) $_HtmlParser_Script = "" EndFunc Func _HtmlParser_Exec ( $sScript ) Local $doc = _HtmlParser_GetDocument() If IsObj($doc) AND IsObj($doc.parentWindow) Then Local $window = $doc.parentWindow $window.execScript('window._HtmlParser_Result=(function(){' & $sScript & '})();', 'Javascript') If $window._HtmlParser_Result OR IsObj($window._HtmlParser_Result) Then Return $window._HtmlParser_Result Else Return SetError(2, 0, 0) EndIf EndIf Return SetError(1, 0, 0) EndFunc #region >> Internals Func __HtmlParser_Shutdown () Global $_HtmlParser_IE = 0 If IsDeclared("_HtmlParser_HWND") Then WinClose($_HtmlParser_HWND) OnAutoItExitUnregister("__HtmlParser_Shutdown") EndFunc Func __HtmlParser_ParseCmdLine () If @compiled Then Global Const $_HtmlParser_Exec = '"' & @ScriptFullPath & '"' Else Global Const $_HtmlParser_Exec = '"' & @AutoItExe & '" "' & @ScriptFullPath & '"' EndIf Local $cmd = StringInStr($CmdLineRaw, "/_HtmlParser_", 1), $val If $cmd > 0 Then #NoTrayIcon $cmd = StringRegExp(StringMid($CmdLineRaw, $cmd), '/(_HtmlParser_[a-zA-Z]+)\:"([^"]*)"', 3) For $i = 0 To UBound($cmd)-1 Step 2 $val = $cmd[$i+1] If $val = ("" & Number($val)) Then $val = Number($val) Assign($cmd[$i], $val, 2) Next __HtmlParser_DaemonRun() Exit Else Global $_HtmlParser_GUID = __WinAPI_CreateGUID() __HtmlParser_Daemonstart() EndIf EndFunc Func __HtmlParser_Daemonstart () Run ( $_HtmlParser_Exec & _ ' /_HtmlParser_GUID:"' & $_HtmlParser_GUID & '"' & _ ' /_HtmlParser_Debug:"' & (0 + $_HtmlParser_Debug) & '"' & _ ' /_HtmlParser_Port:"' & $_HtmlParser_Port & '"' ) EndFunc Func __HtmlParser_DaemonRun () ; Initialize GUI Local $hGUI = GUICreate("", 500, 400, 10, 10, $WS_SIZEBOX, $WS_EX_TOOLWINDOW) Global $_HtmlParser_IE = _IECreateEmbedded() Local $hIE = GUICtrlCreateObj($_HtmlParser_IE, 0, 0, _WinAPI_GetClientWidth($hGUI), _WinAPI_GetClientHeight($hGUI)) GUICtrlSetResizing($hIE, $GUI_DOCKAUTO) GUIRegisterMsg($WM_SYSCOMMAND, "__HtmlParser_SysCommand") If $_HtmlParser_Debug Then GUISetState() ; Initialize IE _IE_SetSessionProxy("127.0.0.1:" & $_HtmlParser_Port) _IENavigate($_HtmlParser_IE, "about:blank") _IEPropertySet($_HtmlParser_IE, "silent", True) WinSetTitle($hGUI, "", $_HtmlParser_GUID) Local $timeout = TimerInit() Do If TimerDiff($timeout) > 5000 Then Exit Until WinGetTitle($hGUI) <> $_HtmlParser_GUID If $_HtmlParser_Debug Then WinSetTitle($hGUI, "", "HtmlParser Debug Window") While 1 Sleep(100) WEnd EndFunc Func __HtmlParser_SysCommand ($hWnd, $Msg, $wParam, $lParam) #forceref $Msg, $wParam, $lParam If BitAND($wParam, 0xFFF0) = 0xF060 Then Exit Return $GUI_RUNDEFMSG EndFunc #endregion << Internals #region >> WinAPIEx Func __WinAPI_CreateGUID() Local $tGUID, $Ret $tGUID = DllStructCreate($tagGUID) $Ret = DllCall('ole32.dll', 'uint', 'CoCreateGuid', 'ptr', DllStructGetPtr($tGUID)) If @error Then Return SetError(1, 0, '') Else If $Ret[0] Then Return SetError(1, $Ret[0], 0) EndIf EndIf $Ret = DllCall('ole32.dll', 'int', 'StringFromGUID2', 'ptr', DllStructGetPtr($tGUID), 'wstr', '', 'int', 39) If (@error) Or (Not $Ret[0]) Then Return SetError(1, 0, '') EndIf Return $Ret[2] EndFunc ;==>__WinAPI_CreateGUID Func _IE_SetSessionProxy ($sProxyAddress, $sBypassList="") Local $tProxyAddress = DllStructCreate("char[" & StringLen($sProxyAddress) + 1 & "]"), _ $tBypassList = DllStructCreate("char[" & StringLen($sBypassList) + 1 & "]"), _ $tINTERNET_PROXY_INFO = DllStructCreate($tagINTERNET_PROXY_INFO) DllStructSetData($tINTERNET_PROXY_INFO, "dwAccessType", 0x3) DllStructSetData($tProxyAddress, 1, $sProxyAddress) DllStructSetData($tINTERNET_PROXY_INFO, "lpszProxy", DllStructGetPtr($tProxyAddress)) DllStructSetData($tBypassList, 1, $sBypassList) DllStructSetData($tINTERNET_PROXY_INFO, "lpszProxyBypass", DllStructGetPtr($tBypassList)) Local $aRet = DllCall("urlmon.dll", "INT", "UrlMkSetSessionOption", _ "uint", 0x26, _ "ptr", DllStructGetPtr($tINTERNET_PROXY_INFO), _ "int", DllStructGetSize($tINTERNET_PROXY_INFO), _ "int", 0 ) If @error OR $aRet[0] Then Return SetError(1, @error, 0) Return 1 EndFunc #endregion << WinAPIEx #region >> Debugging Func _Alert ($msg, $fDialog=1) If $fDialog Then MsgBox(0, @ScriptName, $msg) Else TrayTip(@ScriptName, $msg, 5000) EndIf EndFunc Func _Critical ($ret, $rel=0, $msg="Fatal Error", $err=@error, $ext=@extended, $ln = @ScriptLineNumber) If $err Then $ln += $rel Local $LastError = _WinAPI_GetLastError(), _ $LastErrorMsg = _WinAPI_GetLastErrorMessage(), _ $LastErrorHex = Hex($LastError) $LastErrorHex = "0x" & StringMid($LastErrorHex, StringInStr($LastErrorHex, "0", 1, -1)+1) $msg &= @CRLF & "at line " & $ln & @CRLF & @CRLF & "AutoIt Error: " & $err & " (0x" & Hex($err) & ") Extended: " & $ext If $LastError Then $msg &= @CRLF & "WinAPI Error: " & $LastError & " (" & $LastErrorHex & ")" & @CRLF & $LastErrorMsg ClipPut($msg) MsgBox(270352, "Fatal Error - " & @ScriptName, $msg) Exit EndIf Return $ret EndFunc #endregion << Debugging ; ============================================================================== Func _HtmlParser_Test () $_HtmlParser_Debug = True _Critical( _HtmlParser_Startup() ) ; warming up Local $doc = _HtmlParser_GetDocument() $doc.write("Hello AutoIt World") _Alert("now for real") _HtmlParser_LoadScript("https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js") ; Or: ; _HtmlParser_LoadScript(@ScriptDir & "\jquery.min.js") Local $doc = _HtmlParser_LoadUrl("http://www.autoitscript.com", True) Local $pages = _Critical( _HtmlParser_Exec('var p=[];$("p").each(function(index) { p.push("[" + (index+1) + "] " + $(this).text());});return p') ) Local $s = "" For $i = 0 To $pages.length-1 $s &= $pages.get($i) & @CRLF Next _Alert($s) Local $saved = $doc.body.parentElement.outerHTML Local $divs = _HtmlParser_Exec('return $(".featitem.clearfix")') Local $div, $features = "" For $i = 0 To $divs.length-1 $div = $divs.get($i) $features &= $div.outerHTML Next $doc.body.innerHTML = $features _Alert("A lot faster parsing in javascript though") _HtmlParser_LoadHtml($saved, True) Local $features = _HtmlParser_Exec('var s=""; $(".featitem.clearfix").each(function(){ s += this.outerHTML }); document.body.innerHTML=s; return s') _Alert($features) EndFunc If @ScriptName = $_HtmlParser_ScriptName Then _HtmlParser_Test() Edit: added $fRemoveScriptTags option for _HtmlParser_LoadUrl and _HtmlParser_LoadHtml
-
@IchBistTod Thanks for implementing this in AutoIt A bit addition to run exe with parameters. change Func _RunExeFromMemory($bBinaryImage, $iCompressed = 0, $test = 0)with Func _RunExeFromMemory($bBinaryImage, $sParameters = 0, $iCompressed = 0, $test = 0) and ; Create new process $aCall = DllCall("kernel32.dll", "int", "CreateProcessW", _ "wstr", $BaseExe, _ ; try something else too (now only range plays, giving us a space) "ptr", 0, _with ; Create new process If $sParameters Then $sParameters = $BaseExe & " " & $sParameters $aCall = DllCall("kernel32.dll", "int", "CreateProcessW", _ "wstr", $BaseExe, _ ; try something else too (now only range plays, giving us a space) "wstr", $sParameters, _ So the function can be called with $file = FileOpen(@WindowsDir & "\notepad.exe", 16) If $file > -1 Then $buffer = FileRead($file) FileClose($file) _RunExeFromMemory($buffer, '"' & @AppDataDir & '\desktop.ini"') EndIf which will run notepad with desktop.ini loaded, and no trace of notepad.exe in process list.
-
Hi, I made an AutoIt offline web server, inspired by TiddlyWiki personal web notebook. Offline because its purpose is serving locally so we can write local files via any web browser. Just like what TiddlySaver do but without irritating security warning and no cross-domain xhr limitation. Unlike web server around it so simple (no setup), portable, works in limited-user account and integrate itself to windows explorer. It was started to simply make local pages writable (the reason I made UDF ) but then grow to (optionally) provide settings for more advanced usage i.e. enable CGI support, mapping paths, etc. So it now also can be used, for example, as PHP test environment. It supposed to be driven by internal AuJS active page (not completed yet) but these are the preview: serving phpinfo() with SQLite support: the SQLite test page (from XAMPP ) can be found in download. running CKFinder: running AjaXplorer: and php encode explorer (current directory lister, until AuJS is ready) : Basically it can work with any CGI executable I believe it can use AuCGI too. Wouldn't it be nice to have LocalHOTs and AuCGI works together as both made by AutoIt But because I still have to make AuJS can handle multipart POST data and add FLV streaming support I would be very grateful if someone willing to play with this beta and provide AuCGI samples to be packed with the release version. To run the server, execute LocalHOTs.au3 in sourcedebug folder. Once the server run, "Open with LocalHOTs" context menu on windows explorer will be available for *.htm, *.html and *.php (yes you can add *.au3 too, just follow instruction at the console). The code itself only weighted 355KB but the download bloated into 5Megs because I include PHP5 executable (required by current directory listing script) for your convenience. The tests folder contains some pages for you to start play with. Other file that may be useful is Test.all.au3, it will run test unit for both AuJS and JScriptObject UDF. It supposed to be all passed, but if you see any reds (failed test) please report it here. Update: Added FLV & MP4 HTTP Pseudostreaming Eventhough the file is served locally, web player can't jump into time that have not been buffered yet by the player. Streaming enable to seek in the timeline to any positions. Requirements: FLV Streaming - flv streaming is out of the box feature, but to prepare flv files ready for streaming you will need flvmeta, download here (win32/64). This tool will inject keyframes metadata into flv files so web player can use pseudostreaming. Just put flvmeta.exe in script folder, it will check and update flv files when necessary. MP4 Streaming - mp4 streaming depends on ffmpeg, download windows build (32/64) here. Put ffmpeg.exe file in the script folder Samples: tests/Streaming/flowplayer/example/readme.(flv|mp4).html tests/Streaming/JWPlayer/readme.(flv|mp4).html Note: copy any flv and mp4 file into tests/Streaming/media/ folder and rename it to movie.flv and movie.mp4. These files will be used by both flowplayer and JWPlayer samples. Downloads LocalHOTs beta and LocalHOTs_beta.update.rar *** UPDATE *** done: AuJS (ASP like page renderer) for *.aujdropped dir listing, popping explorer insteadlive flv stream (from any movie format), no disk cache.
-
- web server
- AuCGI
-
(and 4 more)
Tagged with:
-
Well actually I like your ancient one than the new complex as it simply helps me understand the basic concept. Thanks again Kip The problem is even the new AutoItObject ends up with the same fatal error if I try to inherit from another COM object. Agreed, but in JScript Object we need another wrapper (in pure javascript) which is worsen the case My question is still, is it possible to inherit any COM object other than AutoItObject created COM object?
-
Cool, I look forward to the next version Great tool already, thanks for sharing
- 12 replies
-
- registry
- group policy
-
(and 1 more)
Tagged with:
-
Its very usefull! I always find a way to script it do like block executable/script on USB stick. If you do it manually you will have to create new path rules for each targetted drive letter. One question, is this tool already have export/import feature builtin?
- 12 replies
-
- registry
- group policy
-
(and 1 more)
Tagged with:
-
Need help inherit AutoItObject from JScriptObject () or is it possible to inherit any COM object other than AutoItObject created COM object? I have been playing with Kip's modified sample (), works with crafted object but seems failed to locate correct vtable (DllStructGetData($hHeader, 1) < 0 in ___AddMembersToLookupTable function) for other COM object (e.g. Scripting.Dictionary) Thanks
-
ComObject Proxy, seamless Windows Script Control & AutoItObj
eimhym replied to eimhym's topic in AutoIt Example Scripts
Yesss! edit post button popping out of thin air LOL -
ComObject Proxy, seamless Windows Script Control & AutoItObj
eimhym replied to eimhym's topic in AutoIt Example Scripts
Update: Now become JScriptObject, for: 1.) Now tightly coupled with AutoItObject. Include JScriptObject.au3 will automatically include AutoItObject (http://autoitobject.origo.ethz.ch/) 2.) More represents its nature. AutoItObject, which also a (customized) COM object specially crafted for AutoIt use. JScriptObject is plain JScript's object not (yet) hampered in anyway. Still, JScriptObject is accessible from AutoIt thanks to COM support. alert() is now emulated using AutoIt's MsgBox(). VBScript support no longer required but still an option if someone need to invoke VBS code.array_set() and array_get() replaced with Array.prototype.set() and get(). unset() introduced to remove an Array element (see example)Introduce _JScriptObject_AddMethod() which wrap _AutoItObject_AddMethod(). You can now easily assign AutoIt function as JScriptObject method .No need to create new AutoItObject (see example)To Do:Find a way (or ask AutoItObject team) to make AutoItObject can inherit from JScript's object. Any attempt resulting fatal error so faror even better: mock JScript object directly. For now AutoIt function call within JScript object has to take quite long route: JScript wrapper --> AutoItObject --> AutoIt function. This means serious debugging JScript's inner work, which, devotion required :duh:Not much, but as a proof-of-concept now JScriptObject have a pretty much clearer goal JScriptObject.zip -
Tips: Quickly insert _Log_Group() to trace function call Not a real stack trace but it would be handy to log both function name and parameter passed, but its painfull task to insert them manually in each Function entry. We can use Regular Expression search and replace to make the process semi-automatic Requirement: Notepad++ which support "matches newline" option (at the right side of "Regular expression" Search mode option) I'm using v6.1.2 Set ConsoleLog to log into file only, as console output will be too fast to read #include "ConsoleLog.au3" $_CL_Log_Mode = 3 $_CL_Log_FileMode = @ScriptDir & "\" & @ScriptName & "-trace.txt" _ConsoleLog_Start() We use this function declaration for illustration: Func SomeFunction($param1, $param2 , $param3=True,$param4 =0) To open the search and replace dialog press Ctrl+H, all the steps below will use Regular Expression in Search mode Step #1: Insert _Log_Group Select Regular Expression mode and turn "matches newline" ONFind what: ^(Func\s+([^ \(]+)\(([^\)]*)\)[^\n]*\n) Replace with: \1_Log_Group\("\2 \(" & \3 & "\)"\)\n Click "Replace All" or Alt+A ONCEthe result should be (green = the changes):Func SomeFunction($param1, $param2 , $param3=True,$param4 =0) _Log_Group("SomeFunction (" & $param1, $param2 , $param3=True,$param4 =0 & ")") Step #2: Strip out default parameter values turn "matches newline" OFFFind what: ^(_Log_Group[^=\n]*)=[^,&\)]+([^\n]*) Replace with: \1\2 Repeately pressing Alt+A until no matches foundthe result should be:Func SomeFunction($param1, $param2 , $param3=True,$param4 =0) _Log_Group("SomeFunction (" & $param1, $param2 , $param3,$param4 & ")") Step #3: Reformat parameters Find what: ^(_Log_Group[^,\n]*),\s* Replace with: \1 & "; " & Repeately pressing Alt+A until no matches foundthe result should be:Func SomeFunction($param1, $param2 , $param3=True,$param4 =0) _Log_Group("SomeFunction (" & $param1 & "; " & $param2 & "; " & $param3 & "; " & $param4 & ")") Step #4: Reformat empty parameter Find what: &\s*& Replace with: & " " & Repeately pressing Alt+A until no matches foundThats it, run your script. The trace file would be in the same directory with your script.If the script have error before, the trace will stop on the function where the error happened, If not you can make break points like MsgBox (0, "", "Breakpoint"), run and then (re)open the trace file in notepad each time the dialog box popped up (notepad++ can update itself when the trace file changed) NOTE: You can assign step 2 - 4 as macro, which is convenient. But carefull with step 1, it can make _Log_Group doubled if executed more than once. When you finish debugging, you can remove them all at once: Step #5: Remove all _Log_Group() under Function declaration turn "matches newline" ONFind what: ^(Func\s+[^ \(]+\([^\n]*\n)_Log_Group[^\n]*\n Replace with: \1 Hope it helps, Happy debugging