This is a set of .NET, COM and Win32 tools that Chris Sells has built and contributed to the world. You may use them without royalty (and without support) in your compiled code. You may not redistribute the source code. A mention in the documentation of your products is always appreciated. Enjoy!
P.S. I have no idea where the picture at the top of this page came from -- feel free to use it with the exact same number of permissions I have to use it, i.e. none.
Thu, 9/3/09
Windows 7 took away a feature I use all the time -- Search the Internet:
Here's what I did all day, every day in Windows Vista: Ctrl+Esc to bring up the Start menu, then I start typing. If I'm searching on my HD, I immediately get matches and I can choose one with just the arrows and the Enter key. If I'm typing in the name of a program in the Start menu, I get those matches and choose one. If I want "calc" or "notepad" I can just type those and those work.
However, 80% of the time, I want to search the internet, so enter my search term, optionally including attributes like "site:", I press, down-arrow once, highlight "Search the Internet" and press Enter. This brings up my default browser with my search results in my default search engine without me having to move the mouse or open the browser and wait for the home page or even decide where I want the search results to come from until after I've entered my search phrase.
And we took it out of Windows 7. : (
But, Shawn VanNess has shown me how to put it back! : )
Download this zip file, execute the .reg file, press Yes and OK a bunch, kill and restart the explorer.exe process and the next time you do the Ctrl+Esc+type+something dance, you'll see your old friend "Search the Internet" right back on the Start menu where Bill intended it to be. Thanks, Shawn!
Wed, 4/11/07
Show Me The Template is a tool for exploring the templates that comes with the controls built into WPF for all 6 themes. In addition to the learning experience this provides (I'm constantly figuring stuff out about how WPF works by reading the default templates), it's also a handy way to start when you're building your own templates instead of starting from scratch (particularly for control templates).
Tue, 7/30/06
I updated the SDK RegistrySettingsProvider to implement IApplicationSettings and built a sample to demonstrate how to integrate it (or any .NET 2.0 custom settings provider) with the settings designer-generated code. Enjoy.
Sun, 7/30/06
To capture the work that Doug and I did to make Indigo (WCF) and Avalon (WPF) work together, I tore up our PDC sample application into a set of simpler technology samples. To make it fun for myself, as part of these samples, I built a little library for converting numbers into strings of English words, e.g. 4 is "four:"

To drive home the point (of which there wasn't any because the sample had nothing whatever to do with number to English phrase conversions), I spent some time polishing the algorithm so that it handled decimal points:

and when that didn't satisfy me, I added large numbers and negative numbers:

Before writing this code, I searched the net and didn't find any algorithms that handled both negative numbers and decimal points, let alone for .NET or in the number of lines of code to which I cut it down (93, including comments). I know it's not useful, but it was fun. If you want the code, you can get it by downloading the .NET 3.0 Cross Technology samples and checking out the WinSDK_Samples\CrossTechnology\WpfDataBindingToWcfResults\service\NumberUtility.cs file. I built the file to be dropped into any .NET 2.0+ project (and even .NET 1.x projects, if you remove the "using System.Collections.Generic" statement at the top of the file -- I don't actually use generics), regardless of whether you're using Avalon or Indigo or not.
Enjoy.
Tue, 11/25/03
CsvFileTester is a tool inspired by Shawn Wildermuth's ExcelFileTester, which he wrote 'cuz I kept asking him how to do queries on .xls files. However, because the Excel query language has no where or order by clauses, I gave that up in favor of comma-separated text files.
I wrote CsvFileTester (with Shawn's help) to explore the ADO.NET/ODBC/JET support for CSV files and I was amazed at how comprehensive the support was. And, since I can never remember the syntax and limitations between one use of Jet expression syntax and the next, I put a bunch of samples in the combobox.
Enjoy.
Wed, 8/6/03
FormatDesigner is an application to experiment with the format strings used to format data in String.Format and various type's ToString functions.
Click here to launch the application directly (requires the .NET Framework 1.1).
Click here to download the source code.
Enjoy.
Wed, 6/18/03
Tired of the XmlSerializer's generic "File or assembly name ctewkx4b.dll, or one of its dependencies, was not found" exception? The XmlSerializerPreCompiler tools checks to see if a type can be serialized by the XmlSerializer class and if it can't, shows the compiler errors happening behind the scenes so that the type can be modified. Enjoy.
This just in: Mathew Nolton has posted a GUI front-end to my XmlSerializerPreCompiler that you might find useful. Thanks, Matt!
Fri, 6/13/03
The fact that Windows XP Find in Files only searches files with known file extensions drives me crazy because it skips, among other things, .cs files. Every time I set up a new system, I have to re-figure out how to fix this. To facilitate that, I put together a .reg file that will search all unknown file extensions as text files. Enjoy.
Fri, 1/10/03
In writing the resources chapter of my WinForms book, I found that there was no single utility for displaying the resource contents of assemblies, .resx files and .resource files (even embedded .resources files) in a way that made sense to me. So, I built one and called it ResourceExplorer.

ResourceExplorer is very simple and could stand some extension to show specific resources at images, text, data, etc, but it certainly served my needs, especially when it came to understanding the usage and limitations of the ResourceReader (for reading .resources files) and the ResXResourceReader (for reading .resx files). Enjoy.
Sun, 10/13/02
Scancode Mapper is a GUI tool for setting the Scan Code Mapper for Windows Registry settings for Win2K+:
As an example of what this tool does to the Registry, this .reg file turns off the CapsLock key. Of course, changing scancode mappings is a risky business, so be sure of what you're doing before committing the changes and restarting Windows. No warranties extended. Use at your own risk. Enjoy. : )
9/10/02
I built the TAPI Explorer (tExplorer) to allow me to understand the various capabilities of the telephony devices installed on my system when I was developing TAPI applications and writing my TAPI book. It grew into a utility for showing all line, address and phone capabilities as well as other TAPI settings, e.g. country codes, telephony locations, service providers, etc. If you're running into TAPI errors that you don't understand, TAPI Explorer will help you work through them.
This version has been run and tested on Windows 98, Windows ME, Windows NT 4.0, Windows 2000 and Windows XP and supports TAPI versions 1.4 through 3.1.
VS.NET Source | VC6 Source (previous version)
Fri, 5/17/02
XsdClassesGen is a Custom Tool Add-In to VS.NET 2002 & 2003 to generate type-safe wrapper classes for serializing to and from XML documents. It takes as input an XSD and produces the C# or VB.NET code to do the serialization using the XmlSerializer. This is really just the output of running xsd.exe /classes, but integrated directly into VS.NET.
If you'd like to know more about what a custom tool is and how to build your own, check out CollectionGen.
Also, Atif Aziz used some of my custom tool code and built a generic VS.NET code generator shim that allows you to build a code generator that plugs into VS.NET by implementing a single method.
And, as if that weren't enough, Stephane Tombeur has posted the code to VS2005. Thanks, Stephane!
Thu, 4/12/02
USE THIS FILE WITH CARE. It causes problems with image lists for .NET EXEs that don't also use the same manifest file.
Just drop this devenv.exe.manifest file next to devenv.exe in your VS.NET install directory and the next time you start VS.NET under XP, it'll look mostly the same! (well, maybe a little different : )
Wed, 4/10/02
[Note: As of 5/5/03, the functionality of CollectionGen has been sucked into Eric Smith's CodeSmith. I asked Eric to take on these features because CodeSmith does all of what CollectionGen does and more. All new feature requests/bug reports should go his way.]
CollectionGen is a Custom Tool Add-In to VS.NET 2002 & 2003 to generate type-safe collections. As it turns out, I did almost none of the work. Jon Flanders figured out how to add a custom tool. Shawn Van Ness implemented the template for type-safe collections. I just put it together.
CollectionGen is an add-on to generate code for type-safe collections until we have templates in C# (likely) and VB (unlikely). The benefit of a type-safe collection, of course, is that you can use it without having to cast items to and from objects. Also, Shawn has been very careful to implement a collection class that is very efficient for both reference types and value types.
Once you've setup it up and defined your collections in a collection definition file in your project, you'll have type-safe collection classes generated as part of your design-process, as shown here:

Figure 1: collections.xml collection definition file

Figure 2: collections.xml and generated collection.cs implementation file

Figure 3: CollectionGen custom tool add-in associated with the collections.xml file

Figure 4: Generate type-safe collection code
Enjoy!
Also, Atif Aziz used some of my custom tool code and built a generic VS.NET code generator shim that allows you to build a code generator that plugs into VS.NET by implementing a single method.
4/6/2002 (updated 3/4/2005)
RegexDesigner.NET is a powerful visual tool for helping you construct and test .NET Regular Expressions. When you are happy with your regular expression, RegexDesigner.NET lets you integrate it into your application through native C# or VB.NET code generation and compiled assemblies (usable from any .NET language).

Anthony Bova had this to say about RegexD: "Thank you for this program. I had some nasty text files to parse and this cut through it like a hot knife through butter!"
Fri, 3/8/02
Inspired by my need to know who was calling without hauling my butt off the couch to look at the caller ID on the phone across the room (my father always said that "laziness is the mother of invention"), I built a couple of C# classes for managing an IM connection and an IM session. The test client is a console application that just sends messages and dumps whatever it gets from the IM server to the console, but I think it would serve as the code is the beginnings of a real IM client. It does the MD5 stuff properly and handles being redirected to another IM server, so the hard part of the protocol is already implemented. The sample itself is a handy little program that logs in as an IM user, sends a message to another IM user and logs back off again. Perfect for annoying your office mates. Enjoy.
BTW, Harry Pierson has made a number of updates to this core code to support his full-blown .NET IM client application. Check it out!
Sat, 2/16/01
Genghis is a set of extensions built on top of .NET and integrated with WinForms to provide application-level services in the same flavor as the Microsoft Foundation Classes. Genghis gets its name as the functional heir to Attila, a similar set of functionality built on top of ATL.
Tue, 1/22/02
Are you building and deploying .NET applications in a secure environment, e.g. over the intranet or the internet? If so, they you've probably mourned the loss of the binary and SOAP formatters that can automatically serialize a graph of objects that are marked as [Serializable] and that may also implement ISerializable and IDeserializationCallback. Both of these formatters are dependent on reflection, which will not be available in a more restrictive security environment. Likewise, even ISerialization.GetObjectData is verboten if you wanted to do this kind of thing yourself. As far as that goes, [Serializable] and ISerialization should be forbidden in a secure environment, as it allows a client to get and set the private variables of an object, potentially causing harm.
Still, security is the enemy of usability, to paraphrase Keith Brown. So, in the spirit of a balancing the design need for objects that can serialize themselves with the goal of complete disclosure in a secure world, I've built my own "safe" formatter. It only uses facilities of the runtime that work in the most secure environment of the default settings for the internet zone. So that objects can guard themselves against malicious data, I define a new interface called ISafelySerializeable that they need to implement to support this serialization facility. The protocol is exactly the same as ISerializable, so if that interface is already being implemented, the implementation of GetObjectData can be shared between both interfaces.
Currently, the code is in alpha and is riddled with TODO statements, but its functional enough today for actual usage. My SafeFormatter and test harness are available for your feedback. Enjoy.
1/6/02
If you haven't seen it yet, check out the VS.NET Fun Facts piece that started as praise and bitching about VS.NET, but turned into something pretty useful if you'd like to get the most out of VS.NET.
Wed, Oct 10, 2001
I've updated CorPub to show *all* managed AppDomains by initializing the COR debugging sub-system prior to enumerating them. Thanks to Atif Aziz for the tip.
Thu, Sept 13, 2001
I built the CorPub utility when my friend Jason pointed me at the .NET corpub.idl interfaces (his exact words were "ICorPublishProcess rocks!"). CorPub lists the managed processes on the current machine and the AppDomains in each process, as follows:
Managed process 0xa54: D:\project\mine\RegexPlorer\bin\Debug\RegexPlorer.exe AppDomain 0x1: RegexPlorer.exe Managed process 0xdc8: C:\vs.net\Common7\IDE\devenv.exe AppDomain 0x1: DefaultDomain Managed process 0x1ec: C:\PROGRA~1\MICROS~2.NET\FRAMEW~1\Bin\ildasm.exe AppDomain 0x1: DefaultDomain
It's fun for spelunking. Enjoy.
NOTE: .NET beta 2 is required to run this utility.
Mon, 26 Jun 2000
To deal w/ the number of wrapped URLs I get in my email box, I built UrlRun. It checks the clipboard for an URL, no matter how broken, strips spaces, newlines and greater thans out of it and runs IE. To handle an URL as show above, select it, copy it to the clipboard and launch UrlRun.exe. I keep it on my QuickStart toolbar.
If you happen to be using Outlook 2000 or Outlook XP, Tim Tabor has built an UrlRun add-in that does the magic by simply right-clicking on a mangled URL that's you've selected. It's pure sex.
Wed, Aug 8, 2001
xmlValid is simple command line utility that will check an xml file for well-formedness and, optionally, will validate it against a supplied XML schema file (xsd). I built it to check that my site's HTML files were well-formed (and therefore XHTML-compliance), but it's got all kinds of other uses, including checking .NET .config files. Source is included. Enjoy.
Usage: xmlValid.exe xmlFile [xsdFile]
Note that this utility requires .NET beta 2 to be installed.
Wed, Aug 8, 2001
Whenever I set up a new machine (which happens a lot as WinXP and .NET go through their beta & RC cycles), I always need to manually set up the completion character (to TAB, of course) in the Registry. Shawn VanNess posted a .rgs file that would set this up without the lengthy search through the Registry. Inspired by Shawn, here's my own completionChar.reg that doesn't require a program to parse .rgs files (which doesn't come with Windows).
BTW, if you don't know about the command shell's Completion Character, stop right now, run the completionChar.reg file, start up a WinNT/Win2K/WinXP command shell, type "cd c:\p[TAB]" and watch while the shell expands it to "cd C:\Program Files\" for you. If you have other directories that start with "c:\p", continue to hit [TAB] to cycle through them. This works for any directory or file name and it boosts my productivity by about 100% on the command line. I can't live without it!
Wow. I'm impressed as all get out. Hugh Brown has reverse-engineered Gen<X> as one of the tests of his NullScript implementation. I wish I would have had this when I started Gen<X> a couple of years ago. It would've saved me figuring out how ASP did it.
My thinking along these lines years ago led me to go the opposite way, i.e. I built a front-end ASP parser that generated script for VBS. I called it TextBox (which, as a Win32 programmer, I should've realized was a terrible name...).
Here's my moniker wizard that includes the framework used by the Basic Monikers.
The great and powerful Tim Ewald (author of Transactional COM+: Building Scalable Applications and personal friend of mine) put together a handy little set of COM+ classes and utility functions in a concise header file that he has graciously allowed me to host. Among my favorites are IsInActivity, IsInTransaction, IsSecurityEnabled, GetCallersName, IsCallerInRole, and parameterized versions of CoGetObjectContext and GetAspObject (which is even cooler than my CAspPtr). Download the code! Buy the book! Feed your brain!
I got tired of not having getopt under Win32 and the best version to port doesn't handle slashes (as per the Windows standard) or @files for arguments and it requires you to give away the source for every app that uses it, so, inspired by my friend Josh Gray, I built my own. It supports typed flags and params, @file support and building full usages on the fly.
Plus, the latest version has support for parsing ANSI or Unicode argfiles, as provided by Johan Nilsson. Thanks, Johan! Also, I've added a contribution by Paul Westcott to support arguments with restricted values. Thanks, Paul! And, as if that weren't enough, Adis Delalic contributed a UML diagram to describe how the CLP is built. Wow.
And as if that weren't enough, Keith Brown ported the command line parser to VS.NET. Thanks, Keith!
I've seen lots of interest lately in expando objects, e.g. objects that can add methods and properties on the fly. Joe Graf wrote a piece on IDispatchEx in MIND that was pretty interesting. My own implementation of IDispatchEx is available here. It supports expando objects that have no static properties or methods as well as those that do. Check out the DispExTest.js for a demonstration, dispeximpl.h, dynamemlist.h and dynamemlist.cpp for the implementation and MyExpando.h for the usage.
WTL is, spiritually at least, what the MFC team would've come up with had they started with the C++ language as it is today. It's an extension to ATL and available as a download from Microsoft.
If you have trouble downloading WTL, see Petr Prikryl's "Easy Installation of WTL" post on the Code Project site.
WTL is pretty much completely undocumented, but you can read about it in a 2-part series by Chris Sells, Dharma Shukla and Nenad Stefanovic (chief engineer on WTL at Microsoft):
You can also read about WTL on iDevResource: WTL Architecture by Dr. Richard Grimes.
WTL is officially unsupported, but the ATL mailing list has lots of coverage of WTL.
The CodeProject is gathering a set of WTL resources at www.codeproject.com/wtl.
Yahoo has a WTL newsgroup.
CComBool is a class to prevent the misuse of the VARIANT_BOOL type. VARIANT_BOOL is a problem because its legal values are -1 and 0 instead of 1 and 0, making converting back and forth between bool, BOOL and VARIANT_BOOL problematic. CComBool supports the constructors and operators needed to convert between the three C++ Windows Boolean types. It also supports operator& and CopyTo for common COM client and server usage. CComBool is available here.
The following table lists the various prices you pay for using the CRT and the default Win98 support in VC6. The builds were done with VC6, SP3, ATL COM in-proc server, no classes, no MFC, no merged p/s:
| Target | CRT | Win98 | Size |
| RelMinSize | _ATL_MIN_CRT | yes | 24KB |
| RelMinDepend | _ATL_MIN_CRT | yes | 24KB |
| RelMinSize | _ATL_MIN_CRT | /opt:nowin98* | 7KB |
| RelMinDepend | _ATL_MIN_CRT | /opt:nowin98 | 10KB |
| RelMinSize | MSVCRT | /opt:nowin98 | 20KB |
| RelMinDepend | MSVCRT | /opt:nowin98 | 22KB |
*Note: /opt:nowin98 is a VC6 linker switch that says not to align binaries on a Win98-friendly boundary. /opt:nowin98 builds will still load and run under Win98 without a problem, but the loading time could be longer. Also, when images get above 24KB, the /opt:nowin98 seems not to much of an affect on the size of the image.
Dharma Shukla and I wrote "Extending ATL3.0 Containment to Help You Write Real-World Containers" in the 12/99 issue of MSJ detailing how to add much-needed features to ATL's support for control containment. Dharma wrote the sample code that accompanies the piece and has already made improvements to the code based on feedback. He's maintaining the history and bits here.
Attila stands for "ATL for Applications." Attila is a set of extensions built on top of ATL to provide application-level services in the same flavor as MFC. Towards that end, Attila uses a lot of the same notions as ATL, e.g. heavy use of templates, static binding and reliance on the compiler and the linker doing their job. Also, in the flavor of ATL, Attila is under-documented and requires a lot of user investment to make use of it. However, once you do, we think you'll find the flexibility and efficiency worth it. If you don't, you haven't lost much, 'cuz Attila is free. Enjoy.
The Simple Object II ATL ObjectWizard Extension (whew -- I've got to come up with a shorter name...) provides the following features:
Originally, SimpleObject2 was built to do away with the one benefit of IDispatchImpl over IDelegatingDispImpl -- wizard support. As do most things developed under the greedy eye of my colleagues, it grew to support a few more features than that. It's available for download here. Enjoy.
I got tired of not having a smart type for SAFEARRAYs, so I built one. It's limited to one dimension (does anyone use multi-dimentional SAFEARRAYs?) and provides one class for the SAFEARRAY and another for the data itself (the lock is a resource, too), but the usage is pretty nifty. See comvector.h for the what and the how.
Also, Ron Jacobs sent me an ATL port of COleSafeArray called CComSafeArray that I've made available here.
This zip provides two classes for use with dates and times under Windows:
If you'd like to know about how to expose multiple IDispatch implementations from a single COM object, check out this extensive treatment of that very topic.
At atlmdi.zip, please find Charles Petzold's famous raw Win32 MDI application, MDIDemo, ported to ATL. See atlmdi.h for a set of base classes for building MDI applications in ATL and mdidemo.cpp for an example of their use.
Are you getting this: "Error: object doesn't support this property or method" when you try to call a method on your ATL HTML Control exposed external dispatch (accessed via window.external in the HTML of the control)? Did it used to work with IE4 and now it doesn't with IE5? That's because the ATL boys played fast and loose with the identity laws of COM and, while it took the COM police a while to catch up with them, catch up with them they did.
Download WrapperDispatch.h for an explanation of the problem and my solution to it.
TraceHook is a member function call tracing delegator hook based on Keith Brown's most excellent universal delegator. It allows you to write:
// Get a COM object to wrap
CComPtr<ICalc> spCalc;
spCalc.CoCreateInstance(CLSID_Calc);
// Wrap it (when _DEBUG is defined only)
TRACEHOOK(OLESTR("MyCalc"), &spCalc.p);
// Use it
spCalc->put_Sum(0);
spCalc->Add(2);
spCalc->Add(2);
long nSum;
spCalc->get_Sum(&nSum);
and see the following in the debug output (with no changes to the object's source) :
MyCalc, ICalc::put_Sum(0)
MyCalc, ICalc::Add(2)
MyCalc, ICalc::Add(2)
MyCalc, ICalc::get_Sum()
Notice that the call stack is now dumped (for duals, either directly or via IDispatch, or any method with automation-compliant data types, thanks to features added by the most excellent Simon Fell! He also added the ability to hook objects created in scripting environments (or VB or Java, too), e.g.
' WSH Test script for CalcSvr / TraceHook
' Create the implementation of ITraceHookFactory
set th = CreateObject("UDTraceHookSvr.TraceHook")
' Create an object (an <object> tag in HTML would be fine, too)
set calc = CreateObject("CalcSvr.Calc")
' Trace all further calls on calc
th.ComTrace "MyCalc", calc
calc.sum = 0
calc.add 2
calc.add 2
msgbox "2+2= " & calc.sum
would yield the following debug output:
MyCalc, IDispatch::(Invoke) sum(0)
MyCalc, IDispatch::(Invoke) add(2)
MyCalc, IDispatch::(Invoke) add(2)
MyCalc, IDispatch::(Invoke) sum() returned 4
The source, pre-built binaries and client-side headers are available here. The pre-built binaries include Keith's delegator as well.
If you've ever had to write the code to pull the ASP intrinsic objects from the MTS context, you might appreciate CAspPtr, which allows the following:
STDMETHODIMP CJon::DoIt() {
CAspPtr<IResponse> spResponse;
if( spResponse ) {
spResponse->Write(CComVariant(OLESTR("Baby got <b><i>Response</i></b>.")));
}
return S_OK;
}
CAspPtr is available here and was inspired by Jon Flanders. Thanks, Jon!
Visual Basic and its variants (sic) use IEnumVARIANT to implement the For-Each statement. Unfortunately, they only ask for 1 element at a time, leading to terrible performance across apartments. I propose two solutions. One allows you to wrap any collection in a CollectionBuffer object and set the buffering yourself, e.g.
Dim collBuffer As Object
Set collBuffer = CreateObject("SmartEnumSvr.CollectionBuffer")
collBuffer.Collection = coll ' coll is an interface on any collection
collBuffer.BufferSize = 1024 ' How many items would you like buffered?
c = 0
For Each v In collBuffer ' Uses SmartEnumVARIANT to buffer items
c = c + 1
Next v
MsgBox "Counted " & c
The second solution allows you to leverage SmartEnumVARIANT on the server-side, seamlessly to the client. A detailed explanation and code is available here.
Not too long ago, Jonathan Borden, jborden@MEDIAONE.NET, posted a nifty class called IMarshalByValueImpl that implemented IMarshal for objects interested in being marshaled by value . It was built in the ATL style, i.e. it used fun template tricks, and depended on the COM class also implementing either IPersistStream or IPersistStreamImpl. And, in fact, ATL provides an implementation of IPersistStreamInit called IPersistStreamInitImpl. However, IPersistStreamInitImpl has one fatal flaw: it implements GetSizeMax by returning E_NOTIMPL. This breaks Jonathan's IMarshalByValueImpl, which depends on a sane implementation of GetSizeMax from the class.
IPersistStreamInitImpl2 leverages the property map of ATL's IPersistStreamInitImpl to build GetSizeMax. The code is not pretty. It's just pieced together from ATL's implementation of IPersistStreamInit::Save and CComVariant::WriteToStream, but it seems to work (thanks to Dharma Shukla, v-dharsh@microsoft.com, for testing it!).
Here's the usage for giving a class MBV:
class PassByValue :
public CComObjectRootEx<CComMultiThreadModel>,
public CComCoClass<PassByValue, &CLSID_PassByValue>,
public IDispatchImpl<IPassByValue, &IID_IPassByValue>,
public IMarshalByValueImpl<PassByValue>,
public IPersistStreamInitImpl2<PassByValue>
{
public:
BEGIN_COM_MAP(PassByValue)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(IPassByValue)
COM_INTERFACE_ENTRY(IMarshal)
// Don't need to expose these to the world
//COM_INTERFACE_ENTRY(IPersist)
//COM_INTERFACE_ENTRY
(IPersistStreamInit)
END_COM_MAP()
BEGIN_PROP_MAP(PassByValue)
// List of properties to marshal-by-value
...
END_PROP_MAP()
// IPassByValue methods
...
private:
// Whatever data members you wish to marshal
...
public:
BOOL m_bRequiresSave; // Required by IPersistStreamInitImpl2
};
There are three kinds of ways to declare a dispatch-based interface in IDL, but ATL (as of version 3.0), only supports the implementation of 1.5 of them (duals and a raw dispinterfaces for handling events). The ATL Dispatch Sampledemonstrations the use of three ATL-based classes, one for implementing each type of dispatch-based interface. The header file that defines these classes, dispimpl2.h, is provided for use in your own projects.
BTW, thanks to Ehab Kashkash for making this code work under VS.NET as well as VC6.
If you're into COM Monikers, here's one that I like.
Wish there was a moniker that did CoCreateInstance just like the Class Moniker calls CoGetClassObject? Wish you were able to compose the Class Moniker with a host name? Then you'll want the BasicMonikers project, which bundles together the New moniker and the Host moniker. Sample syntax follows:
dm.newmk.1:Excel.Application dm.newmk.1:00024500-0000-0000-C000-000000000046: dm.hostmk.1:frodo:!dm.newmk.1:00024500-0000-0000-C000-000000000046: dm.hostmk.1:frodo:!clsid:00024500-0000-0000-C000-000000000046:
regsvr.reg is a regedit script file that adds Register COM Server and Unregister COM Server to the context menu for DLLs, OCXs and EXEs under Win95+ and NT4+. In addition, it's also been updated to add Register TypeLib and Unregister TypeLib commands to .tlb, .odl, .dll, .ocx and .exe files, using VC6's new regtlib tool.
I've developed a set of macros to support implementing interfaces using nested composition in ATL (the one common way of implementing interfaces they neglected). The benefit of composition is that it is easy to implement multiple interfaces with methods with the same name but that require different behavior, e.g.
interface IArtist : IUnknown {
HRESULT Draw();
}
interface ICowboy : IUnknown {
HRESULT Draw();
}
The benefit of this particular implementation is that it has no object size overhead. Interfaces implemented using nested composition have no greater overhead than using multiple-inheritance. Feel free to download atlcompose.h for your own use.
Have you ever been jealous of the VB programmer who could write this:
sub EnumVariants(col as Collection)
dim v as variant for each v in col
' Do something with v
next v
end sub
If so, you may be interested in the STL-style IEnumXxx iterator I've built. You'll also need a supporting file, atlcopies.h.
githelp.hdefines a set of wrappers for implementing inter-thread marshaling using the GIT instead of streams. githelp.cpp provides the non-inline implementation. For another spin on GIT usage, check out Don Box's GitLip.