Plotting PIA

Primary Interop Assembly Mapping and ClearCase Integration for .NET

asp:Feature

LANGUAGES: ALL

ASP.NET VERSIONS: 1.x

 

Plotting PIA

Primary Interop Assembly Mapping and ClearCase Integration for .NET

 

By Greg Nudelman

 

There exist numerous good Best Practices documents that describe all the stages of building and deploying a .NET application. However, it is still difficult to find cohesive real-world guidance to the entire process of creating, mapping, and deploying Primary Interop Assemblies (PIAs). This article will show you how to create PIAs, as well as examine three alternative methods for mapping them to your .NET solution: in the application tree, as COM objects, and in the Framework directory. I ll examine the pros and cons of each approach and show that the best mapping for easy deployment and ClearCase integration can be achieved by mapping PIAs in the .NET Framework directory using an absolute file path.

 

What Is PIA?

PIA stands for Microsoft Primary Interop Assembly. PIAs are essentially stubs that have little functionality by themselves, but provide a sort of window into other objects and methods. PIAs are used to map COM objects and native unmanaged Windows code to managed code run by the .NET Common Language Runtime. For example, accessing Microsoft Excel functionality from a .NET application usually requires creating and mapping PIAs. Visit http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndotnet/html/whypriinterop.asp for more background information on PIAs.

 

Creating PIAs

Specifically, the work described herein was performed using .NET Framework 1.1 on Windows 2000 Server Service Pack 4 with Microsoft Office 2000. Given the appropriate adjustments to system directory mappings, the methods described in this article also work well for .NET Framework 1.0.

 

To create a PIA from an existing DLL, the following process can be used. The complete process is demonstrated here using Easybaro.dll, a handy third-party control provided by Bokai Corp. (http://www.bokai.com) and used to create barcode images. Examples that create Microsoft Excel PIA are shown, as well.

 

1. Run Regsvr32 Utility

This tool registers and un-registers (regsvr32 /u) old non-managed DLLs in the Windows Registry. This step is usually done automatically by the install package for the third-party DLLs and is not needed if the third-party install utility works correctly. When Regsvr32.exe is run, it attempts to load the component and call its DLLSelfRegister function. If this attempt is successful, Regsvr32.exe displays a dialog box indicating success. If the attempt is unsuccessful, Regsvr32.exe returns an error message, which may include a Win32 error code. For a complete list of Win32 error codes, visit http://www.microsoft.com/technet/treeview/default.asp?url=/technet/support/eventserrors.asp.

 

Easybaro PIA. Run the following at the Command Prompt:

 

C:\>C:\WINNT\system32\regsvr32.exe

"C:\Clearcase\test_dev_view\Test_Application\Source_Code\

TestApplication\Web\bin\Easybaro.dll"

 

The output of this command should be a succeeded dialog box.

 

Excel PIA. This step is not required for generating Microsoft Excel PIA (DLL registration was performed during the Microsoft Office installation).

 

2. Run SN: Strong Name Tool

This tool generates a strong name key for the new PIA DLL. More information can be found at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cptools/html/cpgrfstrongnameutilitysnexe.asp.

 

Easybaro PIA. Run the following at the Command Prompt:

 

C:\>"C:\Program Files\Microsoft Visual Studio .NET 2003\

SDK\v1.1\Bin\sn.exe" -k "C:\Clearcase\test_dev_view\

Test_Application\Source_Code\TestApplication\Web\bin\key.snk"

 

The output of this command is a key pair file key.snk that is written to the C:\Clearcase\test_dev_view\Test_Application\Source_Code\TestApplication\Web\bin\ directory.

 

Excel PIA. The command is exactly the same for Excel PIA. Be sure you generate a different key.snk for every PIA you are making.

 

3. Run Tlbimp: Type Library Importer Tool

This tool is a type library importer; it makes a bridge-marshaling utility that helps execute conversion of the non-managed code. Tlbimp uses the strong key generated in step 2 above to create an Interop Assembly that contains run-time metadata for the types defined within the original type library.

 

More information can be found at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cptools/html/cpgrftypelibraryimportertlbimpexe.asp.

 

Easybaro PIA. Run the following at the Command Prompt (note that the whole command should be on one line):

 

C:\>"C:\Program Files\Microsoft Visual Studio .NET 2003\

SDK\v1.1\Bin\tlbimp" "C:\Clearcase\test_dev_view\

Test_Application\Source_Code\TestApplication\Web\bin\

Easybaro.dll" /keyfile:"C:\Clearcase\test_dev_view\

Test_Application\Source_Code\TestApplication\Web\bin\

key.snk" /out:"C:\Clearcase\test_dev_view\Test_Application\

Source_Code\TestApplication\Web\bin\Interop.Easybaro.dll"

 

The output of this command is the new Interop.Easybaro.dll PIA that is imported from the original Easybaro.dll. The new PIA will be written to the out/ directory, C:\Clearcase\test_dev_view\Test_Application\Source_Code\TestApplication\Web\bin\.

 

Steps 1-3 generate a working Interop.Easybaro.dll PIA that can be added as a resource to any .NET project. The methods and classes contained in the original Easybaro.dll are now available to be called from the .NET code, and can be examined in step 4.

 

Excel PIA. To generate the Microsoft Office Excel PIAs, this command must be run using the Command Prompt on C:\Program Files\Microsoft Office\Office\EXCEL9.OLB library as follows (note that the whole command should be on one line):

 

C:\>"C:\Program Files\Microsoft Visual Studio .NET 2003\

SDK\v1.1\Bin\tlbimp" "C:\Program Files\Microsoft Office\

Office\EXCEL9.OLB" /keyfile:"C:\Clearcase\test_dev_view\

Test_Application\Source_Code\TestApplication\Web\bin\

key.snk" /out:"C:\Clearcase\test_dev_view\Test_Application\

Source_Code\TestApplication\Web\bin\Excel.dll"

 

This command prints out Type library imported to Excel.dll . In fact, it creates not one, but three new Interop Assemblies, all of which are required for using Excel in the .NET Framework. After the command completes, the following three DLLs are placed in the /out directory (in this case, C:\Clearcase\test_dev_view\Test_Application\Source_Code\TestApplication\Web\bin\):

  • Excel.dll
  • Office.dll
  • VBIDE.dll

 

To avoid confusion, we recommend that you rename these DLLs as:

  • Interop.Excel.dll
  • Interop.Office.dll
  • Interop.VBIDE.dll

 

4. Ildasm: MSIL Disassembler

This tool can be used to examine the contents of the new managed code Interop DLL that was created in step 3. This step is strictly optional, but can be educational. More information can be found at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cptools/html/cpconmsildisassemblerildasmexe.asp.

 

Easybaro PIA. Run the following at the Command Prompt:

 

C:\>"C:\Program Files\Microsoft Visual Studio .NET 2003\

SDK\v1.1\Bin\Ildasm.exe" "C:\Clearcase\test_dev_view\

Test_Application\Source_Code\TestApplication\Web\bin\

Interop.Easybaro.dll"

 

This command launches a new IL DASM UI window that describes the Interop.Easybaro.dll s classes and API.

 

Excel PIA. Assuming the working directory in step 3 was C:\Clearcase\test_dev_view\Test_Application\Source_Code\TestApplication\Web\bin, the three new Interop Assemblies were created there. To examine the methods and objects available in the new PIA, run the following at the Command Prompt:

 

C:\>"C:\Program Files\Microsoft Visual Studio .NET 2003\

SDK\v1.1\Bin\Ildasm.exe" "C:\Clearcase\test_dev_view\

Test_Application\Source_Code\TestApplication\Web\bin\

Interop.Excel.dll"

 

This command launches a new IL DASM UI window that describes the Interop.Excel.dll s classes and API.

 

Office 2003 offers alternative visual tools for PIA generation and mapping. Although this is beyond the scope of this article, interested parties should examine the following links for more information:

 

Mapping PIAs

After PIAs are created, they must be placed somewhere on the server machine and mapped to the .NET application to import Excel functionality into the .NET project. In the previous step, we created three Interop Assemblies required for importing Excel:

  • Interop.Excel.dll
  • Interop.Office.dll
  • Interop.VBIDE.dll

 

We also created Interop.Easybaro.dll, which is needed to import Bokai s Easybaro.dll. To save space, this article shows mapping examples for Interop.Excel.dll only. Note that the other two Interop Assemblies, Interop.Office.dll and Interop.VBIDE.dll, should always be mapped together with the Excel PIA. Interop.Easybaro.dll PIA does not require any supporting files, and can be mapped in exactly the same way as Interop.Excel.dll.

 

In the Test_Application example, the Excel functionality is required for the Common Project. Under this configuration, assuming the code is written in C#, PIA mappings are contained in the Common.csproj Project Configuration file. If the project code is written in VB.NET, the mappings would be contained in the Common.vbproj file instead. The rest of the PIA mapping and configuration details described in this article should be exactly the same regardless of the programming language. The directory structure for Test_Application is shown in Figure 1.

 


Figure 1: The directory structure for the Test_Application example.

 

This article examines the pros and cons of different methods of PIA mappings, PIA integration with the ClearCase code repository, and how the PIA mappings affect the ability to distribute .NET code to other development machines. This article demonstrates how to map PIAs in three ways:

1)     In the application tree.

2)     As COM objects.

3)     In the Framework directory.

 

Method 1: Map PIAs in the Application Tree

Using method 1, Interop.Excel.dll PIA built as described above is placed directly into the Common\obj directory. Then the PIA reference is set up using Visual Studio | Solution Explorer | Common | References (see Figure 2). Right-click on the References folder and select Add Reference.

 


Figure 2: Visual Studio | Solution Explorer | Common | References.

 

In the resulting Add Reference dialog box, click Browse, find and select the Interop.Excel.dll PIA file, then click Select. You should see a dialog box like the one shown in Figure 3.

 


Figure 3: Adding a reference to Interop.Excel.dll PIA in the Common\obj directory.

 

Click OK to save the PIA mappings in the Common.csproj file. After mapping the Interop Assembly as described above, the mapping in the Common.csproj file looks something like this:

 

 Name = "Interop.Excel"

   AssemblyName = "Interop.Excel"

 HintPath = "obj\Interop.Excel.dll"

/>

 

Under Visual Studio | Solution Explorer | Common | References, the reference appears as Interop.Excel . As a final step, Common\obj\Interop.Excel.dll file and the two companion Interop Assemblies, Interop.Office.dll and Interop.VBIDE.dll are added to the ClearCase code repository, and the Common.csproj file that contains the PIA mappings is checked back into ClearCase.

 

This method presents a neat solution because it aggregates all the necessary DLL files in the folder of the .NET project in which they are used. However, this method also presents several significant problems.

 

To begin with, to compile the Common .NET project, all the Interop libraries in the Common\obj\ directory must be made writable (they must be hijacked or permanently checked-out from the ClearCase archive). With every compilation of the files in the Common project, these Interop libraries are copied by the .NET Framework into Web/bin folder, and the timestamps of these copied DLLs are updated. Because of this, all three Interop DLLs in the Web/bin folder must be re-deployed to QA and production environments with every code release.

 

Additional problems occur when the code is first installed on a virgin development machine. In this case, the compilation of the Common project results in numerous errors of the type:

 

can t find method/class X, are you missing an assembly reference?

 

These errors occur because the PIA mappings cannot be automatically established by .NET. The same behavior is observed any time the code base is completely updated from ClearCase on the same development machine. In this case, all the PIA mappings are similarly lost, with the resulting predictable can t find method/class errors.

 

To resolve these problems, the developer must delete and then recreate all the PIA mappings after every complete code update using the process described above. As a result of these drawbacks, mapping PIAs in the application tree is a less than ideal solution.

 

Method 2: Map PIAs as COM Objects

Because method 1 fails to provide a satisfactory solution, I researched an alternative way to map my Interop.Excel.dll and related Interop Assemblies directly as COM objects. To do this, open the Add Reference dialog box as described above and choose the COM tab. Scroll down and highlight just one object, Microsoft Excel 9.0 Object Library, and click Select; the resulting Add Reference dialog box is shown in Figure 4.

 


Figure 4: Adding a reference to Microsoft Excel 9.0 Object Library.

 

Click OK to complete the addition of the COM mapping to the Common project. After completing this step, the COM mapping in the Common.csproj file looks like this:

 

 Name = "Excel"

 Guid =

 "{00020813-0000-0000-C000-000000000046}"

 VersionMajor = "1"

 VersionMinor = "3"

 Lcid = "0"

 WrapperTool = "tlbimp"

/>

 

Office and VBIDE COM objects appear alongside the Excel COM object in the Common.csproj file mapped in a similar way. Under Visual Studio | Solution Explorer | Common | References the references appear as Excel , Office , and VBIDE . As a final step, the Common.csproj file that contains the PIA mappings is checked back into the ClearCase code repository.

 

This is a good workable solution, and one that doesn t even require producing the Interop.Excel.dll, nor keeping it in the ClearCase code repository. An additional advantage to this mapping method is that distributing the project code to another machine often works correctly right out of the box, provided that the Microsoft Office configuration is exactly the same on both machines. However, this solution has several major drawbacks, not the least of which is that it introduces an element of DLL Hell that is a frequent headache with maintaining Windows software.

 

The problem with direct installation of COM objects is that the .NET Framework maps the reference directly to GUID or the address of the COM object in the machine s Registry. Any differences in Microsoft Office configurations between the development machines (including any problems with Office components, upgrades, or patches) can change the GUID or the address of the COM object in the registry. This change has a deleterious effect on maintaining the PIA mappings during code distribution to other machines.

 

The loss of PIA mappings during code distribution results in the same can t find method/class X, are you missing an assembly reference? errors seen during the compile step shown in method 1. Again, the PIA mapping is lost and must be deleted and recreated using the Visual Studio | Solution Explorer | Common | References setup dialog box as previously described. However, in contrast to method 1, reestablishing the direct COM mappings results in having different Common.csproj files on different machines. This means that one csproj file will not work on another machine with a slightly different Microsoft Office configuration, and thus Common.csproj files can NOT be checked into ClearCase. Therefore, although this method of direct COM mapping is a slight improvement over method 1, it is also less than ideal.

 

Method 3: Map PIAs in the Framework Directory

After spending some time trying to understand the intricacies of PIA mapping, and investigating methods 1 and 2, I still had to come up with a satisfactory solution that would work well with my ClearCase repository. What I needed, I theorized, was an equivalent of the Java lib directory. This directory acts as a sort of central library repository: anything placed into this directory is automatically available for mapping to the application and any mappings to the objects in the lib directory can be safely distributed between development machines.

 

I finally found the .NET equivalent of the Java lib directory I was looking for under the .NET tab in the Visual Studio | Solution Explorer | Common | References setup dialog box. I discovered that a great many libraries in this tab are mapped from the C:\WINNT\Microsoft.NET\Framework\v1.1.4322\ directory. If the PIAs are placed in that directory, would .NET maintain persistent mappings to these libraries? As I expected, this was indeed the case.

 

To map the PIA using this method, begin by placing the Interop.Excel.dll and its companion libraries (Interop.Office.dll and Interop.VBIDE.dll) into the C:\WINNT\Microsoft.NET\Framework\v1.1.4322\ directory. As in methods 1 and 2, go to Visual Studio | Solution Explorer | Common | References and select Add Reference. Navigate to the .NET tab and select Interop.Excel.dll PIA. The resulting dialog box is shown in Figure 5.

 


Figure 5: Adding a reference to Interop.Excel.dll PIA in the .NET Framework directory.

 

Map the two remaining Excel companion Interop libraries (Interop.Office.dll and Interop.VBIDE.dll) in the same way and click OK to save the mappings in the Common.csproj file. At this point, the mappings in the Common.csproj file look like this:

 

 Name = "Interop.Excel"

 AssemblyName = "Interop.Excel"

 HintPath =

"..\..\..\..\..\..\WINNT\Microsoft.NET\Framework\

 v1.1.4322\Interop.Excel.dll"

/>

 

Under Visual Studio | Solution Explorer | Common | References the Excel PIA reference appears as Interop.Excel .

 

This method at last presents a workable solution that interfaces very well with the ClearCase repository. As long as every machine has the Interop libraries in the C:\WINNT\Microsoft.NET\Framework\v1.1.4322 directory, the rest of the code can be safely checked into the ClearCase repository, updated, and redeployed without losing the PIA mappings.

 

The only problem with this solution is experienced when some of the dev machines have the ClearCase VOB code base installation on any drive other than the C: drive, or in a different directory structure. In those cases, the relative mapping to:

 

..\..\..\..\..\..\WINNT\Microsoft.NET\Framework\v1.1.4322\

Interop.Excel.dll

 

in the Common.csproj file is in fact pointing to:

 

D:\WINNT\Microsoft.NET\Framework\v1.1.4322\

Interop.Excel.dll

 

or some other incorrect relative path to the PIA file. When the code is distributed to such a machine, the result is the same can t find method/class X, are you missing an assembly reference? errors seen in method 1. This time, however, the problem is easily remedied by manually editing the Common.csproj file to point to the correct .NET Framework directory using the absolute path instead:

 

 Name = "Interop.Excel"

 AssemblyName = "Interop.Excel"

 HintPath =

"C:\WINNT\Microsoft.NET\Framework\v1.1.4322\

 Interop.Excel.dll"

/>

 

The resulting Common.csproj file is then checked back into the ClearCase repository. Because the mappings are absolute, this Common.csproj file can be safely distributed to other machines and is guaranteed to work without any problems regardless of the ClearCase repository folder configuration on the target machines.

 

From the findings, this article draws the conclusion that the best solution for easy deployment and ClearCase integration can be achieved by mapping PIAs in the .NET Framework directory using an absolute file path, as shown in method 3.

 

The method of mapping PIAs to the .NET Framework directory using the absolute path presents a very elegant and flexible real-world solution to a complex problem. The only requirement is that the .NET Framework must be installed on the C: drive on all the development machines, and the Interop DLLs are added to the .NET Framework directory (this can be accomplished easily with a simple batch script). This solution ensures that the absolute mappings always point to the correct PIA files on every development machine, regardless of the individual Microsoft Office configuration. This solution integrates perfectly with the ClearCase code repository, because the code can be safely distributed to other machines requiring nothing extra to be checked into the code repository or mapped manually.

 

Conclusion

This article described the complete process for building and mapping Microsoft .NET Primary Interop Assemblies (PIAs). The mapping method that seems to be best suited to diverse development environments involves placing all the PIAs into C:\WINNT\Microsoft.NET\Framework\v1.1.4322\ and mapping the PIA references in the corresponding project (csproj) file using the absolute PIA file path. This solution allows the easiest distribution of the .NET projects regardless of the Microsoft Office configuration and is independent of the drive letter or folder structure on which the .NET application resides. This method also offers elegant integration with the ClearCase code repository with nothing extra to map or check in. I recommend considering this method of mapping Primary Interop Assemblies in your .NET development project.

 

Greg Nudelman earned his MS CIS from Golden Gate University in San Francisco. He still lives in the San Francisco Bay Area. He has worked with J2EE, .NET, and SQL for more than six years, designing, and developing multi-tier distributed applications for biotechnology and mortgage companies. His latest obsession is Web software usability.

 

 

 

Hide comments

Comments

  • Allowed HTML tags: <em> <strong> <blockquote> <br> <p>

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
Publish