Skip to content

Paket Pack not working with .exe files #3862

Open

Description

@MicaelMor

Description

Paket pack command fails on projects that contain a .exe, with an error like:

Paket failed with ->
C:\Users\Micael\source\repos\ConsoleApp4\ConsoleApp4\bin\Release\netcoreapp3.1\ConsoleAp>p4.exe: bad cli header, rva 0

with the full error message on verbose mode being:

Paket failed with
-> C:\Users\Micael\source\repos\ConsoleApp4\ConsoleApp4\bin\Release\netcoreapp3.1\ConsoleApp4.exe: bad cli header, rva 0
StackTrace:
at ProviderImplementation.AssemblyReader.look@1727(ILModuleReader this, Int32 v, String n, Int32 i, Int32 pos) in D:\code\Paket\paket-files\fsprojects\FSharp.TypeProviders.SDK\src\AssemblyReader.fs:line 1728
at ProviderImplementation.AssemblyReader.ILModuleReader..ctor(String infile, ByteFile is, ILGlobals ilg, Boolean lowMem) in D:\code\Paket\paket-files\fsprojects\FSharp.TypeProviders.SDK\src\AssemblyReader.fs:line 1737
at ProviderImplementation.AssemblyReader.ILModuleReaderAfterReadingAllBytes(String file, ILGlobals ilGlobals) in D:\code\Paket\paket-files\fsprojects\FSharp.TypeProviders.SDK\src\AssemblyReader.fs:line 3619
at Paket.PackageMetaData.readAssembly(String fileName) in D:\code\Paket\src\Paket.Core\Packaging\PackageMetaData.fs:line 69
at Paket.PackageProcess.merge$cont@29(String buildConfig, String buildPlatform, FSharpMap2 specificVersions, ProjectFile projectFile, TemplateFile templateFile, TemplateFile withVersion, Unit unitVar) in D:\code\Paket\src\Paket.Core\Packaging\PackageProcess.fs:line 29 at Paket.PackageProcess.convertRemainingTemplate@193.Invoke(String fileName) in D:\code\Paket\src\Paket.Core\Packaging\PackageProcess.fs:line 203 at Microsoft.FSharp.Collections.Internal.IEnumerator.map@74.DoMoveNext(b& curr) at Microsoft.FSharp.Collections.Internal.IEnumerator.MapEnumerator1.System-Collections-IEnumerator-MoveNext()
at Microsoft.FSharp.Core.CompilerServices.RuntimeHelpers.takeOuter@274[T,TResult](ConcatEnumerator2 x, Unit unitVar0) at Microsoft.FSharp.Collections.SeqModule.ToList[T](IEnumerable1 source)
at Paket.PackageProcess.Pack[a](String workingDir, DependenciesFile dependenciesFile, String packageOutputPath, FSharpOption1 buildConfig, FSharpOption1 buildPlatform, FSharpOption1 version, IEnumerable1 specificVersions, FSharpOption1 releaseNotes, FSharpOption1 templateFile, FSharpOption1 excludedTemplates, Boolean lockDependencies, Boolean minimumFromLockFile, Boolean pinProjectReferences, FSharpOption1 interprojectReferencesConstraint, Boolean symbols, Boolean includeReferencedProjects, FSharpOption1 projectUrl) in D:\code\Paket\src\Paket.Core\Packaging\PackageProcess.fs:line 221 at Paket.Dependencies.Pack[b](String outputPath, FSharpOption1 buildConfig, FSharpOption1 buildPlatform, FSharpOption1 version, FSharpOption1 specificVersions, FSharpOption1 releaseNotes, FSharpOption1 templateFile, FSharpOption1 workingDir, FSharpOption1 excludedTemplates, FSharpOption1 lockDependencies, FSharpOption1 minimumFromLockFile, FSharpOption1 pinProjectReferences, FSharpOption1 interprojectReferencesConstraint, FSharpOption1 symbols, FSharpOption1 includeReferencedProjects, FSharpOption1 projectUrl) in D:\code\Paket\src\Paket.Core\PublicAPI.fs:line 753
at Paket.Program.handleCommand@853-23.Invoke(ParseResults1 results) in D:\code\Paket\src\Paket\Program.fs:line 853 at Paket.Program.processWithValidationEx$cont@42[a](Boolean silent, FSharpFunc2 commandF, a result, Unit unitVar) in D:\code\Paket\src\Paket\Program.fs:line 43
at Paket.Program.processWithValidationEx[a](FSharpFunc2 printUsage, Boolean silent, FSharpFunc2 validateF, FSharpFunc`2 commandF, a result) in D:\code\Paket\src\Paket\Program.fs:line 35
at Paket.Program.handleCommand(Boolean silent, Command command) in D:\code\Paket\src\Paket\Program.fs:line 853
at Paket.Program.main() in D:\code\Paket\src\Paket\Program.fs:line 934

For reference I tried this with a computer without a D: drive and it still showed as it trying/getting files from D:

Repro steps

  1. Create an F# console project with visual studio on windows (visual studio might not be required but windows is)

  2. Install paket on project and convert from nuget to paket

  3. Create paket.template file in the project ConsoleApp folder and add this to it
    type project

  4. Build project in Release mode.

  5. Run the following command:

dotnet paket pack nugets --version 1.0.0 -v

Alternative skip step 1 to 3 by cloning this git https://github.com/MicaelMor/PaketPackExeError

Expected behavior

Paket should create a .nupkg file on the nugets folder with the name of the project and version provided.

Actual behavior

Paket fails with error

NameOfExecutable.exe: bad cli header, rva 0

Known workarounds

Using .Net SDK command dotnet pack works, but ofc this bypasses Paket.

Other potentially relevant information

The Pack command works fine with a library type project (which ofc has no .exe file), so it is quite likely I am just doing something wrong here,

Fails also on a C# project.

Activity

  1. allykzam commented on Jun 11, 2020

    @allykzam
    Contributor

    Coincidentally, I ran into this yesterday as well while trying to see if I could migrate a work project to .NET Core. Seems that this is related to the fact that when you build a .NET Core application and get an executable file, it isn't actually a .NET binary, so much as launcher of some kind; your program actually lives in the NameOfExecutable.dll next to the executable.

    I tried using the latest alpha of Paket (6.0.0-alpha028 at the moment) and had the same results. Unfortunately, for my purposes, dotnet pack does not work, because it omits the executable and throws my application into the lib directory of the resulting NuGet package, rather than tools.

  2. MicaelMor commented on Jun 11, 2020

    @MicaelMor
    Author

    I'm new to .Net Core publishing, in fact the reason why I ran into this problem is basically the same as yours, but I don't believe you are supposed to package the .exe files or any file that isn't necessary to the program (like debug symbols and so on) with the nuget.

    The idea is that since .net core projects are multiplatform you need to choose what packaging and distribution you want to use for each platform you are publishing to.

    For windows distribution you could for example package it with nuget and then use something like https://github.com/Squirrel/Squirrel.Windows which takes that nuget and creates an installer for it (you also get an updater if you modify your project and so on), being that there are ofc alternatives like Wix and InnoSetup which are to my knowledge supported by F# Fake.

    That being said haven't used any of the methods mentioned above yet, so I could be saying something that isn't accurate, so far have published only 1 .net core app to Windows, and that was using the Visual Studio option to Publish, which essentially puts the necessary files to execute the application into a folder, and if you copy that folder to the Windows machine you want to run it, the application should run just fine.

    If you positively need to have the executable inside the .nupkg file, like if for some reason you can only distribute the application using nuget, it would be possible to do so, these files are just renamed .zip files that follow a certain structure, so you could in theory have some build process that after it runs the dotnet pack command, opens the .nupkg file and copies the .exe and what ever other files you need/want into that .npukg.

  3. allykzam commented on Jun 11, 2020

    @allykzam
    Contributor

    I'm not new to publishing .NET Core projects, but the project in question has quite a bit of workflow around it that requires the executable to be packaged the same way it was when targeting .NET Framework. I'm aware of how the NuGet package format works, but currently Paket is the build process that handles this. I could certainly write my own code for packaging the project, but then I also wouldn't need to use dotnet pack.

    Regardless of how the package is being used, I wouldn't think Paket is intended to crash and burn when asked to package a project.

  4. allykzam commented on Jun 11, 2020

    @allykzam
    Contributor

    I was able to locally modify Paket enough to bypass this issue by commenting out these two lines, removing associated code that used the values, and adding the missing data to my paket.template. I also had to add V3_1 and supporting code to the DotNetCoreAppVersion typedef so it would recognize netcoreapp3.1, but it looks like that's already been done in master.

    In production Paket builds, I'd assume that the PackageProcess.merge function would fall back to reading the .dll when packaging a .NET Core or .NET 5+ application, rather than examining the .exe for CIL data. Since self-contained executables are created by dotnet publish separately from the original build, the .dll should always be there for Paket to reference - or at least, I haven't yet run into a .NET Core project where this wasn't the case.

  5. kowalgta commented on Dec 14, 2021

    @kowalgta

    I had the same issue and in my case removal of <OutputType>Exe</OutputType> from the fsproj file fixed the problem. Weirdly output is still *.exe and looks identical to the previous one.

  6. flibustier7seas commented on Jul 11, 2024

    @flibustier7seas

    Any updates?

    I encounter the same issue when I attempt to pack my dotnet tool.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions