The scenario is as follows:
a) An arbitrary MyProject.csproj invokes MyConsoleApp.exe as part of a post build event.
b) MyConsoleApp.exe is packaged and consumed via Nuget with all its dependencies
I am not convinced this is the "dotnet core 2.0" way of doing things, I tried dotnet pack MyConsoleApp.csproj but that doesn't include the dependencies like the .exe file does. Should it include all references in a nupkg and publish the package at build time?
MyProject.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
...
<Target Name="GenerateSomeFiles" BeforeTargets="AfterBuild">
<Exec Command="dotnet run MyConsoleApp.dll $(TargetDir)" />
</Target>
</Project>
You should try running dotnet publish, then running dotnet pack against the publish folder that's created under bin/Release or bin/Debug.
If you still want an exe, you should either setup a target Runtime for x86/x64 in your csproj, or setup multi-targeting for a full framework version.
Related
I have a .NET Framework project (A) which generates an exe which takes html file as input and outputs an autogenerated C# class file (like a template of sorts). The .csproj of A looks like this:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<OutputType>Exe</OutputType>
<AssemblyName>ProjectA</AssemblyName>
</PropertyGroup>
<ItemGroup>
<None Include="ProjectA.exe.config">
<ItemGroup>
</Project>
In project B, we're using the exe like this: (part of csproj of project B)
<Target Name="_EX_MyGenerateFile_cs" Inputs="MyHtml.html" Outputs="$(O)\MyGeneratedFile.cs" Condition="'$(BuildingOutOfProcess)' != 'False' AND '$(BuildingProject)' == 'True'" BeforeTargets="BeforeCompile">
<Exec WorkingDirectory="$(MSBuildProjectDirectory)" LogStandardErrorAsError="true" Command="<path to projectA exe> MyHtml.html $(O)\MyGeneratedFile.cs" />
<Exec WorkingDirectory="$(MSBuildProjectDirectory)" LogStandardErrorAsError="true" Command="if errorlevel 1 echo $(ERR_MSG) Unable to compile MyHtml.html to $(O)\MyGeneratedFile.cs" />
</Target>
Now, I wish to create a Nuget package (.NetCore) that achieves similar functionality as projectA (i.e somehow be able to consume this new package in a different netcore application and autogenerate the files- in a similar way projectB is able to use ProjectA's exe to generate the files). As I understand, .NET Core project would create a dll (not an exe); what is the way of using this dll to achieve what I want?
Any help is appreciated!
As .NET Core is a cross platform framework. This DLL file works across all platforms that are supported by the .NET Core runtime (Windows, Linux, and macOS). This is known as "framework dependent" deployment.
For your case there are 2 options :
To run any .dll of .NET Core application , command dotnet yourProject.dll is used.
Part of projectB.csproj will look like this:
<Target Name="_EX_MyGenerateFile_cs" Inputs="MyHtml.html" Outputs="$(O)\MyGeneratedFile.cs" Condition="'$(BuildingOutOfProcess)' != 'False' AND '$(BuildingProject)' == 'True'" BeforeTargets="BeforeCompile">
<Exec WorkingDirectory="$(MSBuildProjectDirectory)" LogStandardErrorAsError="true" Command="dotnet <path to projectA dll> MyHtml.html $(O)\MyGeneratedFile.cs" />
<Exec WorkingDirectory="$(MSBuildProjectDirectory)" LogStandardErrorAsError="true" Command="if errorlevel 1 echo $(ERR_MSG) Unable to compile MyHtml.html to $(O)\MyGeneratedFile.cs" />
</Target>
If you really want exe file, generate exe file using a Self-Contained deployment.
This will create an output that contains its own copy of the .NET Core runtime and an yourProject.exe file.
Con of this approach:
It increases the size of the published application.
It needs to be updated when new versions of the runtime are released.
The resulting application only works on the published operating system published.
For a C# Console application in VS2019 I issued the following command from .NET CLI (Developer PowerShell):-
dotnet add package <PackageName> --version <Version>
Then from Object Browser I discovered that the package assembly (.dll) has been copied into my local path starting with C:\Users<userid>.nuget\packages<PackageName><Version>. But if I see my project definition (.csproj file) I only see package name and not the path:-
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="<PackageName>" Version="<Version>" />
</ItemGroup>
</Project>
Where is the setting in Visual Studio (or .dotnet CLI) that decides which local path NuGet packages should get downloaded to ?
This is the global NuGet cache, it's configurable (as per the quoted docs below) but yours is the default location
https://www.github.com/NuGet/learn.microsoft.com-nuget/tree/main/docs%2Fconsume-packages%2Fmanaging-the-global-packages-and-cache-folders.md
The global-packages folder is where NuGet installs any downloaded package. Each package is fully expanded into a subfolder that matches the package identifier and version number. Projects using the PackageReference format always use packages directly from this folder. When using the packages.config, packages are installed to the global-packages folder, then copied into the project's packages folder.
Windows: %userprofile%.nuget\packages
Mac/Linux: ~/.nuget/packages
Override using the NUGET_PACKAGES environment variable, the globalPackagesFolder or repositoryPath configuration settings (when using PackageReference and packages.config, respectively), or the RestorePackagesPath MSBuild property (MSBuild only). The environment variable takes precedence over the configuration setting.
On Ubuntu I'd like to wrap a few C# DLL files into a NuGet package. On Windows one would use the NuGet package explorer or nuget.exe + manually edited *.csproj.nuspec. In summary when manually editing the *.nuspec file one may add DLLs via the <files> section:
<files>
<file src="some\Path\YourDll.dll" target="lib"></file>
</files>
On Ubuntu I'd like to use dotnet pack instead. However it seems like it's not able to operate on a *.csproj.nuspec file:
Usage: dotnet pack [options] <PROJECT | SOLUTION>
Arguments:
<PROJECT | SOLUTION> The project or solution file to operate on. If a file is not specified, the command will search the current directory for one.
Options:
-h, --help Show command line help.
-o, --output <OUTPUT_DIR> The output directory to place built packages in.
--no-build Do not build the project before packing. Implies --no-restore.
--include-symbols Include packages with symbols in addition to regular packages in output directory.
--include-source Include PDBs and source files. Source files go into the 'src' folder in the resulting nuget package.
-c, --configuration <CONFIGURATION> The configuration to use for building the package. The default for most projects is 'Debug'.
--version-suffix <VERSION_SUFFIX> Set the value of the $(VersionSuffix) property to use when building the project.
-s, --serviceable Set the serviceable flag in the package. See https://aka.ms/nupkgservicing for more information.
--nologo Do not display the startup banner or the copyright message.
--interactive Allows the command to stop and wait for user input or action (for example to complete authentication).
--no-restore Do not restore the project before building.
-v, --verbosity <LEVEL> Set the MSBuild verbosity level. Allowed values are q[uiet], m[inimal], n[ormal], d[etailed], and diag[nostic].
--runtime <RUNTIME_IDENTIFIER> The target runtime to restore packages for.
--no-dependencies Do not restore project-to-project references and only restore the specified project.
--force Force all dependencies to be resolved even if the last restore was successful.
This is equivalent to deleting project.assets.json.
Can I wrap C# DLLs into a NuGet package on Ubuntu using the dotnet CLI? Or do I have to use the nuget CLI (apt-get install nuget) instead with the approach like on Windows?
I would add this into the .csproj file:
<ItemGroup>
<Content Include="some.dll" PackageCopyToOutput="true">
<pack>true</pack>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
It's not pretty but it works.
We have a nuget package we developed and use internally. One package has addtional unmanaged DLL's that need to be deployed. In VS2015, I right-click on the web application project and publish to a test server. None of the unmanaged DLL's in the package were published, but they are in the bin folder on my machine.
Here's what I'm trying in the package targets file:
<?xml version="1.0" encoding="utf-8" ?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="ExtraFilesPublishTarget">
<Message Text="########### NUGET DEPLOY ###########"/>
<ItemGroup>
<DistFiles Include="$(MSBuildThisFileDirectory)..\lib\dist\**\*.*"/>
<FilesForPackagingFromProject Include="%(DistFiles.Identity)">
<DestinationRelativePath>\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
</FilesForPackagingFromProject>
</ItemGroup>
</Target>
<Target Name="DistBuildTarget" AfterTargets="Build">
<ItemGroup>
<DistFiles Include="$(MSBuildThisFileDirectory)..\lib\dist\**\*.*"/>
</ItemGroup>
<Microsoft.Build.Tasks.Copy SourceFiles="#(DistFiles)" DestinationFiles="#(DistFiles->'$(OutputPath)\%(RecursiveDir)%(Filename)%(Extension)')" />
</Target>
<PropertyGroup>
<copyallfilestosinglefolderforpackagedependson>
ExtraFilesPublishTarget;
$(copyallfilestosinglefolderforpackagedependson);
</copyallfilestosinglefolderforpackagedependson>
<copyallfilestosinglefolderformsdeploydependson>
ExtraFilesPublishTarget;
$(copyallfilestosinglefolderforpackagedependson);
</copyallfilestosinglefolderformsdeploydependson>
</PropertyGroup>
</Project>
When I publish, I see the NUGET DEPLOY message, but the next line in the output window is "Target "ExtraFilesPublishTarget" skipped. Previously built successfully."
The link above (http://blog.mjjames.co.uk/2012/10/deploying-non-project-files-with-web.html) solved my problems.
I did have another issue with targets not found. To save time in testing, I would edit my .targets file in the packages folder for my solution. If you add or rename a target in the local .targets file, VS2015 won't find the change since it caches the target names. You have to close down VS or reinstall the package to it to be found. You can change the elements within the target, you just can't change the name of the target or add a target.
I am building a modular .NET core application that can load extensions at runtime using MEF. I have 2 projects, one is a library that I want to be able to load at runtime, then I have my main application that will do the loading.
My library project has some Nuget dependencies. In order to load my library at runtime, I need those Nuget dependencies to be available next to the library at runtime, but building using VS2017 does not include these Nuget DLLs as part of the output.
How do I get Nuget DLLs included when I build my library?
Edit: I have tried dotnet publish and dotnet pack, but both of those make me a nupkg file only containing my DLL and not the nuget DLLs I need with it. Also, I can't load a nupkg file at runtime very easily, which is why I'd like to just get the resulting assemblies themselves on their own.
For what it's worth, this is what my csproj looks like:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp1.1</TargetFramework>
<AssemblyName>JSON.plugin</AssemblyName>
<IncludeBuiltProjectOutputGroup>true</IncludeBuiltProjectOutputGroup>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Composition" Version="1.0.31" />
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\BDDGen.Types\BDDGen.Types.csproj" />
</ItemGroup>
</Project>
In order to make the build process copy all referenced dll files from NuGet packages from the cache folder into the build output, set this property inside a <PropertyGroup>:
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>