Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / .NET Framework / Interop / August 2006

Tip: Looking for answers? Try searching our database.

Array Marshalling different between VB6 & Script to an interop C#

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
KirkViehland - 29 Aug 2006 06:36 GMT
I have a very simple C# library that demonstrates a problem that I am trying
to figure out right now. I could post a full example, if this forum allowed
posting attachments.

Anyway, like I said, I have a very simple C# class...

namespace ScriptMarshalTester
{
   using System;
   using System.Reflection;
   using System.Runtime.InteropServices;

   [ComVisible(true)]
   [Guid("AD07359C-D5D6-4A22-89D7-7DA80D3C4973")]
   [ProgId("ScriptMarshalTester.StringTester")]
   [ClassInterface(ClassInterfaceType.None)]
   public class StringTester
     : ScriptMarshalTester.IStringTester
   {
       public StringTester(){}

       public void TestString
         (
           [In, MarshalAs(UnmanagedType.BStr)]
           string value
         )
       {
           Console.WriteLine( "\r\n" + MethodInfo.GetCurrentMethod().Name +
"\r\n" );
           Console.WriteLine( new String('-',20) );
           Console.WriteLine( "value=" + value );
       }

       public void TestStringArray
         (
           [MarshalAs(UnmanagedType.SafeArray,
               SafeArraySubType=VarEnum.VT_BSTR)]
           ref string[] values
         )
       {
           Console.WriteLine( "\r\n" + MethodInfo.GetCurrentMethod().Name +
"\r\n" );
           Console.WriteLine( new String('-',20) );

           for ( int i = 0; i < values.Length; i++ )
               Console.WriteLine( "values[" + i.ToString() + "]=" +
values[i]);
       }

       public void TestStringAndStringArray
         (
           [In, MarshalAs(UnmanagedType.BStr)]
           string value,

           [In, Out, MarshalAs(UnmanagedType.SafeArray,
               SafeArraySubType=VarEnum.VT_BSTR)]
           ref string[] values
         )
       {
           Console.WriteLine( "\r\n" + MethodInfo.GetCurrentMethod().Name +
"\r\n" );
           Console.WriteLine( new String('-',20) );

           Console.WriteLine( "value=" + value );

           for ( int i = 0; i < values.Length; i++ )
               Console.WriteLine( "values[" + i.ToString() + "]=" +
values[i]);
       }
   }
}

And its interface definition is as follows...

namespace ScriptMarshalTester
{
   using System;
   using System.Runtime.InteropServices;
   
   [ComVisible(true)]
   [Guid("10F83921-A0EA-4270-8574-5D7577EB72EA")]
   [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
   public interface IStringTester
   {
       [DispId(1)]        
       void TestString
         (
           [In, MarshalAs(UnmanagedType.BStr)]
           string value
         );

       [DispId(2)]
       void TestStringArray
         (
           [In, MarshalAs(UnmanagedType.SafeArray,
               SafeArraySubType=VarEnum.VT_BSTR)]
           ref string[] values
         );

       [DispId(3)]
       void TestStringAndStringArray
         (
           [In, MarshalAs(UnmanagedType.BStr)]
           string value,
           
           [In, MarshalAs(UnmanagedType.SafeArray,
               SafeArraySubType=VarEnum.VT_BSTR)]
           ref string[] values
         );
   }
}

Now, if I compile this and try to execute it with the following VB6 code
everything works as expected, ** Meaning no exceptions are thrown **. Here is
some sample VB6 code. You will notice in this snippet that the original
library has been compiled and registered with COM as ScriptMarshalTester. The
ProgId for the class that we will be interacting with is
ScriptMarshalTester.StringTester. Here is the VB6 subroutine...

Private Sub TestStrings()
   Dim tester          As ScriptMarshalTester.StringTester
   Dim testValue       As String
   Dim testValues()    As String
   
   ReDim testValues(1)
   
   Set tester = New ScriptMarshalTester.StringTester
   
   testValue = "Hello World"
   testValues(0) = "Hello"
   testValues(1) = "World"
   
   Call tester.TestString(testValue)
   Call tester.TestStringArray(testValues())
   Call tester.TestStringAndStringArray(testValue, testValues())
End Sub

At this point, everything behaves as expected. Once we introduce the script
client into the mix things start to take a quick downhill. I have 2 script
clients which both exhibit the same behavior, a VBScript client and a JScript
client. Here is the same method as the TestStrings method above in VBScript...

private sub TestStrings()
       
   dim tester
   dim testValue
   dim testValues()
       
   ReDim testValues(1)
       
   set tester = WSCript.CreateObject("ScriptMarshalTester.StringTester")
   testValue = "Hello World"
   testValues(0) = "Hello"
   testValues(1) = "World"
       
   call tester.TestString(testValue)
   call tester.TestStringArray(testValues)
   call tester.TestStringAndStringArray(testValue,testValues)
           
end sub

And also in the following JScript...

function testStrings()
{
   var tester     = new ActiveXObject("ScriptMarshalTester.StringTester");  
     
   var testValue  = new String("Hello World");
   var testValues = new Array();

   testValues[0]  = "Hello";
   testValues[1]  = "World";
   
   try
   {
       tester.TestString(testValue);
       tester.TestStringArray
         (
           CreateSafeArray(testValues)
         );
       tester.TestStringAndStringArray
         (
           testValue,
           CreateSafeArray(testValues)
         );
   }
   catch(e)
   {
       WScript.StdOut.WriteLine(e);
       WScript.StdOut.WriteLine(e.number & 0xFFFF);
       WScript.StdOut.WriteLine(e.description);
   }
}

// Converts a JScript Array to a SAFEARRAY
function CreateSafeArray( jsArray )
{
   var dictionary = new ActiveXObject("Scripting.Dictionary");

   for ( var i = 0; i < jsArray.length; i++ )
       dictionary.add( i, jsArray[i] );

   return(new VBArray(dictionary.Items()));
}

The problem surfaces in that the tester.TestStringArray method gets an
"Invalid procedure call or argument" while trying to pass the array of
strings to the TestStringArray method. Likewise, if the same script is coded
in JScript and the argument is converted to a SAFEARRAY the executing script
gets an "Invalid Procedure call or argument" while trying to marshall the
array parameter to the managed code.

Unless I have missed something in the documentation, I think that I have
declared these interfaces correctly. I know that it is something very simple,
but I can't seem to make this work. One requirement however is that the same
.Net component should be useable from both VB6 as well as script components.

Any help would be appreciated.

Thanks,
Kirk A. Viehland
TDC - 29 Aug 2006 13:36 GMT
I think you need to be declaring a Variant which contains an array or
strings, as opposed to an array of strings.

The scripts require all data types to be Variants.

Tom

> I have a very simple C# library that demonstrates a problem that I am trying
> to figure out right now. I could post a full example, if this forum allowed
[quoted text clipped - 217 lines]
> Thanks,
> Kirk A. Viehland

Rate this thread:







Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.