![]() |
#1 |
Участник
|
With NAV 2009 it has been made available to the users a messaging system based on Notes / MyNotes page parts. Note records are stored as BLOBs inside table 2000000068 Record Link. It is known that you cannot handle Notes using normal C/AL code and, in particular, correctly stream in and out the content of those BLOB fields.
![]() In this blog you will find the source code in order to implement a COM Stream Wrapper object to write and read Notes. You may use this COM object to generate and handle Notes when needed without being bound to Notes and MyNotes system part. This object may give you much more flexibility in your RTC code development. NOTE: the Stream Wrapper is working correctly (writing) only when code is executed in a RTC based environment. It will give unpredictable and wrong results if executed using Classic Client. If you want to know more about Notes you can refer to MSDN link: Touring the RoleTailored Client Pages http://msdn.microsoft.com/en-us/library/dd301400.aspx My ingredients:
A. Create a New Class Project
// This code released under the terms of the // Microsoft Public License (MS-PL, http://opensource.org/licenses/ms-pl.html.) using System; using System.IO; using System.Collections.Generic; using System.Text; using System.Runtime.InteropServices; using System.Runtime.InteropServices.ComTypes; namespace StreamWrp { [ComVisible(true)] [Guid("2F870D88-FEA5-4F27-81FB-6775D7436E52")] public interface IStreamHelper { string Text { get; set; } int Transform(int encodeRead, int encodeWrite, IStream reader, IStream writter); } [ClassInterface(ClassInterfaceType.None)] [Guid("B4E5F8F4-5225-4B3A-998A-B82A8A7C6B8E")] public class StreamHelper : IStreamHelper { public string Text { get { throw new Exception("The method or operation is not implemented."); } set { throw new Exception("The method or operation is not implemented."); } } public int Transform(int encodeRead, int encodeWrite, IStream reader, IStream writter) { byte[] pv = new byte[4098]; int read = 0; unsafe { IntPtr pcbRead = new IntPtr(&read); reader.Read(pv, pv.Length, pcbRead); } MemoryStream innerStream = new MemoryStream(pv, 0, read); string note = String.Empty; if (innerStream.Length != 0) { //Select InS encoding and ReadChars Ins Encoding inEncode; if (encodeRead != 0) { inEncode = Encoding.GetEncoding(encodeRead); using (BinaryReader innerreader = new BinaryReader(innerStream, inEncode)) { note = new string(innerreader.ReadChars((int)innerStream.Length)); innerreader.Close(); } } else { using (BinaryReader innerreader = new BinaryReader(innerStream)) { note = new string(innerreader.ReadChars((int)innerStream.Length)); innerreader.Close(); } } MemoryStream stream2 = new MemoryStream(); //Select OutS Encoding and Write OutS Encoding outEncode; if (encodeWrite != 0) { outEncode = Encoding.GetEncoding(encodeWrite); using (BinaryWriter writer = new BinaryWriter(stream2, outEncode)) { writer.Write((string)note); writer.Close(); pv = stream2.ToArray(); } } else { using (BinaryWriter writer = new BinaryWriter(stream2)) { writer.Write((string)note); writer.Close(); pv = stream2.ToArray(); } } unsafe { IntPtr pcbWrite = new IntPtr(&read); writter.Write(pv, pv.Length, pcbWrite); } } return read; } } } D. Strong sign and build your COM object
This is just a Warning about a substitution from IStream to IUnknown. There is no problem with this warning message. The compilation is successful. E. Place DLLs into a folder and Register them
(hit return) NOTE: there can be some warning messages (type) gacutil /I StreamWrp.dll (hit return) ![]() Develop the C/AL code A. Develop the C/AL code to WRITE and READ Notes in RTC environments How this COM Wrapper works? It accepts a Stream and returns a modified Stream. Nothing more. It needs to be feed up with 2 encoding values depending if the Wrapper is used to write or read Notes. A useful example of encoding (overall if there are special characters that need to be handled, e.g. double S, umlaut, etc.) can be found at this link: http://msdn.microsoft.com/en-us/libr...scodepage.aspx In this example, I am using a DEU standard database, therefore I am using IBM437 CodePage to correctly encode/decode the stream (note that IBM437 is also part of the Windows CodePage 1252). The 2 following Codeunits attached in TXT format are used to Write and Read Notes. NOTE: in order to let this example works you must have, at least, 1 note created from RTC (it merely use a copy from the last record, just as example). This is the C/AL code snippet to WRITE Notes using RTC ... // Copyright © Microsoft Corporation. All Rights Reserved. // This code released under the terms of the // Microsoft Public License (MS-PL, http://opensource.org/licenses/ms-pl.html.) IF ISSERVICETIER THEN BEGIN CLEAR(NoteText); // Add special chars NoteText.ADDTEXT(STRSUBSTNO(Text1000000001,USERID,TODAY,TIME) + ' - ìèòàù - Österreich - '); // Browse country table and create the Note by pasting Code and Name into the NoteText CountryRec.RESET; IF CountryRec.FINDFIRST THEN REPEAT NoteText.ADDTEXT(' ** Country ' + FORMAT(CountryRec.Code)+ ' - ' + FORMAT(CountryRec.Name)); UNTIL CountryRec.NEXT = 0; // Find the last Record Link to retrieve the ID RecordLink.RESET; RecordLink.FINDLAST; LinkID := RecordLink."Link ID"; // Create ID+1 Record Link with empty Note (copy the link above) LinkID := LinkID + 1; RecordLink2.INIT; RecordLink2."Link ID" := LinkID; RecordLink2."Record ID" := RecordLink."Record ID"; RecordLink2.URL1 :=RecordLink.URL1; RecordLink2.Type := RecordLink2.Type :: Note; RecordLink2.Created := CURRENTDATETIME; RecordLink2."User ID" := USERID; RecordLink2.Company := COMPANYNAME; RecordLink2.Notify := TRUE; // Stream the NoteText inside the note RecordLink2.CALCFIELDS(Note); RecordLink2.Note.CREATEOUTSTREAM(OutS); NoteText.WRITE(OutS); RecordLink2."To User ID" := USERID; RecordLink2.INSERT; // Find the record inserted in order to 'adjust' it with the StreamWrapper RecordLink2.INIT; RecordLink2."Link ID" := LinkID; RecordLink2.FIND('='); RecordLink2.CALCFIELDS(Note); RecordLink2.Note.CREATEINSTREAM(InS); RecordLink2.Note.CREATEOUTSTREAM(OutS); // Let the COM StreamWrapper transform the Blob correctly EncodeIn := 437; //CodePage IBM437 EncodeOut := 0; //No CodePage in output IF ISCLEAR(Transform) THEN CREATE(Transform); InSVar := InS; OutSVar := OutS; Transform.Transform(EncodeIn, EncodeOut, InSVar, OutSVar); RecordLink2.MODIFY(); END; MESSAGE('WRITE : DONE'); ... And this is the C/AL code snippet to READ Notes using RTC ... IF ISSERVICETIER THEN BEGIN CLEAR(TempBlobRec); CLEAR(NoteText); // Find the right Record Link RecordLink.RESET; RecordLink.FINDLAST; IF RecordLink.Note.HASVALUE THEN BEGIN RecordLink.CALCFIELDS(Note); RecordLink.Note.CREATEINSTREAM(InS); //Note --> InS // Init a Temp Blob IF TempBlobRec.GET(10000) THEN TempBlobRec.DELETE; TempBlobRec.INIT; TempBlobRec."Primay Key" := 10000; TempBlobRec.INSERT; // Stream the 'modified back' Note onto this Blob field TempBlobRec.GET(10000); TempBlobRec.CALCFIELDS(Blob); TempBlobRec.Blob.CREATEOUTSTREAM(OutS); // Let the COM StreamWrapper transform the Blob correctly EncodeIn := 0; // Read raw data from BLOB EncodeOut := 437; // Use CodePage IBM437 in output IF ISCLEAR(Transform) THEN CREATE(Transform); InSVar := InS; OutSVar := OutS; Transform.Transform(EncodeIn, EncodeOut, InSVar, OutSVar); TempBlobRec.MODIFY; // Get the modified Blob rec and read it TempBlobRec.GET(10000); TempBlobRec.CALCFIELDS(Blob); TempBlobRec.Blob.CREATEINSTREAM(InS2); // Algorithm to READ the Blob output IsFirstTxtLine := TRUE; WHILE NOT (InS2.EOS()) DO BEGIN Int:= InS2.READ(Txt); IF Int <> 0 THEN BEGIN IF IsFirstTxtLine THEN BEGIN LengthStr := STRLEN(Txt); CASE LengthStr OF 1..126 : Txt := COPYSTR(Txt,3,STRLEN(Txt)); 127 : Txt := COPYSTR(Txt,4,STRLEN(Txt)); ELSE Txt := COPYSTR(Txt,5,STRLEN(Txt)); END; IsFirstTxtLine := FALSE; END; MESSAGE(Txt); END; CLEAR(Txt); CLEAR(Int); END; END; END; MESSAGE('READ - DONE'); ... These postings are provided "AS IS" with no warranties and confer no rights. You assume all risk for your use. Duilio Tacconi (dtacconi) Microsoft Dynamics Italy Microsoft Customer Service and Support (CSS) EMEA A special thanks to Jorge Alberto Torres - DK-MBS NAV Development Источник: http://feedproxy.google.com/~r/Micro...m-wrapper.aspx
__________________
Расскажите о новых и интересных блогах по Microsoft Dynamics, напишите личное сообщение администратору. |
|