Fody / Costura

Embed references as resources
MIT License
2.41k stars 275 forks source link

The type initializer for 'Microsoft.Data.SqlClient.TdsParser' threw an exception #901

Closed ZedZipDev closed 1 year ago

ZedZipDev commented 1 year ago

NET Framework 4.8 Costura.Fody 5.7.0 Windows 10

My application starts and connects to SQL Server, then open a Forms etc It worked fine. I have replaced System.Data.SqlClient with recommended Microsoft.Data.SqlClient. I have built the app with Costura.Fody and run it. During the SqlCnnection.Open(str) The type initializer for 'Microsoft.Data.SqlClient.TdsParser' threw an exception

How to fix it? What should I include to Costura files?

GeertvanHorrik commented 1 year ago

We have no fodyweavers.xml contents, so we can only guess. But I think you should include Microsoft.Data.Sql* in your fodyweavers and all should work.

ZedZipDev commented 1 year ago

My fodyweavers.xml

<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
  <Costura>
  </Costura>
</Weavers>

Should I add Microsoft.Data.SqlClient.dll (only) to this file?

ZedZipDev commented 1 year ago

I have made

<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
  <Costura>
       <IncludeAssemblies>
          Microsoft.Data.SqlClient
    </IncludeAssemblies>
  </Costura>
</Weavers>

and rebuilt the app (Release). The bin\Release\net48 contains large set of assemblies. it seems not packed by costura

GeertvanHorrik commented 1 year ago

You need more than "just" Microsoft.Data.SqlClient. You can use wildcards.

ZedZipDev commented 1 year ago

Thank you, but little bit more details If I use default file

<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
  <Costura>
  </Costura>
</Weavers>

after VS2022 build I have a 15MB exe.. But when I use

<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
  <Costura>
       <IncludeAssemblies>
          Microsoft.Data.SqlClient
    </IncludeAssemblies>
  </Costura>
</Weavers>

then i have a large file set . Could you please write me: what is incorrect?

GeertvanHorrik commented 1 year ago

If you use the 2nd one: only Microsoft.Data.SqlClient will be embedded, the rest will not be embedded. I think you also need to embeded the native runtime assemblies. Please check the example apps on how to do this, because officially there is no support for Costura anymore.

0xced commented 1 year ago

I wrote How to package a single-file executable using the SQLite EF Core Database Provider on .NET Framework? for SQLite but you can probably adapt it for Microsoft.Data.SqlClient. Sorry I can't help more from my phone.

ZedZipDev commented 1 year ago

If you use the 2nd one: only Microsoft.Data.SqlClient will be embedded, the rest will not be embedded. I think you also need to embeded the native runtime assemblies. Please check the example apps on how to do this, because officially there is no support for Costura anymore.

"no support for Costura anymore" - why? Where can I find examples?

ZedZipDev commented 1 year ago

I wrote How to package a single-file executable using the SQLite EF Core Database Provider on .NET Framework? for SQLite but you can probably adapt it for Microsoft.Data.SqlClient. Sorry I can't help more from my phone.

Microsoft.Data.SqlClient is NuGet package. How to include NuGet dlls + all referenced dlls to fodyweavers.xml?

ZedZipDev commented 1 year ago

If you use the 2nd one: only Microsoft.Data.SqlClient will be embedded, the rest will not be embedded. I think you also need to embeded the native runtime assemblies. Please check the example apps on how to do this, because officially there is no support for Costura anymore.

I have checked the exe: it contains microsoft.data.sqlclient.dll in Resources // 0x001F42AA: costura.microsoft.data.sqlclient.dll.compressed‎ (628010 bytes, Embedded, Private)

What can I do else?

GeertvanHorrik commented 1 year ago

As stated in the readme, Costura is no longer actively supported, closing this issue.

Please look for another solution to create single file executables.

0xced commented 1 year ago

I forgot that I had already documented how to package Microsoft.Data.SqlClient with Costura in the Microsoft.Data.SqlClient repository, see https://github.com/dotnet/SqlClient/issues/793 🤦

Here's a full working sample code producing a single exe.

SqlServerSingleExe.csproj

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

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net48</TargetFramework>
    <LangVersion>10.0</LangVersion>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <PropertyGroup>
    <DebugType>embedded</DebugType>
    <AutoGenerateBindingRedirects>false</AutoGenerateBindingRedirects>
    <GenerateSupportedRuntime>false</GenerateSupportedRuntime>
    <CopySNIFiles>false</CopySNIFiles>
  </PropertyGroup>

  <Target Name="EmbedSqlClientNativeLibraries" BeforeTargets="ResolveReferences">
    <ItemGroup>
      <EmbeddedResource Include="@(SNIDllFiles)">
        <Visible>false</Visible>
        <Link Condition="$([MSBuild]::ValueOrDefault('%(Identity)', '').Contains('x86'))">costura32\%(Filename)%(Extension)</Link>
        <Link Condition="$([MSBuild]::ValueOrDefault('%(Identity)', '').Contains('x64'))">costura64\%(Filename)%(Extension)</Link>
      </EmbeddedResource>
    </ItemGroup>
  </Target>

  <ItemGroup>
    <PackageReference Include="Costura.Fody" Version="5.7.0" PrivateAssets="all" />
    <PackageReference Include="Microsoft.Data.SqlClient" Version="5.1.1" />
  </ItemGroup>

</Project>

FodyWeavers.xml

<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
  <Costura />
</Weavers>

Program.cs

using System;
using Microsoft.Data.SqlClient;

var connectionString = args.Length == 1 ? args[0] : "Server=sqlprosample.database.windows.net;Database=sqlprosample;User=sqlproro;Password=nh{Zd?*8ZU@Y}Bb#";

try
{
    using var connection = new SqlConnection(connectionString);
    await connection.OpenAsync();
    using var command = new SqlCommand("SELECT @@VERSION", connection);
    var sqlServerVersion = await command.ExecuteScalarAsync();
    Console.WriteLine($"✔️ Successfully connected to {sqlServerVersion}");
    return 0;
}
catch (Exception exception)
{
    Console.Error.WriteLine($"❌ {exception}");
    return 1;
}

Executing dotnet run -c Release should produce the following output.

✔️ Successfully connected to Microsoft SQL Azure (RTM) - 12.0.2000.8 Jul 17 2023 18:40:52 Copyright (C) 2022 Microsoft Corporation

You'll also find a single file (SqlServerSingleExe.exe) inside the bin\Release\net48 directory.