AutoHotkey_L v1.0.91.05
All changes in this release are COM-related.
Added: ComObjError now returns the previous setting.
Added: ComObjType(co) and ComObjValue(co).
Added: ComObjMissing().
Added: ComObjArray() and basic SAFEARRAY support.
Added: "Take ownership" parameter for ComObjParameter().
Changed: Values passed to COM functions via ComObjParameter are no longer freed in the process of calling the function.
Changed: ComObj.x() now falls back to PROPERTYGET if member 'x' is not found. This fixes for-loops for some objects.
Changed: Wrap unhandled variant types in an object rather than returning integer value.
Changed: Manage VT_UNKNOWN/VT_ARRAY lifetime automatically, by default.
1.0.91.01
Fixed: Unexpected results with File.Write(Str) after text-reading.
Fixed: UTF BOM check caused unexpected results in files without a BOM.
Fixed (ANSI): Parsing loops and File.ReadLine() treated Chr(255) as EOF.
Fixed (Unicode): RegExReplace errors where the UTF-8 and UTF-16 lengths differed.
Fixed: Disabling the last hook hotkey breaks Input.
Added: Simple optimization for RegExMatch/Replace.
1.0.91.02 - December 26, 2010
COM: Added protection against NULL IDispatch/IUnknown pointers.
COM: Skip QueryInterface for IDispatch if VT_DISPATCH is passed explicitly.
Minor fix regarding obj.field := var, for maintainability.
1.0.91.03 - December 27, 2010
Fixed: RegEx callout subpattern vars - broken by v1.0.90.00.
1.0.91.04 - December 29, 2010
Fixed (Unicode): RegExReplace omitted all text up to StartingPosition (broken by v1.0.90.00).
1.0.91.05 - January 1, 2011
Fixed: Cleanup code in COM method calls was freeing the wrong parameters.
Fixed (ANSI): DllCall set incorrect length for wstr parameters on output.
Fixed: Variadic function calls were unstable when param object was empty.
Downloads and More
I'll be away for the next few days, so Merry Christmas to those who celebrate it.
[*:17idt3v1]Updated Process list example (#4) for x64 compatibility.
[*:17idt3v1]Added a much simpler example (#5) for using COM to list processes.
[*:17idt3v1]Added example (with reusable function) for passing a VARIANT ByRef. The example shows how to create a VBScript function and pass values to/from it via a ByRef parameter.
Index := 1 ; access 2nd array element (value of 8) xlApp := [color=#107095]ComObjCreate[/color]([color=#666666]"Excel.Application"[/color]) xlApp.WorkBooks.Add xlApp.Visible := true [color=#107095]for[/color] cell in xlRng := xlApp.Range([color=#666666]"A1:A5"[/color]) cell.value := [color=brown]A_Index[/color]**3 [color=#107095]if[/color] ComObjType(arr := xlRng.value) & 0x2000 ; verify SafeArray [color=#107095]MsgBox[/color], 0, % [color=#666666]"Cells: "[/color] arr.MaxIndex(), % arr[Index] ; <-- shows 5 cells, but blank value ; Manually extract 2nd array element pva := [color=#107095]NumGet[/color](ComObjValue(arr)+12) [color=#107095]MsgBox[/color], % [color=#107095]NumGet[/color](pva+(Index+1) * 16 - 8, 0, [color=#666666]"double"[/color])... and of course, Merry Christmas!
EDIT -
Hint: use example #2 for ComObjArray.
MsgBox, % arr[2,1] ; access 2nd array element (value of 8)
XmlData = ( <?xml version="1.0" ?> <tv> <channel id="1tvrus.com"> <display-name>Channel One</display-name> <icon src="http://www.lyngsat-logo.com/icon/tv/pp/perviy_1_kanal.gif" /> <url>http://www.1tvrus.com/channel1/schedule/</url> </channel> <channel id="rt.com"> <display-name>RT</display-name> <url>http://rt.com/programs/schedule/</url> </channel> </tv> ) oXmlDoc := ComObjCreate("MSXML2.DOMDocument.6.0") oXmlDoc.async := false oXmlDoc.loadXML(XmlData) oNodeList := oXmlDoc.selectNodes("/tv/channel") For oNode in oNodeList { MsgBox, % "id:`t`t" . oNode.getAttribute("id") . "`n" . "display-name:`t" . [color=red]oNode.selectSingleNode("./display-name").text[/color] . "`n" . "icon:`t`t" . [color=red]oNode.selectSingleNode("./icon").attributes.getNamedItem("src").value[/color] . "`n" . "url:`t`t" . [color=red]oNode.selectSingleNode("./url").text[/color] }v1.0.91.01 crashes at non-existent element whereas v1.0.90.00 just produces empty string.
And, there seems to be no obvious way to bypass AddRef in ComObjUnwrap, which I'd also like to have.
I've just done some debugging, and I've found out that the revised COM code doesn't check for returned NULL IDispatch/IUnknown objects (!). Depending on how you look at it, it could also be that the Invoke function doesn't check if the current IDispatch pointer is NULL.v1.0.91.01 crashes at non-existent element whereas v1.0.90.00 just produces empty string.
EDIT: This code gives an assertion failure:
func("text") func(var) { obj := Object() [color=red]obj.field := var[/color] }
script_expression.cpp, line 427:
ASSERT(this_token.symbol == SYM_STRING);
Two somethings. Hint: use example #2 for ComObjArray.Am I missing something?
Thanks. It should work in v1.0.91.02.v1.0.91.01 crashes at non-existent element whereas v1.0.90.00 just produces empty string.
I was a bit iffy about that; if the script explicitly states "this value is VT_DISPATCH", I suppose the QI call isn't appropriate. I've changed it for v1.0.91.02. However, I'm curious: Why would the wrapper object need the original (IAccessible) pointer? Because it affects what type info ComObjConnect retrieves?However, there is now no way to bypass QueryInterface for IDispatch with VT_DISPATCH (:ComObject(VT_DISPATCH, pdisp) used to do the job).
"Unwrap" implies some action is being taken on the wrapper. Use ComObjValue if you just want to retrieve the value stored within.And, there seems to be no obvious way to bypass AddRef in ComObjUnwrap, which I'd also like to have.
Thanks for doing the legwork. Originally there were two functionally equivalent sections of code: a section for return values and a function "VariantToToken" for enumerators/ComEvent parameters. I had replaced the former (which checked for NULL) with a call to VariantToToken (which did not check for NULL). I have corrected this and also added a check to ComObject::Invoke in case of ComObj(VT_DISPATCH, 0).I've just done some debugging, and I've found out that the revised COM code doesn't check for returned NULL IDispatch/IUnknown objects (!). Depending on how you look at it, it could also be that the Invoke function doesn't check if the current IDispatch pointer is NULL.
Thanks. At one point any string returned as SYM_OPERAND was not handled correctly, so I added that assertion. Now it should be safe, but I've corrected it anyway, for consistency and maintainability.EDIT: This code gives an assertion failure
1.0.91.02
COM: Added protection against NULL IDispatch/IUnknown pointers.
COM: Skip QueryInterface for IDispatch if VT_DISPATCH is passed explicitly.
Minor fix regarding obj.field := var, for maintainability.
With this it's not possible bypassing AddRef while keeping QueryInterface. Actually I thought your previous implementation was good, the only complaint I had was that the default should be no AddRef, to be compatible with the corresponding functions COM_Enwrap and COM_Parameter. I think It'll be enough just to extend ComObjConnect and ComObjType to allow VT_UNKNOWN too.I was a bit iffy about that; if the script explicitly states "this value is VT_DISPATCH", I suppose the QI call isn't appropriate. I've changed it for v1.0.91.02.
This may appear dubious or a little dangerous to some members, but, it's in fact necessary or meaningful as some objects never respond to QueryInterface for IDispatch but are nevertheless dispatchable.
I'd like to be brief here. IAccessible to IDispatch is sort-of up-casting, and this will end in a loss of information with out-of-process com objects, for example, if want to use IAccessible's VTABLE.However, I'm curious: Why would the wrapper object need the original (IAccessible) pointer?
I disagree. Unwrap is merely a little fancier term over GetValue/Pointer. That alone doesn't justify the new addition of AddRef, breaking the campatibility with COM_Unwrap."Unwrap" implies some action is being taken on the wrapper.
I noticed that, so I changed from no way to no obvious way. IMO, you had just broken a backward compatibility with COM.ahk. Many members were already accustomed with COM_E(U)nwrap and its usage, and expected similar behaviors with ComObjE(U)nwrap. I even claimed to be so. But you simply broke the accustomed function ComObjUnwrap with no obvious reason, and now introduce and force to use new function ComObjValue for the old functionality.Use ComObjValue if you just want to retrieve the value stored within.
I think the behaviors of the above two should be switched, i.e., restore the old behavior of ComObjUnwrap, and move AddRef into ComObjValue.
PS. As pure discussion only seems to be futile, I uploaded the original version for the native COM of Misc.ahk in Zip. This will also work with COM_L as it is with only the obvious change ComObjE(U)nwrap to COM_E(U)nwrap.
Thanks a lot! It's working fine now.
Thanks. It should work in v1.0.91.02.v1.0.91.01 crashes at non-existent element whereas v1.0.90.00 just produces empty string.
while AHK_Basic did understand variables like this:
tooltip_]] = hallo
AHK_L throws an error.
Could this be fixed? The german magazine company ct from heise has a big program activ'aid which runs on autohotkey. They have defined much variables like this.....
Tanks.
Regular expressions are your friend. I did this on bunch of my scripts using that notation.Could this be fixed? The german magazine company ct from heise has a big program activ'aid which runs on autohotkey. They have defined much variables like this.....