dotnet / SqlClient

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

Investigate SNI.dll transitive loading in MSIX project #612

Open cheenamalhotra opened 4 years ago

cheenamalhotra commented 4 years ago

Investigate native SNI transitive loading issue for MSIX projects, as tested and reported not working here: https://github.com/dotnet/SqlClient/issues/441#issuecomment-637477576

jeremy-waguet commented 4 years ago

Hi @cheenamalhotra

Here is a sample solution that tests if Native SNI DLLs are presents. It required SqlLocalDb to be installed (see readme.txt) and only contain .NET FX 4.7.2 projects (Console, WinForms, WPF) that works with ClickOnce and associated MSIX projects which does NOT work yet!

I also tried UWP but it seems that SqlLocalDb is not well supported and SNI DLLs are included by the way.

Please don't forget to 'restore' NuGet packages as the packages are not included in this sample ZIP. TestSNI.zip

Hope you will get a fix quite soon since I plan to migrate my project to .NET Core 3.1 (and MSIX seems to the supported .NET Core alternative to ClickOnce in .NET FX)

yosefmah commented 4 years ago

We also have the same issue which has started with version 2.0.0 on a .NET Core 3.1 WPF app being deployed via MSIX. It works fine with v1.1.3.

This is the error:

Description: A .NET Core application failed.
Application: App.exe
Path: C:\Program Files\WindowsApps\29311429-bfbd-4963-bd9c-a789267b50fe_2020.6.34.0_x64__g1afbts45jdzr\App\App.exe
Message: Error:
  An assembly specified in the application dependencies manifest (App.deps.json) was not found:
    package: 'Microsoft.Data.SqlClient.SNI.runtime', version: '2.0.0'
    path: 'runtimes/win-x64/native/Microsoft.Data.SqlClient.SNI.pdb'

For what its worth, we have the same issue with an EF Core module again only when deployed as an MSIX: https://github.com/dotnet/efcore/issues/21383

cheenamalhotra commented 4 years ago

Hi @yosefmah

The difference between v1.1.3 and v2.0.0 is that we have now included symbols in the SNI runtime packages.

The issue you're facing was also reported in https://github.com/dotnet/sdk/issues/10523, please try adding <IncludeSymbolsInSingleFile>true</IncludeSymbolsInSingleFile> to your project.

yosefmah commented 4 years ago

Hi @cheenamalhotra

Thanks for your reply. I have added that to my .csproj file (both the Windows Packaging Project and the WPF App) but the issue still seems to persist, unless I'm adding it in the wrong place. I'm attaching a sample project which runs when published as a standard WPF app but not when published through the MSIX Packaging project.

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

  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <UseWPF>true</UseWPF>
    <IncludeSymbolsInSingleFile>true</IncludeSymbolsInSingleFile>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.Data.SqlClient" Version="2.0.0" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.1.5" />
  </ItemGroup>

</Project>

Update: Attaching the sample project. MsixModuleError.zip

grant-hoelscher commented 4 years ago

Good afternoon,

I have also experienced this issue with a .NET Core 3.1 WPF Desktop app published using a Windows Packaging Project. When the Windows Packaging Project publishes the required dependencies for the WPF Desktop app, it will pack all of the PDB files into an appxsym package. As far as I can tell, there is no way to instruct the MSIX or APPX installers to unpack the appxsym package into the final installation directory.

Is there a way to use v2.0.0 of the SNI runtime without a dependence on the SNI.pdb? I have also temporarily rolled our code back to v1.1.3 and the WPF Desktop app can deploy and run without issue.

Thank you!

jeremy-waguet commented 4 years ago

@mrholshi

Hi,

A dirty workaround can be to add SNI DLLs (x86 & x64) in the project as content resources. They will be deployed in the MSIX package and your application will be able to run (and no PDB deployed)! This is a temporary fix that has to be removed until this issue fixed.

jeremy-waguet commented 4 years ago

@mrholshi

I edited my project csproj this way and I can confirm that SNI DLLs are bundled in the MSIX package and that the app works as expected :

<Content Include="..\packages\Microsoft.Data.SqlClient.SNI.2.1.0\build\net46\Microsoft.Data.SqlClient.SNI.x64.dll">
  <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="..\packages\Microsoft.Data.SqlClient.SNI.2.1.0\build\net46\Microsoft.Data.SqlClient.SNI.x86.dll">
  <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
gseketa commented 4 years ago

@jeremy-waguet

I have the same problem described here with my WPF project in .NET Core 3.1. Do you maybe know how your workaround would look like for a .NET Core application (i don't have any packages folder with the dlls you included as content resource...)?

Thanks

jeremy-waguet commented 4 years ago

@gseketa

I tried editing WPF csproj this way and it seems to work for me (SNI DLLs are present in the MSIX package but I don't know if it work or not). Please give some feedback:

  <ItemGroup>
    <Content Include="$(UserProfile)\.nuget\packages\microsoft.data.sqlclient.sni.runtime\2.0.1\runtimes\win-arm\native\Microsoft.Data.SqlClient.SNI.dll" Link="runtimes\win-arm\native\Microsoft.Data.SqlClient.SNI.dll">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </Content>
    <Content Include="$(UserProfile)\.nuget\packages\microsoft.data.sqlclient.sni.runtime\2.0.1\runtimes\win-arm64\native\Microsoft.Data.SqlClient.SNI.dll" Link="runtimes\win-arm64\native\Microsoft.Data.SqlClient.SNI.dll">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </Content>
    <Content Include="$(UserProfile)\.nuget\packages\microsoft.data.sqlclient.sni.runtime\2.0.1\runtimes\win-x64\native\Microsoft.Data.SqlClient.SNI.dll" Link="runtimes\win-x64\native\Microsoft.Data.SqlClient.SNI.dll">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </Content>
    <Content Include="$(UserProfile)\.nuget\packages\microsoft.data.sqlclient.sni.runtime\2.0.1\runtimes\win-x86\native\Microsoft.Data.SqlClient.SNI.dll" Link="runtimes\win-x86\native\Microsoft.Data.SqlClient.SNI.dll">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </Content>
  </ItemGroup>
jeremy-waguet commented 4 years ago

@gseketa

PDBs files seem to be required as well as requested by 'WpfApp1.deps.json'. Please include them as well the same way I did for DLLs!

When I run the self-signed sample package I got this in the windows event viewer (Application log):

Description: A .NET Core application failed.
Application: WpfApp1.exe
Path: C:\Program Files\WindowsApps\a6ecf8ea-fdf6-497a-97f2-85ac64c57bb0_1.0.5.0_x86__kp1tw81z64n68\WpfApp1\WpfApp1.exe
Message: Error:
  An assembly specified in the application dependencies manifest (WpfApp1.deps.json) was not found:
    package: 'Microsoft.Data.SqlClient.SNI.runtime', version: '2.0.1'
    path: 'runtimes/win-x86/native/Microsoft.Data.SqlClient.SNI.pdb'
grant-hoelscher commented 4 years ago

@jeremy-waguet

This is the issue that I ran into before. Even if you add the corresponding pdb files as "Content" as above with the dll files, the MSIX installer will remove all pdb symbol files and place the symbols into a appxsym package. Since the SNI runtime is dependent directly on the pdb files being deployed alongside the application, v2.0.0 and greater will not work with an MSIX installer project.

Until this project is updated to not rely on the pdb symbol files being deployed with the application, I have been using v1.1.3 with little issue with the MSIX installer.

jeremy-waguet commented 4 years ago

@mrholshi You are true! PDBs are not beeing deployed along the Appx package. Right know I looked at the "microsoft.data.sqlclient.sni.runtime\2.0.1" folder to look for any msbuild target file but I can't see any. So for now I have NO workaround for .net core project (mine does work with .net fx project) :-(

gseketa commented 4 years ago

@jeremy-waguet & @mrholshi

Unfortunatelly I can confirm that the proposed workaround didn’t work for me and I got the same error. Thank you for your help...

mwmccallum commented 4 years ago

The requirement of the Microsoft.Data.SqlClient.SNI.pdb for Microsoft.Data.SqlClient.SNI.dll file breaks any use of Microsoft.Data.SqlClient v2.x using MSIX. MSIX will not deploy Microsoft.Data.SqlClient.SNI.pdb with the project. Therefore when the exe is run, the error noted above about dependency for Microsoft.Data.SqlClient.SNI.runtime is found in the Event Viewer. If I pull the installation into a folder I can update, and drop the Microsoft.Data.SqlClient.SNI.pdb into the folder with the Microsoft.Data.SqlClient.SNI.dll the application runs as expected.

gradyal commented 4 years ago

Any updates on this? I am seeing this same issue where the Microsoft.Data.SqlClient.SNI DLLs are not bundled with MSIX. In my case, that breaks the Serilog MSSQLSERVER sink functionality. Is there any upcoming fix or workaround other than hard-coding the nuget references to the DLLs as project content resources?

cheenamalhotra commented 4 years ago

Hi @gradyal

The fix is in progress and is planned to be released with upcoming v2.1.0-preview2 release of Microsoft.Data.SqlClient.

gradyal commented 4 years ago

@cheenamalhotra Thanks! When is v2.1.0-preview2 set to be released?

cheenamalhotra commented 4 years ago

It's planned for this month (October), you'll hear from us soon! :)

cheenamalhotra commented 4 years ago

Closing this issue as pdbs have been removed from Microsoft.Data.SqlClient.SNI.runtime v2.1.1 to be picked by Microsoft.Data.SqlClient v2.1.0-preview2 onwards.

gradyal commented 4 years ago

@cheenamalhotra, I just updated my Winforms project's Microsoft.Data.SqlClient package to 2.1.0-preview2.20297.7. I published the MSIX package locally and the SNI DLLs are still not copying over. Is there another release coming with that fix?

jeremy-waguet commented 3 years ago

Hi @cheenamalhotra. I agree with @gradyal

By simply referencing the 'Microsoft.Data.SqlClient' package dependent SNI DLLs do not get copied to the MSIX package (even by using the now available 'Microsoft.Data.SqlClient.SNI' v2.1.1). But by forcing reference to SNI DLLs this way in your project csproj it does work : both the MSIX project is deployable and SNI DLLs are present in the AppX package.

<ItemGroup>
  <Content Include="..\packages\Microsoft.Data.SqlClient.SNI.2.1.1\build\net46\Microsoft.Data.SqlClient.SNI.x64.dll">
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  </Content>
  <Content Include="..\packages\Microsoft.Data.SqlClient.SNI.2.1.1\build\net46\Microsoft.Data.SqlClient.SNI.x86.dll">
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  </Content> 
</ItemGroup>

I think there is still an issue as it should work out of the box by simply referencing 'Microsoft.Data.SqlClient' nuget package.

cheenamalhotra commented 3 years ago

Ok, I closed it in light of .NET Core projects as discussed above which was fixed with pdb removal (https://github.com/dotnet/SqlClient/issues/612#issuecomment-698484488). Seems like the issue in .NET Framework application + MSIX still persists.

Reopening for further investigation.

jeremy-waguet commented 3 years ago

@cheenamalhotra Thanks !

gradyal commented 3 years ago

@cheenamalhotra, just checking in to see if there is any news on a release timeline for a fix for this with .NET Framework + MSIX projects?

huoyaoyuan commented 3 years ago

Also mentioned this issue when using Microsoft.EntityFrameworkCore.SqlServer with WinUI 3, which requires Desktop Bridge and msix.

It's fixed by adding reference of Microsoft.Data.SqlClient v2.1.0

gradyal commented 3 years ago

@cheenamalhotra I updated the SqlClient package to 2.1.1 and re-tested to see if this issue has been fixed with .NET Framework/MSIX. It is still not copying the SNI DLLs when I publish locally. Do you have any update on when this will be fixed?

LevYas commented 3 years ago

I have .NET 5 WPF app, and for some reason, MSIX package did not include SqlClient-related libraries. I managed to fix this by creating a publishing profile (self-contained) and using it in the packaging project as described here https://techcommunity.microsoft.com/t5/windows-dev-appconsult/packaging-a-net-core-3-0-application-with-msix/bc-p/2098665/highlight/true#M497

cheenamalhotra commented 1 year ago

I tried these targets that can be appended with CopySNIFiles in Microsoft.Data.SqlClient.SNI.targets file or directly in .wapproj file, pasting here for reference. Running wapproj in Visual Studio is able to load SNI.xxx.dll properly with these targets:

<!-- Include SNI Targets file in wapproj file to be able to copy SNI files from reference projects -->
<!-- TODO: Please update referenced project version to include correct library version -->
<ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
    <Import Project="$(NuGetPackageRoot)\microsoft.data.sqlclient.sni\5.1.0\buildTransitive\net462\Microsoft.Data.SqlClient.SNI.targets" Condition="Exists('$(NuGetPackageRoot)\microsoft.data.sqlclient.sni\5.1.0\buildTransitive\net462\Microsoft.Data.SqlClient.SNI.targets')" />
</ImportGroup>

<!-- You can include these targets directly in wapproj file too -->
<Target Name="CopySNIProjectFiles"
    Condition="'$(CopySNIProjectFiles)' != 'false' And
                    '$(OutDir)' != '' And
                    Exists('$(OutDir)')"
    Inputs="@(SNIFiles)"
    Outputs="@(SNIFiles -> '$(OutDir)\%(_TargetAssemblyProjectName)\%(RecursiveDir)%(Filename)%(Extension)')">

    <Copy SourceFiles="@(SNIFiles)"
            DestinationFiles="@(SNIFiles -> '$(OutDir)\%(_TargetAssemblyProjectName)\%(RecursiveDir)%(Filename)%(Extension)')" />
</Target>
<Target Name="CopySNIAppFiles"
    Condition="'$(CopySNIAppFiles)' != 'false' And
                    '$(LayoutDir)' != '' And
                    Exists('$(LayoutDir)')"
    Inputs="@(SNIFiles)"
    Outputs="@(SNIFiles -> '$(LayoutDir)\%(_TargetAssemblyProjectName)\%(RecursiveDir)%(Filename)%(Extension)')">

    <Copy SourceFiles="@(SNIFiles)"
            DestinationFiles="@(SNIFiles -> '$(LayoutDir)\%(_TargetAssemblyProjectName)\%(RecursiveDir)%(Filename)%(Extension)')" />
</Target>

 <PropertyGroup>
    <PostBuildEventDependsOn>
      $(PostBuildEventDependsOn);
      CopySNIFiles;
      CopySNIAppFiles;
      CopySNIProjectFiles;
    </PostBuildEventDependsOn>
    <BuildDependsOn>
      $(BuildDependsOn);
      CopySNIFiles;
      CopySNIAppFiles;
      CopySNIProjectFiles;
    </BuildDependsOn>
    <PrepareForRunDependsOn>
      $(PrepareForRunDependsOn);
      CopySNIFiles;
      CopySNIAppFiles;
      CopySNIProjectFiles;
    </PrepareForRunDependsOn>
  </PropertyGroup>

Example minimal WPF app for reference: cheenamalhotra/wpf-sqlclient