none
FAXCOMEXLib and Return Types RRS feed

  • Question

  • I have an ActiveX control I built in VB 6.0 a long time ago to facilitate faxing and now I need to effectively translate this control into a C# class library.

    I've added the reference to the FAXCOMEXLib library and Visual Studio has no problems seeing the objects, Properties, and Methods, but when I compile my DLL I run into two problems.

    Firstly, the class library only seems to contain the properties and methods from FAXCOMEXLib that are actually used within my library. This is a problem because I expose the COM objects through read-only properties.

    public FaxServer   Server    {get { return m_Server;  }}
    public FaxDocument Document  {get { return m_Document;}}
    

    but if you call those properties and try to use the objects returned, you'll only have access to a limited number of methods and properties. I thought that this could have been a compiler option that cut out code that wasn't used, but I can't find the option to turn it off.

    -------------

    My second problem is that the FaxServer.Connect() method returns an HRESULT according to the documentation, but Visual studio is treating it like a void return. I can't have this because I need to be able to check the return value in the code that uses this library.

      m_Server = new FaxServer();
      if (m_Server.Connect("") == 0) // error CS0019 here
            throw new Exception("Could not connect to Server.");
    

    Generates error CS0019 "Operator '==' cannot be applied to operands of type 'void' and 'int'"

    I don't know why it thinks that FaxServer.Connect() returns void.

    Any help would greatly be appreciated.

    Thanks,

    Ken

    Monday, February 12, 2018 9:56 PM

All replies

  • Hi TheCTutor,

    Thank you for posting here.

    For your question is related to VB6.0, you could post a new thread in vb6 forum for suitable support.

    The Visual C# forum discuss and ask questions about the C# programming language, IDE, libraries, samples, and tools.

    Best Regards,

    Wendy


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Wednesday, February 14, 2018 7:44 AM
    Moderator
  • Um... this is definitely a question about C# and how it interacts with COM object.
    Wednesday, February 14, 2018 2:55 PM
  • "Firstly, the class library only seems to contain the properties and methods from FAXCOMEXLib " 

    Not sure what you mean by this but when the typelib is imported the generated .NET code will contain the members that are defined on the COM interface and nothing more. By default the COM types will be private as they are an implementation detail. As for your code, you shouldn't be exposing the COM classes directly. COM is an interface based system so you should always be returning COM interfaces from your code (even when it is used internally). If you don't do this then QueryInterface on COM isn't going to behave correctly.

    "My second problem is that the FaxServer.Connect() method returns an HRESULT according to "

    This is the expected behavior. In COM all (standard) methods return HRESULT. If a method needs to return data then it would use an out parameter. This is so that the COM object can be used in languages that don't support returning objects. Since .NET can handle this it will look for an out parameter on the method. If it finds one then it uses that as the return type otherwise the method returns null. Under the hood the RCW will invoke the method and then process the HRESULT for you automatically. If the HRESULT doesn't indicate success then it throws an exception. This lines up with the .NET mentality of throwing exceptions rather than using return values. So you're example code should simply be this.

    m_Server = new FaxServer();
    
    //This will automatically throw an exception if the connection fails
    m_Server.Connect("");
    
    //If you want to handle the error or change it to something else then use a try-catch
    try
    {
       m_Server.Connect("");
    } catch(Exception e)
    {
       //Not needed in this case but wrap the exception
       //in something more generic and pass the actual exception
       //as the inner exception
       throw new Exception("Could not connect", e);
    };
    

    So I'm going to say that everything is probably working correctly. But there may be times when you really don't want/need the standard .NET behavior. While rare it may happen. In those cases you'll have to control the import manually. To do that you'll have to run the same tool that the ID runs tlbimp but pass it the parameters you want to control how the .NET type is created. It will produce an assembly that you'll then reference instead of the original COM object. The process is documented here.


    Michael Taylor http://www.michaeltaylorp3.net

    Thursday, February 15, 2018 4:25 PM
    Moderator