Outlook Security Manager 2010 deployment: Reg Free COM & ClickOnce for Outlook 2010 64-bit, part 5

In the following article HowTo: Deploy Outlook Security Manager with ClickOnce using Reg Free COM we had a close look at how to deploy your standalone application with ClickOnce, if it uses the Outlook Security Manager component. But, taking into account that a 64-bit version of Outlook 2010 has already emerged, the question may arise how to deploy a standalone application that uses the Outlook Security Manager to automate Outlook 64-bit via ClickOnce? Let’s try to sort it out.

First off, I advise that you read through part 1 – Outlook Security Manager 2010 deployment: .net, ActiveX and VCL basics. You will learn that for a successful operation of your standalone application on a target PC, you need to register either secman.dll or secman64.dll depending on the bitness of your Outlook. You will also lean that for Outlook 32-bit, your application must be compiled for an x86 platform, and for Outlook 64-bit – for an x64 platform.

How to register the proper COM dll on a target PC with ClickOnce? If you are a novice in this area, I recommend that you read part 2 of this series to get insight of the Reg Free COM technology.

Basing on the information from those articles, I’ve tried to add a new reference to secman64.dll, set the Isolated property to True for the given reference and … my project stopped compiling… I got this error: “Problem isolating COM reference ’secman64Lib’: No registered classes were detected for this component”. No wonder, Visual Studio that works as an x86 process cannot see an x64 COM library. What shall we do in this case?

If you do the same with the 32-bit version of secman (secman.dll), you will notice that when setting Isolated to True, the following XML element is included in the manifest file of your application:


<file name="secman.dll" asmv2:size="144664" xmlns="urn:schemas-microsoft-com:asm.v1">
    <typelib tlbid="{11549fe4-7c5a-4c17-9fc3-56fc5162a994}" version="1.0" helpdir="" resourceid="0" flags="HASDISKIMAGE" />
   <comClass clsid="{826d7151-8d99-434b-8540-082b8c2ae556}" threadingModel="Apartment" tlbid="{11549fe4-7c5a-4c17-9fc3-56fc5162a994}"
       progid="secman.OutlookSecurityManager" description="OutlookSecurityManager Class" />
</file>

By analogy, I created the same XML element for secman64.dll (I got all necessary information from the Windows registry):


<file name="secman64.dll" asmv2:size="126744" xmlns="urn:schemas-microsoft-com:asm.v1">
    <typelib tlbid"{2C8CCB3A-CE4F-40A2-AA1C-E891338BF189}" version="1.0" helpdir="" resourceid="0" flags="HASDISKIMAGE" />
   <comClass clsid="{2F35794D-4574-4BCF-B0A5-3B16AF985788}" threadingModel="Apartment" tlbid="{2C8CCB3A-CE4F-40A2-AA1C-E891338BF189}"
    progid="secman64.OutlookSecurityManager64" description="OutlookSecurityManager64 Class"/>
</file>

So, depending on your Outlook bitness, you need to add one of these elements to the manifest file of your application on a target PC.

Step-by-step instructions:

1. Add 2 dlls (secman.dll and secman64.dll) to your project via Project –> Add Existing Item… (You can find these dlls in the Redistributables subfolder of the Outlook Security Manager installation folder)

2. Set the Copy Local property to True for the SecurityManager.2005 reference. This  reference should be added automatically after you place the Security Manager component onto your form, if not, just add it through Project –> Add reference…

3. You need to modify the manifest file of your application on the target PC accordingly, by correcting or adding the above XML element for secman.dll or secman64.dll.

You’d better do this in the initialization code at the start of your application.  IsNetworkDeployed property and IsFirstRun property will help you in this. They will return True at the first launch of your application on the target PC. Also, please don’t forget that after correcting the manifest file, you will need to restart your application because, as Microsoft states, “Windows builds an internal table that relates each identifier (CLSID) to its corresponding component file early in CreateProcess, before any application code is run”.

I wrote the ManifestFix.exe utility which you can use to perform all needed actions described above. As input arguments, you need to pass ProcessID (ID of your application’s process) and a path to the executable:

ManifestFix.exe {ProcessID} {Path to executable }

You can find the utility and its source files at the end of this article.

In the ManifestFix.exe utility, I allowed for the second condition too – for Outlook 32-bit, your application must be compiled under an x86 platform, for Outlook 64-bit – under x64. I used the CorFlags Conversion Tool for this. We have already used a similar method in part 4 of this series Outlook Security Manager 2010 deployment: compiling a standalone application with “AnyCPU”.

So, add 2 files to your project – CorFlags.exe (you can find it in the {SDK}\v2.0\Bin directory) and ManifestFix.exe. Add the following code to the initialization code of your application:

C#:


using System.IO;
using System.Diagnostics;
using System.Reflection;
...

try
{
    if (System.Deployment.Application.ApplicationDeployment.IsNetworkDeployed &&
        System.Deployment.Application.ApplicationDeployment.CurrentDeployment.IsFirstRun)
    {
        string ManifestFixPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "ManifestFix.exe");
        Process ManifestFixProc = null;
        try
        {
            ManifestFixProc = new Process();
            ManifestFixProc.StartInfo.FileName = "\"" + ManifestFixPath + "\"";
            ManifestFixProc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
            ManifestFixProc.StartInfo.Arguments = Process.GetCurrentProcess().Id + " \"" + Assembly.GetExecutingAssembly().Location + "\"";
            ManifestFixProc.Start();
            Process.GetCurrentProcess().Kill();
        }
        catch { }
    }
}
catch { }

VB.NET:


Imports System.IO
Imports System.Diagnostics
Imports System.Reflection
...

Try
    If (System.Deployment.Application.ApplicationDeployment.IsNetworkDeployed And _
        System.Deployment.Application.ApplicationDeployment.CurrentDeployment.IsFirstRun) _
    Then
        Dim ManifestFixPath As String = _
            Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "ManifestFix.exe")
        Dim ManifestFixProc As Process = Nothing
        Try
            ManifestFixProc = New Process()
            ManifestFixProc.StartInfo.FileName = """" + ManifestFixPath + """"
            ManifestFixProc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden
            ManifestFixProc.StartInfo.Arguments = Process.GetCurrentProcess().Id.ToString() + " """ + _
               Assembly.GetExecutingAssembly().Location + """"
            ManifestFixProc.Start()
            Process.GetCurrentProcess().Kill()
        Catch
        End Try
    End If
Catch
End Try

The code launches the ManifestFix.exe utility with parameters: Process.GetCurrentProcess().Id (ID of the current process) and a path to the executable file.

4. Now you can publish your application (Solution Properties –> Publish).

How does ManifestFix.exe work?

As input parameters, the following ones are accepted: 

  • ID of the current process of your standalone application
  • path to the executable file of your standalone application

First, the utility waits for the completion of the process with the ID that was passed as an input parameter. After the process is completed, a corresponding manifest file is opened and required XML elements are added into it (the XML elements are replaced if they already exist). After that, the CorFlags Conversion Tool is run, if needed. And finally, your standalone application is launched using the path passed in the second parameter.

In the code of my ManifestFix.exe utility, I used the Is64BitOutlook() function, you can find more information about it in Outlook Security Manager 2010 deployment: bitness and regsvr32 utility, part 2. Also I rely on IntPtr.Size – the value of this property is 4 on a 32-bit platform, and 8 on a 64-bit platform.

Available downloads:

ManifestFix.zip
ManifestFix source (C# solution)
ManifestFix source (VB solution)

Post a comment

Have any questions? Ask us right now!