Looking back at the earlier posts of this blog; i have to admit time really flies by fast. It has been almost a year since my last post on the subject of the GotCAL.CSideInstaller. There have been lots of comments and new threads mainly on www.mibuso.com on the subject, and peoples interesting discoveries.
The main purpose of publishing the code i had, was to share and learn more about it. Here is a great comment, that i think deserves a post by itself from ghuebner:
"@Soren:
There is annother way to handle the IStream interface without the need for unsafe code or MemoryStream. The essential point is, that some methods of IStream use int* (Pointer to int) as parameters. This gives rise to a problem, if one implements those pointers in the managed memory area as IntPtr, e.g. - The trick is to simply define the pointers in the unmanaged memory area (global heap). The following (minimized) code-snipet copies an object to a file:
IntPtr pLEN = Marshal.AllocHGlobal(4);
IStream pOutStm;
CreateStreamOnHGlobal(0, true, out pOutStm);
INSObjectDesigner IOD = (INSObjectDesigner)RunningObjectTable.GetRunningCOMObjectByName("!C/SIDE!navision://client/run?");
int res = IOD.ReadObjects("WHERE(Type=CONST(Table),ID=CONST(3))", pOutStm);
pOutStm.Seek(0, 0, pLEN);
FileStream outputStream = new FileStream(@"C:\Temp\Table3.txt", FileMode.Create, FileAccess.Write);
int cnt, LEN = 4096;
byte[] buffer = new byte[LEN];
do
{
pOutStm.Read(buffer, LEN, pLEN);
cnt = Marshal.ReadInt32(pLEN);
outputStream.Write(buffer, 0, cnt);
}
while (cnt == LEN);
The essential point is the variable pLEN which resides on the (unmanaged) global memory heap."