Может ли приложение Windows.NET быть сжато в один .exe?

Я не слишком хорошо знаком с настольными приложениями .NET(используя Visual Studio 2005). Можно ли запустить все приложение из одного файла .exe?

Ответ 1

Да, вы можете использовать инструмент ILMerge.

Ответ 2

Да. В .NET вы можете включить все ваше приложение в виде одного EXE файла. Просто убедитесь, что ваше решение имеет только один проект приложения Windows (и никаких других проектов, кроме настроек).

EXE файл, созданный вашим проектом .NET, не будет автономным исполняемым файлом, но единственная зависимость, которую он будет иметь, будет .NET runtime (если вы не добавите ссылки на другую DLL узлы). Если вы используете .NET 2.0 (который я рекомендую), среда выполнения устанавливается на более новые ПК и очень легко и быстро настраивается на старых компьютерах (установщик составляет около 23 МБ).

Если вашему приложению нужно ссылаться на другие сборки (например, DLL с доступом к данным или DLL-проект библиотеки .NET), вы можете использовать один из инструментов, на которые ссылаются другие плакаты здесь, чтобы объединить EXE и все связанные DLL файлы в один EXE файл. Тем не менее, обычная практика будет диктовать простое развертывание EXE файла вместе с любыми зависимыми DLL в качестве отдельных файлов. В .NET развертывание зависимых DLL довольно просто: просто поместите их в ту же папку, что и EXE файл на клиентской машине, и все готово.

Хорошей практикой является развертывание вашего приложения (будь то одного или нескольких файлов) в качестве установщика с одним файлом (либо setup.EXE, либо setup.MSI)..NET поставляется с шаблонами проектов развертывания, которые могут создавать установщики для вас довольно легко.

Немного не по теме: вы можете использовать NGEN для компиляции своего .NET-приложения в качестве родного EXE, но оно все равно будет зависеть от среды выполнения .NET. Преимущество родной компиляции заключается в том, что некоторые вещи можно предварительно скомпилировать, но я никогда не видел ситуации, когда это небольшое увеличение производительности стоит того, чтобы беспокоиться.

Ответ 3

Сегодня, в 2015 году, вы можете использовать Costura.Fody для этого. Его использование сводится к добавлению пакета NuGet к вашему проекту и перекомпиляции. Я не уверен, что он работает с Visual Studio 2005, как в вопросе, но потом это не год 2008. Я использовал его в нескольких моих проектах, и он отлично работал.

Fody является общим назначением Code Weaver который является бесплатным и открытым исходным кодом. Основная идея заключается в том, что он позволяет выполнять пост-обработку скомпилированного .NET-кода, чтобы улучшить его с помощью функций. Например, регистрация может быть добавлена ​​к каждому вызову метода и т.д. В нашем случае он упаковывает зависимые файлы DLL в ресурсы сборки, чтобы их можно было загружать во время выполнения программы, как если бы они были автономными зависимостями.

Ответ 4

Существует сторонний инструмент .NET Reactor, который может сделать это за вас. Я не использовал инструмент, поэтому не уверен, насколько он работает.

Ответ 5

Я использовал . NETZ.NET исполняемый пакет с открытым исходным кодом для упаковки EXE и DLL файлов в один файл EXE. Ниже приведен пример командной строки для того, как упаковать файлы DLL в один файл:

netz -s application.exe foo.dll bar.dll

Ответ 6

Как уже было сказано, вы можете использовать ILMerge.

Однако может быть проще, если вы используете бесплатный протектор Phoenix, который также защищает ваш код.

Ответ 7

Вы можете попробовать утилиту NBox.

Ответ 8

Джеффри Рихтер написал в своем выдержке из книги, что метод обратного вызова с доменами приложений Событие ResolveAssembly можно зарегистрировать, чтобы включить CLR для поиска сторонних сборок и файлов DLL во время инициализации программы:

AppDomain.CurrentDomain.AssemblyResolve += (sender, 
  args) => {
    String resourceName = "AssemblyLoadingAndReflection." +
    new AssemblyName(args.Name).Name + ".dll";
    using (var stream =       
      Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName)){
        Byte[] assemblyData = new Byte[stream.Length];
        stream.Read(assemblyData, 0, assemblyData.Length);
        return Assembly.Load(assemblyData);
      }
   };

Отказ от ответственности: я не использовал это сам. Насколько я понял, клиент все еще должен иметь установленную платформу .NET.

Ответ 9

Вы не должны разделить его на несколько сборок (обычно это проекты внутри решения Visual Studio). В любом случае требуется .NET Framework, нет способа - и это правильный способ - вставить его.

Ответ 11

ILMerge может комбинировать сборки с одной сборкой, если сборка имеет только управляемый код. Вы можете использовать приложение командной строки или добавить ссылку на EXE файл и программно объединить. Для версии GUI существует Eazfuscator, а также . Netz, оба из которых бесплатны. Платные приложения включают BoxedApp и SmartAssembly.

Если вам нужно объединить сборки с неуправляемым кодом, я бы предложил SmartAssembly. У меня никогда не было икоты с SmartAssembly, но со всеми остальными. Здесь он может встраивать необходимые зависимости в качестве ресурсов в ваш основной EXE файл.

Вы можете сделать все это вручную, не нужно беспокоиться о том, управляется ли сборка или в смешанном режиме, вставляя DLL файл в ваши ресурсы, а затем полагаясь на AppDomain Assembly ResolveHandler. Это универсальное решение, приняв наихудший случай, то есть сборки с неуправляемым кодом.

class Program
{
    [STAThread]
    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);
        };
    }
}

Где Program - это имя класса. Ключевым моментом здесь является запись байтов в файл и загрузка из его местоположения. Чтобы избежать проблемы с курицей и яйцом, вы должны убедиться, что вы объявляете обработчик перед доступом к сборке и что вы не получаете доступа к членам собрания (или создаете экземпляр всего, что связано с сборкой) внутри загрузки (разрешение сборки) часть. Также будьте осторожны, чтобы гарантировать, что GetMyApplicationSpecificPath() не является временным каталогом, так как временные файлы могут быть удалены другими программами или самим собой (не то, что он будет удален, пока ваша программа будет обращаться к DLL файлу, но, по крайней мере, это неприятность AppData - хорошее место). Также обратите внимание, что вы должны каждый раз писать байты; вы не можете загрузить из местоположения только потому, что там находится DLL файл.

Для управляемых DLL файлов вам не нужно писать байты, а загружать их непосредственно из места расположения DLL файла или просто читать байты и загружать сборку из памяти. Примерно так или иначе:

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

// Or just

return Assembly.LoadFrom(dllFullPath); // If location is known.

Если сборка полностью неуправляема, вы можете увидеть эту ссылку или this как загрузить такие DLL файлы.

Ответ 12

Я использую . netshrink сам, и он делает именно то, что вам нужно. Он объединяет основные и дополнительные сборки (файлы DLL) в одно исполняемое изображение.

Я использую его уже один год, и я не вернусь к ILMerge (он всегда сбой в какой-то момент...).

.netshrink main window from the product's page