GetRunningObjectTable(0, &rot);The rot object contains a method to get an enumerator to enumerate the monikers to the running objects:
rot->EnumRunning(&enumMoniker);When Navision is running you'll see three instances with different names but it seems it doesn't matter which one you choose. Weird. You can find the displayname of the moniker by calling:
CreateBindCtx(0, &bc); moniker->GetDisplayName(bc, 0, &displayname);When you've choosen the moniker which you would like to use you can get the object.
rot->GetObject(moniker, &iunknown);This object has multiple interfaces:
[object, uuid (50000004-0000-1000-0001-0000836BD2D2)] interface INSObjectDesigner : IUnknown { HRESULT ReadObject([in] int objectType, [in] int objectId, [in] IStream *destination); HRESULT ReadObjects([in] LPOLESTR filter, [in] IStream *destination); HRESULT WriteObjects([in] IStream *source); HRESULT CompileObject([in] int objectType, [in] int objectId); HRESULT CompileObjects([in] LPOLESTR filter); HRESULT GetServerName([out] LPOLESTR *serverName); HRESULT GetDatabaseName([out] LPOLESTR *databaseName); HRESULT GetServerType([out] int *serverType); HRESULT GetCSIDEVersion([out] LPOLESTR *csideVersion); HRESULT GetApplicationVersion([out] LPOLESTR *applicationVersion); HRESULT GetCompanyName([out] LPOLESTR *companyName); }
INSObjectDesignerPtr insobjectdesigner; iunknown->QueryInterface(IID_INSObjectDesigner, (void**)&insobjectdesigner);
CreateStreamOnHGlobal(NULL, TRUE, &strm); insobjectdesigner->ReadObject(5, 1, strm); LARGE_INTEGER li = {0}; strm->Seek(li, STREAM_SEEK_SET, 0); strm->Read(buf, 100, &cbRead);
Comments
I've found a great tool called NDR INSPECTOR (by Vito Plantamura) which extracts the definition of the navision interfaces!
It can be downloaded here: http://www.vitoplantamura.com/index.asp ... rinspector
This is the IDL as far as I know it:
notes:
- GetForm returns a null pointer in form
- I haven't made an implementation of INSCallbackEnum yet so I couldn't test it
- INSHyperlink->proc4 returns a large (constant) number, I don't know what it is.
- The first and last parameter of INSAppBase are empty in my current setup
Soren
http://gotcal.com
A new concept in the whole discussion is the MarshalAs directive, which permits the use of complex data types within COM Interop.
Note also that the declaration of the interfaces is sufficient. We don't have to declare any COM coclasses because we are not creating new objects (NAV client must be already running).
Here is a (minimal) sample C#-code-snippet which retrieves the value of field no. 2 (Name) for the open Customer Card. Note that the customer card has to be opened and should be activated. The RunningObjectTable.GetRunnigCOMObjectByName function can be found here:
http://www.mycsharp.de/wbb2/thread.php?threadid=36340
During my tests, I had a problem that every now and then the customer card was not the active form. In this case IF == null is returned and you will encounter a System.NullReferenceExeption in the above code. To get the customer card the active form, just switch to the NAV client and move the customer card around (do not work in full screen modus) in order to make it the active form (it is not sufficient to just click into the card form).
INSApplication.GetForm returned only 0 for me, did you do something special in Navision (open a certain form or something like that?)
The following code worked for me in all cases. All you have to do is to start NAV Client and open a company (not even a form). With the INSHyperlink.Open method you can open an arbitrary form showing an arbitrary record (just create a Link for an open form with the Edit, "Copy Link" from the main menu of NAV, paste this link into a texteditor and customize it - for some reason the direct paste into the visual studio editor doesn't work for me).
With that method you can draw arbitrary data from NAV Client (supposed you have got a form in NAV Client).
It would be nice however, if there would be a possibility to close the form again after use... - as a workaround one can use OnTimer trigger with Currform.Close to close the form automatically after 1 sec, e. g.
Note that the data retrieved with the INSRec.GetFieldValue method can be manipulated within the form. It seems to be that the Rec variable of the form is used to get the field data. But the fields of Rec can be set manually in the OnAfterGetCurrRecord trigger of the form, e. g.
So unfortunately this method cannot be used to retrieve for example the license no. of the NAV license from the virtual "License Information" table 2000000040 in a safe way...
I'm trying to make an alternative object designer.
Anyone knows how to implement the new/design/run buttons maybe using one of these interfaces? If we would now that we could build a much better object designer with many more functions.
MVP - Dynamics NAV
My BLOG
NAVERTICA a.s.
The INSHyperlink interface Open returns an integer value.
What happens if you pass this returned value into the Proc4 function of the same inteface? The first parameter also accepts an integer.
Concerning the COM Interface for objects, etc. I would be mainly interested in a way to retrieve the actual NAV license no. from a running client (like the info that is displayed, if one clicks Extra/License Information), because this would allow something like a copy protection for addon components like COM automation servers, or OCXs, etc.) - this information cannot in general be found in the license file of the client, because the NAV license file (fin.flf) need only to be on the NAV server or in the SQL database, respectively, so the information can only be retrieved from a running NAV client process...
The system will connect to a kind of 'source safe' environment. Will be much more advanced then this. And what to think of extra long version list codes?? A lot more features then you can currently imagine.
I gues the SERIALNUMBER C/AL instruction isn't good enough . Maybe C/Front has a function? The function might be hidden somewhere in those interfaces.
Maybe it is a good idea to create a DLL that supports the interface we have now with just the Proc functions, put it in downloads of Mibuso so everyone interested can start testing those functions and see what they do and post there findings in the download topic?? With all gathered knowledge we can create a more programmer friendly DLL. Who knows what extra possibilities come available.
Has someone created something like this already??
so proc4 could be renamed to GetNavWindow, GetNavWindowHandle or something like that.
by the way, great investigation!
Nice work. :thumbsup: =D> I already had my own function for this, although i have had an ocasion where this function did not prove relaible. So i think i'm going to replace the function with this one in the future.
More functions please !!
proc8 of INSAppBase is actually EnumTables.
it takes as parameters a callback enumerator and a table ID. if table ID is 0, all Navision tables are enumerated, including the virtual ones.
the function invokes proc6 (I named it "NextTable") with 1st parameter - the table ID, and 2nd - the table name.
more news are on the way abt INSTable's enumeration methods.
if languageID is 0 it uses the default Nav language.
the function invokes proc7 of INSCallbackEnum (I named it "NextFieldDef") for each table field with params: a=fieldID, b=fieldName, c=fieldCaption, d=dataType, e=dataLength, f=1.
2. proc9 of INSTable is "EnumRecords(callbackEnum)"
the function invokes proc3 of INSCallbackEnum ("NextRecord") for each table record with params: a=theRecord
3. proc8 of INSTable - invokes nothing, but as to me should invoke proc5 of INSCallbackEnum. a mistery. still investigating...
4. proc5 of INSRec is "EnumFieldValues(callbackEnum)"
the function invokes proc4 of INSCallbackEnum ("NextFieldValue") for each record field with params: a=fieldID, b=fieldValue, c=dataType.
I wished i had more time to be able to dig into this
Just found this really interesting thread, thanks all for posting all this information! I was wondering if it is possible to invoke some of these same methods from inside Navision with automation objects? I tried referencing rotaccess.dll and invoking GetObjectByMoniker but I can't find any suitable parameter for that call that would actually work.
I'm not sure if that's even the right way to access this problem, but hey, you got to start somewhere. So, any hints would be appreciated!
Regards,
rotoflex
How's your project progressing?
http://www.mibuso.com/dlinfo.asp?FileID=1193
As you can see, you can enumerate records from any table, filter them, insert/modify/delete them. Even you can subscribe for some events from the client. I just didn't find the way to work with the INSMenuButton (never retrieved it successfully), INSMenuButtonEvents (because I never got INSMenuButton), INSHook (do not know where to take the ConnectionPoint supporting it).
MVP - Dynamics NAV
My BLOG
NAVERTICA a.s.
I traded my sanity for a railgun
MVP - Dynamics NAV
My BLOG
NAVERTICA a.s.
On a somewhat related note one of my other projects is a Navision Object Parser that will parse any Navision text object file into a .Net class instance. Currently properties are only parsed as a text blob but I am adding contextual parsing of all the property types such that you should be able to do something like the following to retrieve the spanish caption for an instance of the customer table: The project includes a serializer for writing to/from the Navision text object format. All classes are also serializable using the binary and xml serializers in the .Net framework. I will be open sourcing my parser (probably under Apache 2 license) once I have it finished and cleaned up. I'm shooting for a release in second quarter of next year.
I traded my sanity for a railgun
MVP - Dynamics NAV
My BLOG
NAVERTICA a.s.
I started with visual studio but after various frustrations went with a third party editor/parser framework which I have built upon. I actually have a working editor with auto-formatting, syntax highlighting and various code completion features as well as "Go To Definition" support. I'm still a way from having a finished product. My editor project is the one piece I will not be open sourcing, partly because I hope to make a little profit from all the work I have put into it and also because I'm using licensed components within it. I will offer an express (free) edition with most of the features available. Things like refactoring and some other tools will be available in a professional (pay) version. I am looking for more testers right now if you are interested.
My goal is to release most of the projects I'm building my editor upon as open source, so that other people in the community can create some very cool tools. I figure if someone uses my own tools to build a better editor than my own, then I just need to work that much harder
I traded my sanity for a railgun
I was under the mistaken assumption that one of the methods would return an instance of an INSCallbackEnum, but apparently not. Where do you get this instance from?
After looking at it a bit I'm guessing I create a new class that implements the INSCallbackEnum and then pass that instance into the methods that take one, and they in turn call the appropriate callback methods on my class?
I traded my sanity for a railgun
MVP - Dynamics NAV
My BLOG
NAVERTICA a.s.
Something else worth metioning is that while EnumTables does return some of the virtual tables, it does not return all of them. Strangely enough, however, you can still use GetTable() to retrieve an instance to any of those tables :-k . I'll continue to post further discoveries as I build my wrapper.
I traded my sanity for a railgun