.NET Application Packaging, Deployment and Configuring Application.


Deployment and Packaging .NET Assemblies.
Deployment and Packaging of .NET Application
Today, applications are created using the types developed by Microsoft or custom built by you. If these types are developed using any language that targets the common language runtime (CLR), they can all work together seamlessly, i.e. different types created using different .NET languages can interact seamlessly.

.NET Framework Deployment Objectives:

All applications use DLLs from Microsoft or other vendors. Because an application executes code from various vendors, the developer of any one piece of code can’t be 100 percent sure how someone else is going to use. Even if this kind of interaction is unsafe and dangerous. End users have come across this scenario quiet often when one company decides to update its part of the code and ship it to all its users. Usually these code should be backward-compatible with previous version, since it becomes impossible to retest and debug all of the already-shipped applications to ensure that the changes will have no undesirable effect.

When installing a new application you discover that it has somehow corrupted an already-installed application. This predicament is known as “DLL hell”. The end result is that users have to carefully consider whether to install new software on their machines.

The problem with this is that the application isn’t isolated as a single entity. You can’t easily back up the application since you must copy the application’s files and also the relevant parts of the registry you must run the installation program again so that all files and registry settings are set properly. Finally, you cant easily uninstall or remove the application without having this nasty feeling that some part of the application is still lurking on your machine.

When application are installed, they come with all kinds of files, from different companies. This code can perform any operation, including deleting files or sending e-mail. To make users comfortable, security must be built into the system so that the users can explicitly allow or disallow code developed by various companies to access their system resources.

The .NET framework addresses the DLL hell issue in a big way. For example, unlike COM, types no longer require settings in the registry. Unfortunately, application still require shortcut links. As for security, the .NET Framework includes a security model called code access security   Whereas Windows security is based on a user’s identity, code access security is based on permissions that host applications that loading components can control. As you’ll see, the .NET Framework enables users to control what gets installed and what runs, and in general, to control their machines, more than Windows ever did.

Developing Modules with Types

Lets start with an example as shown below:

public sealed class Appln {

public static void Main() {

System.Console.WriteLine(“Hello My world”);

}

}

This application defines type called Appln. This type has a single public, static method called Main. Inside Main is a reference to another type called System.Console. System.Console is a type implemented by Microsoft, and the intermediate Language (IL) code that implements this type’s methods is in the MSCorLib.dll file. To build it write the above source code into a C# file and then execute the following command line:

csc.exe /out : Appln.exe /t:exe /r:MSCorLib.dll Appln.cs

This command line tells the C# compiler to emit an executable file called Appln.exe (/out: Appln.exe). The type of file produced is a win32 console application (/t[arget]:exe).

When the C# compiler processes the source file, it sees that the code references the System.Console type’s WriteLine method. At this point, the compiler wants to ensure that this type exists somewhere, that it has a WriteLine method, and that the argument being passed to this method matches the parameter the method expects. Since this type is not defined in the C# source code, to make the C# compiler happy, you must give it a set of assemblies that it can use to resolve references to external types. In the command line above /r[eference]:MSCorLib.dll switch, which tells the compiler to look for external types in the assembly identified by the MSCorLib.dll file.

MSCorLib.dll is a special file in that contains all the core types: Byte, Char, String, Int32 and many more. In fact these types are so frequently used that the C# compiler automatically references the MSCorLib.dll assembly. i.e. the above command line can be shortened as

csc.exe /out : Appln.exe /t:exe Appln.cs

Further you can drop /out and /t:exe since both match, so the command would be

csc.exe Appln.cs

If for some reason, you really don’t want the C# compiler to reference the MSCorLib.dll assembly, you can use the /nostdlib switch. Microsoft uses this switch when building the MSCorlib.dll assembly itself. For e.g. the following will throw error since the above code references System.Console type which is defined in MSCorLib.dll

csc.exe /out: Appln.exe /t:exe /nostdlib Appln.cs

This means that a machine running 32-bit or 64-bit versions of Windows should be able to load this file and do something with it. Windows supports two types of applications, those with a console user interface (CUI) and those with a graphical user interface (GUI). Because I specified the /t:exe switch, the C# compiler produced a CUI application. You’d use the /t: winexe switch to cause the C# compiler to produce a GUI application.

Response Files

I’d like to spend a moment talking about response files. A response file is a text file that contains a set of compiler command-line switches. You instruct the compiler to use a response file by specifying its name on the command line by an @sign. For e.g. you can have response file called myApp.rsp that contains the following text

/out: MyAppln.exe

/target: winexe

To cause CSC.exe to use these settings you’d invoke it as follows:

csc.exe @myAppln.rsp codeFile1.cs CodeFile2.cs

This tells the C# compiler what to name the output file and what kind of target to create. The C# compiler supports multiple response files. The compiler also looks in the directory containing the CSC.exe file for a global CSC.rsp file. Settings that you want applied to all of your projects should go in this file. The compiler aggregates and uses the settings in all of these response files. If you have conflicting settings in the local and global response file, the settings in the local file override the settings in the global life. Likewise, any settings explicitly passed on the command line override the settings taken from a local response file.

When you install the .NET Framework, it installs a default global CSC.rsp file in the %SystemRoot%\Microsoft.NET\Framework\vX.X.Xdirectory where X.X.X is the version of the .NET Framework you have installed). The 4.0 version of the file contains the following switches.

# This file contains command-Line options that the C# Compiler has to process during compilation

# process, unless “noconfig” option is specified.

# Reference the common Framework libraries

/r: Accessibility.dll

/r: Microsoft.CSharp.dll

/r: System.Configuration.Install.dll

/r: System.Core.dll

/r: System.Data.dll

/r: System.Data.DataSetExtensions.dll

/r: System.Data.Linq.dll

/r: System.Deployment.dll

/r: System.Device.dll

/r: System.DirectoryServices.dll

/r: System.dll

/r: System.Drawing.dll

/r: System.EnterpriseServices.dll

/r: System.Management.dll

/r: System.Messaging.dll

/r: System.Numerics.dll

/r: System.Runtime.Remoting.dll

/r: System.Runtime.Serialization.dll

/r: System.Runtime.Serialization.Formatters.Soap.dll

/r: System.Security.dll

/r: System.ServiceModel.dll

/r: System.ServiceProcess.dll

/r: System.Transactions.dll

/r: System.Web.Services.dll

/r: System.Windows.Forms.dll

/r: System.Xml.dll

/r: System.Xml.Linq.dll

Because the global CSC.rsp file references all of the assemblies listed, you do not need to explicitly references all of the assemblies by using the C# compiler’s /reference switch. This response file is a big convenience for developers because it allows them to use types and namespaces defined in various Microsoft-published assemblies without having to specify a /reference compiler switch for each when compiling.

When you use the /reference compiler switch to reference an assembly, you can specify a complete path to a particular file. However, if you do not specify a path, the compiler will search for the file in the following places (in the order listed)

– working directory

– The directory that contains the CSC.exe file itself. MSCorLib.dll is always obtained from the directory. The path looks something like this %SystemRoots%\Microsoft.NET\Framework\v4.0.#####

– Any directories specified using the /lib compiler switch.

– any directories specified using the LIB environment variable

you are welcome to add your own switches to the global CSC.rsp file if you want to make your life even easier, but this makes it more difficult to replicate the build environment on different machines you have to remember to update the CSC.rsp the same way on each build machine. Also you can tell the compiler to ignore both local and global CSC.rip files by specifying the /noconfig command-line switch.

A managed PE file has four main parts the PE32(+) header, the CLR header, the metadata and the IL . the PE32(+) header is the standard information that Windows expects. The CLR header is a small block of information that is specific to modules that require the CLR (managed modules). The header includes the major and minor version number of the CLR that the module was built for: some flags, a MethodDef token (described later) indicating the module’s entry point method if this module  is CUI or GUI executable, and an optional strong-name. You can see the format of the CLR header by examining the IMAGE_COR20_HEADER defined in the CorHdr.h header file.

The metadata is a block of binary data that consists of several tables. There are three categories of tables: definition tables, reference tables and manifest tables. The following table describes some of the more common definition tables that exist in a module’s metadata block.

Metadata Definition
Table Name
Description
ModuleDef Always contains one entry that identifies the module. The entry includes the module’s filename and a extension and a module version ID. This allows the file to be  renamed while keeping a record of its original name.
TypeDef Contains one entry for each type defined in the module. Each entry includes the type’s name, base type and flags (public, private etc, ) and contains indexes to the methods it owns in the MethodDef table, the fields it owns in the fieldDef table, the properties it owns in the PropertyDef table, and the events it owns in the EventDef table.
MethodDef Contains one entry for each method defined in the module. Each entry includes the method’s name, flags (private, public, virtual, abstract, static, final, etc) signature and offset within the module where its IL code can be found. Each entry can also refer to a ParamDef table entry in which more information about the method’s parameters can be found.
FieldDef Contains one entry for every defined in the module. Each entry includes flags (in, out, retval, etc) type and name.
ParamDef Contains one entry for each parameter defined in the module. Each entry includes flags (in, out, retval etc) type and name.
PropertyDef Contains one entry for each property defined in the module. Each entry includes flags, type and name.
EventDef Contains one entry for each event defined in the module. Each entry includes flags and name.

Compiler during compilation creates an entry for every definition in the source code to be created in one of the tables defined above. Metadata table entries are also  created as the compiler detects the types, fields, methods, properties and events that the source code references. The metadata created includes a set of reference tables that keep a record of the referenced items. Table below gives some more common reference metadata tables.

Metadata Reference
Table Name
Description
AssemblyRef Contains one entry for each assembly referenced by the module. Each entry includes the information necessary to bind to the assembly: the assembly’s name (without path and extension), version number, culture and public key token. Each entry also contains some flags and a hash value.
ModuleRef Contains one entry for each PE module that implements types referenced by this module. Each entry includes the module’s filename and extension. This table is used to bind to types that are implemented in different modules of the calling assembly’s module.
TypeRef Contains one entry for each type referenced by the module. Each entry includes the type’s name and a reference to where the type can be found. If the type is implemented within another type, the reference will indicate a TypeRef entry. If the type is implemented in the same module , the reference will indicate a ModuleDef entry.  If the type is implemented in the another module within the calling assembly , the reference will indicate a ModuleRef entry. If the type is implemented in the different assembly, the reference will indicate a AssemblyRef entry.
MemberRef Contains one entry for each member referenced by the module. Each entry includes the member’s name and signature and points to the TypeRef entry for the type that defines the member.

My personal favorite is ILDasm.exe, the IL Disassembler. To see the metadata tables, executes the following command line

ILDasm MyAppln.exe

To see the metadata in a nice, human-readable form, select the View/MetaInfo/Show! menu item.

The important thing to remember is that MyAppln.exe contains a TypeDef whose name is MyAppln. This type identifies a public sealed class that is derived from System.Object (a type referenced from another assembly). The program type also defines two methods Main and .ctor (a constructor).

Main is a public, static method whose code is IL. Main has a void return type and takes no arguments. The constructor method is public and its code is also IL. The constructor has a void return type has no arguments and has a this pointer,  which refers to the object’s memory that is to be constructed when the method is called.

Combining Modules to Form an Assembly

An assembly is a collection of one or more files containing type definitions and resource files. One of the assembly’s files is chosen to hold a manifest. The manifest is another set of metadata tables that basically contain the names of the files that are part of the assembly. They also describe the assembly’s version, culture, publisher, publicly exported types and all of the files that comprise the assembly.

The CLR always loads the file that contains the manifest metadata tables first and then uses the manifest to get the names of the other files that are in the assembly. Here are some characteristics of assemblies that you should remember:

– An assembly defines the reusable types.

– An assembly is marked with a  version number.

– An assembly can have security information associated with it.

An assembly’s individual files don’t have these attributes – except for the file that contains the manifest metadata tables. To package, version, secure and use types, you must place them in modules that are part of an assembly

The reason is that an assembly allows you to decouple the logical and physical notion of reusable types. for e.g. an assembly can consist of several types. You couldn’t put the frequently used types in one file and the less frequently used types in another file.

You configure an application to download assembly files by specifying a codeBase element in the application’s configuration file. The codeBase element identifies a URL pointing to where all of an assembly’s files can be found. When attempting to load an assembly’s file, the CLR obtains the codeBase element’s URL and checks the machine’s download cache to see if the file is present. If it is, the file is loaded. If the file isn’t in the cache, the CLR downloads the file into cache from the location the URL points to. If the file can’t be found, the CLR throws a FileNotFoundException exception at runtime.

I’ve identified three reasons to use multifile assemblies:

– You can partition  your types among separate files, allowing for files to be incrementally downloaded as described in the Internet download scenario. Partitioning the types into separate files also allows for partial or piecemeal packaging and deployment for applications you purchase and install.

-You can add resource or data files to your assembly. for example, you could have a type that calculates some insurance information using actuarial table. Instead of embedding the actuarial table in the source code, you could use a tool so that the data file is considered to be part of  the assembly.

-You can create assemblies consisting of types implemented in different programming languages. To developers using the assembly, the assembly appears to contain just a bunch of types; developers wont even know that different programming languages were used. By the way, if you prefer, you can run ILDasm.exe on each of the modules to obtain an IL source code file. Then you can run ILAsm.exe and pass it all of the IL source code files. ILAsm.exe will produce a single file containing all of the types. This technique requires your source code compiler to produce IL-only code.

Manifest Metadata
Table Name
Description.
AssemblyDef Contains a single entry if this module identifies as assembly. The entry includes the assembly’s name, version, culture, flags, hash algorithm, and the publisher’s public key.
FileDef contains one entry for each PE and resource file that is part of the assembly. The entry includes the file’s name and extension, hash value and flags. If the assembly consists only of its own file, the FileDef table has no entries.
ManifestResourceDef Contains one entry for each resource that is part of the assembly. The entry includes the resource’s name, flags and an index into the FileDef table indicating the file that contains the resource isn’t a stand-alone file, the resource is a stream contained within a PE file. For an embedded resource, the entry also includes an offset indicating the start of the resource stream within the PE file.
ExportedTypesDef Contains one entry for each public type exported from all of the assembly’s PE modules. The entry includes the type’s name, an index into the FileDef table and an index into the TypeDef table. To save file space, types exported from the file containing the manifest are not repeated in this table because the type information is available using the metadata’s TypeDef table.

The C# compiler produces an assembly when you specify any of the following command-line switches: /t[arget]:exe, /t[arget]:winexe or t[arget]:library. All of these switches cause the compiler to generate a single PE file that contains the manifest metadata tables. The resulting file is either a CUI executable, GUI executable or a DLL, respectively.

The C# compiler supports the /t[arget]:module switch. This switch tells the compiler to produce a PE file that doesn’t contain the manifest metadata tables. The PE file produced is always a DLL PE file, and this file must be added to an assembly before the CLR can access any types within it. When you use the /t:module switch, the C# compiler, by default, names the output file with an extension of .netmodule.

There are many ways to add a module to an assembly. If you are using the  C# compiler to build a PE file with a manifest, you can use the /addmodule switch. Let’s assume that we have two source code files:

– File1.cs which contains rarely used types

– File2,cs which contains frequently used types

Lets compile the rarely used types into their own module so that users of the assembly won’t need to deploy this module if they never access the rarely used types:

csc /t:module File1.cs

This line causes the C# compiler to create a File1.netmodule file. Next let’s compile the frequently used types into their module, because this module will now represent the entire assembly.

We change the name of the output file to myappln.dll instead of calling it File2.dll

csc /out:File2.dll /t:library /addmodule:File1.netmodule File2.cs

This line tells the C# compiler to compile the File2.cs  file to produce the myappln.dll file Because /t:library is specified, a DLL PE file containing the manifest metadata tables is emitted into the myappln.dll file. The /addmodule:File1.netmodule switch tells the compiler that File1.netmodule is a file that should be considered part of the assembly. Specifically, the addmodule switch tells the compiler to add the file to the FileDef manifest metadata table and to add File1.netmodule’s publicly exported types to the ExportedtypesDef manifest metadata table.

The two files shown below are created. The module on the right contains the manifest.

File1.netmodule myappln.dll
IL compiled from File1.cs IL compiled from File2.cs
Metadata Types, methods and so on defined by file1.csTypes, methods and so on referenced by File1.cs Metadata Types, methods and so on defined by file2.csTypes, methods and so on referenced by File2.cs

Manifest Assembly files (self and File2.netmodule)
Public assembly types (self and File2.netmodule)

The File1.netmodule file contains the IL code generated by compiling File1.cs. This file also contains metadata table s that describe the types, methods fields, properties, events and so on that are defined by File1.cs. The metadata tables also describe the types, methods and so on that are referenced by File1.cs. The myappln.dll is a separate file. Like File1.netmodule this file includes the IL code generated by compiling File2.cs and also includes similar definition and reference metadata tables. However myappln.dll contains the additional manifest metadata tables, making myappln.dll an assembly. The additional manifest metadata tables describe all of the files that make up the assembly. The manifest metadata tables also include all of the public types exported from myappln.dll and File2.netmodule.

Any client code that consumes the myappln.dll assembly’s types must be built using the /r[eference]:myappln.dll compiler switch. This switch tells the compiler to load the myappln.dll assembly and all of the files listed in its FileDef table when searching for an external type.

The CLR loads assembly files only when a method referencing a type in an unloaded assembly  is called. This means that to run an application, all of the files from a referenced assembly do not need to be present.

Using the Assembly Linker

The Al.exe utility can produce an EXE or a DLL  PE file that contains only a manifest describing the types in other modules. To understand how AL.exe works, lets change the way the myappln.dll assembly is built:

csc /t:module File1.cs

csc /t:module File2.cs

al /out:myappln.dll /t: library File1.netmodule File2.netmodule

In this example, two separate modules, File1.netmodule and File2.netmodule, are created. Neither module is an assembly because they don’t contain manifest metadata tables. Then a third file is produced: myappln.dll which is a small DLL PE file that contains no IL code but has manifest metadata tables indicating that File1.netmodule and File2.netmodule are part of the assembly. The resulting assembly consists of the three files: myappln.dll, File1.netmodule and File2.netmodule. The assembly linker has no way to combine multiple files into a single file.

The AL.exe utility can also produce CUI and GUI PE files using the /t[arget]:exe or /t[arget]:winexe command line switches. You can specify which method in a module should be used as an entry point by adding the /main command-line switch when invoking AL.exe. The following is an example of how to call the Assembly Linker, AL.exe, by using the /main command-line switch.

csc /t:module /r:myappln.dll Program.cs

al /out: Program.exe /t:exe /main: Program.Main Program.netmodule

Here the first line builds the Program.cs file into a Program.netmodule file. The second line produces a small Program.exe PE file that contains the manifest metadata tables. In addition there is a small global function named __EntryPoint that is emitted by AL.exe because of the /main: Program.Main command-line switch. This function, __EntryPoint, contains the following IL code:

.method privatescope static void __EntryPoint$PST06000001() cli managed

{

}

As you can see, this code simply calls the Main method contained in the Program type defined in the Program.netmodule file.

Adding Resource Files to an Assembly

When using AL.exe to create an assembly you can add a file as a resource to the assembly by using the /embed[resource] switch. this switch takes a file and embeds the file’s contents into the resulting PE file. The manifest’s ManifestResourceDef table is updated to reflect the existence of the resources.

AL.exe also supports a link[resource] switch, which also takes a file containing resources. However, the /link[resource] switch updates the manifest’s ManifestResourceDef and FileDef tables, indicating that the resource exists and identifying which of the assembly’s files contains it. The resource file is not embedded into the assembly PE file; it remains separate and must be packaged and deployed with the other assembly files.

The C# compiler’s /resource switch embeds the specified resource file into the resulting assembly PE file, updating the ManifestResourceDef table. The compiler’s /linkresource switch adds an entry to the ManifestResourceDef and the FileDef manifest tables to refer to a stand-alone resource file.

You can do this easily by specifying the pathname of a res file with the /win32res switch when using either AL.exe or CSC.exe. In addition you can quickly and easily embed a standard win32 icon resource into an assembly by specifying the pathname of the .ico file with the win32icon switch when using either AL.exe or CSC.exe. Within Visual Studio you can add resource files to your assembly by displaying your project’s properties and then clicking the application tab.

Assembly Version Resource Information

When AL.exe  or CSC.exe produces a PE file assembly, it also embeds into the PE file a standard Win32 version resource. Application code can also acquire and examine this information at runtime by calling System.Diagnostic.FileversionInfo’s static GetVersionInfo method.

Here’s what the code that produced the version information looks like

using System.Reflection;

//FileDescription version version information

[assembly: AssemblyTitle(“MyAppln.dll”)]

// Comments version information:

[assembly: AssemblyCompany(“Wintellect”)]

// ProductName version information

[assembly: AssemblyProduct(“Wintellect ® Jeff’s Type Library”)]

// LegalCopyright version information

[assembly: AssemblyCopyright(“Copyright © wintellect 2010”)]

// LegalTrademask version information:

[assembly:AssemblyTrademark(“JeffTypes is a registered trademark of wintellect”)]

// AssemblyVersion version information

[assembly: AssemblyVersion(“3.0.0.0”)]

// FILEVERSION/Fileversion version information:

[assembly: AssemblyinformationalVersion(“2.0.0.0”)]

// Set the language field (discussed  later in the “Culture” section)

[assembly: AssemblyCulture(“”)]

The table below shows the Version Resource Fields and Their Corresponding AL.exe Switches and Custom attributes

Version Resource Al.exe Switch Custom Attribute/Comment
FILEVERSION /fileversion System.Reflection.AssemblyFileVersionAttribute
PRODUCTVERSION /productversion System.Reflection.AssemblyInformationalVersionAttribute
FILEFLAGSMASK (none) Always set to VS_FFI_FILEFLAGSMASK
FILEFLAGS (none) Always 0
FILEOS (none) Currently always VOS__WINDOWS32
FILETYPE /target Set to VFT_APP if /target:exe or /target:winexe is specified set to VFT_DLL if /target:library is specified
FILESUBTYPE (none) Always set to VFT2_UNKNOWN
AssemblyVersion /version System.Reflection.AssemblyVersionAttribute
Comments /description System.Reflection.AssemblyDescriptionAttribute
CompanyName /company System.Reflection.AssemblyCompanyAttribute
FileDescription /title System.Reflection.AssemblyTitleAttribute
FileVersion /version System.Reflection.AssemblyFileVersionAttribute
InternalName /out Set the name of the output file specified without the extension
LegalCopyright /copyright System.Reflection.AssemblyCopyrightAttribute
LegalTrademarks /trademark System.Reflection.AssemblyTrademarkAttribute
OriginalFileName /out set to the name of the output file (without a path)
PrivateBuild (none) Always blank
ProductName /product System.Reflection.AssemblyProductAttribute
ProductVersion /productversion System.Reflection.AssemblyInformationalVersionAttribute
SpecialBuild (none) Always blank
  • AssemblyFileVersion This version number is stored in the Win32 version resource. This number is for information purposes only; the CLR doesn’t examine this version number in any way.
  • AssemblyinformationalVersion This version number is also stored in the Win32 version resource and again, this number is for information purposes only;
  • AssemblyVersion This version is stored in the AssemblyDef manifest metadata table. The CLR uses this version number when binding to strongly named assemblies. This number is extremely important and is used to uniquely identify an assembly. when starting to develop an assembly, you should set the major , minor, build and revision numbers and shouldn’t change them until you’re ready to being work on the next deployable version of your assembly. When you build an assembly, this version m\number of the referenced assembly is embedded in the AssemblyRef table’ entry. This means that an assembly is tightly bound to a specific version of a referenced assembly.

Simple Application Deployment

Assemblies don’t dictate or require any special means of packaging. The easiest way to package a set of assemblies is simply to copy all of the files directly. Because the assemblies include all of the dependent assembly references and types, the user can just run the application and the runtime will look for referenced assemblies in the application’s directory. No modifications to the registry  are necessary for the application to run. To uninstall the application, just delete all the files.

You can use the options available on the publish tab to cause Visual Studio to produce and MSI file can also install any prerequisite components such as the .NET Framework or Microsoft SQL Server 2008 Express Edition. Finally, the application can automatically check for updates and install them on the user’s machine by taking advantage of ClickOnce technology.

Assemblies deployed to the same directory as the application are called privately deployed assemblies. Privately deployed assemblies can simply be copied to an application’s base directory, and the CLR will load them and execute the code in them. In addition, an application can be uninstalled by simply deleting the assemblies in its directory. This allows simple lookup and restore as well.

This simple install/remove/uninstall scenario is possible because each assembly has metadata indicating which referenced assembly should be loaded, no registry settings are required. An  application always binds to the same type it was built and tested with; the CLR can’t load a different assembly that just happens to provide a type with the same name.

Simple Administrative Control

To allow administrative control over an application a configuration file can be placed in the application’s directory. The setup program would then install this configuration file in the application’s base directory. The CLR interprets the content of this file to alter its policies for locating and loading assembly files.

Using a separate file allows the file to be easily backed up and also allows the administrator to copy the application to another machine – just copy the necessary files and the administrative policy is copied too.

The CLR won’t be able to locate and load these files; running the application will cause a System.IO.FileNotFoundException exception to be thrown. To fix this, the publisher creates an XML configuration file and deploys it to the application base directory. The name of this file must be the name of the application’s main assembly file with a .config extension: program.exe.config for this example. This configuration file should look like this:

<configuration>

<runtime>

<assemblyBinding xmlns=”urn: schema-microsoft-com:asm.v1”>

<probing privatePAth=”AuxFiles” />

<assemblyBinding>

<runtime>

<configuration>

Whenever the CLR attempts to locate an assembly file, it always looks in the application’s directory first and if it cant find the file there, it looks in the AuxFiles subdirectory. You can specify multiple semicolon-delimited paths for the probing element’s privatePath attribute. Each path is considered relative to the application’s base directory. You can’t specify an absolute or a relative path identifying a directory that is outside of the application base directory.

The name and location of this XML configuration file is different depending on the application type

  • For executable applications(EXE), the configuration file must be in the application’s base directory, and it must be the name of the EXE file with “config” appended to it.
  • For microsoft ASP.NET Web Form applications, the file must be in the web application’s virtual root directory and is always named web.config

When you install the .NET Framework, it creates a Machine config file. There is one Machine.config file per version of the CLR you have installed on the machine.

The Machine.config file is located in the following directory:

%SystenRoot%\Microsoft.NET\Framework\version\CONFIG

Of course, %SystemRoot% identifies your windows directory (usually C:\WINDOWS), and version is a version number identifying a specific version of the .NET Framework. Settings in the Machine.config file represent default settings that affect all applications running on the machine. An administrator can create a machine-wide policy by modifying the single Machine.config file. However, administrators and users should avoid modifying this file. Plus you want the application’s settings to be backed up and restored, and keeping an application’s settings in the application-specific configuration file enables this.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s