Reading Attributes
Attributes are read with the reflection API. There are several ways to read the attributes on a type, depending on whether you are reading the attribute on an instance of the type or through type metadata. If you have an instance, you can create an instance of the System.Reflection.TypeDelegator class and call GetCustomAttributes to get an array of attributes MyAttributedClass myclass new MyAttributedClass TypeDelegator td new TypeDelegator myclass.GetType foreach object o in...
COM Interop
Earlier in this chapter I covered interop with native code, and I showed how this worked with Win32 APIs. The .NET Framework also has support for accessing COM components, and for native code to access .NET components as if they were COM components. This access is seamless in both directions, and the VS.NET debugger has been written to take COM Interop into account, so stepping from managed code to unmanaged code and vice versa also happens seamlessly. In this section I will outline how to use...
COM Callable Wrapper
Figure 4.2 shows the COM callable wrapper in action. The COM client calls coCreateInstance with the appropriate CLSID which I will talk about later and gets the COM callable wrapper with the interface that the client requested. The CCW conceptually has two parts a managed part and a native part. The COM client accesses the native part, which implements iunknown and hence has a COM identity. The managed part of the CCW holds a managed reference to the component and hence keeps the component...
SidebySide Components
Side-by-side COM components are components for which two or more versions exist on the same machine and each version can run at the same time in different processes. Strictly speaking, COM should not allow side-by-side components because different versions of coclasses should have different names. In practice, however, you will always come across the situation in which a component needs to be updated to fix a bug, and you do not want to have to update the clients that use instances of this...
Figure 923 Schematic of trace settings
pszFileName NULL const pszFileName NULL const This information can be changed at runtime by calls to the methods on the global allocator instance. In addition, you can use this global object to persist the settings to disk SaveSettings or to load them from a disk file LoadSettings . If you call LoadSettings without a file name, the name of the current module is used appended with .trc. However, you cannot call SaveSettings without a file name. This information can be changed at runtime by calls...
Performance Counting
I have already mentioned that the event log API is arcane, and that .NET could have improved on it significantly but instead has merely provided a weak alternative. The Win32 performance monitor API is also arcane, and it is also complicated, but in this case the .NET designers have provided a much better solution. To provide even the simplest performance monitor counter, you have to write a sharable DLL that manipulates the system registry and creates some complicated, multinested structures....
NET Remoting
Now let's take a look at how remoting is handled in .NET. There are three ways to access a .NET component remotely 1. NET remoting. Components are exposed through .NET channels and use distributed garbage collection. Components can be activated by the client one component per client or by the server singleton, or single call and then accessed by the client. 2. Web Services. Essentially these are singleton components, accessed through a well-known Web Service interface. The transport protocol is...
Unmanaged Exceptions
Unmanaged code may throw exceptions. When your code calls unmanaged code, any SEH structured exception handling exception thrown by this code will be caught by the runtime, which will attempt to convert the exception into an exception type it understands. The following code, for example will throw an exception of the type System.NullReferenceException in the managed code that called the function. In some cases the runtime cannot convert the exception type e.g., if you throw a C exception , so...
Explicit Allocation of Buffers
The Marshal class in the System.Runtime.InteropServices namespace has methods to allow you to allocate buffers, read and write data in unmanaged buffers, access COM objects, and access exception and error values from unmanaged code. In this section I will cover unmanaged buffers. The Marshal class allows you to allocate buffers using two general-purpose allocators the Win32 hglobal allocator and the COM IMalloc allocator. In addition, it allows you to allocate bstr values, which use the bstr...
Marshaling Objects between Contexts
When you pass an object across an application domain or a context boundary, you have to explicitly tell the runtime how the object should be marshaled Is the most important point of the object its location or its state If the location is important that is, the object must be accessed from a specific context then the object should be marshaled by reference. If the location is not important, the object can be marshaled by value. Of course, there are other criteria to take into account the size...
Creating Resources
Assemblies contain either compiled resources or uncompiled resources, and these can be either embedded within the assembly or supplied as a separate file and a link provided within the manifest of the assembly. Resources in an assembly are named. For example, here is some IL .hash algorithm 0x00008004 .ver 0 0 0 0 This code indicates that an assembly called App.exe has a resource called MyRes.resources, which can contain several items, but ILDASM does not decompile the resource format, so these...
ASPNET Services
ASP.NET will implement all that is needed to accept requests and encode the returned data. All your Web Service class needs to do is implement the methods and mark them with WebMethod . However, your Web Service may want to use some of the facilities of ASP.NET it should be derived from System.Web.Services.WebService. I mentioned earlier that as they stand, Web Services are essentially stateless. Through the Webservice class, however, you can have application and session state application state...
ATL Projects
ATL has undergone a total revamp since VS6. There are essentially three main changes VC Visual C attributes, the ATL7 library, and ATL Server. The ATL7 library consists of many new utility classes and owes its existence partially to ATL Server and partially to the tighter integration between ATL and MFC. Indeed, many MFC features, such as CString, are now implemented by ATL classes. So rather than having to import MFC to use those classes in an ATL project, as the ATL3 developer must do, the...
Startup Options
If the project is a DLL, you can use the Debugging properties Command property C to identify the process to start for the DLL. This can be any process that you choose, or it can be one of the options in Table 9.5. You get these options whether the DLL is managed C or unmanaged C , an ATL or MFC control, an ATL in-process server, or an MFC DLL. If you create an ATL Server project, the Debugging properties page for the ATL Server DLL will give the URL to the .srf file for the HTTP URL property...
Managed C and Interfaces
You can declare an interface in VC 7.0 using the_interface keyword. In previous versions interface was declared as a struct, which meant that you could derive an interface from another struct, and you could add method implementations and data members i.e., storage for data . To a certain extent declaring interface as a struct could be beneficial the following is an excerpt from unknwn.h 6 virtual HRESULT STDMETHODCALLTYPE QueryInterface REFIID riid, void ppvObject 0 virtual ULONG...
The VSNET Command Line
The Visual Studio application is devenv.exe. You can run devenv as a command-line application, which is particularly useful for building solutions as part of an automated build process. The build command-line switches are summarized in Table 5.10. You have the option of building a project within a solution or the entire solution. If you choose to build just a project in a solution, then you need to use the project switch to indicate which project. Each of the various build command-line switches...
Figure 915 The VSNET debuggers
Two debuggers are provided with the .NET Framework cordbg.exe and DbgCLR.exe. The former is a command-line application, and the latter is a GUI debugger that is essentially a cut-down version of the VS.NET managed debugger. If you select a new instance of VS.NET, VS7Jit starts the IDE by launching it as a COM local server. The IDE has the following CLSID BC104 6A0-CB4 4-42 41-B8D9-0 68 82 4 3AFBC3 If you look at the LocalServer32 key for this server, you'll see that the development environment...
File Function and Address
The location of a breakpoint is shown on three tabs of the Breakpoint Properties dialog. The File tab shows the name and path of the file, and the Line and Character text boxes indicate the actual position of the breakpoint. Typically, whatever value you set to the Character position, the breakpoint is treated as if it were at character position 1. The Function tab gives details about the actual function where the breakpoint is to be found The Function text box gives the fully qualified name of...
Object Browser
The Object Browser window allows you to browse objects, their base classes, and their interfaces. To be able to show this information it needs type information, and the source of this information depends on whether the code is managed or unmanaged. The Class View window also needs type information so that it can show you the types in your project , and this information will be held in the project's .ncb file. The Object Browser window also has access to the .ncb file, so it will show the same...
Executing Code
Figure 1.1 shows a schematic of how code is executed in .NET. All .NET code is contained in deployment packages called assemblies. These include the IL of the types that they contain and the metadata that describes those types. Each assembly also has information about the assemblies that its types use so that when the code calls a type in another assembly, the runtime can locate and load the assembly and finally load the type. When the runtime has loaded the type, it replaces the entry point of...
Deployment Solutions
To deploy a solution, you copy appropriate files to a specific location, register those files in the registry, or maybe make configuration changes to another file , create shortcuts and Start menu entries, and possibly make changes to a log file that can be viewed later. However, it does not end there because well-behaved code will also provide uninstall information so that the user can completely remove the code from her system. Removing code is often far more difficult than installing it...
Debugging ATL Server Projects
ATL7 has new facilities for providing tracing information and detecting memory leaks. ATL7 is now fully integrated with MFC, so MFC applications can use these facilities too. The development of these new facilities has been driven by the necessity to make ATL Server as robust as possible, and as you'll see, it has resulted in a rich API of debugging classes. You make assertions in your code on expressions that must be true for the code to work. Assertions compile to nothing in release code, so...
Class Declaration
The_gc and_value keywords have a profound effect on C classes. Without either of these, a C class will be allocated according to normal C rules When you declare the variable as an auto variable, it will be allocated on the stack and when you explicitly allocate it with the C new operator, the object will be created on the C heap. This is true even if the code is compiled with clr. Applying_gc indicates that instances of the class are allocated on the GC-managed heap, which means that you can...
Global Methods
The main , wmain , WinMain , or wWinMain function in a source file is treated as the entry point of a .NET executable assembly. By default, you do not write a DllMain function for library assemblies, although you can do so, as shown here stdcall DllMain unsigned int hinstDLL, unsigned int fdwReason, void lpvReserved When the library assembly is loaded, the operating system will call the exported DllMain . The interesting point is that this function will be IL and needs the runtime to be called....
Boxing
Console WriteLine Sthe value is 0 , 42 This seemingly innocuous code will not compile. The reason is that the static method Console WriteLine has many overloaded forms, but none that take a string and an integer. The nearest form looks like this csAppearance Color.Wheat, Color.Blue , csAppearance Color.LightYellow, Color.Blue , csAppearance Color.Black, Color.Brown , csAppearance Color.Brown, Color.Green static void WriteLine String , Object The format string is passed in the string parameter,...
Component Services
Any discussion about .NET and COM component services must start with this statement COM component services are .NET component services. .NET does not replace COM because .NET does not provide component services This implementation has always been the intention, and the reason that we had COM when Windows 2000 was released is that Microsoft decided that that part of the component framework was ready for release and would be useful to COM but the managed runtime part what we call .NET wasn't....
ATL Server Project and ATL Server Web Service
The C C category of the Project wizard includes the following two entries for creating wizards ATL Server Project and ATL Server Web Service. In fact, these wizards are the same, which is why I am covering both of them in this section. Figure 7.1 shows the relationship between the ATL Server ISAPI and IIS. When an HTTP request comes into IIS, it is handled by a thread taken from a pool maintained by IIS. This thread will locate the ISAPI DLL that has been registered in the IIS metabase to...
Calling Managed Code
Your unmanaged code is allowed to host the .NET Runtime 21 . That is, Microsoft has provided the code that allows you to load and initialize the runtime, create an application domain, and load .NET objects. This code is naturally provided through a COM API. The prototypes for these functions and interfaces can be found in mscoree .h, and they are exported from mscoree.dll. 2 For a more complete description of this mechanism, see Steven Pratschner's article Implement a Custom Common Language...
Figure 35 Context sink chains
The context sinks are used to process messages as they enter or leave the context. Context sinks implement the IMessageSink interface and are created in response to a call to a context property. To create a context property, you derive an attribute from ContextAttribute and implement either IContributeClientContextSink or IContributeServerContextSink or both , and then apply this attribute to the class that needs to use the custom context. The runtime calls GetClientContextSink or...
Figure 921 The failedassertion dialog
Program File c temp asserttest asserttest.cpp Line 8 For information on how your program can cause an assertion failure, see the Visual C documentation on asserts. Press Retry to debug the application The failed-assertion dialog has three buttons. If you click the Abort button, the program will be aborted immediately. If you click the Ignore button, processing will continue, but you should be aware that something is wrong in the process, so an exception could occur later. The final button,...
Hosting Remote Objects in IIS
Earlier in this section I showed the minimal code for a remote server. It looked rather sparse, with just a call to RemotingConfiguration.Configure and a call to Console.ReadLine to prevent the server from finishing early. Because the configuration file has all the information about the channels to register and the objects that will be available as remote objects, it seems that there ought to be a standard server process that exists simply to call RemotingConfiguration.Configure . Such a...
Figure 98 The Locals window showing a linked list
public List next null name null public string name public List next static public List AddLink List node, string s if node null node.next current public List next null name null public string name public List next static public List AddLink List node, string s if node null node.next current This class has a member that is a reference to another node in the linked list. The class could be used as follows List beatles null List current null beatles current List.AddLink null, John current...
ATL Object Map
There is one nagging issue that I need to address at this point the object map. In the old ATL3 days, the object map was a map implemented in the main .cpp class. The Object wizard would update this map when it added a class to a project, but if you changed the class or indeed removed it from your project, the onus was on you to change the class's entry in the object map. This meant that a piece of information about the class was stored in a location completely separate from the class. This...










