在Wix工具集自定义操作

时间:2017-12-13 12:28:03

标签: c# generics wix mef

我有一些通用接口

namespace SimpleLibrary
{
    public interface IImported<T>
    {
        T Value { get; set; }
    }
}

及其在另一个.dll

中的实施
namespace ImportedLibrary
{
    [Export(typeof(IImported<>))]
    public class ExportedEntry<T> : IImported<T>
    {
        public T Value { get; set; }
    }
}

然后我将导入到另一个类

namespace SimpleLibrary
{
    public class MainEntry
    {
        [Import]
        public IImported<string> Imported { get; set; }

        public MainEntry()
        {
            try
            {
                var catalog = new DirectoryCatalog(Dir);
                var container = new CompositionContainer(catalog);
                container.ComposeParts(this);

                Imported.Value = "Gomo Sapiens";
            }
            catch (CompositionException ex)
            {
                System.Diagnostics.Debugger.Launch();
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debugger.Launch();
            }
        }

        private string Dir
        {
            get
            {
                var dir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "SimpleLibrary");

                if (!Directory.Exists(dir))
                {
                    dir = AppDomain.CurrentDomain.BaseDirectory;
                }

                return dir;
            }
        }
    }
}

然后我创建控制台应用程序,将.dll标记为[Export]的文件夹放在bin\Debug文件夹中并运行

static void Main(string[] args)
{
    MainEntry me = new MainEntry();
    Console.WriteLine(me.Imported.Value);

    Console.ReadLine();
}

一切正常,控制台显示“Gomo Sapiens”系列。 但是,当我使用一些使用相同MainEntry类并在InstallFinalize之后运行的自定义操作创建Wix Installer时,导入不起作用:

<Binary Id="ServerActions" SourceFile="path to CA.dll" />

<CustomAction Id="RunMainEntry" BinaryKey="ServerActions" DllEntry="RunMainEntry" Execute="immediate" Return="check" />

<InstallExecuteSequence>
  <Custom Action='RunMainEntry' After='InstallFinalize'>NOT Installed AND NOT WIX_UPGRADE_DETECTED</Custom>
</InstallExecuteSequence>

和自定义操作代码

public class CustomActions
{
    [CustomAction]
    public static ActionResult RunMainEntry(Session session)
    {
        MainEntry me = new MainEntry();
        session.Log(me.Imported.Value);

        return ActionResult.Success;
    }
}

自定义操作会引发CompositionException。请注意,我的安装程序最初会复制.dll内的所有文件(.exeProgram Files(x86)\SimpleLibrary),然后使用MEF合成调用自定义操作。我想强调的是,在调用MainEntry构造函数时,所有.dlls都位于Program Files文件夹中,而MEF会看到它们但无法找到要导入的内容。问题只出现在泛型类型中,简单的接口会导入。

.NET Framework版本为4.5C# 6.0CustomAction.config

<configuration>
    <startup useLegacyV2RuntimeActivationPolicy="true">          
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>
</configuration>

还尝试使用MefContrib,情况相同。

重要的是,当我在安装完成后从Program Files(x86)手动运行控制台应用程序时,一切正常。

所以问题是我如何使用MEF来自Wix's自定义操作,如果我不能 - 为什么?

1 个答案:

答案 0 :(得分:0)

我非常确定在运行自定义操作时,安装程​​序会将CA.dll二进制文件解压缩到一个临时目录中并从那里运行它。如果您向PATH添加了任何内容,它将不会反映在安装程序的环境中,因此您无法检测到任何新文件。

您可以使用msi日志记录(/ l * v log.txt)运行和/或同时运行procmon也可以进行验证。

您可能需要在自解压CA.dll本身中打包依赖DLL。

您可以通过在自定义操作项目中定义<CustomActionContents>并将此MSBuild属性的值设置为依赖DLL的路径的分隔列表来执行此操作。然后在构建时,这些DLL以及自定义操作dll将打包到CA.dll中,CA.dll将被解压缩到临时目录,以便在运行时用于自定义操作。

我实际上有另一个答案,更详细地了解CustomActionContents是什么以及它做什么here。它说&#34;空间划界&#34;在评论中,但我已经证实它是; - 定界。如果您还想要读取该代码,这也为您提供了定义MSBuild目标和属性的文件的位置。