3

I'm trying to convert a classic VSTO Outlook add-in project to SDK-style format while maintaining full VSTO functionality. Both csproj project files compile successfully and produces a working .dll, but the SDK-style csproj fails to generate the required VSTO deployment files (.vsto and .dll.manifest) - why and how to fix it?
Any insights into resolving this SDK-style + VSTO compatibility issue would be greatly appreciated!

TL-DR: Solution is in this question below,
thanks to @lauxjpn and his tips from here and here.

Problem

Working: BIEM-OldStyle.csproj - Classic MSBuild format project generates all required files incl. .vsto and .dll.manifest
Not Working: BIEM-SdkStyle.csproj - SDK-style project compiles .dll but missing deployment manifests .vsto and .dll.manifest

Project Files
Working Classic Project BIEM-OldStyle.csproj
This classic format works perfectly and generates all required VSTO files:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
  <PropertyGroup>
    <ProjectTypeGuids>{BAA0C2D2-18E2-41B9-852F-F413020CAA33};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProjectGuid>{2F40F2E6-067E-42CA-99AE-F2B33A9E1F5F}</ProjectGuid>
    <OutputType>Library</OutputType>
    <RootNamespace>Minimal.BIEM</RootNamespace>
    <AssemblyName>Minimal.BIEM.Outlook</AssemblyName>
    <TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
    <TargetFrameworkProfile>
    </TargetFrameworkProfile>
    <DefineConstants>VSTO40</DefineConstants>
    <IsWebBootstrapper>False</IsWebBootstrapper>
    <OldToolsVersion>4.0</OldToolsVersion>
    <VSTO_TrustAssembliesLocation>true</VSTO_TrustAssembliesLocation>
    <!-- VSTO-specific properties for the ClickOnce deployment -->
    <!-- The ApplicationVersion is used in .VSTO file and in .dll.manifest The ApplicationVersion cannot be added to AssemblyInfo.cs -->
    <ApplicationVersion>3.2.4.0</ApplicationVersion>
    <OfficeApplication>Outlook</OfficeApplication>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>bin\Debug\</OutputPath>
    <EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
    <DefineConstants>$(DefineConstants);DEBUG;TRACE</DefineConstants>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <PropertyGroup>
    <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
    <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
  </PropertyGroup>
  <PropertyGroup>
    <SignAssembly>true</SignAssembly>
    <AssemblyOriginatorKeyFile>config\MyPrivateKey.snk</AssemblyOriginatorKeyFile>
  </PropertyGroup>
  <PropertyGroup>
    <SignManifests>true</SignManifests>
    <ManifestKeyFile>config\BIEM20_TemporaryKey.pfx</ManifestKeyFile>
    <ManifestCertificateThumbprint>6E88CD736C2FD0A5EEDD529E060650F99DADEB89</ManifestCertificateThumbprint>
  </PropertyGroup>
  <PropertyGroup>
    <DelaySign>false</DelaySign>
  </PropertyGroup>
  <ItemGroup>
    <None Include="config\BIEM20_TemporaryKey.pfx" />
    <Compile Include="ThisAddIn.cs">
      <SubType>Code</SubType>
    </Compile>
    <None Include="ThisAddIn.Designer.xml">
      <DependentUpon>ThisAddIn.cs</DependentUpon>
    </None>
    <Compile Include="ThisAddIn.Designer.cs">
      <DependentUpon>ThisAddIn.Designer.xml</DependentUpon>
    </Compile>
    <AppDesigner Include="Properties\" />
    <None Include="config\MyPrivateKey.snk">
      <Link>MyPrivateKey.snk</Link>
    </None>
  </ItemGroup>
  <ItemGroup>
    <Reference Include="Accessibility" />
    <Reference Include="Microsoft.Office.Interop.Outlook, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c, processorArchitecture=MSIL">
      <SpecificVersion>False</SpecificVersion>
      <EmbedInteropTypes>True</EmbedInteropTypes>
    </Reference>
    <Reference Include="Microsoft.Office.Tools, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
      <SpecificVersion>False</SpecificVersion>
      <EmbedInteropTypes>False</EmbedInteropTypes>
    </Reference>
    <Reference Include="Microsoft.Office.Tools.Common, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
      <SpecificVersion>False</SpecificVersion>
      <EmbedInteropTypes>False</EmbedInteropTypes>
    </Reference>
    <Reference Include="Microsoft.Office.Tools.Common.v4.0.Utilities, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
      <SpecificVersion>False</SpecificVersion>
      <Private>True</Private>
    </Reference>
    <Reference Include="Microsoft.Office.Tools.Outlook, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
      <SpecificVersion>False</SpecificVersion>
    </Reference>
    <Reference Include="Microsoft.Office.Tools.Outlook.v4.0.Utilities, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
      <SpecificVersion>False</SpecificVersion>
      <Private>True</Private>
    </Reference>
    <Reference Include="Microsoft.Office.Tools.v4.0.Framework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
      <SpecificVersion>False</SpecificVersion>
    </Reference>
    <Reference Include="Microsoft.VisualStudio.Tools.Applications.Runtime, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
      <SpecificVersion>False</SpecificVersion>
    </Reference>
    <Reference Include="Office, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c, processorArchitecture=MSIL">
      <SpecificVersion>False</SpecificVersion>
      <EmbedInteropTypes>True</EmbedInteropTypes>
    </Reference>
    <Reference Include="stdole, Version=7.0.3300.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
      <SpecificVersion>False</SpecificVersion>
      <EmbedInteropTypes>False</EmbedInteropTypes>
    </Reference>
    <Reference Include="System" />
    <Reference Include="System.Data" />
    <Reference Include="System.DirectoryServices" />
    <Reference Include="System.DirectoryServices.AccountManagement" />
    <Reference Include="System.Drawing" />
    <Reference Include="System.Net.Http" />
    <Reference Include="System.Web" />
    <Reference Include="System.Windows.Forms" />
    <Reference Include="System.Xml" />
    <Reference Include="System.Core" />
    <Reference Include="System.Xml.Linq" />
    <Reference Include="System.Data.DataSetExtensions" />
    <Reference Include="Microsoft.CSharp" />
  </ItemGroup>
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
  <!-- Include additional build rules for an Office application add-in. -->
  <Import Project="$(VSToolsPath)\OfficeTools\Microsoft.VisualStudio.Tools.Office.targets" Condition="'$(VSToolsPath)' != ''" />
  <!-- This section defines VSTO properties that describe the host-changeable project properties. -->
</Project>

Non-Working SDK-Style Project: BIEM-SdkStyle.csproj
This SDK-style format compiles successfully but fails to generate .vsto and .dll.manifest: NOTE: I had to removed the non working BIEM-SdkStyle.csproj from this place in a sake of the working one down below.

Build Commands Tested
Classic Project (Works - generates .vsto and .dll.manifest)

msbuild BIEM-OldStyle.csproj `
   /p:Platform=AnyCPU `
   /p:SignAssembly=true `
   /p:SignManifests=true `
   /p:RunCodeAnalysis=false `
   /p:SkipInvalidConfigurations=true `
   /p:RegisterForComInterop=false

SDK-Style Project Attempts - both compile but no manifests

# Attempt 1: Visual Studio MSBuild with Publish target
dotnet restore "BIEM-SdkStyle.csproj"
msbuild BIEM-SdkStyle.csproj /p:Configuration=Debug /p:Platform=AnyCPU /p:SignAssembly=true /p:SignManifests=true

# Attempt 2: .NET SDK build
dotnet build BIEM-SdkStyle.csproj --verbosity detailed

I use the MSBuild on this path locally:
C:\Program Files\Microsoft Visual Studio\2022\Professional\MSBuild\Current\Bin\MSBuild.exe

What Works vs What Doesn't
Successful Results (All builds of both Projects)

  • Compilation completes without errors
  • Minimal.BIEM.Outlook.dll generated
  • All Office interop references resolved
  • Strong name signing works
  • Certificate validation passes

Missing from SDK-Style Project

  • Minimal.BIEM.Outlook.vsto (VSTO deployment manifest)
  • Minimal.BIEM.Outlook.dll.manifest (ClickOnce application manifest)

Certificate Validation (Confirmed Working)
Both projects use the same certificates which are validated and working:

PS> sn -p "config\MyPrivateKey.snk" "temp_public.snk"
PS> sn -tp "temp_public.snk"
Public key token is 013cc860b885f10e

PS> Get-PfxCertificate -FilePath "config\BIEM20_TemporaryKey.pfx"
Thumbprint: 6E88CD736C2FD0A5EEDD529E060650F99DADEB89
Subject: CN=MyCompany BIEM
EnhancedKeyUsageList: Code Signing

Environment:

  • Visual Studio: 2022 Professional (Version 17.14.12)
  • .Net SDK 9.0.304
  • .NET Framework: 4.7.2
  • MSBuild: Both .NET SDK MSBuild and Visual Studio MSBuild tested
  • VSTO Runtime: Microsoft Visual Studio Tools for Office Runtime 4.0
  • Office: Outlook (Office 15.0/2013+ interop assemblies)
  • Operating System: Windows 11 with PowerShell 7.5.2

Edit / Solution

Thanks to guidance from @lauxjpn, I was able to resolve this issue. The key takeaways were:

  1. Import order is critical: SDK targets must be imported before VSTO targets.
<!-- Import .NET SDK targets FIRST -->
<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />

<!-- Import VSTO targets AFTER SDK targets -->
<Import Project="$(VSTOTargetsPath)" Condition="Exists('$(VSTOTargetsPath)') and '$(MSBuildRuntimeType)' == 'Full'" />
  1. I had to add CertificateThumbprint next to ManifestCertificateThumbprint with the same content:
    <SignManifests>true</SignManifests>
    <ManifestKeyFile>config\BIEM20_TemporaryKey.pfx</ManifestKeyFile>
    <ManifestCertificateThumbprint>6E88CD736C2FD0A5EEDD529E060650F99DADEB89</ManifestCertificateThumbprint>
    <CertificateThumbprint>6E88CD736C2FD0A5EEDD529E060650F99DADEB89</CertificateThumbprint>
  1. I must use:
<Project>
  <!-- Import .NET SDK props and targets manually -->
  <Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />
  <Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />
  ...

instead of:

<Project Sdk="Microsoft.NET.Sdk">

otherwise the <Import Project="$(VSTOTargetsPath)" will be ignored.

  1. I need to use Conditional VSTO Import: The condition '$(MSBuildRuntimeType)' == 'Full' ensures VSTO targets are only imported when using MSBuild.exe (which can generate .vsto and .dll.manifest files) but not when using dotnet build (which cannot).
    I need both builds because of our GitHub Actions - many of them are using dotnet build

Final Working Configuration: The complete working BIEM-SdkStyle.csproj file is:

<Project>
  <!-- Import .NET SDK props manually -->
  <Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />
  <PropertyGroup>
    <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">17.0</VisualStudioVersion>
    
    <!-- Detect Visual Studio edition - try multiple possible locations -->
    <VisualStudioEditionPath Condition="'$(VisualStudioEditionPath)' == '' and Exists('C:\Program Files\Microsoft Visual Studio\2022\Enterprise')">C:\Program Files\Microsoft Visual Studio\2022\Enterprise</VisualStudioEditionPath>
    <VisualStudioEditionPath Condition="'$(VisualStudioEditionPath)' == '' and Exists('C:\Program Files\Microsoft Visual Studio\2022\Professional')">C:\Program Files\Microsoft Visual Studio\2022\Professional</VisualStudioEditionPath>
    <VisualStudioEditionPath Condition="'$(VisualStudioEditionPath)' == '' and Exists('C:\Program Files\Microsoft Visual Studio\2022\Community')">C:\Program Files\Microsoft Visual Studio\2022\Community</VisualStudioEditionPath>
    
    <!-- Use the detected edition for VSTO targets path -->
    <VSToolsPath Condition="'$(VSToolsPath)' == '' and '$(VisualStudioEditionPath)' != ''">$(VisualStudioEditionPath)\MSBuild\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
    <VSTOTargetsPath Condition="'$(VSTOTargetsPath)' == '' and '$(VSToolsPath)' != ''">$(VSToolsPath)\OfficeTools\Microsoft.VisualStudio.Tools.Office.targets</VSTOTargetsPath>
    <VSCommon7IDE Condition="'$(VSCommon7IDE)' == '' and '$(VSToolsPath)' != ''">$(VisualStudioEditionPath)\Common7\IDE</VSCommon7IDE>
    <VSCommonRefAssembilies4 Condition="'$(VSCommonRefAssembilies4)' == '' and '$(VSToolsPath)' != ''">$(VSCommon7IDE)\ReferenceAssemblies\v4.0</VSCommonRefAssembilies4>
  </PropertyGroup>
  <Target Name="LogVariables" BeforeTargets="Compile">
    <Message Text="MSBuildRuntimeType: $(MSBuildRuntimeType), VisualStudioVersion: $(VisualStudioVersion)" Importance="High" />
    <Message Text="MSBuildExtensionsPath32 (exists: True): $(MSBuildExtensionsPath32)" Importance="High" Condition="Exists('$(MSBuildExtensionsPath32)')" />
    <Message Text="MSBuildExtensionsPath32 (exists: False): $(MSBuildExtensionsPath32)" Importance="High" Condition="!Exists('$(MSBuildExtensionsPath32)')" />
    <Message Text="VisualStudioEditionPath (exists: True): $(VisualStudioEditionPath)" Importance="High" Condition="Exists('$(VisualStudioEditionPath)')" />
    <Message Text="VisualStudioEditionPath (exists: False): $(VisualStudioEditionPath)" Importance="High" Condition="!Exists('$(VisualStudioEditionPath)')" />
    <Message Text="VSToolsPath (exists: True): $(VSToolsPath)" Importance="High" Condition="Exists('$(VSToolsPath)')" />
    <Message Text="VSToolsPath (exists: False): $(VSToolsPath)" Importance="High" Condition="!Exists('$(VSToolsPath)')" />
    <Message Text="VSTOTargetsPath (exists: $([System.IO.File]::Exists('$(VSTOTargetsPath)'))): $(VSTOTargetsPath)" Importance="High" />
    <Message Text="VSCommon7IDE (exists: True): $(VSCommon7IDE)" Importance="High" Condition="Exists('$(VSCommon7IDE)')" />
    <Message Text="VSCommon7IDE (exists: False): $(VSCommon7IDE)" Importance="High" Condition="!Exists('$(VSCommon7IDE)')" />
    <Message Text="VSCommonRefAssembilies4 (exists: True): $(VSCommonRefAssembilies4)" Importance="High" Condition="Exists('$(VSCommonRefAssembilies4)')" />
    <Message Text="VSCommonRefAssembilies4 (exists: False): $(VSCommonRefAssembilies4)" Importance="High" Condition="!Exists('$(VSCommonRefAssembilies4)')" />
  </Target>
  <PropertyGroup>
    <TargetFramework>net472</TargetFramework>

    <!-- BIEM-specific assembly metadata -->
    <AssemblyTitle>My Minimal.BIEM</AssemblyTitle>
    <AssemblyDescription>Lorem ipsum....</AssemblyDescription>
    <AssemblyProduct>BIEM</AssemblyProduct>
    
    <!-- VSTO-specific properties -->
    <ProjectTypeGuids>{BAA0C2D2-18E2-41B9-852F-F413020CAA33};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
    <OutputType>Library</OutputType>
    <NoStandardLibraries>false</NoStandardLibraries>
    <RootNamespace>Minimal.BIEM</RootNamespace>
    <AssemblyName>Minimal.BIEM.Outlook</AssemblyName>
    <DefineConstants>VSTO40</DefineConstants>
    <VSTO_TrustAssembliesLocation>true</VSTO_TrustAssembliesLocation>
    
    <!-- Office application -->
    <OfficeApplication>Outlook</OfficeApplication>
    
    <!-- Publishing settings -->
    <IsWebBootstrapper>False</IsWebBootstrapper>
    <BootstrapperEnabled>true</BootstrapperEnabled>
    <TargetCulture>en</TargetCulture>
    <AutoIncrementApplicationRevision>true</AutoIncrementApplicationRevision>
    <UpdateEnabled>true</UpdateEnabled>
    <UpdateInterval>7</UpdateInterval>
    <UpdateIntervalUnits>days</UpdateIntervalUnits>
    <ProductName>MyAddIn</ProductName>
    <FriendlyName>MyAddIn</FriendlyName>
    <LoadBehavior>3</LoadBehavior>
    <UseWindowsForms>true</UseWindowsForms>
    <ImportWindowsDesktopTargets>true</ImportWindowsDesktopTargets>
    
    <!-- Additional VSTO properties for manifest generation -->
    <UseVSTO40>true</UseVSTO40>
    <GenerateManifests>true</GenerateManifests>
    <ApplicationRevision>0</ApplicationRevision>
    <ApplicationVersion>2.3.4.5</ApplicationVersion>
    <UseApplicationTrust>false</UseApplicationTrust>
  </PropertyGroup>
  
  <!-- All VSTO and signing properties must be set BEFORE importing VSTO targets -->
  <PropertyGroup>
    <SignAssembly>true</SignAssembly>
    <AssemblyOriginatorKeyFile>config\MyPrivateKey.snk</AssemblyOriginatorKeyFile>
    <DelaySign>false</DelaySign>
    <SignManifests>true</SignManifests>
    <ManifestKeyFile>config\BIEM20_TemporaryKey.pfx</ManifestKeyFile>
    <ManifestCertificateThumbprint>6E88CD736C2FD0A5EEDD529E060650F99DADEB89</ManifestCertificateThumbprint>
    <CertificateThumbprint>6E88CD736C2FD0A5EEDD529E060650F99DADEB89</CertificateThumbprint>
  </PropertyGroup>

  <!-- Import .NET SDK targets manually -->
  <Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />
    
  <!-- Import VSTO targets AFTER all properties are set - only when using MSBuild.exe (not dotnet CLI) -->
  <Import Project="$(VSTOTargetsPath)" Condition="Exists('$(VSTOTargetsPath)') and '$(MSBuildRuntimeType)' == 'Full'" />
  
  <ItemGroup>
    <Reference Include="Accessibility" />
    <Reference Include="Microsoft.Office.Interop.Outlook, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c, processorArchitecture=MSIL">
      <SpecificVersion>False</SpecificVersion>
      <EmbedInteropTypes>True</EmbedInteropTypes>
      <HintPath>C:\Program Files (x86)\Microsoft Visual Studio\Shared\Visual Studio Tools for Office\PIA\Office15\Microsoft.Office.Interop.Outlook.dll</HintPath>
    </Reference>
    <Reference Include="Microsoft.Office.Tools, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
      <SpecificVersion>False</SpecificVersion>
      <EmbedInteropTypes>False</EmbedInteropTypes>
      <HintPath>$(VSCommonRefAssembilies4)\Microsoft.Office.Tools.dll</HintPath>
    </Reference>
    <Reference Include="Microsoft.Office.Tools.Common, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
      <SpecificVersion>False</SpecificVersion>
      <EmbedInteropTypes>False</EmbedInteropTypes>
      <HintPath>$(VSCommonRefAssembilies4)\Microsoft.Office.Tools.Common.dll</HintPath>
    </Reference>
    <Reference Include="Microsoft.Office.Tools.Common.v4.0.Utilities, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
      <SpecificVersion>False</SpecificVersion>
      <Private>True</Private>
      <HintPath>$(VSCommonRefAssembilies4)\Microsoft.Office.Tools.Common.v4.0.Utilities.dll</HintPath>
    </Reference>
    <Reference Include="Microsoft.Office.Tools.Outlook, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
      <SpecificVersion>False</SpecificVersion>
      <HintPath>$(VSCommonRefAssembilies4)\Microsoft.Office.Tools.Outlook.dll</HintPath>
    </Reference>
    <Reference Include="Microsoft.Office.Tools.Outlook.v4.0.Utilities, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
      <SpecificVersion>False</SpecificVersion>
      <Private>True</Private>
      <HintPath>$(VSCommonRefAssembilies4)\Microsoft.Office.Tools.Outlook.v4.0.Utilities.dll</HintPath>
    </Reference>
    <Reference Include="Microsoft.Office.Tools.v4.0.Framework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
      <SpecificVersion>False</SpecificVersion>
      <HintPath>$(VSCommonRefAssembilies4)\Microsoft.Office.Tools.v4.0.Framework.dll</HintPath>
    </Reference>
    <Reference Include="Microsoft.VisualStudio.Tools.Applications.Runtime, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
      <SpecificVersion>False</SpecificVersion>
      <HintPath>$(VSCommonRefAssembilies4)\Microsoft.VisualStudio.Tools.Applications.Runtime.dll</HintPath>
    </Reference>
    <Reference Include="Office, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c, processorArchitecture=MSIL">
      <SpecificVersion>False</SpecificVersion>
      <EmbedInteropTypes>True</EmbedInteropTypes>
      <HintPath>$(VSCommonRefAssembilies4)\Office15\Office.dll</HintPath>
    </Reference>
    <Reference Include="stdole, Version=7.0.3300.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
      <SpecificVersion>False</SpecificVersion>
      <EmbedInteropTypes>False</EmbedInteropTypes>
      <HintPath>$(VSCommon7IDE)\PublicAssemblies\stdole.dll</HintPath>
    </Reference>
  </ItemGroup>

  <ProjectExtensions>
    <VisualStudio>
      <FlavorProperties GUID="{BAA0C2D2-18E2-41B9-852F-F413020CAA33}">
        <ProjectProperties HostName="Outlook" HostPackage="{29A7B9D7-A7F1-4328-8EF0-6B2D1A56B2C1}" OfficeVersion="15.0" VstxVersion="4.0" ApplicationType="Outlook" Language="cs" TemplatesPath="VSTOTemplates" DebugInfoExeName="#Software\Microsoft\Office\16.0\Outlook\InstallRoot\Path#outlook.exe" AddItemTemplatesGuid="{A58A78EB-1C92-4DDD-80CF-E8BD872ABFC4}" />
        <Host Name="Outlook" GeneratedCodeNamespace="BIEM" IconIndex="0">
          <HostItem Name="ThisAddIn" Code="ThisAddIn.cs" CanonicalName="AddIn" CanActivate="false" IconIndex="1" Blueprint="ThisAddIn.Designer.xml" GeneratedCode="ThisAddIn.Designer.cs" />
        </Host>
      </FlavorProperties>
    </VisualStudio>
  </ProjectExtensions>
</Project>

Build Commands remain the same.

This solution provides a single project file that works with both MSBuild.exe (for VSTO deployment) and dotnet CLI (for development), automatically adapting based on the build tool used.

1 Answer 1

1

Here is a working Outlook SDK style project file I use in one of my add-in projects. Building it generates a .vsto file as well as an .dll.manifest file (among others):

<Project>
  <Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />
  <PropertyGroup>
    <OutputType>Library</OutputType>
    <TargetFramework>net48</TargetFramework>
    <ImplicitUsings>disable</ImplicitUsings>
    <Nullable>disable</Nullable>
    <UseWindowsForms>true</UseWindowsForms>
    <LangVersion>latest</LangVersion>
  </PropertyGroup>
  <PropertyGroup>
    <!--<MSBuildExtensionsPath32 Condition="'$(MSBuildExtensionsPath32)' == ''">C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild</MSBuildExtensionsPath32>-->
    <VstoMSBuildExtensionsPath32>C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild</VstoMSBuildExtensionsPath32>
  </PropertyGroup>
  <PropertyGroup>
    <DefineConstants>VSTO40</DefineConstants>
    <IsWebBootstrapper>False</IsWebBootstrapper>
    <BootstrapperEnabled>true</BootstrapperEnabled>
  </PropertyGroup>
  <PropertyGroup>
    <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
    <!--<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>-->
    <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(VstoMSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
  </PropertyGroup>
  <PropertyGroup>
    <!--
      OfficeApplication
        Add-in host application
    -->
    <OfficeApplication>Outlook</OfficeApplication>
  </PropertyGroup>
  <PropertyGroup>
    <SignManifests>true</SignManifests>
    <ManifestKeyFile>MyOutlookAddIn_TemporaryKey.pfx</ManifestKeyFile>
    <ManifestCertificateThumbprint>DF359B8D9E3512AD3B1A6B6EDE011F550D8145C7</ManifestCertificateThumbprint>
  </PropertyGroup>
  <ItemGroup>
    <BootstrapperPackage Include="Microsoft.VSTORuntime.4.0">
      <Visible>False</Visible>
      <ProductName>Microsoft Visual Studio 2010 Tools for Office Runtime %28x86 and x64%29</ProductName>
      <Install>true</Install>
    </BootstrapperPackage>
  </ItemGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
  </ItemGroup>
  <ItemGroup>
    <Reference Include="Microsoft.Office.Interop.Outlook">
      <HintPath>C:\Users\Username\.nuget\packages\microsoft.office.interop.outlook\15.0.4797.1004\lib\netstandard2.0\Microsoft.Office.Interop.Outlook.dll</HintPath>
      <EmbedInteropTypes>true</EmbedInteropTypes>
    </Reference>
    <Reference Include="Microsoft.Office.Tools">
      <HintPath>C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\ReferenceAssemblies\v4.0\Microsoft.Office.Tools.dll</HintPath>
    </Reference>
    <Reference Include="Microsoft.Office.Tools.Common">
      <HintPath>C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\ReferenceAssemblies\v4.0\Microsoft.Office.Tools.Common.dll</HintPath>
    </Reference>
    <Reference Include="Microsoft.Office.Tools.Common.v4.0.Utilities">
      <HintPath>C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\ReferenceAssemblies\v4.0\Microsoft.Office.Tools.Common.v4.0.Utilities.dll</HintPath>
    </Reference>
    <Reference Include="Microsoft.Office.Tools.Outlook">
      <HintPath>C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\ReferenceAssemblies\v4.0\Microsoft.Office.Tools.Outlook.dll</HintPath>
    </Reference>
    <Reference Include="Microsoft.Office.Tools.Outlook.v4.0.Utilities">
      <HintPath>C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\ReferenceAssemblies\v4.0\Microsoft.Office.Tools.Outlook.v4.0.Utilities.dll</HintPath>
    </Reference>
    <Reference Include="Microsoft.Office.Tools.v4.0.Framework">
      <HintPath>C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\ReferenceAssemblies\v4.0\Microsoft.Office.Tools.v4.0.Framework.dll</HintPath>
    </Reference>
    <Reference Include="Microsoft.VisualStudio.Tools.Applications.Runtime">
      <HintPath>C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\ReferenceAssemblies\v4.0\Microsoft.VisualStudio.Tools.Applications.Runtime.dll</HintPath>
    </Reference>
    <Reference Include="Office">
      <HintPath>C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\ReferenceAssemblies\v4.0\Office15\Office.dll</HintPath>
    </Reference>
  </ItemGroup>
  
  <ItemGroup>
    <EmbeddedResource Include="MyOutlookAddInRibbonBar.xml">
      <SubType>Designer</SubType>
    </EmbeddedResource>
  </ItemGroup>

  <Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />

  <!-- Include additional build rules for an Office application add-in. -->
  <Import Project="$(VSToolsPath)\OfficeTools\Microsoft.VisualStudio.Tools.Office.targets" Condition="'$(VSToolsPath)' != ''" />

  <!-- This section defines VSTO properties that describe the host-changeable project properties. -->
  <ProjectExtensions>
    <VisualStudio>
      <FlavorProperties GUID="{BAA0C2D2-18E2-41B9-852F-F413020CAA33}">
        <ProjectProperties HostName="Outlook" HostPackage="{29A7B9D7-A7F1-4328-8EF0-6B2D1A56B2C1}" OfficeVersion="15.0" VstxVersion="4.0" ApplicationType="Outlook" Language="cs" TemplatesPath="" DebugInfoExeName="#Software\Microsoft\Office\16.0\Outlook\InstallRoot\Path#outlook.exe" AddItemTemplatesGuid="{A58A78EB-1C92-4DDD-80CF-E8BD872ABFC4}" />
        <Host Name="Outlook" GeneratedCodeNamespace="MyOutlookAddIn" PublishedHash="69C324AB27932AA2FBF2B7EA72250886FF164DE6" IconIndex="0">
          <HostItem Name="ThisAddIn" Code="ThisAddIn.cs" CanonicalName="AddIn" CanActivate="false" IconIndex="1" Blueprint="ThisAddIn.Designer.xml" GeneratedCode="ThisAddIn.Designer.cs" PublishedHash="6FEA796644CCCAE297DAE2381C82EF1EC27828E0" />
        </Host>
      </FlavorProperties>
    </VisualStudio>
  </ProjectExtensions>
</Project>

Build using the MSBuild version shipped with Visual Studio (not the one shipped with .NET).

In case you want to debug this (or your) build's .binlog file (using the MSBuildStructuredLog), then you are looking for the VisualStudioForApplicationsBuild target and its GenerateDeploymentManifest task in the Microsoft.VisualStudio.Tools.Office.targets SDK file, which is responsible for generating the .vsto file, and the GenerateApplicationManifest task (responsible for the .dll.manifest file).

Let me know if this is enough to get you going.

Sign up to request clarification or add additional context in comments.

3 Comments

many thanks @lauxjpn! I was able to solve my problem - see the Edit / Solution in my question above :)
I have a serious problem with my MSI. The VSTO installs fine when run directly (double-click) and works in Outlook. The MSI from wixproj/wxs installs fine too, but the SDK-style VSTO won't load in Outlook after MSI install. Outlook always says: "Not loaded. A runtime error occurred during the loading of the COM add-in." No hints in Event Viewer or Outlook logs. I tested a whole day, cleaned registry entries (HKCU/HKLM), all reproducible. The same VSTO via double-click works (HKCU), but via MSI (HKLM) it fails. Old-csproj VSTO with the same MSI works. Any idea, or should I open a new ques

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.