BUG: You receive a "TargetParameterCountException" exception when you call the COM method with a Retval attribute (814721)



The information in this article applies to:

  • Microsoft Visual C++ .NET (2003)
  • Microsoft .NET Framework 1.1

SYMPTOMS

When dispinterface has a retval attribute in the Interface Definition Language (IDL) file of the Microsoft Component Object Model (COM) server, and when you use the Add Reference tool to import the COM server that you want to use from Microsoft Visual C++ .NET 2003 managed code, you may receive the following exception:
An unhandled exception of type 'System.Reflection.TargetParameterCountException' occurred in mscorlib.dll Additional information:

Invalid number of parameters.

CAUSE

When you use the Add Reference tool in Visual C++ .NET 2003, the Type Library Importer (Tlbimp.exe) internally generates an interop assembly. Tlbimp.exe does not run with the /transform:dispret option.

WORKAROUND

To work around this problem, create an interop assembly manually, and then import the newly created assembly in your code. To create an interop assembly, run Tlbimp.exe with the /transform:dispret command-line option.

To do this, follow these steps:
  1. Remove the reference to the MyServer.DLL COM component.
  2. Open a Microsoft Visual Studio .NET command prompt.
  3. Type the following command, and then press ENTER:

    tlbimp /transform:dispret YourCOMDLName /out:Interop.YourCOMDLLName.dll

  4. In Solution Explorer, right-click Reference, and then click Add Reference.
  5. On the .NET tab, click Browse.
  6. Locate the interop .dll file that you created in step 3. Click Open, and then click OK.
  7. In the ManagedClient.cpp file, change the following code:
    mysrv-> GetOffsetNum(100,&i);
    to this:
    i = mysrv->GetOffsetNum(100);
  8. On the Debug menu, click Start.
Note The .NET Framework 1.0 does not support the /transform:dispret command-line option for Ttlbimp.exe.

STATUS

Microsoft has confirmed that this is a bug in the Microsoft products that are listed at the beginning of this article.

MORE INFORMATION

Steps to Reproduce the Behavior

Create a COM Server

  1. Create a new file that is named MyServer.cpp in the MyServer folder.
  2. Open the MyServer.cpp file in Notepad, and then paste the following code to it:
    #pragma once
    #define STRICT
    
    #ifndef _WIN32_NT
    #define _WIN32_NT 0x400
    #endif
    
    #define _ATL_ATTRIBUTES
    #define _ATL_APARTMENT_THREADED
    #define _ATL_NO_AUTOMATIC_NAMESPACE
    #include <atlbase.h>
    #include <atlcom.h>
    #include <atlwin.h>
    #include <atltypes.h>
    #include <atlctl.h>
    #include <atlhost.h>
    using namespace ATL;
    
    [ module(dll, name = "MyServer", helpstring = "MyServer 1.0 Type Library") ];
    [ emitidl ];
    
    [
       uuid("D963977F-9058-492d-9530-470C9E7B3443"),
       dispinterface,
       helpstring("IMyServerObj Interface"),
     ]
    __interface IMyServerObj : IDispatch
    {
       [id(1)] HRESULT GetOffsetNum([in] int iNum,[out, retval]int* pInt);
    };
    [
       coclass,
       threading("apartment"),
       vi_progid("MyServer.MyServerObj"),
       progid("MyServer.MyServerObj.2"),
       version(1.0),
       uuid("858DC2A5-444F-417e-9B5B-8D80654E1D83"),
       helpstring("My Server class ")
    ]
    class ATL_NO_VTABLE CMyServerObj : 
       public IMyServerObj
    {
    public:
       CMyServerObj()
       {
       }
       HRESULT GetOffsetNum(int iNum, int* pInt){
          *pInt = 500;
          return S_OK;
       }
       DECLARE_PROTECT_FINAL_CONSTRUCT()
       HRESULT FinalConstruct()
       {
          return S_OK;
       }	
       
       void FinalRelease() 
       {
       }
    };
    
  3. Save the MyServer.cpp file.
  4. Open a Microsoft Visual Studio .NET command prompt.
  5. Change the folder to the MyServer folder.
  6. To create a COM DLL, type the following command at the command prompt:

    cl /LD MyServer.cpp

    A COM DLL that is named MyServer.DLL is created.
  7. To register the COM DLL, type the following command at the command prompt:

    regsvr32 MyServer.dll

Access COM DLL from Managed Code

  1. Start Visual Studio .NET 2003.
  2. On File menu, point to New, and then click Project.
  3. Under Project Types, click Visual C++ Projects. Under Templates, click Console Application (.NET). In the Name box, type ManagedClient, and then click OK.
  4. In Solution Explorer, right-click Reference, and then click Add Reference.
  5. On the COM tab, locate MyServer 1.0 Type Library, click Select, and then click OK.
  6. Copy the following code to ManagedClient.cpp:
    // This is the main project file for the Visual C++ .NET application project.
    // The file was generated by using an Application Wizard.
    
    #include "stdafx.h"
    
    #using <mscorlib.dll>
    
    using namespace System;
    using namespace Interop;
    int _tmain()
    {
             MyServer::IMyServerObj *mysrv = new MyServer::CMyServerObjClass();
            int i = 12;
    
            // Call the method from the COM DLL.
            mysrv->GetOffsetNum(100,&i);
            Console::WriteLine(S"The new value of i is {0}",i.ToString());
    }
  7. On Debug menu, click Start. You receive the TargetParameterCountException exception that is described in the "Symptoms" section of this article.

Modification Type:MinorLast Reviewed:1/18/2006
Keywords:kbpending kberrmsg kbCOMInterop kbbug KB814721 kbAudDeveloper