mibuso.com

Microsoft Business Solutions online community
It is currently Tue Sep 07, 2010 10:47 am

All times are UTC + 1 hour [ DST ]




Post new topic Reply to topic  [ 37 posts ]  Go to page 1, 2, 3  Next
Author Message
 Post subject: NAV Text Object Handler
PostPosted: Sat Sep 27, 2008 4:06 pm 
Offline
Site Admin

Joined: Sun Nov 07, 1999 8:01 am
Posts: 1342
Location: Edegem, Belgium
Country: Belgium (be)
NAV Text Object Handler
This download is a poorly written (I don't know C# at all) DLL file that exposes Søren's ability to Import From / Export To text files directly to NAV via Automation.

This would absolutely not be possible but for the wonderful work of Søren Nielsen, provided freely to the community on his blog, http://www.gotcal.com.

See the included example FOB for usage. Very bare-bones, but anyone who wants this can certainly make use of it.

To make use of this DLL (which is a .NET DLL), you'll have to use the included installation batch file, which relies on 'regasm' from the v2.0.050727 .NET Framework, typically located in C:\Windows\Microsoft.NET\Framework. You *must* run this in the same directory as the NAV Client or you'll get errors when attempting to use.

http://www.mibuso.com/dlinfo.asp?FileID=1012

Discuss this download here.


Top
 Profile  
 
 Post subject: Re: NAV Text Object Handler
PostPosted: Sat Sep 27, 2008 6:33 pm 
Offline

Joined: Wed Jan 02, 2002 8:01 am
Posts: 58
Location: NY, USA
Country: United States (us)
I'll be happy to discuss any details or provide source. I'm hoping folks can get really creative with this in the area of version control... whether linking to VCS or building an 'in NAV' VCS.

As for the code that accesses the NAV object tables? All came from http://gotcal.com/ - particularly this post. Søren explains how he managed it using the Running Object Table in this post. Thanks Søren!

Also thanks to Luc for putting up with a small array of emails trying to make it portable and safe to upload



Edit: I should clarify: I've tested this only with 5.0 and 5.0 SP1. I cannot answer to it working for earlier versions, and I'll try to test it with 2009 sometime later this week.


Top
 Profile E-mail WWW  
 
 Post subject: Re: NAV Text Object Handler
PostPosted: Sun Sep 28, 2008 8:21 am 
Offline
MVP Microsoft Dynamics NAV
mibuso.conference Attendee

Joined: Thu Oct 16, 2003 8:50 am
Posts: 10404
Location: Brno
Country: Czech Republic (cz)
Thanks for that. I never had enough time to make something like that even when I read the blog few weeks ago. I will try when I had time.

For now one question: is it working correctly when I have more NAV clients opened on my PC?

_________________
Kamil Sacek
MVP - Dynamics NAV
My BLOG


Top
 Profile E-mail WWW  
 
 Post subject: Re: NAV Text Object Handler
PostPosted: Sun Sep 28, 2008 6:46 pm 
Offline

Joined: Fri Nov 17, 2000 8:01 am
Posts: 22
Location: California, USA
Country: United States (us)
Right now it will grab the first NAV instance from the Running Object Table, so no it does not support multiple running NAV versions at the same time.

I have an example for a all object exporter that queries the user like the Developers Toolkit does, so you can select what NAV client to export objects from (check the blog during this coming week).

Another interesting thing, is it allows you to extract objects to text without the use of a developer license! For importing though it honors the permissions, and throws a:
"HRESULT = 0x8004005 : You do not have permission to run the 'File, Import, Text' System"

But it will give end users access to do some object comparison, and version management. When we get a tool together for it.


Top
 Profile E-mail WWW  
 
 Post subject: Re: NAV Text Object Handler
PostPosted: Tue Sep 30, 2008 5:29 pm 
Offline

Joined: Fri Dec 01, 2006 12:01 pm
Posts: 111
Location: London
Country: United Kingdom (uk)
Kine,
Based on the code of Søren Nielsen I've modified the functions to input also the instance of Navision to read so you'll be able to select the database and the company when you are calling the export function.
If you are interested I can explain in more detail what I did.

Søren,
Thank you so much again, Do you know if it would be possible to extract objects with NAS?
I'm trying with no success even if I leave a Navision Client opened...
Any Idea?

Thanks :wink:

_________________
Why don't you try my compare tool?
http://www.mibuso.com/dlinfo.asp?FileID=1123


Top
 Profile  
 
 Post subject: Re: NAV Text Object Handler
PostPosted: Tue Sep 30, 2008 7:36 pm 
Offline

Joined: Wed Jan 02, 2002 8:01 am
Posts: 58
Location: NY, USA
Country: United States (us)
Unfortunately, I've been told about and discovered a particularly challenging item: In the text export, the dll writes not the object name in the first line! It writes the object caption.

So, for example, if you have Form 50000 - Something Card and you set the form's caption to "My Awesome Form", the first line of the file would read:

Code: Select all
OBJECT Form 50000 My Awesome Form



I'm not sure if Søren will be able to help that, but I might able able to re-write the Export routine in the DLL to do a little post-processing fix to that item.

The other issue (thanks Matthias!) is that it uses local language strings, like german 'Ja' instead of 'Yes'. I might be able to do something clever with .stx files, but likely not anytime this week.


Top
 Profile E-mail WWW  
 
 Post subject: Re: NAV Text Object Handler
PostPosted: Thu Oct 02, 2008 1:20 pm 
Offline

Joined: Wed May 14, 2008 11:51 am
Posts: 4
Location: Münster
Country: Germany (de)
no problem JDVyska ;)

a little workaround: use this DLL with a Report and change the language... but this is not the fine way.

if there is an update, i will be happy to get this information :)


Top
 Profile  
 
 Post subject: Re: NAV Text Object Handler
PostPosted: Thu Oct 02, 2008 6:42 pm 
Offline

Joined: Fri Feb 28, 2003 5:53 pm
Posts: 264
Location: Dordrecht
Country: Netherlands (nl)
Hello!

Thanks for the great idea! Good to see that we finally we can extract txt files automatically from Navision. I have been searching for this sollution. I knew there had to be a way because the developer tool was doing the same thing as well! Great job for everyone involved! =D>

So with this lead you gave me i dove into the problem a bit more. I rewrote some functions to share with you all; maybe you can improve your own software with it.

I added a companyname paramter to the objectdesinger class constructor. Since you can get the companyname with the COMPANYNAME instruction in Navision, this is the best way you can automatically select the database from where the DLL call is made. This is 100% foolproof unless you have multiple databases open with the same database name! (wich may occur maybe in upgrade projects)

Hopefully not too many bugs; i don't have a lot of time though this was too interesting to leave for weeks :P

ObjectDesigner class constructor rewrite:

Code: Select all
        public ObjectDesigner(String CompanyName)
        {
            Guid guid = new Guid("50000004-0000-1000-0001-0000836BD2D2");
            Hashtable runningObjects = GetActiveObjectList(DefaultMonikerName);

            foreach (DictionaryEntry de in runningObjects)
            {
                string progId = de.Key.ToString();
                if (progId.IndexOf("{") != -1)
                {
                    // Convert a class id into a friendly prog Id
                    progId = ConvertClassIdToProgId(de.Key.ToString());
                }
               
                if (progId.EndsWith(CompanyName))
                {
                    object getObj = GetActiveObject(progId);
                    if (getObj != null)
                    {
                        this._objectDesigner = getObj as IObjectDesigner;
                        break;
                    }
                    else
                    {
                        throw new Exception("Could not connect to Dynamics NAV " + progId);
                    }
                }
            }

            if (this._objectDesigner == null)
            {
                throw new Exception("Could not find a Dynamics NAV instance with companyname " + CompanyName );
            }
        }


And the wrapper class wich is exposed to COM (Navision) contains this function:

Code: Select all
        public void GetNavisionObject(int ObjectType, int ObjectID, string ObjectName, string CompanyName, string FileName)
        {
            //Codeunit = 5,
            //Dataport = 4,
            //Form = 2,
            //Report = 3,
            //Table = 1
            if (System.IO.File.Exists(FileName))
                System.IO.File.Delete(FileName);

            System.IO.FileStream fs;           
            System.IO.MemoryStream ob;
            ObjectDesigner od = new ObjectDesigner(CompanyName);
            ob = od.ReadObjectToStream((NavObjectType)ObjectType, ObjectID);

            fs = new System.IO.FileStream(FileName, System.IO.FileMode.OpenOrCreate);
            ob.WriteTo(fs);
           
            fs.Close();
            fs.Dispose();
            fs = null;

            ob.Dispose();
            ob = null;

            od = null;
        }


I bet it is not necesarry to explain what parameters should be put into the function from Navision ;)

_________________
In a world without Borders or Fences, who needs Windows and Gates?


Top
 Profile E-mail  
 
 Post subject: Re: NAV Text Object Handler
PostPosted: Fri Oct 03, 2008 10:29 am 
Offline

Joined: Fri Dec 01, 2006 12:01 pm
Posts: 111
Location: London
Country: United Kingdom (uk)
Hello Hello!
I've also added as parameter the database name so you will be able from Navision to select the correct database and company (we could also add the SQL server).
Using the Database table you'll know the databse name if you are in SQL.
Modifing the function GetActiveObject you can return directly the object that you want without looping them later.

In the test of the GetActiveObject I've added the following code and then removed the for loop in the ObjectDesigner.

Code: Select all
                    if (displayName.IndexOf(dbname) != -1 &&
                        displayName.IndexOf(dbcompanyname) != -1)

_________________
Why don't you try my compare tool?
http://www.mibuso.com/dlinfo.asp?FileID=1123


Top
 Profile  
 
 Post subject: Re: NAV Text Object Handler
PostPosted: Fri Oct 03, 2008 5:33 pm 
Offline

Joined: Fri Feb 28, 2003 5:53 pm
Posts: 264
Location: Dordrecht
Country: Netherlands (nl)
Hello me again!

Pureheart i don't think your code would be convinient in our case we commonly use local copies (just fdb file format) on our harddisk. I gues you won't be able to retrieve databasename from these navision instances? Although thanks for the input.

I have been working on the object caption / object name and yes/no local issue and came up with the following sollution wich is 99% secure. Only when you create a constant variable wich uses simular characters as the replaced strings the code might replace too much. I gues strings like '=Ja }' are not used in constant variable. ;)

I replaced the ToMemoryStream function in the objectdesginer class with the following code. This code will create importable object text files for me. It returns an adjusted memorystream. When you save it all dutch and german 'Ja' strings will be converted to 'Yes' and the object caption is replaced with the object name.

Code: Select all
        private unsafe MemoryStream ToMemoryStream(IStream comStream, string ObjectName, string YesValue, string NoValue)
        {
            bool bFirst = true;

            MemoryStream stream = new MemoryStream();
            byte[] pv = new byte[100];
            uint num = 0;
            IntPtr pcbRead = new IntPtr((void*) &num);
            comStream.Seek((long) 0, 0, IntPtr.Zero);

            do
            {
                num = 0;
                comStream.Read(pv, pv.Length, pcbRead);

                // start - this part replaces object caption with object name
                // modify first line of file
                if (bFirst)
                {
                    System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
                    string strFilePart = enc.GetString(pv);

                    char[] splitter = { '\r' };
                    char[] splitter2 = { ' ' };
                   
                    string[] arSplitted = new string[20];
                    string[] arSplitted2 = new string[20];

                    arSplitted = strFilePart.Split(splitter);
                    arSplitted2 = arSplitted[0].Split(splitter2);

                    arSplitted[0] = arSplitted2[0] + " " + arSplitted2[1] + " " + arSplitted2[2] + " " + ObjectName;
                    strFilePart = string.Join("\r", arSplitted);

                    num = (uint)strFilePart.Length;
                    pv = enc.GetBytes(strFilePart);
                    bFirst = false;
                }
                // end - this part replaces object caption with object name

                stream.Write(pv, 0, (int) num);
            }
            while (num > 0);

            // start - this part replaces local yes and no attributes with yes and no ENU captions
            string s = System.Text.Encoding.Default.GetString(stream.GetBuffer(), 0, (int)stream.Length);
            s = s.Replace("=" + YesValue + " }", "=Yes }");
            s = s.Replace("=" + YesValue + ";", "=Yes;");
            s = s.Replace("CONST(" + YesValue + ")", "CONST(Yes)");
            s = s.Replace("FILTER(" + YesValue + ")", "FILTER(Yes)");
            s = s.Replace("=" + NoValue + " }", "=No }");
            s = s.Replace("=" + NoValue + ";", "=No;");
            s = s.Replace("CONST(" + NoValue + ")", "CONST(No)");
            s = s.Replace("FILTER(" + NoValue + ")", "FILTER(No)");

            System.Text.UTF8Encoding utf8Encoding = new System.Text.UTF8Encoding();
            stream = new MemoryStream(utf8Encoding.GetBytes(s)); 
            // end - this part replaces local yes and no attributes with yes and no ENU captions

            return stream;
        }


To provide this function with the proper parameters use this code in navision and create the com wrapper function with these parameters. Should work for all countries like this..!

code exports first 10 of every navision 3.70 objects
Code: Select all
CREATE(lclsAutoNavisionTextExport);                     

lrecObject.RESET;
lrecObject.SETRANGE(ID, 1, 10);
lrecObject.SETRANGE(Type, lrecObject.Type::Table, lrecObject.Type::Codeunit);
IF lrecObject.FIND('-') THEN
BEGIN
  REPEAT
    lclsAutoNavisionTextExport.GetNavisionObject(lrecObject.Type,
                                                 lrecObject.ID,
                                                 lrecObject.Name,
                                                 COMPANYNAME,
                                                 'c:\' + FORMAT(lrecObject.Type) + '_' + FORMAT(lrecObject.ID) + '.txt',
                                                 FORMAT(TRUE),
                                                 FORMAT(FALSE));
  UNTIL lrecObject.NEXT = 0;
END;


Have fun with this ;)

_________________
In a world without Borders or Fences, who needs Windows and Gates?


Top
 Profile E-mail  
 
 Post subject: Re: NAV Text Object Handler
PostPosted: Fri Oct 03, 2008 5:46 pm 
Offline

Joined: Wed Jan 02, 2002 8:01 am
Posts: 58
Location: NY, USA
Country: United States (us)
Interesting...

I'll incorporate some of the proposed changes from this thread into a new release this weekend. I'll probably take jan's clever yes/no fix and make that a separate function call for multilingual uses, just to make the function calls simpler for most folks. Or I may create a codeunit wrapper to ease function calls to require minimal parameters. One of the two (or maybe both, since the target audience is developers, naturally).

Thanks for all the continuing development!


Top
 Profile E-mail WWW  
 
 Post subject: Re: NAV Text Object Handler
PostPosted: Fri Oct 03, 2008 5:51 pm 
Offline

Joined: Fri Dec 01, 2006 12:01 pm
Posts: 111
Location: London
Country: United Kingdom (uk)
janpieter the problem is that if you have more than one fdb opened with the same company name the dll will fail to recognize the correct instance of Navision...Intestead having the db name (could be a setup name...) will allow you to select the correct Instance! :mrgreen:

_________________
Why don't you try my compare tool?
http://www.mibuso.com/dlinfo.asp?FileID=1123


Top
 Profile  
 
 Post subject: Re: NAV Text Object Handler
PostPosted: Sat Oct 04, 2008 4:23 am 
Offline

Joined: Fri Feb 28, 2003 5:53 pm
Posts: 264
Location: Dordrecht
Country: Netherlands (nl)
JDVyska,

If you like i can send you my VS 2005 project. Just PM your e-mail. I forgot to mention that i somehow didn't get your application to work; it just crashes when you call the function.

Since it is not a big deal; i recreated the C# wrapper anyway, because i also like to fool arround with it :mrgreen:

Purheart,

You are absolutely right; when i think it over it is too poor to rely only on companyname. Happens often that you work on a live database and a testdatabase who share the same companyname. And that is waiting for a disaster to happen, where everyone is blindly relying on version management software using this system.

A setup entry is a lot better; though i still find it is not perfect as databases are being copied.

I will keep thinking. I have a way to get the window handles of the current used navision session; maybe i'll find a way to extract preciser information about the used client process using those handles.

_________________
In a world without Borders or Fences, who needs Windows and Gates?


Top
 Profile E-mail  
 
 Post subject: Re: NAV Text Object Handler
PostPosted: Fri Oct 10, 2008 5:41 pm 
Offline

Joined: Fri Feb 28, 2003 5:53 pm
Posts: 264
Location: Dordrecht
Country: Netherlands (nl)
I've worked out a thought about how to get a fool-proof reference to the calling navision client without relying on the company name which isn't unique.

I was thinking of creating a mostly empty dummy object in Navision with an unique code hidden in the tablename just before calling the DLL. In the DLL we can read this object first and compare it's unique value with the value passed into the function from navision. When it matches, then we know we have the current session.

Now i wouldnt rely on the randomizer function to generate an unique number. I don't think the randomizer is random at all. The hwnd definitly is unique i have a VB6 function that successfully retrieves the current window handle. This is a way that can work although i should convert this function to C#.

Maybe there is a better way. Any thoughts?? Any navision command i can use to generate some string that is unique for every session you have opened??

Maybe other thoughts on this issue you may want to share?

_________________
In a world without Borders or Fences, who needs Windows and Gates?


Top
 Profile E-mail  
 
 Post subject: Re: NAV Text Object Handler
PostPosted: Fri Oct 10, 2008 5:49 pm 
Offline

Joined: Wed Jan 02, 2002 8:01 am
Posts: 58
Location: NY, USA
Country: United States (us)
One of my coworkers claims to have figured out a way. He's been going full tilt on that for a while, since he is envisioning ways to massively improve the toolset to help speed upgrades and such.

Hopefully he'll be sharing that to me soon. He also split up the DLL a few ways to make it more well-designed. The COM interface becomes just an interface to the DLL, some other odds and ends like that.


Top
 Profile E-mail WWW  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 37 posts ]  Go to page 1, 2, 3  Next

All times are UTC + 1 hour [ DST ]


Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum


Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group