НейроАгент

Полное руководство: Развертывание .NET 9 Excel Interop

Решите проблемы развертывания .NET 9 Excel interop. Узнайте, как встраивать типы interop и избегать перераспределения DLL в установщике приложения.

Как развернуть приложение .NET 9, использующее Microsoft.Office.Interop.Excel, без включения Interop DLL?

Недавно я перенес большой кодовой проект с .NET Framework 4.7.2 на .NET 9. В этом проекте у нас есть несколько проектов C++/CLI, которые ссылаются на пакет NuGet Microsoft.Office.Interop.Excel для создания файлов Excel.

Описание проблемы

При выполнении с локальной компиляции все работает нормально. Однако при развертывании на компьютере клиента мы не включаем office.dll и Microsoft.Office.Interop.Excel.dll, поскольку, как я понимаю, мы не имеем на это юридического права.

В .NET Framework 4.7.2 это работало благодаря GAC (Global Assembly Cache), который позволял приложению находить эти DLL-файлы в установке Office на компьютере клиента. Но теперь, с .NET 9, мы получаем исключение, говорящее, что DLL не найдена:

Could not load file or assembly 'Microsoft.Office.Interop.Excel, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c'. The system cannot find the file specified.

Что я уже пробовал

  1. Внедрение типов взаимодействия в сборку

    • Я считаю, что это невозможно с C++/CLI. Поэтому вместо этого я создал проект C#, ссылающийся на пакет с <EmbedInteropTypes>true</EmbedInteropTypes>, а затем сослался на эту сборку в сборке C++/CLI.
    • Это не сработало, так как у меня возникли ошибки компиляции, говорящие, что типы не определены.
  2. Обновление пакета NuGet

    • Это не сработало, так как мы все равно получаем то же исключение во время выполнения (но с новым номером версии).
  3. Использование COM-ссылки вместо этого

    • В Visual Studio: щелкните правой кнопкой мыши по проекту > Добавить ссылку > COM > Библиотека объектов Microsoft Excel 16.0.
    • Это не сработало, так как мы все равно получаем похожее исключение во время выполнения:
    Could not load file or assembly 'Interop.Microsoft.Office.Interop.Excel.1.9, Version=1.9.0.0, Culture=neutral, PublicKeyToken=null'. The system cannot find the file specified.
    

Дополнительная информация

Я также рассматривал возможность использования других библиотек, но я не думаю, что в отведенные сроки будет возможно переписать наш код взаимодействия с Excel.

Вопрос

Существует ли способ развернуть приложение .NET 9, использующее взаимодействие с Excel, на компьютере клиента без включения Microsoft.Office.Interop.Excel.dll в установщик?

НейроАгент

В .NET 9 вы можете развертывать приложения с использованием Microsoft.Office.Interop.Excel без повторного распространения interop DLL, используя функцию “Embed Interop Types” и обеспечивая правильную установку Office на клиентских машинах. Этот подход устраняет необходимость включать interop сборки в ваше приложение, сохраняя совместимость с разными версиями Office.

Содержание

Основные требования

Microsoft.Office.Interop.Excel в первую очередь требует установки Microsoft Office на целевой машине. Как четко указано в результатах исследования, “Вы не можете использовать Microsoft.Office.Interop.Excel без установленного MS Office” [источник]. Это связано с тем, что interop сборки по сути являются .NET-обертками для COM-объектов, которые являются частью установки Office.

При миграции с .NET Framework 4.7.2 на .NET 9 поведение значительно меняется. В эпоху .NET Framework Глобальный кэш сборок (GAC) позволял приложениям находить interop сборки, установленные вместе с Office. Однако .NET 9 не полагается на GAC таким же образом, что объясняет исключение “Не удалось загрузить файл или сборку”.

Ключевое замечание из документации Microsoft заключается в том, что “Дополнительные улучшения возможны при вызове COM-типа, который не требует основной сборки взаимодействия (PIA) во время выполнения. Устранение зависимости от PIA приводит к независимости от версии и упрощению развертывания” [источник].

Решение с внедрением типов взаимодействия

Основным решением для избежания повторного распространения interop DLL в .NET 9 является включение функции “Embed Interop Types” для ваших ссылок на interop. Эта функция была представлена в .NET 4.0 и усовершенствовалась в последующих версиях.

Как включить внедрение типов взаимодействия:

  1. Для проектов C#:

    • Щелкните правой кнопкой мыши по ссылке на Microsoft.Office.Interop.Excel
    • Выберите “Свойства”
    • Установите для “Embed Interop Types” значение True
  2. Для проектов C++/CLI (Ваша текущая проблема):

    xml
    <ItemGroup>
      <Reference Include="Microsoft.Office.Interop.Excel">
        <EmbedInteropTypes>true</EmbedInteropTypes>
      </Reference>
    </ItemGroup>
    

Согласно исследованиям, “Нет, это больше не необходимо с VS2010 и .NET 4.0. Просто установите свойство Embed Interop Types для ссылки на interop сборку в True” [источник]. Это внедряет информацию о типах взаимодействия непосредственно в вашу сборку, устраняя необходимость в отдельных interop DLL.

Преимущества этого подхода:

  • Независимость от версии: Ваше приложение работает с разными версиями Office
  • Отсутствие требований к распространяемым компонентам: Не нужно включать interop DLL в установщик
  • Упрощенное развертывание: единый пакет развертывания без внешних зависимостей
  • Соответствие требованиям лицензирования: Избегает распространения interop сборок Microsoft

Важное замечание: Даже с внедренными типами взаимодействия, Microsoft Office по-прежнему должен быть установлен на целевой машине. Внедренные типы только устраняют необходимость в повторном распространении самих interop сборок.

Преодоление ограничений C++/CLI

Ваша конкретная проблема с проектами C++/CLI хорошо задокументирована в исследованиях. C++/CLI имеет ограничения при работе с внедренными типами взаимодействия, что объясняет, почему вы столкнулись с ошибками компиляции, говорящими о неопределенных типах.

Архитектура решения:

Вот рекомендуемый подход для вашей ситуации с C++/CLI:

  1. Создайте проект-обертку на C#:

    csharp
    // Проект на C# с внедренными типами взаимодействия
    public class ExcelInteropWrapper
    {
        public void CreateExcelFile(string filePath)
        {
            var excelApp = new Microsoft.Office.Interop.Excel.Application();
            // Операции с Excel здесь
            excelApp.Quit();
        }
    }
    
  2. Ссылка из C++/CLI:

    cpp
    // Проект C++/CLI с ссылкой на обертку C#
    public ref class ExcelManager
    {
    public:
        void CreateExcelFile(String^ filePath)
        {
            CSharpWrapper::ExcelInteropWrapper^ wrapper = 
                gcnew CSharpWrapper::ExcelInteropWrapper();
            wrapper->CreateExcelFile(filePath);
        }
    };
    
  3. Конфигурация проекта:

    • Установите <EmbedInteropTypes>true</EmbedInteropTypes> в проекте на C#
    • Ссылайтесь на сборку C# из C++/CLI без ссылок на interop

Этот подход обеспечивает безопасность типов, сохраняя преимущества внедренных типов взаимодействия.

Альтернативное решение для C++/CLI:

Если вы предпочитаете оставить все в C++/CLI, рассмотрите позднее связывание вместо раннего:

cpp
using namespace System::Runtime::InteropServices;

public ref class ExcelManager
{
public:
    void CreateExcelFile(String^ filePath)
    {
        Type^ excelType = Type::GetTypeFromProgID("Excel.Application");
        dynamic excelApp = Activator::CreateInstance(excelType);
        
        // Используйте динамическое распределение для операций с Excel
        excelApp->Visible = true;
        // Дополнительные операции с Excel...
        
        excelApp->Quit();
    }
};

Позднее связывание полностью устраняет необходимость в ссылках на interop, но требует тщательной обработки и теряет проверку типов времени компиляции.

Альтернативные подходы к развертыванию

1. Установка основных сборок взаимодействия Office (PIA)

Если внедренные типы взаимодействия не подходят для вашей ситуации, вы можете убедиться, что PIA Office установлены на целевых машинах:

  • Загрузка: Получите соответствующую PIA с центра загрузки Microsoft
  • Развертывание: Включите установщик PIA в пакет развертывания
  • Установка: Запустите установщик перед развертыванием вашего приложения

Согласно исследованиям, “Проверьте правильный распространяемый компонент, предназначенный для interop, которые вас интересуют” [источник]. Этот подход обеспечивает полную поддержку interop, но требует дополнительных этапов установки.

2. Подход на основе регистрации COM

Для сценариев, где Office установлен, но PIA отсутствуют:

csharp
// Используйте регистрацию COM вместо ссылок на interop
Type excelType = Type::GetTypeFromProgID("Excel.Application");
dynamic excelApp = Activator::CreateInstance(excelType);

Этот подход работает с любой версией Office, имеющей необходимые зарегистрированные COM-компоненты.

3. Framework NetOffice

Рассмотрите использование открытого фреймворка NetOffice:

  • Независимость от версии: Работает с разными версиями Office
  • Отсутствие зависимостей от interop: Не требует PIA
  • Упрощенное развертывание: Развертывание одной DLL

Как упоминалось в исследованиях, “Вместо раннего связывания ссылки, существует проект с открытым исходным кодом под названием NetOffice, который абстрагирует это от вашего проекта, значительно упрощая жизнь” [источник].

Зависимости времени выполнения и установка Office

Совместимость версий Office:

Версия Office Версия Interop Совместимость с .NET
Office 2003 11.0.0.0 .NET Framework 2.0+
Office 2007 12.0.0.0 .NET Framework 2.0+
Office 2010 14.0.0.0 .NET Framework 4.0+
Office 2013 15.0.0.0 .NET Framework 4.0+
Office 2016 16.0.0.0 .NET Framework 4.0+
Office 2019 16.0.0.0 .NET Framework 4.0+
Office 365 16.0.0.0 .NET 5.0+

Контрольный список развертывания:

  1. Проверьте установку Office: Убедитесь, что на целевых машинах установлена совместимая версия Office
  2. Проверьте архитектуру: Сопоставьте архитектуру Office (32/64-бит) с вашим приложением
  3. Установите PIA при необходимости: Для полной поддержки interop
  4. Проверьте поведение времени выполнения: Проверьте операции interop на целевых машинах

Решение ошибок:

Исключение времени выполнения, с которым вы столкнулись, возникает потому, что .NET 9 не может найти interop сборку. После внедрения типов взаимодействия, если вы все еще видите ошибки:

  1. Проверьте установку Office: Подтвердите, что Office правильно установлен
  2. Проверьте архитектуру: Обеспечьте совместимость 32/64-бит
  3. Зарегистрируйте COM-компоненты: Используйте regsvr32 при необходимости
  4. Обновите среду выполнения: Убедитесь, что установлена среда выполнения .NET 9

Лучшие практики для Office Interop в .NET 9

1. Используйте позднее связывание, когда это возможно

csharp
dynamic excelApp = Activator.CreateInstance(Type.GetTypeFromProgID("Excel.Application"));
excelApp.Visible = true;
excelApp.Workbooks.Add();
excelApp.Cells[1, 1].Value = "Привет, мир";
excelApp.ActiveWorkbook.SaveAs("output.xlsx");
excelApp.Quit();

2. Реализуйте правильное управление ресурсами

csharp
Excel.Application excelApp = null;
Excel.Workbook workbook = null;

try
{
    excelApp = new Excel.Application();
    excelApp.Visible = false;
    workbook = excelApp.Workbooks.Add();
    
    // Операции с Excel
    workbook.SaveAs("output.xlsx");
}
finally
{
    if (workbook != null) workbook.Close();
    if (excelApp != null) excelApp.Quit();
    
    // Принудительная сборка мусора
    GC.Collect();
    GC.WaitForPendingFinalizers();
}

3. Корректно обрабатывайте различия версий

csharp
public static Excel.Application GetExcelApplication()
{
    try
    {
        // Попробуйте получить существующий экземпляр
        return (Excel.Application)Marshal.GetActiveObject("Excel.Application");
    }
    catch
    {
        // Создайте новый экземпляр
        return new Excel.Application();
    }
}

4. Рассмотрите альтернативные библиотеки для будущего развития

Хотя вам нужно поддерживать текущую кодовую базу, рассмотрите эти альтернативы для новой функциональности:

  • EPPlus: Для манипулирования .xlsx файлами без Excel
  • NPOI: Открытая .NET-версия POI
  • ClosedXML: .NET библиотека для чтения/записи Excel файлов

Эти библиотеки не требуют установки Office и более подходят для серверных сценариев.

Заключение

Развертывание приложений .NET 9 с Office Interop без повторного распространения DLL достижимо с помощью функции “Embed Interop Types”. Вот ключевые выводы:

  1. Установка Office обязательна: Microsoft.Office.Interop.Excel требует установки Office на целевых машинах
  2. Внедрение типов взаимодействия: Установите <EmbedInteropTypes>true</EmbedInteropTypes> для устранения необходимости повторного распространения interop DLL
  3. Обход для C++/CLI: Используйте проект-обертку на C# с внедренными типами взаимодействия, на который ссылаются из C++/CLI
  4. Независимость от версии: Внедренные типы обеспечивают совместимость между версиями Office
  5. Альтернативные подходы: Рассмотрите позднее связывание или фреймворки, такие как NetOffice, для сложных сценариев

Для вашей конкретной ситуации я рекомендую реализовать подход с оберткой на C# с внедренными типами взаимодействия, так как он обеспечивает наилучший баланс между безопасностью типов, простотой развертывания и соответствием требованиям лицензирования. Этот подход решит ваши проблемы развертывания, сохраняя функциональность существующей кодовой базы.

Источники

  1. How to access Office interop objects - C# | Microsoft Learn
  2. c# - How to reference Microsoft.Office.Interop.Excel dll? - Stack Overflow
  3. c# - How to use Microsoft.Office.Interop.Excel on a machine without installed MS Office? - Stack Overflow
  4. c# - Distribution of an application that requires Microsoft.Office.Interop.Excel - Stack Overflow
  5. Painless Office Interop Using Visual C# - Claudio Bernasconi
  6. How to use Microsoft.Office.Interop.Excel without installing - C# Corner
  7. r/csharp on Reddit: Can I use Microsoft.Office.Interop.Excel without having Excel installed?
  8. c# - Use Office 2003 interop DLLs without installing the redistributable - Stack Overflow
  9. c# - Export to excel without using third party dll - Stack Overflow
  10. asp.net - How to deploy my application with Excel Export feature? - Stack Overflow
  11. How to: Register Primary Interop Assemblies - .NET Framework | Microsoft Learn
  12. Deploying an Interop Application - .NET Framework | Microsoft Learn
  13. Build and Deploy a .NET COM Assembly - Simple Talk
  14. How to install folder Microsoft.NET\Primary Interop Assemblies?? - MSDN Forums
  15. c# - Should I deploy Interop.x.dll files with .NET application? - Stack Overflow