title: Exposing C# struct to COM breaks for VB6 app
body: <p><strong>Last Updated:</strong> 2009-08-11 2:30pm EDT</p>
  
  <p>A few days ago I posted <a href="https://stackoverflow.com/questions/1159728/compiling-vb6-app-w-net-interop-only-runs-if-compiled-on-my-machine">this question</a> about some very strange problems. Well, I figured out what specifically was causing a build on one machine to not run on others and even came up with a work-around, but now it leaves me with a nice, specific question: Why?</p>
  
  <p>To reproduce the problem, I create a new InteropUserControl and do the following:</p>
  
  <ol>
  <li>Add a new <code>public struct MyStruct</code>:</li>
  <li>Give it a GUID and <code>ComVisible</code> attributes</li>
  <li>Add a <code>GetMyStruct</code> member to the <code>_InteropUserControl</code> interface and implement it in <code>InteropUserControl</code>.</li>
  </ol>
  
  <p><code>MyStruct</code>:</p>
  
  <pre><code>[Guid("49E803EC-BED9-4a08-B42B-E0499864A169")]
  [ComVisible(true)]
  public struct MyStruct {
      public int mynumber;
  }
  </code></pre>
  
  <p><code>_InteropUserControl.GetMyStruct()</code>:</p>
  
  <pre><code>[DispId(7)]
  void getMyStruct( int num, ref MyStruct data );
  </code></pre>
  
  <p>(I have tried returning <code>MyStruct</code> instead of passing by reference, as well.)</p>
  
  <p><code>InteropUserControl.GetMyStruct()</code> implementation:</p>
  
  <pre><code>public void getMyStruct( int num, ref MyStruct data ) {
      data = new MyStruct();
      data.mynumber = num * 2;
  }
  </code></pre>
  
  <p>I also sign the assembly and install it to the GAC and register with Regasm. Upon adding it to a new VB6 project and adding a call to <code>GetMyStruct()</code> and compiling on our build machine, it refuses to run on other machines.</p>
  
  <p>To get around this, I had to expose a class to COM instead of the struct, and basically change <code>GetMyStruct</code> to this:</p>
  
  <pre><code>public void GetMyData( int num, MyClass data ) {
      data.mynumber = num * 2;
  }
  </code></pre>
  
  <p>In my actual project, I retrieve the struct internally, and then copy all the field values from the struct to the matching members on the instance of the class passed to the method by the client.</p>
  
  <p>So why did a struct cause this behavior and a class worked fine? Is there some magic to exposing a struct to COM for using in VB6?</p>
  
  <p>I think it may have something to do with OLE Automation.</p>
  
  <p>Note: I also tried returning the struct rather than using a <code>ref</code> parameter, but that did not change the behavior.</p>
  
  <p><strong>Edit to add link to project template:</strong></p>
  
  <p><a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=934DE3C5-DC85-4065-9327-96801E57B81D&amp;displaylang=en" rel="nofollow noreferrer">Interop Forms Toolkit 2.0</a> is the original VB.NET project template and dll. I don't reference the dll, so you may not need to install this.</p>
  
  <p><a href="http://www.codeproject.com/KB/vb-interop/VB6InteropToolkit2.aspx" rel="nofollow noreferrer">C# Translations of templates on CodeProject</a> is what I used to create mine (the project template, not the item template). The VB.NET version generates the <code>__InteropUserControl</code> event interface, the <code>_InteropUserControl</code> interface, and a few relevant attributes automagically. Those are explicitly coded in the C# version, and that's about all that's different between the two.</p>