Rainer2 Posted December 31, 2010 Share Posted December 31, 2010 Hello everybody,I am stuck at my futile attempts to access Microsoft OneNote 2010 with the COM interface. I need the help of you AutoIt COM experts out there. :-) Here is the situation: I want to retrieve content from OneNote in XML format. However, all of the OneNote methods that provide XML data use out-parameters, which means that I have to use DllCall() instead of ObjCreate(). This is how far I got on my own: First, I can access OneNote from AutoIt with ObjCreate(), using this (obvious) line of code:Local $objOneNote = ObjCreate("Onenote.Application")This works fine; I used this line of code _Assert(IsObj($objOneNote))to check that $objOneNote actually points to a COM object. Furthermore, I was able to close an open notebook with this call to CloseNotebook, a method of the OneNote API: $objOneNote.CloseNotebook("{MY_GUID}")Basically, it seems that I can access OneNote via COM. However, when I want to retrieve OneNote content as XML data, I need to use a method like GetHierarchy(), which uses an out-parameter to pass the content as an XML string. The GetHierarchy method has the following signature: HRESULT GetHierarchy( [in]BSTR bstrStartNodeID, [in]HierarchyScope hsScope, [out]BSTR * pbstrHierarchyXmlOut);(source: http://msdn.microsoft.com/en-us/library/ms788684(office.12).aspx)Since out-parameters don't work with ObjCreate, I have to use DllCall. I am trying to do something like this (Warning: The following line of code is wrong): Local $intRetVal = DllCall("Onenote.Application", "long", "GetHierarchy", "str", "", "int", 4, "str *", $sXml)$sXml - the out-parameter - comes back empty. I have two questions about this:First, I am fully aware that "Onenote.Application" has to be replaced with the correct name of the dll. How can I find the name of a dll, when I only know that "Onenote.Application" is the correct string to work with ObjCreate()?Second, are there any other problems or errors with my attempt to translate the signature of GetHierarchy() into a DllCall()? I apologize if my questions are stupid; I am not really a COM expert. (In other words: Please be gentle, it's my first time with DllCall :-)Any help will be greatly appreciated. Link to comment Share on other sites More sharing options...
trancexx Posted December 31, 2010 Share Posted December 31, 2010 Find UDF called AutoItObject. It comes with nice help file and plenty of examples in and around it. Everything that you ask for in your post is covered there. That's not in domain of DllCall function. Good luck and may the COM Go(o)d be on your side. ♡♡♡ . eMyvnE Link to comment Share on other sites More sharing options...
Rainer2 Posted December 31, 2010 Author Share Posted December 31, 2010 Hello trancexx, thank you for the hint. I will check AutoItObject out right now. Kind regards, Rainer P.S.: I must confess that I'm a bit surprised that my problem is not within the reach of "normal" AutoIt; does that mean that everybody who wants to do out-parameters with a COM-dll needs to work with AutoItObject? Link to comment Share on other sites More sharing options...
trancexx Posted December 31, 2010 Share Posted December 31, 2010 Hello trancexx, thank you for the hint. I will check AutoItObject out right now.Kind regards,RainerP.S.: I must confess that I'm a bit surprised that my problem is not within the reach of "normal" AutoIt; does that mean that everybody who wants to do out-parameters with a COM-dll needs to work with AutoItObject?Normal AutoIt, as you call it, is usually used by people with Send(), Run() and WinActivate() functions as their upper programming limit. Some devs (I don't dare say all) are satisfied with that fact. Chances for AutoIt3 to be more than just another little game were lost few months ago. Sadly.Use AutoItObject and you will be just fine....But hey, miracles happen. Who knows what tomorrow brings. ♡♡♡ . eMyvnE Link to comment Share on other sites More sharing options...
Rainer2 Posted January 1, 2011 Author Share Posted January 1, 2011 Normal AutoIt, as you call it, is usually used by people with Send(), Run() and WinActivate() functions as their upper programming limit. Some devs (I don't dare say all) are satisfied with that fact. Chances for AutoIt3 to be more than just another little game were lost few months ago. Sadly.Use AutoItObject and you will be just fine....But hey, miracles happen. Who knows what tomorrow brings.I know, since it's tomorrow now: Happy new year! I have taken a first look at AutoItObject. Looks like a great tool to create and access objects with AutoIt. I have been working with object-oriented languages on and off since the late 1980s when Smalltalk was the "hot" OO language and C++ was still a C preprocessor named "C with classes"; I'm more than willing to work with AutoItObject, but unfortunately I can't see how this is going to solve my problem from above, as I am trying to manipulate an existing COM object called "OneNote.Application". I want to get XML content from a call to GetHierarchy(). Could you point me in the right direction? Which AutoItObject function(s) should I give a closer look in order to retrieve the out-parameters from GetHierarchy()? This is my only problem, as AutoIt cannot access out-parameters via COM. (As I said before, I am not very proficient with COM, so forgive me if the question is dumb.)Thanks in advance for any hints, and "Happy new year" again! Rainer Link to comment Share on other sites More sharing options...
trancexx Posted January 1, 2011 Share Posted January 1, 2011 (edited) Thanks. Happy New Year to you too!It doesn't matter if Object is "existing" one. There are more than one way to process objects with AutoItObject. That include both existing object as well as those that needs to be created. Main thing to do is to find vtable definition for the object (I've posted a tool to do that in examples forum, btw). That link you gave conveniently doesn't list methods in vtable appearance order. I can write something like this:expandcollapse popup#AutoIt3Wrapper_UseX64=n #include <AutoItObject.au3> ;=============================================================================== #interface "OneNoteIApplication" Global Const $sCLSID_OneNoteApplication = "{0039FFEC-A022-4232-8274-6B34787BFC27}" Global Const $sIID_IOneNoteApplication = "{2DA16203-3F58-404F-839D-E4CDE7DD0DED}" ; Definition Global $dtagIOneNoteApplication = $dtagIDispatch & _ "GetHierarchy hresult(bstr;dword;bstr*);" & _ "UpdateHierarchy hresult(bstr);" & _ "OpenHierarchy hresult(bstr;bstr;bstr*;dword);" & _ "DeleteHierarchy hresult(bstr;double);" & _ "CreateNewPage hresult(bstr;bstr*;dword);" & _ "CloseNotebook hresult(bstr);" & _ "GetHierarchyParent hresult(bstr;bstr*);" & _ "GetPageContent hresult(bstr;bstr*;dword);" & _ "UpdatePageContent hresult(bstr;double);" & _ "GetBinaryPageContent hresult(bstr;bstr;bstr*);" & _ "DeletePageContent hresult(bstr;bstr;dword);" & _ "NavigateTo hresult(bstr;bstr;bool);" & _ "Publish hresult(bstr;bstr;dword;bstr);" & _ "OpenPackage hresult(bstr;bstr;bstr*);" & _ "GetHyperlinkToObject hresult(bstr;bstr;bstr*);" & _ "FindPages hresult(bstr;bstr;bstr*;bool;bool);" & _ "FindMeta hresult(bstr;bstr;bstr*;bool);" & _ "GetSpecialLocation hresult(dword;bstr*);" ; List Global $ltagIOneNoteApplication = $ltagIDispatch & _ "GetHierarchy;" & _ "UpdateHierarchy;" & _ "OpenHierarchy;" & _ "DeleteHierarchy;" & _ "CreateNewPage;" & _ "CloseNotebook;" & _ "GetHierarchyParent;" & _ "GetPageContent;" & _ "UpdatePageContent;" & _ "GetBinaryPageContent;" & _ "DeletePageContent;" & _ "NavigateTo;" & _ "Publish;" & _ "OpenPackage;" & _ "GetHyperlinkToObject;" & _ "FindPages;" & _ "FindMeta;" & _ "GetSpecialLocation;" ;=============================================================================== _AutoItObject_StartUp() #cs ;You can create object like this: Global $objOneNote = ObjCreate("Onenote.Application") Global $pOneNote = _AutoItObject_IDispatchToPtr($objOneNote) _AutoItObject_IUnknownAddRef($objOneNote) Global $oOneNote = _AutoItObject_WrapperCreate($pOneNote, $dtagIOneNoteApplication) #ce ; But it's easier like this: Global $oOneNote = _AutoItObject_ObjCreate("Onenote.Application", Default, $dtagIOneNoteApplication) ; or $sIID_IOneNoteApplication instead of "Default" ; Check if object is created: If Not IsObj($oOneNote) Then MsgBox(48, "Error", "Object not created. Something is wrong.") Exit EndIf ; Work with object now ;... $aCall = $oOneNote.GetHierarchy("", 4, "") $sHierarchy = $aCall[3] ConsoleWrite("Hierarchy = " & $sHierarchy & @CRLF) ;...I can't test it because I don't have it installed on my system. It's written upon the link you provided and quick google search.edit: don't forget to try commented part of the code if _AutoItObject_ObjCreate would fail in creating this object (that function currently uses CLSCTX_INPROC_SERVER as context for CoCreateInstance). Edited January 1, 2011 by trancexx ♡♡♡ . eMyvnE Link to comment Share on other sites More sharing options...
hench Posted January 1, 2011 Share Posted January 1, 2011 [...] Chances for AutoIt3 to be more than just another little game were lost few months ago. Sadly. To feed my curiosity, may I ask what are you referring to? Thanks. Best wishes for the now and then! hench Link to comment Share on other sites More sharing options...
Rainer2 Posted January 3, 2011 Author Share Posted January 3, 2011 I can't test it because I don't have it installed on my system. It's written upon the link you provided and quick google search. edit: don't forget to try commented part of the code if _AutoItObject_ObjCreate would fail in creating this object (that function currently uses CLSCTX_INPROC_SERVER as context for CoCreateInstance). Thank you for your help, Trancexx. I tried out your code. With the commented part, the object gets created - at least the message box doesn't complain. Unfortunately, the script doesn't write anything on the console. After a while, the console says: !>12:46:44 AutoIT3.exe ended.rc:-1073741819 >Exit code: -1073741819 Time: 23.192 Also, "CloseNotebook" is not working anymore. I experimented with the code you gave me and changed it like this: ; Work with object now ;... ;Close a notebook (no out-parameters necessary, used to work without using "AutoItObject") msgbox(0, "CloseNotebook", "before CloseNotebook") $oOneNote.CloseNotebook("{MyGuid}") msgbox(0, "CloseNotebook", "after CloseNotebook") $aCall = $oOneNote.GetHierarchy("", 4, "") MsgBox(0, "GetHierarchy", "after GetHierarchy") $sHierarchy = $aCall[3] ConsoleWrite("Hierarchy = " & $sHierarchy & @CRLF) ;... This piece of code shows the message boxes before and after the call to "CloseNotebook" - but doesn't actually close the notebook. I also don't get an error message that something went wrong; the messagebox "after CloseNotebook" shows up immediately. The message box "after GetHierarchy" never gets shown. Instead, the aforementioned return code -1073741819 shows up on the console after a few seconds. Any ideas what I'm doing wrong? Link to comment Share on other sites More sharing options...
trancexx Posted January 3, 2011 Share Posted January 3, 2011 I can only speculate on why your app crashes...Indicative is the fact that _AutoItObject_ObjCreate() can't create the object (did I understood right?). If that's the case than can you check in task manager if new process gets created when you create the object with the code that works for you. That .Application suffix suggest it. CLSCTX_INPROC_SERVER is used as precaution to avoid situations you have with the object. Methods of that interface are fed with BSTRs. That means pointers, and that pointers are valid only in this process' scope. Passing that pointer to another process can lead only to a crash (and apparently that's the case with you).Try calling some method that take and return some other data type; integer:$aCall = $oOneNote.GetTypeInfoCount(0) $iTypeInfoCount = $aCall[1] ConsoleWrite("$iTypeInfoCount = " & $iTypeInfoCount & @CRLF)If that works then I'm likely right about the cause of the crashes.Unfortunately, I don't know how to send BSTR to another process. ♡♡♡ . eMyvnE Link to comment Share on other sites More sharing options...
Rainer2 Posted January 13, 2011 Author Share Posted January 13, 2011 Hello trancexx, sorry for the delay, but I was really busy with other projects. I just tried out your piece of code: $aCall = $oOneNote.GetTypeInfoCount(0) $iTypeInfoCount = $aCall[1] ConsoleWrite("$iTypeInfoCount = " & $iTypeInfoCount & @CRLF) If that works then I'm likely right about the cause of the crashes. Unfortunately, I don't know how to send BSTR to another process. The console says: $iTypeInfoCount = 1 Since this worked, you are probably right about the cause of the crashes. Anyway, I consider the problem solved for now, since I was able to access OneNote with Windows PowerShell. If you have any ideas how to do the same thing with AutoIt, here is my code (Warning: PowerShell syntax, not AutoIt! Uses a .NET assembly and a reference parameter!) Add-Type -AssemblyName Microsoft.Office.Interop.OneNote $global:OneNote = New-Object -type "Microsoft.Office.Interop.OneNote.ApplicationClass" $PowerShellFlashCardPage = "{MyGUID}" $myXml = "" $OneNote.GetHierarchy($PowerShellFlashCardPage, [int][Microsoft.Office.Interop.OneNote.HierarchyScope]::hsChildren, [ref] $myXml) $myXml now contains precisely the Xml data I am after. If you have any idea how to do this with AutoIt, don't hesitate to let me know. (But that's very low priority, since my problem is solved now.) Thank you for your help with this, I sure learned a lot in the process! Link to comment Share on other sites More sharing options...
timmalos Posted December 12, 2017 Share Posted December 12, 2017 (edited) Hey guys. I run into the exact same issue , so I update a little this topic in any case situation has changed since this time. I tried with the new ObjCreateInterface without having more success. _AutoItObject_StartUp() ;~ Global $oOnenote = ObjCreateInterface($sCLSID_OneNoteApplication,$sIID_IOneNoteApplication,$dtagIOneNoteApplication,True) Global $objOneNote = ObjCreate("Onenote.Application") Global $pOneNote = _AutoItObject_IDispatchToPtr($objOneNote) _AutoItObject_IUnknownAddRef($objOneNote) Global $oOneNote = _AutoItObject_WrapperCreate($pOneNote, $dtagIOneNoteApplication) ; Check if object is created: If Not IsObj($oOneNote) Then MsgBox(48, "Error", "Object not created. Something is wrong.") Exit EndIf $aCall = $oOneNote.GetTypeInfoCount(0) $iTypeInfoCount = $aCall[1] ConsoleWrite("$iTypeInfoCount = " & $iTypeInfoCount & @CRLF) This works well. ($iTypeInfoCount = 1) However, Issue is : how to be able to retrieve (and send) BSTR in this situation? Meaning, how to get this code work without Autoit crashing ? $aCall = $oOneNote.GetHierarchy("", 3, "") ;$sHierarchy = $aCall[3] ;ConsoleWrite("Hierarchy = " & $sHierarchy & @CRLF) Edited December 12, 2017 by timmalos Link to comment Share on other sites More sharing options...
qsek Posted August 29, 2019 Share Posted August 29, 2019 I know this is 2 years old but maybe this can still help you. Global $OneNote = ObjCreate("OneNote.Application.12") $string = "" $OneNote.GetHierarchy("", 3, $string); ConsoleWrite($string & @CRLF) You dont need AutoitObject UDF. However this works only for OneNote 2010. It selects the Microsoft OneNote 12.0 Type Lib specifically, which functions (like GetHierarchy) should work like intended (for OneNote 2010) But im having a really hard time to get it working in a system with OneNote 2016 installed. The Object Is created, but calling functions yields "The requested action with this object has failed." Both the 12.0 and 15.0 Type Libs are present. Maybe you have any clue whats the problem? What OneNote version are you working on? Teamspeak 3 User Viewer - Quick and functional TS3 Query script, which shows online users.Cached Screenshot Deleter - Deletes older Fraps Screenshots if they exceed a specified limit.Unresolved Topics:Intercept and modify dragdrop text behaviour in scite Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now