Deploying Private Assemblies



Deploying Private Assemblies

Private assemblies are the simplest to deploy. All you need to do to deploy private assemblies is to copy them to the application's base directory or one of its subdirectories. In this section, you create a simple application that uses a private assembly. You then use this application to experiment with how the CLR locates private assemblies and how to configure the behavior of the CLR by using the application configuration file.

In Step-by-Step 10.1, you create two assemblies: One is a Windows application and the other is a library application, which is used by only the Windows application.

STEP BY STEP

10.1 Creating and Deploying an Application That Uses a Privately Deployed Assembly

  1. Launch Visual Studio .NET. Select File, New, Blank Solution, and name the new solution 320C10.

  2. Add a new Visual C# .NET Class library named MathLib to the solution.

  3. In the Solution Explorer, rename the default Class1.cs to MathLib.cs.

  4. Open the MathLib.cs and replace the code with the following code:

    
    using System;
    
    public class MathLib
    
    {
    
        public static int Add(int n1, int n2)
    
        {
    
            return n1 + n2;
    
        }
    
    }
    
    
  5. Build the project.

  6. Add a new Visual C# .NET Windows application named MathApp to the solution.

  7. In the Solution Explorer, right-click project MathApp and select Add Reference from the context menu to add a reference to the MathLib component.

  8. In the Solution Explorer, rename the default Form1.cs to MathApp.cs. Open the form in code view and change all occurrences of Form1 to refer to MathApp instead.

  9. Place four Label controls, three TextBox controls (txtN1, txtN2 and txtResult) and a Button control (btnAdd) on the form. Change one of the label's Size – Height property to 1 and BorderStyle property to Fixed3D, to represent it as a line. Arrange the controls as shown in Figure.

    Figure. The MathApp.exe application calls methods from the MathLib.dll to add two numbers.

    graphics/10fig01.jpg

  10. Double-click the Button control and add the following code in the Click event handler:

    
    private void btnAdd_Click(
    
        object sender, System.EventArgs e)
    
    {
    
        txtResult.Text =
    
            MathLib.Add(Convert.ToInt32(txtN1.Text),
    
                Convert.ToInt32(txtN2.Text)).ToString();
    
    }
    
    
  11. Run the project. Enter the two numbers in the text boxes and click the Add button. You should see the result of adding the two numbers in the third text box.

  12. Change the solution configuration to Release mode and build the project. The project is now ready for deployment.

  13. Create a folder on your hard drive, named C:\MyPrograms\MathApplication. Copy the MathApp.exe and MathLib.dll files from the bin\Release folder of the MathApp project to this folder.

  14. Run MathApp.exe from C:\MyPrograms\MathApplication. Add two numbers. MathApp.exe successfully calls methods from MathLib.dll.

In Step-by-Step 10.1, you can see that MathApp.exe can call methods from MathLib.dll. This is possible because MathApp.exe stores information about the assemblies it needs to refer to. This information is a part of the assembly manifest for MathApp.exe. You can check the contents of an assembly manifest by using the MSIL Disassembler (ildasm.exe). An alternative way to check this information is by using the .NET Framework Configuration tool as shown in Step-by-Step 10.2.

STEP BY STEP

10.2 Viewing Assembly Dependence Information for an Application

  1. Open the Microsoft .NET Framework Configuration tool from the Administrative Tools section of the Windows Control Panel.

  2. Click the Applications node in the tree view, as shown in Figure.

    2. The .NET Framework Configuration tool enables you to configure an application.

    graphics/10fig02.jpg

  3. Click the Add an Application to Configure link.

  4. In the Configure an Application dialog box, click the Other button and browse to the C:\MyPrograms\MathApplication folder to select MathApp.exe. Select this application and click OK.

  5. Expand the new MathApp node in the tree view under the Applications node. Click the Assembly Dependencies child node to view all the MathApp.exe dependencies, as shown in Figure.

    3. You can view an assembly's dependencies by using the .NET Framework Configuration tool.

    graphics/10fig03.jpg

In Figure, you see that unique public key tokens distinguish shared assemblies from private assemblies. If the public key token is not present, it means that the assembly is a private assembly. You also can see from Figure that an application does not contain the complete file name and the location of the assembly file to which it needs to refer. The CLR instead uses a process called probing to locate the privately deployed assemblies. You can have a certain degree of control over the probing process if you modify the binding policy by using the application configuration file.

Binding Policy for Privately Deployed Assemblies

Binding policy for privately deployed assemblies is a set of rules that instructs the CLR to search for an assembly in specific locations. By default, the CLR uses a default binding policy, but you can use the application configuration file to specify binding rules that instruct the CLR to search for assemblies in additional locations.

For Windows applications, the application configuration file is application specific and is located in the application's base directory (where the EXE file is located). The name of application configuration file is of the format ExecutableFileName.config. For example, the application configuration file for MathApp.exe would be MathApp.exe.config. In the case of Web applications, the application configuration file is stored in the application's root directory and is named web.config.

The application configuration file is an XML file that may contain different elements for configuring various aspects of an application. The element in which you'll be most interested in this section is the <probing> element, which specifies additional search locations for an assembly. A stripped-down version of an application configuration file containing the <probing> element is as follows:


<?xml version="1.0"?>

<configuration>

  <runtime>

    <assemblyBinding

          xmlns="urn:schemas-microsoft-com:asm.v1">

      <probing privatePath="bin\retail;bin\debug" />

    </assemblyBinding>

  </runtime>

</configuration>

You can use the privatePath attribute of the <probing> element to specify the subdirectories of the application's base directory that might contain assemblies. Each of these subdirectories is delimited with a semicolon.

This application configuration file instructs the CLR to search assemblies in the application's bin\retail and bin\debug subdirectories, in addition to the search locations that are part of the default binding policy. You learn about the complete binding process for a privately deployed assembly in the following section.

How the CLR Binds to a Privately Deployed Assembly

The CLR takes the following steps to locate a privately deployed assembly:

  1. The CLR determines the assembly's name from the manifest of the requesting assembly.

  2. The CLR checks to see whether the requested assembly has already been loaded from the previous requests. If the assembly has already been loaded, the CLR binds to the assembly and stops searching any further.

  3. The CLR reads the application configuration file to check whether any private path hints are available in the <probing> element. If there are hints, the CLR will use these directory locations to search the assembly.

  4. If the referenced assembly has no culture information, the CLR uses the following locations in the given order to find the assembly:

    • ApplicationBase\AssemblyName.dll

    • ApplicationBase\AssemblyName\AssemblyName.dll

    • ApplicationBase\PrivatePath1\AssemblyName.dll

    • ApplicationBase\PrivatePath1\AssemblyName\AssemblyName.dll

    • ApplicationBase\PrivatePath2\AssemblyName.dll

    • ApplicationBase\PrivatePath2\AssemblyName\AssemblyName.dll

      .

      .

      .

    • ApplicationBase\AssemblyName.exe

    • ApplicationBase\AssemblyName\AssemblyName.exe

    • ApplicationBase\PrivatePath1\AssemblyName.exe

    • ApplicationBase\PrivatePath1\AssemblyName\AssemblyName.exe

    • ApplicationBase\PrivatePath2\AssemblyName.exe

    • ApplicationBase\PrivatePath2\AssemblyName\AssemblyName.exe

      .

      .

      .

    Here ApplicationBase is the directory where the requesting application is installed; AssemblyName is the name of the assembly to search; and PrivatePath1 and PrivatePath2 are the hints provided in the <probing> element of the application configuration file. Note that the assembly name does not contain the extension; therefore the CLR searches for both DLL as well as EXE files. If the assembly is found in any of these locations, the CLR binds to the assembly and does not search any further.

  5. If the referenced assembly has culture information, the following directories are searched:

    • ApplicationBase\Culture\AssemblyName.dll

    • ApplicationBase\Culture\AssemblyName\AssemblyName.dll

    • ApplicationBase\PrivatePath1\Culture\AssemblyName.dll

    • ApplicationBase\PrivatePath1\Culture\AssemblyName\AssemblyName.dll

    • ApplicationBase\PrivatePath2\Culture\AssemblyName.dll

    • ApplicationBase\PrivatePath2\Culture\AssemblyName\AssemblyName.dll

      .

      .

      .

    • ApplicationBase\Culture\AssemblyName.exe

    • ApplicationBase\Culture\AssemblyName\AssemblyName.exe

    • ApplicationBase\PrivatePath1\Culture\AssemblyName.exe

      NOTE

      Private Assembly's Version Any version information contained in the private assembly is for informational purpose only. The CLR does not use the version information of a private assembly to bind to a specific version.

    • ApplicationBase\PrivatePath1\Culture\AssemblyName\AssemblyName.exe

    • ApplicationBase\PrivatePath2\Culture\AssemblyName.exe

    • ApplicationBase\PrivatePath2\Culture\AssemblyName\AssemblyName.exe

      .

      .

      .

    Here Culture is a culture code corresponding to the assembly. If the assembly is found in any of these locations, the CLR binds to the assembly and does not search any further.

  6. If the CLR cannot locate the assembly after following the preceding steps, assembly binding fails.

Using the Assembly Binding Log Viewer Tool to Diagnose the Binding Process

The .NET Framework's Assembly Binding Log Viewer tool (fuslogvw.exe) displays the following information for failed assembly binds:

  • A specific reason for the bind failure; for a privately deployed assembly the reason is usually "The system cannot find the file specified."

  • Information about the calling assembly, including its name, the base directory, and a description of the private search paths.

  • Identity of the requested assembly, including its name, version, culture, and public key token.

  • A description of any Application, Publisher, or Administrator version policies that have been applied.

  • Whether the assembly was found in the global assembly cache (GAC).

  • A list of all probing URLs.

Some of the information from this list, such as version and version policies, applies to only the shared assemblies that you will learn later in this chapter. Still, the other pieces of information, such as the list of probing URLs, helps you diagnose why the CLR cannot locate a private assembly. You can use the output of the Assembly Binding Log Viewer tool to understand how the CLR locates assemblies, as shown in Step-by-Step 10.3.

STEP BY STEP

10.3 Using the Assembly Binding Log Viewer Tool to Understand How the CLR Locates Assemblies

  1. Launch the Visual Studio .NET command prompt. Type fuslogvw to open the Assembly Binding Log Viewer tool.

  2. Select the Log Failures check box, as shown in Figure.

    4. The Assembly Binding Log Viewer tool enables you to view the details of the failed assembly binds.

    graphics/10fig04.jpg

  3. Delete the MathApp.dll file from the C:\MyPrograms\MathApplication folder. This enables the binding to fail when an application requests this assembly.

  4. Run the MathApp.exe from the C:\MyPrograms\MathApplication folder. You should see a dialog box showing the error message that the file or its dependencies are not found.

  5. Now switch to Assembly Binding Log Viewer tool and click on the Refresh button. You should see an entry for the failed assembly bind, as shown in Figure.

  6. Select the entry for MathApp.exe and click the View Log button. You should see a browser window displaying the following code:

    *** Assembly Binder Log Entry (12/1/2002 @ 10:30:08 AM) *** The operation failed. Bind result: hr = 0x80070002. The system cannot find the file graphics/ccc.gifspecified. Assembly manager loaded from: C:\WINNT\Microsoft.NET\Framework\ graphics/ccc.gifv1.0.3705\fusion.dll Running under executable C:\MyPrograms\MathApplication\MathApp. graphics/ccc.gifexe --- A detailed error log follows. === Pre-bind state information === LOG: DisplayName = MathLib, Version=1.0.1065.18779, graphics/ccc.gifCulture=neutral, PublicKeyToken=null (Fully-specified) LOG: Appbase = C:\MyPrograms\MathApplication\ LOG: Initial PrivatePath = NULL LOG: Dynamic Base = NULL LOG: Cache Base = NULL LOG: AppName = NULL Calling assembly : MathApp, Version=1.0.1065.18782, graphics/ccc.gifCulture=neutral, PublicKeyToken=null. === LOG: Processing DEVPATH. LOG: DEVPATH is not set. Falling through to regular bind. LOG: Policy not being applied to reference at this time (private, graphics/ccc.gif custom, partial, or location-based assembly bind). LOG: Post-policy reference: MathLib, Version=1.0.1065.18779, graphics/ccc.gifCulture=neutral, PublicKeyToken=null LOG: Attempting download of new URL file:///C:/MyPrograms/ graphics/ccc.gifMathApplication/MathLib.DLL. LOG: Attempting download of new URL file:///C:/MyPrograms/ graphics/ccc.gifMathApplication/MathLib/MathLib.DLL. LOG: Attempting download of new URL file:///C:/MyPrograms/ graphics/ccc.gifMathApplication/MathLib.EXE. LOG: Attempting download of new URL file:///C:/MyPrograms/ graphics/ccc.gifMathApplication/MathLib/MathLib.EXE. LOG: All probing URLs attempted and failed.

The binding log file displays valuable information about the binding process. The probing URLs at the end of the list show which directories the CLR searched for the assembly. If you had placed the assembly in any of these directories, the application would have executed successfully.

The MathLib assembly referenced in Step-by-Step 10.3 does not have any culture information in it. It would be a good exercise to specify the culture information for the MathLib assembly and then use the assembly binding log to analyze the behavior of the CLR. You can associate culture information with the MathLib assembly by changing the AssemblyCulture attribute of the assembly in the AssemblyInfo.cs file as shown here:


[assembly: AssemblyCulture("en-US")]

When you use such an assembly to build the MathApp.exe file and then follow the steps in Step-by-Step 10.3, you find that the CLR probes for assembly in only the following locations:


C:\MyPrograms\MathApplication\en-US\MathLib.DLL

C:\MyPrograms\MathApplication\en-US\MathLib\MathLib.DLL

C:\MyPrograms\MathApplication\en-US\MathLib.EXE

C:\MyPrograms\MathApplication\en-US\MathLib\MathLib.EXE

Using the .NET Framework Configuration Tool to Specify an Additional Probing Location

In Step-by-Step 10.3, the CLR used only its default binding policy to locate assemblies. Step-by-Step 10.4 shows how to use the .NET Framework Configuration tool to specify additional search locations for an assembly.

STEP BY STEP

10.4 Using the .NET Framework Configuration Tool to Specify Additional Probing Locations

  1. Open the Microsoft .NET Framework Configuration Administrative tool from the Administrative Tools section of Windows Control Panel.

  2. Right-click the MathApp application node (which was added in Step-by-Step 10.2) under the Applications node in the tree view and select Properties from the context menu.

  3. In the Properties dialog box, enter additional probing locations in the Relative Search Path for Additional Assemblies text box, as shown in Figure. Click OK.

    5. You can specify additional probing locations for an assembly by using the .NET Framework Configuration tool.

    graphics/10fig05.jpg

  4. Open Windows Explorer, and navigate to the C:\MyPrograms\MathApplication folder. You should see an application configuration file named MathApp.exe.config containing the following code:

    
    <?xml version="1.0"?>
    
    <configuration>
    
      <runtime>
    
        <gcConcurrent enabled="true" />
    
        <assemblyBinding
    
          xmlns="urn:schemas-microsoft-com:asm.v1">
    
          <publisherPolicy apply="yes" />
    
          <probing privatePath="bin\debug;bin\retail" />
    
        </assemblyBinding>
    
      </runtime>
    
    </configuration>
    
    

In Step-by-Step 10.4, you see that an easy way to specify additional probing locations for an assembly is to use the .NET Framework Configuration tool. This tool in fact stores this information in the application configuration file. You can also include probing information manually by using any editor to modify the application configuration file.

At this stage, you have a clear idea about how the CLR searches for privately deployed assemblies. You can use this knowledge to decide where you should deploy the assemblies while deploying an application that uses private assemblies.

REVIEW BREAK

  • The set of rules that the CLR uses to locate an assembly is called a binding policy. Binding policy is a deciding factor in how and where an application's assemblies should be deployed.

  • A private assembly is identified by its simple text name and is deployed for use by a single application.

  • Use the application configuration file to modify binding policy for private assemblies. To do so, specify additional search locations for the assembly in the <probing> XML element.