dotnet / SqlClient

Microsoft.Data.SqlClient provides database connectivity to SQL Server for .NET applications.
MIT License
858 stars 287 forks source link

Project that contains a <NativeRefrence> and references Microsoft.Data.SqlClient.SNI causes duplicate entries in manifest file #2173

Open cgreger96 opened 1 year ago

cgreger96 commented 1 year ago

Describe the bug

This issue occurs when in the Microsoft.Data.SqlServer.SNI package when it is referenced by a project either directly or transitively and also contains a NativeReference.

Using a native reference causes a Native.{project}.mainifest to be generated for the project and all projects downstream.

Microsoft.Data.SqlClient.SNI package contains targets that add the Microsoft.Data.SqlClient.SNI.{arm64|x64|x86} to the manifest file. The target is AppendSNIDllsInManifest

This causes an issue with the project structured like in the linked repo since Microsoft.Data.SqlClient will add the dlls to both the generated Native manifest and the application manifest causing the following error event

<EventData>
  <Data>Microsoft.Data.SqlClient.SNI.arm64.dll</Data> 
  <Data>Two or more components referenced directly or indirectly by the application manifest have files by the same name.</Data> 
  <Data /> 
  <Data /> 
  <Data /> 
  <Data /> 
  <Data /> 
  <Data /> 
  <Data /> 
  <Data /> 
  <Data>{removed}\ConsoleApp1\bin\Debug\ConsoleApp1.exe.Manifest</Data> 
  <Data /> 
  <Data /> 
  <Data /> 
  <Data /> 
  <Data /> 
  <Data /> 
  <Data /> 
  <Data /> 
  <Data /> 
</EventData>

To reproduce

Example project: https://github.com/cgreger96/Manifest.Issue/

High level steps to reproduce

  1. Create .NET Framework class library
  2. Add reference to Microsoft.Data.SqlClient
  3. Add reference to Native manifest file
  4. Add a .NET Framework Console application
  5. Add a reference to the library
  6. Build
  7. Launch the console application

Expected behavior

Dlls are not added to native manifest files only to application manifest files

Further technical details

Microsoft.Data.SqlClient.SNI version: Seems to be in all versions after Microsoft.Data.SqlClient.SNI 2.0.0

.NET target: Framework 4.8.0

SQL Server version: NA

Operating system: Windows 10

Additional context

Workaround

The only work around I have found is to exclude buildTransitive from the SNI package from being used in projects the projects that generate Native manifests

    <PackageReference Include="Microsoft.Data.SqlClient.SNI">
        <ExcludeAssets>buildTransitive</ExcludeAssets>
    </PackageReference>

Generated manifest files

Interop.Accessibility.dll.manifest (Generated with mt.exe for this proof of concept)

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
    <assemblyIdentity name="Interop.Accessibility.dll" version="1.1.0.0" processorArchitecture="msil"></assemblyIdentity>
    <clrSurrogate clsid="{3C157C7C-1B32-3EAE-8135-C4803D1F7BA1}" name="Accessibility.AnnoScope"></clrSurrogate>
    <clrSurrogate clsid="{C81D1FBC-1883-30E8-9C25-F0CFFCBC7B51}"
        name="Accessibility._RemotableHandle"></clrSurrogate>
    <clrSurrogate clsid="{9D071F73-DE7F-335C-ABF4-EDC6A2AA38CE}"
        name="Accessibility.__MIDL_IWinTypes_0009"></clrSurrogate>
    <clrSurrogate clsid="{B5F8350B-0548-48B1-A6EE-88BD00B4A5E7}"
        name="Accessibility.CAccPropServicesClass"></clrSurrogate>
    <file name="Interop.Accessibility.dll" hashalg="SHA1"></file>
</assembly>

Native.ClassLibrary1.manifest

<?xml version="1.0" encoding="utf-8"?>
<assembly xsi:schemaLocation="urn:schemas-microsoft-com:asm.v1 assembly.adaptive.xsd" manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:co.v1="urn:schemas-microsoft-com:clickonce.v1" xmlns:co.v2="urn:schemas-microsoft-com:clickonce.v2">
  <assemblyIdentity name="Native.ClassLibrary1" version="1.0.0.0" type="win32" />
  <dependency>
    <dependentAssembly asmv2:dependencyType="install" asmv2:codebase="Interop.Accessibility.dll.manifest" asmv2:size="846">
      <assemblyIdentity name="Interop.Accessibility.dll" version="1.1.0.0" processorArchitecture="msil" />
      <hash xmlns="urn:schemas-microsoft-com:asm.v2">
        <dsig:Transforms>
          <dsig:Transform Algorithm="urn:schemas-microsoft-com:HashTransforms.Identity" />
        </dsig:Transforms>
        <dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
        <dsig:DigestValue>JpTY8l9nE8SUGUVnyxQpN+nJOWE=</dsig:DigestValue>
      </hash>
    </dependentAssembly>
  </dependency>
  <file name="Microsoft.Data.SqlClient.SNI.arm64.dll" size="491424" xmlns="urn:schemas-microsoft-com:asm.v2">
    <hash>
      <dsig:Transforms>
        <dsig:Transform Algorithm="urn:schemas-microsoft-com:HashTransforms.Identity" />
      </dsig:Transforms>
      <dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
      <dsig:DigestValue>+YP7Bt6zRlIBadWdZYcNT+EczvM=</dsig:DigestValue>
    </hash>
  </file>
  <file name="Microsoft.Data.SqlClient.SNI.x64.dll" size="506272" xmlns="urn:schemas-microsoft-com:asm.v2">
    <hash>
      <dsig:Transforms>
        <dsig:Transform Algorithm="urn:schemas-microsoft-com:HashTransforms.Identity" />
      </dsig:Transforms>
      <dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
      <dsig:DigestValue>Dz0UTswEQjMU9TqTbQ3puB6+6VI=</dsig:DigestValue>
    </hash>
  </file>
  <file name="Microsoft.Data.SqlClient.SNI.x86.dll" size="414096" xmlns="urn:schemas-microsoft-com:asm.v2">
    <hash>
      <dsig:Transforms>
        <dsig:Transform Algorithm="urn:schemas-microsoft-com:HashTransforms.Identity" />
      </dsig:Transforms>
      <dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
      <dsig:DigestValue>gg3nO9o1UxdWz9st6dKpW9vxPhI=</dsig:DigestValue>
    </hash>
  </file>
</assembly>

ConsoleApp1.exe.manifest

<?xml version="1.0" encoding="utf-8"?>
<assembly xsi:schemaLocation="urn:schemas-microsoft-com:asm.v1 assembly.adaptive.xsd" manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:co.v1="urn:schemas-microsoft-com:clickonce.v1" xmlns:co.v2="urn:schemas-microsoft-com:clickonce.v2">
  <assemblyIdentity name="ConsoleApp1.exe" version="1.0.0.0" type="win32" />
  <dependency>
    <dependentAssembly asmv2:dependencyType="install" asmv2:codebase="Interop.Accessibility.dll.manifest" asmv2:size="846">
      <assemblyIdentity name="Interop.Accessibility.dll" version="1.1.0.0" processorArchitecture="msil" />
      <hash xmlns="urn:schemas-microsoft-com:asm.v2">
        <dsig:Transforms>
          <dsig:Transform Algorithm="urn:schemas-microsoft-com:HashTransforms.Identity" />
        </dsig:Transforms>
        <dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
        <dsig:DigestValue>JpTY8l9nE8SUGUVnyxQpN+nJOWE=</dsig:DigestValue>
      </hash>
    </dependentAssembly>
  </dependency>
  <dependency>
    <dependentAssembly asmv2:dependencyType="install" asmv2:codebase="Native.ClassLibrary1.manifest" asmv2:size="2622">
      <assemblyIdentity name="Native.ClassLibrary1" version="1.0.0.0" type="win32" />
      <hash xmlns="urn:schemas-microsoft-com:asm.v2">
        <dsig:Transforms>
          <dsig:Transform Algorithm="urn:schemas-microsoft-com:HashTransforms.Identity" />
        </dsig:Transforms>
        <dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
        <dsig:DigestValue>Y4mE7xI8dSmwx819eGrYcJ0CsU4=</dsig:DigestValue>
      </hash>
    </dependentAssembly>
  </dependency>
  <file name="Microsoft.Data.SqlClient.SNI.arm64.dll" size="491424" xmlns="urn:schemas-microsoft-com:asm.v2">
    <hash>
      <dsig:Transforms>
        <dsig:Transform Algorithm="urn:schemas-microsoft-com:HashTransforms.Identity" />
      </dsig:Transforms>
      <dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
      <dsig:DigestValue>+YP7Bt6zRlIBadWdZYcNT+EczvM=</dsig:DigestValue>
    </hash>
  </file>
  <file name="Microsoft.Data.SqlClient.SNI.x64.dll" size="506272" xmlns="urn:schemas-microsoft-com:asm.v2">
    <hash>
      <dsig:Transforms>
        <dsig:Transform Algorithm="urn:schemas-microsoft-com:HashTransforms.Identity" />
      </dsig:Transforms>
      <dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
      <dsig:DigestValue>Dz0UTswEQjMU9TqTbQ3puB6+6VI=</dsig:DigestValue>
    </hash>
  </file>
  <file name="Microsoft.Data.SqlClient.SNI.x86.dll" size="414096" xmlns="urn:schemas-microsoft-com:asm.v2">
    <hash>
      <dsig:Transforms>
        <dsig:Transform Algorithm="urn:schemas-microsoft-com:HashTransforms.Identity" />
      </dsig:Transforms>
      <dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
      <dsig:DigestValue>gg3nO9o1UxdWz9st6dKpW9vxPhI=</dsig:DigestValue>
    </hash>
  </file>
</assembly>
JRahnama commented 1 year ago

@cgreger96 We will look into this and will get back to you.

jhennessey commented 4 months ago

Still seeing this issue.

For those looking for an alternative work-around, you can add this to a Directory.Build.props file to prevent the SNI files from being added to the manifest. If you are actually using ClickOnce you probably want to add the items as Content too (before AssignTargetPaths) to ensure they show in the application manifest.

  <Target Name="RemoveSqlClientNativeFilesFromManifest" BeforeTargets="GenerateApplicationManifest" Condition=" '@(_DeploymentManifestFiles)' != '' ">
    <ItemGroup>
      <ExcludedDeploymentManifestFiles Include="@(_DeploymentManifestFiles)" Condition=" $([System.String]::Copy('%(Filename)').Contains('Microsoft.Data.SqlClient.SNI')) " />
      <_DeploymentManifestFiles Remove="@(ExcludedDeploymentManifestFiles)" Condition=" '@(ExcludedDeploymentManifestFiles)' != '' " />
    </ItemGroup>

    <Message Text="Removed the following item from the '_DeploymentManifestFiles' itemgroup: %(ExcludedDeploymentManifestFiles.FullPath)" Importance="High" Condition=" '@(ExcludedDeploymentManifestFiles)' != '' " />
  </Target>

Is there any reason why these files are directly added to the _DeploymentManifestFiles itemgroup? If they were added as Content items I think that may solve the issue and eliminate the need for the special copying logic in the .targets file?