it-swarm-pt.tech

Como pode um windows C++ dll ser mesclado em um exe de aplicativo c #?

Eu tenho um programa de Windows c # que usa uma dll de C++ para dados de i/o. Meu objetivo é implantar o aplicativo como um único EXE.

Quais são as etapas para criar um executável?

32
Noah

Implantação de assembly único do código gerenciado e não gerenciado Domingo, 4 de fevereiro de 2007

Os desenvolvedores do .NET adoram a implantação do XCOPY. E eles adoram componentes de montagem única. Pelo menos eu sempre me sinto meio desconfortável, se eu tiver que usar algum componente e precisar lembrar de uma lista de arquivos para incluir também no Assembly principal daquele componente. Então, quando eu recentemente tive que desenvolver um componente de código gerenciado e tive que aumentá-lo com algum código não gerenciado de um C DLL (thx para Marcus Heege por me ajudar com isso!), Eu pensei sobre como fazer isso mais fácil implantar as duas DLLs. Se fossem apenas dois conjuntos, eu poderia ter usado o ILmerge para empacotá-los em apenas um arquivo. Mas isso não funciona para componentes de código misto com DLLs gerenciadas e não gerenciadas.

Então aqui está o que eu criei para uma solução:

Eu incluo quaisquer DLLs que eu queira implantar com o Assembly principal do meu componente como recursos incorporados. Então eu configurei um construtor de classe para extrair as DLLs como abaixo. O class ctor é chamado apenas uma vez dentro de cada AppDomain, então é uma sobrecarga negligenciável, eu acho.

namespace MyLib
{
    public class MyClass
    {
        static MyClass()
        {
            ResourceExtractor.ExtractResourceToFile("MyLib.ManagedService.dll", "managedservice.dll");
            ResourceExtractor.ExtractResourceToFile("MyLib.UnmanagedService.dll", "unmanagedservice.dll");
        }

        ...

Neste exemplo, incluí duas DLLs como recursos, sendo um deles um código não gerenciado DLL e um deles um código gerenciado DLL (apenas para fins de demonstração), para mostrar como essa técnica funciona para os dois tipos de código.

O código para extrair as DLLs em arquivos próprios é simples:

public static class ResourceExtractor
{
    public static void ExtractResourceToFile(string resourceName, string filename)
    {
        if (!System.IO.File.Exists(filename))
            using (System.IO.Stream s = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName))
                using (System.IO.FileStream fs = new System.IO.FileStream(filename, System.IO.FileMode.Create))
                {
                    byte[] b = new byte[s.Length];
                    s.Read(b, 0, b.Length);
                    fs.Write(b, 0, b.Length);
                }
    }
}

Trabalhar com um código gerenciado O assembly como este é o mesmo de sempre - quase. Você faz referência a ele (aqui: ManagedService.dll) no projeto principal do seu componente (aqui: MyLib), mas define a propriedade Copy Local como false. Além disso, você vincula a montagem como um item existente e define a ação de compilação para o recurso incorporado.

Para o código não gerenciado (aqui: UnmanagedService.dll), você apenas vincula a DLL como um Item Existente e define a Ação de Construção como Recurso Incorporado. Para acessar suas funções, use o atributo DllImport como de costume, por exemplo,.

[DllImport("unmanagedservice.dll")] public extern static int Add(int a, int b);

É isso aí! Assim que você cria a primeira instância da classe com o código estático, as DLLs inseridas são extraídas em arquivos próprios e estão prontas para serem usadas como se fossem implantadas como arquivos separados. Contanto que você tenha permissões de gravação para o diretório de execução, isso deve funcionar bem para você. Pelo menos para o código prototípico, acho que esse modo de implementação única do Assembly é bastante conveniente.

Apreciar!

http://weblogs.asp.net/ralfw/archive/2007/02/04/single-Assembly-deployment-of-managed-and-unmanaged-code.aspx

16
Nick

Tente boxedapp ; permite carregar todas as DLLs da memória. Além disso, parece que você pode até incorporar o tempo de execução do .net. É bom criar aplicativos realmente independentes ...

3
Art

Basta clicar com o botão direito do mouse em seu projeto no Visual Studio, escolha Propriedades do projeto -> Recursos -> Adicionar recurso -> Adicionar arquivo existente ... E inclua o código abaixo em seu App.xaml.cs ou equivalente.

public App()
{
    AppDomain.CurrentDomain.AssemblyResolve +=new ResolveEventHandler(CurrentDomain_AssemblyResolve);
}

System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
    string dllName = args.Name.Contains(',') ? args.Name.Substring(0, args.Name.IndexOf(',')) : args.Name.Replace(".dll","");

    dllName = dllName.Replace(".", "_");

    if (dllName.EndsWith("_resources")) return null;

    System.Resources.ResourceManager rm = new System.Resources.ResourceManager(GetType().Namespace + ".Properties.Resources", System.Reflection.Assembly.GetExecutingAssembly());

    byte[] bytes = (byte[])rm.GetObject(dllName);

    return System.Reflection.Assembly.Load(bytes);
}

Aqui está o meu post original no blog: http://codeblog.larsholm.net/2011/06/embed-dlls-easily-in-a-net-Assembly/

1
Lars Holm Jensen

Use Fody.Costura nuget

  1. Abra sua solução -> Projeto -> Gerenciar Pacotes Nuget
  2. Pesquisa por Fody.Costura
  3. Compile seu projeto

É isso aí !

Fonte: http://www.manuelmeyer.net/2016/01/net-power-tip-10-merging-assemblies/

1
automan

Você já tentou o ILMerge? http://research.Microsoft.com/~mbarnett/ILMerge.aspx

O ILMerge é um utilitário que pode ser usado para mesclar vários assemblies do .NET em um único Assembly. Está disponível gratuitamente para uso na página Ferramentas e Utilitários no Microsoft .NET Framework Developer Center. 

Se você está construindo o C++ DLL com o sinalizador /clr (todo ou parcialmente C++/CLI), então deve funcionar:

ilmerge /out:Composite.exe MyMainApp.exe Utility.dll

Ele não funcionará com um Windows comum (nativo) DLL. 

1
Raithlin

Smart Assembly pode fazer isso e muito mais. Se a sua dll tiver código não gerenciado, ela não permitirá que você mescle as dlls em um único Assembly, em vez disso, ela poderá incorporar as dependências necessárias como recursos ao seu exe principal. Seu flip-side, não é livre.

Você pode fazer isso manualmente, incorporando dll aos seus recursos e, em seguida, confiando no Assembly do AppDomain ResolveHandler. Quando se trata de dlls modo misto, eu encontrei muitas das variantes e sabores da abordagem ResolveHandler para não funcionar para mim (tudo o que ler bytes DLL para a memória e ler a partir dele). Todos eles trabalhavam para dlls gerenciados. Aqui está o que funcionou para mim:

static void Main()
{
    AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
    {
        string assemblyName = new AssemblyName(args.Name).Name;
        if (assemblyName.EndsWith(".resources"))
            return null;

        string dllName = assemblyName + ".dll";
        string dllFullPath = Path.Combine(GetMyApplicationSpecificPath(), dllName);

        using (Stream s = Assembly.GetEntryAssembly().GetManifestResourceStream(typeof(Program).Namespace + ".Resources." + dllName))
        {
            byte[] data = new byte[stream.Length];
            s.Read(data, 0, data.Length);

            //or just byte[] data = new BinaryReader(s).ReadBytes((int)s.Length);

            File.WriteAllBytes(dllFullPath, data);
        }

        return Assembly.LoadFrom(dllFullPath);
    };
}

A chave aqui é gravar os bytes em um arquivo e carregar a partir de sua localização. Para evitar problemas com ovos e galinhas, você deve garantir que declara o manipulador antes de acessar o Assembly e que não acessa os membros do Assembly (ou instancia qualquer coisa que tenha que lidar com o Assembly) dentro da parte de carregamento (resolução de montagem). Também tome cuidado para garantir GetMyApplicationSpecificPath() não é qualquer diretório temporário desde arquivos temporários podem ser tentados para ser apagados por outros programas ou por si mesmo (não que ele será excluído enquanto o programa está acessando a dll, mas pelo menos é um incômodo. AppData é boa localização). Note também que você tem que escrever os bytes a cada vez, você não pode carregar a partir do local apenas porque a dll já reside lá.

Se o Assembly estiver totalmente não gerenciado, você pode ver este link ou this sobre como carregar tais dlls.

0
nawfal

Thinstall é uma solução. Para um aplicativo nativo do Windows, sugiro incorporar o DLL como um objeto de recurso binário e, em seguida, extraí-lo em tempo de execução antes de você precisar dele.

0
titanae