June 2004 - Posts

One year with .Text!

How ironic! I was googling today for something .NET related and came across a link to my old Radio weblog. I clicked on the link and read my last post. It mentioned my move to weblogs.asp.net -- and it was dated one year ago today! Anyway, it's been a great year with .Text and I've never had any problems like I used to with Radio. Thanks Scott!
Posted by PSteele | with no comments

Creating a COM object from a ProgID

Suppose you have an architecture where you expose interfaces to your clients and they can create their own COM objects to extend your application by simply implementing one of your interfaces. You don't force them to use a particular ProgID (they may have multiple objects that implement the same interface). Instead, the ProgIDs are stored somewhere (database, XML file, whatever).

You're now porting your application to .NET and still want your client's customizations to work. In your VB6 code, you currently use CreateObject and the interface to call your client's code (ProgID hard-coded for sample purposes):

Public Sub CallExtender()
    Dim oFoo    As IFoo
    
    Set oFoo = CreateObject("Client.ProgID")
    oFoo.DoSomething
End Sub

How to do the same thing in your C# .NET code? Very easy. You create your interop library for your Interfaces DLL using tlbimp and add it to your C# project. Then:

public void CallExtender()
{
	Type comType = Type.GetTypeFromProgID("Client.ProgID");
	object comObj = Activator.CreateInstance(comType);
	IFoo foo = (IFoo) comObj;
	foo.DoSomething();
}

No knowledge of the client's current COM objects (like an imported type library) is required.

Posted by PSteele | with no comments

Was that assembly built in Debug or Release?

Ted Graham posts about determing if an assembly is a debug assembly or a release assembly. His solution was to use the AssemblyDescription attribute:

#if DEBUG
[assembly: AssemblyDescription("Debug")] 
#else 
[assembly: AssemblyDescription("Release")] 

Others have posted comments on different, perhaps better ways, of doing this. The problem I have with using the AssemblyDescription attribute is that if you plan on doing anything with COM interop, the value of AssemblyDescription is used as the "helpstring" (i.e. Description) of the COM typelibrary generated by REGASM (or TLBEXP). In Ted's example above, the description for your assembly in the VB6 References dialog would be either "Debug" or "Release" -- not too descriptive.

Posted by PSteele | 2 comment(s)

REGASM, COM and Type Libraries

If you've ever done any work with making .NET components that are exposed to COM, you're familiar with REGASM. This utility makes registry entries to make your .NET object look like a COM object. In its simplest form, you can do:

REGASM MyAssembly.dll

Now, all of the COM-compatible classes are registered as COM objects. You can fire up VB6 and start writing code:

Dim net As Object

Set obj = CreateObject("NETProject.Foo")
obj.Move

Pretty easy. Except that you're late binding because you don't have a COM type library.

No problem! REGASM can generate a type library for you and even register it:

REGASM MyAssembly.dll /tlb:MyAssembly.tlb

Now, in VB6 you can add a reference to the type library and use early binding:

Dim net As Foo

Set obj = New NETProject.Foo
obj.Move

Suppose you want to "unregister" this assembly? REGASM has a "/unregister" switch:

REGASM /u MyAssembly.dll

The thing you want to watch out for (and the real reason for this post) is that if you used the /tlb option to register a type library, you need to make sure you include the /tlb option when unregistering. If you don't, only the COM object is unregistered, but the type library is still registered. And you can't unregister the type library by itself.

So, rule of thumb:

REGASM MyAssembly.dll /tlb:MyAssembly.tlb

Balance that with:

REGASM /u MyAssembly.dll /tlb:MyAssembly.tlb
Posted by PSteele | 9 comment(s)

Determining if a COM+ application is running.

I needed to know if one of my COM+ applications was currently running. Some Googling came up with an "ApplicationInstances" collection by interop'ing with the COMAdmin library, but that only works for XP and Win2K3 Server. Of course, I needed this for Win2k.

Some more Googling returned information on the IMtsGrp interface in the COMSvcs library. This works from NT4 through to XP and was just what I needed. I generated a RCW for it and coded my function:

private bool IsRunning(string applicationName)
{
	IMtsGrp group = new MtsGrpClass();

	for(int i=0; i<group.Count ; i++ )
	{
		object outEvents;
		group.Item(i, out outEvents);
		COMEvents eventObj = (COMEvents) outEvents;
		if( eventObj.PackageName == applicationName )
			return true;
	}

	return false;
}
Posted by PSteele | 1 comment(s)

Whidbey gets FTP support

From Brad Abrams:

...we're adding FTP support in Whidbey

And in a followup from Lance Olson (System.Net Team)

Our FTP implementation in Whidbey includes support for FTP over SSL.
Posted by PSteele | with no comments

Cool Screensaver

Ok, kind of off-topic, but we're all geeks, aren't we? Found this cool Matrix-style screensaver that's highly customizable (and small too -- only 50k).
Posted by PSteele | with no comments
More Posts