title: Why is this C# COM class usable from VBScript but not JScript?
body: <p>Consider the automation-compatible COM library in C#, given below. It follows a common COM pattern of having a visible factory coclass FooFactory implementing ICreateFoos which creates an object of type IFoo. FooFactory is the <em>only</em> coclass in the type library. (The factory pattern is particularly useful with COM, as it does not allow for parameterized constructors).</p>
  
  <p>In the code below, I'm finding that I cannot access the returned IFoo interface from <em>jscript</em> <strong>unless I make the FooImpl class ComVisible</strong> (by uncommenting commented lines; this causes it to appear as a coclass in the type library). <em>There is no such problem accessing this from VBscript</em>.</p>
  
  <p>That is, I can run this VBScript:</p>
  
  <pre><code>set ff = CreateObject("jstest.FooFactory")
  set foo = ff.CreateFoo(0)
  foo.Foo
  </code></pre>
  
  <p>But this <em>functionally identical</em> JScript fails, with the error "C:\temp\jstest\jstest.js(4, 1) Microsoft JScript runtime error: 'foo' is null or not an object":</p>
  
  <pre><code>var ff = new ActiveXObject("jstest.FooFactory");
  var foo = ff.CreateFoo(0)
  //WScript.Stdout.WriteLine(null==foo)
  foo.Foo();
  </code></pre>
  
  <p>If I uncomment the line, I can see that null==foo is false.</p>
  
  <p>Why does this happen? Is it a bug? Note that I think this is a problem is a combination of JScript and the C#/.net-specific implementation (possibly of IDispatch), because I have other similar COM servers - implemented in C++ - that do not exhibit this problem from JScript.</p>
  
  <p>The problem goes away if I uncomment the commented lines in the code below, making FooImpl visible as a coclass - but I specifically do not want to do this as I don't want to expose implementation details. A workaround seems to be to make FooImpl ComVisible, but mark its constructor internal, which prevents clients from being able to CoCreate it, but that's hardly elegant.</p>
  
  <p>I'm running on WinXP SP3 with Visual Studio 2005, .net 2, and have been able to reproduce the issue on a completely fresh install of TinyXP on a VirtualBox (both with Windows Script Host 5.7), and also on Windows 7 Ultimate using .net SDKs 2.0, 3.0, 3.5 and 4.0 (WSH 5.8). All OSes were 32-bit.</p>
  
  <p>The library code:</p>
  
  <pre><code>using System;
  using System.Runtime.InteropServices;
  
  [assembly: ComVisible(false)]
  
  namespace jstest
  {
      [ComVisible(true)]
      public interface ICreateFoos
      {
          IFoo CreateFoo(int importantNumber);
      }
  
      [ComVisible(true)]
      public interface IFoo
      {
          void Foo();
      }
  
      [ComVisible(true)]
      public class FooFactory : ICreateFoos
      {
          public IFoo CreateFoo(int importantNumber)
          {   // in *this* version, we don't use importantNumber yet
              return new FooImpl();
          }
      }
  
      //[ComVisible(true)]
      public class FooImpl : IFoo
      {
          public void Foo()
          {
              Console.WriteLine("Foo");
          }
      }
  }
  </code></pre>
  
  <p>You can compile and register (you may have to run as admin to regasm) this with </p>
  
  <pre><code>csc /target:library jstest.cs
  regasm /codebase jstest.dll
  </code></pre>