Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1122
  • Last Modified:

URGENT: Cause of Invalid ProgID in .NET DLL registered for COM Interop

ASP code (tomtest.asp):

<%
Set DBObj = Server.CreateObject("BFUser.BFTom")
Response.Write("From CSharp COM Object:  " & DBObj.GetNetworkLoginName())
Set DBObj = Nothing
%>

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

C# DLL code (user.dll):

using System;

      public class BFTom
      {
            public BFTom()
            {
                  //
                  // TODO: Add constructor logic here
                  //
            }

            public string GetNetworkLoginName()
            {
                  
                  //System.Security.Principal.WindowsIdentity ident = System.Security.Principal.WindowsIdentity.GetCurrent();
                  //return ident.Name;
                  return "Some cool thing";

            }

      }



~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


ERROR:

The page cannot be displayed
There is a problem with the page you are trying to reach and it cannot be displayed.

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

Please try the following:

Click the Refresh button, or try again later.

Open the localhost home page, and then look for links to the information you want.
HTTP 500.100 - Internal Server Error - ASP error
Internet Information Services

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

Technical Information (for support personnel)

Error Type:
Server object, ASP 0177 (0x800401F3)
Invalid ProgID. For additional information specific to this message please visit the Microsoft Online Support site located at: http://www.microsoft.com/contentredirect.asp.
/tomtest.asp, line 2


Browser Type:
Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; .NET CLR 1.0.3705)

Page:
GET /tomtest.asp

Time:
Wednesday, November 19, 2003, 1:02:01 PM


More information:
Microsoft Support
 
0
Tom Knowlton
Asked:
Tom Knowlton
  • 13
  • 7
  • 3
  • +1
2 Solutions
 
Tom KnowltonWeb developerAuthor Commented:
Here is the process I am using to register the DLL for use by ASP 3.0:

stop web service
unregister DLL
copy in new DLL
register DLL
start web service
run test web page


BATCH FILE:

net stop w3svc
cd\
cd WINNT
cd MICROS~1.NET
cd FRAMEW~1
cd V10~1.370
gacutil -u BFUser.dll
regasm c:\winnt\system32\BFUser.dll /unregister
pause
cd\
cd WINNT
cd MICROS~1.NET
cd FRAMEW~1
cd V10~1.370
gacutil -u BFUser.dll
regasm c:\winnt\system32\BFUser.dll /unregister
pause
net start w3svc

then I go to the test ASP page and get the error above...
0
 
Göran AnderssonCommented:
You have not registered the dll. You can either register it with regsvr32 in a dos prompt:

regsvr32 c:\path\to\the\dll\user.dll

Or you can create an application for it in Component Services, and add it as a component.
0
 
Tom KnowltonWeb developerAuthor Commented:
GreenGhost:

Okay...but I thought under .NET you did not use regsvr32.

I thought instread you used gacutil   and    regasm   to do what regsvr32 does?
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
Göran AnderssonCommented:
You unregister the component twice, shouldn't you register it the second time?

net stop w3svc
cd\
cd WINNT
cd MICROS~1.NET
cd FRAMEW~1
cd V10~1.370
gacutil -u BFUser.dll
regasm c:\winnt\system32\BFUser.dll /unregister
pause
cd\
cd WINNT
cd MICROS~1.NET
cd FRAMEW~1
cd V10~1.370
gacutil BFUser.dll
regasm c:\winnt\system32\BFUser.dll
pause
net start w3svc
0
 
Tom KnowltonWeb developerAuthor Commented:
UNREGISTER:

gacutil -u BFUser.dll
regasm c:\winnt\system32\BFUser.dll /unregister


REGISTER:
gacutil -i BFUser.dll
regasm c:\winnt\system32\BFUser.dll

I was missing the -i in the register call....

hmmm....better double-check my batch file....I think that was a typo here in EE when I posted.

0
 
Göran AnderssonCommented:
But you are not using the component from APS.NET but from ASP. I don't know if gacutil and regasm works then.

I see now that the second call to gacutil should be like this:
gacutil /i BFUser.dll
0
 
purpleblobCommented:
Wow, I went off for a few minutes to try this out and all of a sudden there's several answers :-)

Anyway I hadn't tried this before, so thought I'd give it a try. I had no problems whatsoever, so if I tell you what I did, then you can see if it works as per your

I created a Class library and added the following code

using System;

namespace MyNamespace
{
      public class MyObject
      {
            public string MyName()
            {
                  return "I am called MyObject";
            }
      }
}

I then open project properties and selected the Configuration Properties, build option and set Register for COM interop to True (you can also use regasm or tlbexp and then register the object yourself if you prefer but this option will do all the work for you when you build the DLL).

Okay now I created the ASP

<%
Set obj = Server.CreateObject("MyNamespace.MyObject")
Response.Write(obj.MyName)
Set obj = Nothing
%>

And that's it everything worked first time - cool.

Not sure if this helps you but it appears your TLB is/was not registered, I noticed when I used regasm one time it didn't create the TLBand hence didn't register anything - don't know if you've been using this to create the typelib.

Hope this helps
0
 
purpleblobCommented:
I notice you're alsoi registering your object with the GAC - this isn't required for COM interop so I've not used it - obviously you may be aware of this and registering for other purposes, but just thought I'd highlight this point :-)
0
 
Tom KnowltonWeb developerAuthor Commented:
GreenGhost / purpleblob:

Some very good input from both of you!!!

Give me a few minutes to digest your ideas and try a few more things (per your recommendations).

I'll be back in 10 or 15 minutes.

Tom
0
 
Tom KnowltonWeb developerAuthor Commented:
I did not know that gacutil was needed to be run for COM Interop!!!!

Okay...I'll try commenting this line out....
0
 
purpleblobCommented:
gacutil is not required for COM interop.

Basically you create the typelib using regasm (which also registers it or tlbexp (there you have to register the typelib yourself).

MS supply's a surrogate (mscoree.dll) which interacts with the .NET DLL - so you only require the typelib for your .NET DLL and this will (I assume) be late bound using mscoree.dll.

Anyway, I'm thankful to knowlton for asking the question - it forced me to look into this which is something I'd wondered about for some time :-)
0
 
Tom KnowltonWeb developerAuthor Commented:
Okay:

Here is my REVISED BATCH FILE:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


REM
REM  STOP WEB SERVICE
REM
net stop w3svc
pause

REM
REM  COPY IN NEW DLL...
REM
copy n:\%1.dll c:\winnt\system32
pause


REM
REM  REGISTER COM DLL
REM
cd\
cd WINNT
cd MICROS~1.NET
cd FRAMEW~1
cd V10~1.370
regasm c:\winnt\system32\%1.dll
pause

REM
REM  START WEB SERVICE
REM
net start w3svc
pause




I tried this with a BRAND NEW COM DLL called SimpleTest:



using System;

namespace SimpleTest
{
      /// <summary>
      /// Summary description for Class1.
      /// </summary>
      public class ClassTest
      {
            public ClassTest()
            {
                  //
                  // TODO: Add constructor logic here
                  //
            }

            public string Speak()
            {
                  return "Bark Bark";
            }
      }
}


NOTES:  

1)  I created a strong name for the DLL:   sn -k key.snk
2)  I set "Register for COM Interop" to TRUE before compiling.


Worked JUST GREAT the first time......


Going to test a second time here in a little bit....see if I can get BFUser.dll to work also.....



Tom
0
 
purpleblobCommented:
Yippeee :-) Well done
0
 
Bob LearnedCommented:
I think that you are skirting around the issue.  This is what I have taken from this discussion:

1.  .NET assembly in .COM   Look at this article:  
     Calling .NET From COM
     http://www.csharpfriends.com/Articles/getArticle.aspx?articleID=113

2.  This is not COM Interoperability, that applies to running a COM object in a .NET assembly.

3.  The ProgID for a .NET assembly is Namespace.Object.  I don't see any reference to Namespace, so I imagine that it is being taken from the Default Namespace property of the project.

4.  RegAsm give the .NET assembly a COM-like reference in the registry.  GACUtil places a link in the Global Assembly Cache for the .NET assembly.
0
 
Tom KnowltonWeb developerAuthor Commented:
I made some changes to SimpleTest and ran through the process again....IT WORKS!!!!


Now....I still need to see if BFUser can be made to work...that was the original problematic DLL that prompted this question in the first place.  :)

Back in a few....

Tom
0
 
Tom KnowltonWeb developerAuthor Commented:
Still no luck with BFUser.DLL

here is the ASP page trying to use BFUser.DLL:

<%
Set DBObj = Server.CreateObject("BFUser.BFTom")
Response.Write("From CSharp COM Object:  " & DBObj.GetNetworkLoginName())
Set DBObj = Nothing
%>

Here is the current code for BFUser.DLL:

using System;

      public class BFTom
      {
            public BFTom()
            {
                  //
                  // TODO: Add constructor logic here
                  //
            }

            public string GetNetworkLoginName()
            {
                  
                  //System.Security.Principal.WindowsIdentity ident = System.Security.Principal.WindowsIdentity.GetCurrent();
                  //return ident.Name;
                  return "Some cool thing";

            }

      }

0
 
Tom KnowltonWeb developerAuthor Commented:
Does the namspace and the DLL name have to match?
0
 
purpleblobCommented:
Okay I've looked into the regasm util a little further as I found this didn't create my typelib and register it (well it wouldn't if it never created it :-) ). Basically the info. I found previously on using this feature of COM interop (i.e. creating COM wrappers to a .NET DLL) all states you simply type

regasm MyAssembly.dll

This appears to be incorrect as no .tlb is created, instead you need to type

regasm MyAssembly.dll /tlb

this will both create the .tlb and register it. This may have been where you were having problems previously with your batch file.
0
 
Tom KnowltonWeb developerAuthor Commented:
TheLearnedOne:

The link you provided was EXCELLENT:

http://www.csharpfriends.com/Articles/getArticle.aspx?articleID=113

Why can't all tutorials be this CLEAR?
0
 
purpleblobCommented:
No the namespace and DLL should not have to match as this is simply a ProgID - which could be anything as long as it references the correct surrogate and typelib.

Sorry, but more on regasm, it appears that regasm with the /tlb still doesn't correctly register a tyelib - curious it appears this util is buggy. Anyway, enough about that. Using the standard tylib registation techniques will register the tylib correctly.
0
 
Tom KnowltonWeb developerAuthor Commented:
purpleblob:

What you say may be true....but my batch file is working just fine without the /tlb switch added to the regasm call!!!!

Go figure.

I think the problem with BFUSER.DLL is the namespace (or lack thereof).
0
 
Tom KnowltonWeb developerAuthor Commented:
I added the namespace back into BFUSER.DLL's C# source code like this:

using System;

namespace BFUser
{
      public class BFTom
      {
            public BFTom()
            {
                  //
                  // TODO: Add constructor logic here
                  //
            }

            public string GetNetworkLoginName()
            {
                  
                  //System.Security.Principal.WindowsIdentity ident = System.Security.Principal.WindowsIdentity.GetCurrent();
                  //return ident.Name;
                  return "Some cool thing";

            }

      }
}



And now IT WORKS!!!!!


I think the syntax in ASP 3.0 is

Set DBObj = Server.CreateObject("[namespace].[class name]")

OR

Set DBObj = Server.CreateObject("[user specified progid].[class name]")


NOT

Set DBObj = Server.CreateObject("[DLL name].[class name]")

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

If you use the default code when constructing a C# Class Library....the namespace DOES MATCH the DLL Name....hence my confusion when I:

1)  Deleted the namespace code
2)  Referenced the DLL name (not the namespace)


0
 
purpleblobCommented:
How odd my version doesn't seem to be creating the tlb - ah well less said the better :-)

As per the article references by TheLearnedOne you can simply prefix your class with a namespace yourself if you desire, i.e.

using System;
using System.Runtime.InteropServices;

namespace MyNamespace
{
      [ProgId("Whatsup.Doc")]
      public class MyObject
      {
            public string MyName()
            {
                  return "I am called MyObject";
            }
      }
}

Or obviously you can let the tools create the ProgId for you and as you've found out this consists of your Namespacename.Classname. I've used the ProgId attribute and it works fine.
0
 
Tom KnowltonWeb developerAuthor Commented:
Correct.
0

Featured Post

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 13
  • 7
  • 3
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now