none
I need to call a .Net C# web service from a VB6 client RRS feed

  • Question

  • I posted this in the ASMX Web services and XML serialization forum .... but someone suggested this forum is better to get this question answered.

    Thanks,

    Sriram Ranganathan

    ************************************************************************************************

    There is this old VB6 program that is running in my company. And there is this new web service in C# (.Net 2.0 using Visual Studio 2005) that I have created. I need that VB6 program to make a call to the web service.

    1. Using the wsdl.exe, I create a proxy file - say, TransparancieCalcEngineProxy.cs, which can be used by clients. When I try to use this proxy file from a .Net client (another C# program, for example), the invocation of the web service works fine.

    2. In order to call the web service from the VB6 program, this is what I am trying to do - I create a .Net project in Visual Studio 2005 of type "C# - Class Library" and I name it "TransparencyCalcEngineConsumerDll". I copy paste the proxy file TransparancieCalcEngineProxy.cs into a folder in this new class library project, so this proxy file is now part of the class library. Note - while there might be people saying "this is not the proper way to do this ... this proper way is .....", I appreciate all comments on this aspect and will learn from them, but my final requirement from this post is still how to invoke this .Net class library from VB6.

    3. I create an interface called Interface1 and a class called Class1 in the project WebServiceConsumerDll. Since this is only a test, the codes are pretty simple and r given below:

    Note - The GUIDs have been taken from some article from the internet but I will generate some GUID later when the code actually works. Though I dno't know exactly, I have read that .Net provides some GUID generator tool and I will use that.

    ***************************************** Interface1.cs START ************************

    using System;

    using System.Runtime.InteropServices;

    namespace TransparencyCalcEngineConsumerDll

    {

    [ComVisible(true), GuidAttribute("137AD71F-4657-4362-B9E4-C6D734F1F530")]

    [InterfaceType(ComInterfaceType.InterfaceIsDual)]

    public interface Interface1

    {

    String function1();

    long function2();

    }

    }

    ***************************************** Interface1.cs END ************************

    ******************************** Class1.cs START ******************************

    using System;

    using System.Runtime.InteropServices;

    namespace TransparencyCalcEngineConsumerDll

    {

    [ComVisible(true), GuidAttribute("89BB4535-5A89-43a0-89C5-19A4697E5C5C")]

    [ProgId("SomeNameProject.SomeNameClass1")]

    [ClassInterface(ClassInterfaceType.None)]

    public class Class1 : Interface1

    {

    public String function1()

    {

    //This is code that is calling the web service proxy .... ignore the logic as the same code works perfectly from a .Net
    // windows client

    WSNamespaceTransparantie.ParameterContainer[] listOfParameters = new WSNamespaceTransparantie.ParameterContainer[3];

    WSNamespaceTransparantie.ParameterContainer paramContainer = new WSNamespaceTransparantie.ParameterContainer();

    paramContainer.ParameterName = WSNamespaceTransparantie.EnumParamNames.ProvisieGrondslag;

    paramContainer.ParameterValue = "2000";

    listOfParameters[0] = paramContainer;

    paramContainer = null;

    paramContainer = new WSNamespaceTransparantie.ParameterContainer();

    paramContainer.ParameterName = WSNamespaceTransparantie.EnumParamNames.Product;

    paramContainer.ParameterValue = "Generic TAS Product 1";

    listOfParameters[1] = paramContainer;

    paramContainer = null;

    paramContainer = new WSNamespaceTransparantie.ParameterContainer();

    paramContainer.ParameterName = WSNamespaceTransparantie.EnumParamNames.SubProduct;

    paramContainer.ParameterValue = "Generic TAS Sub - Product 1";

    listOfParameters[2] = paramContainer;

    paramContainer = null;

    WSNamespaceTransparantie.Service service = new WSNamespaceTransparantie.Service();

    WSNamespaceTransparantie.InputObjectTAS tasObj = new WSNamespaceTransparantie.InputObjectTAS();

    tasObj.ServiceConsumer = WSNamespaceTransparantie.EnumServiceConsumer.TAS;

    tasObj.ListOfParameters = listOfParameters;

    WSNamespaceTransparantie.OutputObjectGeneric outObj = service.calculateCommission_returnGeneric(tasObj);

    String returnVal = null;

    //Do a dummy and just concatenate everything in a string for now and return it

    foreach (WSNamespaceTransparantie.ParameterContainer_o p in outObj.ListOfParameters)

    {

    returnVal += p.ParameterName + " = " + p.ParameterValue + " ||| ";

    }

    return returnVal;

    }

    public long function2()

    {

    return 100; //dummy code

    }

    }

    }

    ******************************** Class1.cs END******************************

    In the project properties of TransparencyCalcEngineConsumerDll, in the Application --> Assembly Information, I specify the "Make Assembly COM-visible" check box as true. I do NOT check the checkbox for "Register for COM interop" in the BUILD tab of the project properties.

    I build my project. I get a TransparencyCalcEngineConsumerDll.dll file in the bin/debug folder.

    I run the following command from the .Net command prmopt : 

    regasm /tlb /codebase TransparencyCalcEngineConsumerDll.dll

    tlbexp TransparencyCalcEngineConsumerDll.dll (this gives me TransparencyCalcEngineConsumerDll.tlb file in the same folder)

    4. I open up a new project in VB6. I add reference to the .tlb file I have just created. Then I write the code in a button click in the form (just for testing):

    dim obj as Object
    Set obj = CreateObject("SomeNameProject.SomeNameClass1")

    Result:
    Firstly the call failed saying "this is not a proper assembly" ... then I registered / unregistered / nonsense a couple of times without doing anything new and suddenly the error changed to "could not locate TransparencyCalcEngineConsumerDll or one of its referenced components". This clearly shows that the VB6 is trying to do something with the TransparencyCalcEngineConsumerDll component ..... coz the createobject is actually done for "SomeNameProject.SomeNameClass1". There is no problem with just keeping the .tlb in my references, coz if I comment out the line which does the CreateObject then the execution of the project is fine .... of course it doesn't do anything but it doesn't generate any runtime error either.

    So what am I doing wrong???

    Many thanks!

    Sriram Ranganathan

    Wednesday, September 17, 2008 12:15 PM

Answers

  • IT WORKSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS

    Simple change .... just stumbled across it by mistake.

    There is a file called VB6.exe.config ... in the same folder which contains the VB6.exe

    In that it was specified that VB6 should use the 1.1 version of .Net

    So I just changed the version number specified in the config file .... and BINGO!!!

    Thanks all those who spent time thinking on this one.

    Hope this helps someone in future.

    Cheers

    Sriram Ranganathan
    • Marked as answer by Zhi-Xin Ye Tuesday, September 23, 2008 10:41 AM
    Thursday, September 18, 2008 4:44 PM

All replies

  • "or one of its referenced components" is probably the key phrase in the error message.  The registry information will help the CLR to locate TransparencyCalcEngineConsumerDll.dll but not any of the other assemblies it might need to do its job.  Use Fuslogvw.exe to troubleshoot this.  Avoid using /codebase, these assemblies belong in the GAC so you can have multiple versions of them side-by-side.  That will solve the assembly locating problem too.
    Hans Passant.
    Wednesday, September 17, 2008 1:45 PM
    Moderator
  • Ok I tried  some extra things but no go for working.

    1. I unregistered my Dll and tlb files by using regasm /unregister /tlb TransparencyCalcEngineConsumerDll.dll

    2. I used a registry crawler tool to ensure the registry had no entries of the Dll or tlb

    3. I added these lines to the AssemblyInfo.cs file of the TransparencyCalcEngineConsumerDll project.

     


    //sranganathan

    [assembly: AssemblyDelaySign(false)]

    [assembly: AssemblyKeyFile(@"C:\tester\test111.snk")]

    [assembly: AssemblyKeyName("")]

    //sranganathan

    4. Using the .Net command prompt, I create a .snk file as specified in the above code block. This is because I want to put the assembly in the GAC (which I didn't do before) and I can't do it without the strong naming.

    >>sn -k test111.snk (this is saved in the folder c:\tester .... hardcoded so that this doesn't give problems ... later i will see how to avoid hardcoding)

    5. Build the Dll again .... with options "Visible to COM" as yes and "Register for COM interop" as no.

    6. I registered by Dll from the .Net command prompt with the following command:

    regasm /tlb TransparencyCalcEngineConsumerDll.dll (note - no "codebase" option as suggested by you)

    7. Add the Dll to the GAC with the following command:

    >>GACUtil -if TransparencyCalcEngineConsumerDll.dll

    So now the Assembly is registered and also in the GAC.

    8. I open VB6 and add a reference to the tlb file created in step 6

    9. Tried to execute the following lines of code:


    Dim obj As Object  
    Set obj = CreateObject("TransparencyCalcEngineConsumerDll.Class1") 'THIS LINE FAILS  
     
    OR (this is a diff piece of VB6 code ... I thought should be similar to above code)  
     
    Dim obj2 As New TransparencyCalcEngineConsumerDll.Class1 'THIS LINE SUCCEEDS .... WHY????  
    MsgBox (obj2.function1()) 'THIS LINE FAILS 

    In both places above marked as 'THIS LINE FAILS, the message VB6 gives me is - "File or assembly name TransparencyCalcEngineConsumerDll, or one of its dependencies, was not found". When I look at the fuslogvw.exe, this is what it says:

    *** Assembly Binder Log Entry  (9/18/2008 @ 1:30:50 PM) ***  
     
    The operation failed.  
    Bind result: hr = 0x80070002. The system cannot find the file specified.  
     
    Assembly manager loaded from:  C:\WINNT\Microsoft.NET\Framework\v1.1.4322\fusion.dll  
    Running under executable  C:\Program Files\Microsoft Visual Studio\VB98\VB6.EXE  
    --- A detailed error log follows.   
     
    === Pre-bind state information ===  
    LOG: DisplayName = TransparencyCalcEngineConsumerDllVersion=1.0.0.0, Culture=neutralPublicKeyToken=56bff8e72210b896 
     (Fully-specified)  
    LOG: Appbase = C:\Program Files\Microsoft Visual Studio\VB98\  
    LOG: Initial PrivatePath = NULL 
    LOG: Dynamic Base = NULL 
    LOG: Cache Base = NULL 
    LOG: AppName = NULL 
    Calling assembly : (Unknown). 
    ===  
     
    LOG: Processing DEVPATH.  
    LOG: DEVPATH is not set. Falling through to regular bind.  
    LOG: Publisher policy file is not found.  
    LOG: Host configuration file not found.  
    LOG: Using machine configuration file from C:\WINNT\Microsoft.NET\Framework\v1.1.4322\config\machine.config.  
    LOG: Post-policy reference: TransparencyCalcEngineConsumerDll, Version=1.0.0.0, Culture=neutralPublicKeyToken=56bff8e72210b896 
    LOG: Cache Lookup was unsuccessful.  
    LOG: Attempting download of new URL file:///C:/Program Files/Microsoft Visual Studio/VB98/TransparencyCalcEngineConsumerDll.DLL.  
    LOG: Attempting download of new URL file:///C:/Program Files/Microsoft Visual Studio/VB98/TransparencyCalcEngineConsumerDll/TransparencyCalcEngineConsumerDll.DLL.  
    LOG: Attempting download of new URL file:///C:/Program Files/Microsoft Visual Studio/VB98/TransparencyCalcEngineConsumerDll.EXE.  
    LOG: Attempting download of new URL file:///C:/Program Files/Microsoft Visual Studio/VB98/TransparencyCalcEngineConsumerDll/TransparencyCalcEngineConsumerDll.EXE.  
    LOG: All probing URLs attempted and failed.  
     
     

    Being the clever chap I am (right now I don't care how it works as long as it works ... if it works then I see how to make it better), I copy the TransparencyCalcEngineConsumerDll.dll file to the C:/Program Files/Microsoft Visual Studio/VB98/TransparencyCalcEngineConsumerDll/TransparencyCalcEngineConsumerDll.DLL directory

    And I try the same VB6 code again ... and I get a different error message. VB6 says "the format of the file TransparencyCalcEngineConsumerDll is invalid" .... and in the fuslogvw.exe, this is what is given:

     
    *** Assembly Binder Log Entry  (9/18/2008 @ 1:34:31 PM) ***  
     
    The operation failed.  
    Bind result: hr = 0x80131107. No description available.  
     
    Assembly manager loaded from:  C:\WINNT\Microsoft.NET\Framework\v1.1.4322\fusion.dll  
    Running under executable  C:\Program Files\Microsoft Visual Studio\VB98\VB6.EXE  
    --- A detailed error log follows.   
     
    === Pre-bind state information ===  
    LOG: DisplayName = TransparencyCalcEngineConsumerDllVersion=1.0.0.0, Culture=neutralPublicKeyToken=56bff8e72210b896 
     (Fully-specified)  
    LOG: Appbase = C:\Program Files\Microsoft Visual Studio\VB98\  
    LOG: Initial PrivatePath = NULL 
    LOG: Dynamic Base = NULL 
    LOG: Cache Base = NULL 
    LOG: AppName = NULL 
    Calling assembly : (Unknown). 
    ===  
     
    LOG: Processing DEVPATH.  
    LOG: DEVPATH is not set. Falling through to regular bind.  
    LOG: Publisher policy file is not found.  
    LOG: Host configuration file not found.  
    LOG: Using machine configuration file from C:\WINNT\Microsoft.NET\Framework\v1.1.4322\config\machine.config.  
    LOG: Post-policy reference: TransparencyCalcEngineConsumerDll, Version=1.0.0.0, Culture=neutralPublicKeyToken=56bff8e72210b896 
    LOG: Cache Lookup was unsuccessful.  
    LOG: Attempting download of new URL file:///C:/Program Files/Microsoft Visual Studio/VB98/TransparencyCalcEngineConsumerDll.DLL.  
    LOG: Attempting download of new URL file:///C:/Program Files/Microsoft Visual Studio/VB98/TransparencyCalcEngineConsumerDll/TransparencyCalcEngineConsumerDll.DLL.  
    LOG: Assembly download was successful. Attempting setup of file: C:\Program Files\Microsoft Visual Studio\VB98\TransparencyCalcEngineConsumerDll\TransparencyCalcEngineConsumerDll.DLL  
    LOG: Entering run-from-source setup phase.  
    ERR: Error extracting manifest import from file (hr = 0x80131107).  
    ERR: Failed to complete setup of assembly (hr = 0x80131107). Probing terminated.  
     
     

    So now I know more than I knew before but I am still stuck.

    Any ideas, anyone?

    Note - I have both .Net 1.1 and 2.0 on my machine. Might that be the reason for the shuck-up? The above log clearly shows that the .Net 1.1 runtime is trying to do something .... how can I make the 2.0 runtime do the job so I can see if that works? I don't see any setting anywhere in my .Net Dll project to say whether .Net 1.1 or 2.0 should load the Dll whenever any COM application calls it (or even any application, COM or otherwise, calls it).

    Thanks in advance.

    Rgds

    Sriram Ranganathan


    Thursday, September 18, 2008 11:19 AM
  • Yup, that's almost certainly the problem.  The .NET 1.1 version of the CLR can't load .NET 2.0 assemblies.  My best guess is that you've accidentally used the .NET 1.1 version of Regasm.exe
    Hans Passant.
    Thursday, September 18, 2008 2:31 PM
    Moderator
  • Ok then how can I change that .... I just went to the .Net command prompt and did regasm .... shuold I use a normal command prompt .... navigate to the 2.0 folder where regasm is present .... and repeat all teh registering / de-registering etc?

    Isn't there any good way of doing this?

    Thanks!

    Sriram Ranganathan
    Thursday, September 18, 2008 2:45 PM
  • I read somewhere that I can force the 2.0 version of .Net to load the assembly instead of the 1.1 version by using config files .... how is that ... I am not able to find details ... any useful links?

    Thanks

    Sriram Ranganathan
    Thursday, September 18, 2008 4:06 PM
  • IT WORKSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS

    Simple change .... just stumbled across it by mistake.

    There is a file called VB6.exe.config ... in the same folder which contains the VB6.exe

    In that it was specified that VB6 should use the 1.1 version of .Net

    So I just changed the version number specified in the config file .... and BINGO!!!

    Thanks all those who spent time thinking on this one.

    Hope this helps someone in future.

    Cheers

    Sriram Ranganathan
    • Marked as answer by Zhi-Xin Ye Tuesday, September 23, 2008 10:41 AM
    Thursday, September 18, 2008 4:44 PM