Nuget package issues - buildAction, copyToOutput, flatten are ignored
Package project (ThisProject.vbproj)- .Net Standard Library 2.0, .nuspec file:
<references>
<reference file="ThisProject.dll"></reference>
<reference file="First.dll"></reference>
<reference file="Second.dll"></reference>
<reference file="...."></reference>
</references>
<contentFiles>
<files include="any/any/*" buildAction="Content" copyToOutput="true" flatten="true" />
</contentFiles>
</metadata>
<files>
<file src="contentFiles\any\any\First.dll" target="lib\any\any\First.dll"></file>
<file src="contentFiles\any\any\Second.dll" target="lib\any\any\Second.dll"></file>
<file src="contentFiles\any\any\....dll" target="lib\any\any\.....dll"></file>
</files>
When importing in .net ClickOnce Framework 4.6.1 Project, the contentFiles are still in the subfolders (flatten is ignored), Build Action and CopyToOutputDirectory are the defaults (buildAction,copyToOutput are ignored)
Read all the documentation I could find e.g.
https://learn.microsoft.com/en-us/nuget/reference/nuspec
What am I doing wrong?
I think you have some misunderstanding about this part.
First, contentFiles works for new-sdk projects(Net Core and Net Standard) with PackageReference nuget management format rather than Net Framework project with packages.config nuget management format.
And contentFiles works for content files rather than lib folder. So you should not pack these dll files on target="lib\any\any\.....dll". You should pack them into contentFiles folder.
Use this:
<contentFiles>
<files include="any/any/*" buildAction="Content" copyToOutput="true" flatten="true" />
</contentFiles>
<files>
<file src="xxx\First.dll(the physical, relative path of the dll on your project folder)" target="contentFiles\any\any\First.dll"></file>
<file src="xxx\Second.dll(the physical, relative path of the dll on your project folder)" target="contentFiles\any\any\Second.dll"></file>
<file src="xxx\....dll(the physical, relative path of the dll on your project folder)" target="contntFiles\any\any\.....dll"></file>
<files>
Then, you should install this nuget package on a Net Core project.
When you finish it, repack the project with nuget pack command, then, before you install the new one, clean the nuget caches first to remove the old previous version. Then, install the new version on a Net Core project and you can see the effect like this:
======================================================================
If you still want to have this function on a Net Framework project, you should pack these files on content node rather than contentFiles.
And you only need to add two lines:
<contentFiles>
<files include="any/any/*" buildAction="Content" copyToOutput="true" flatten="true" />
</contentFiles>
<files>
<file src="xxx\First.dll(the physical, relative path of the dll on your project folder)" target="contentFiles\any\any\First.dll"></file>
<file src="xxx\Second.dll(the physical, relative path of the dll on your project folder)" target="contentFiles\any\any\Second.dll"></file>
<file src="xxx\....dll(the physical, relative path of the dll on your project folder)" target="contntFiles\any\any\.....dll"></file>
<file src="xxx\First.dll(the physical, relative path of the dll on your project folder)" target="content"></file>
<file src="xxx\Second.dll(the physical, relative path of the dll on your project folder)" target="content"></file>
..........
<files>
But these simply cannot change the attributes of the imported file. And for net framework project, changing the property of the files cannot be done on xxx.nuspec file.
You should use <packages_id>.props or targets file.
1) create a file called <packages_id>.props under the build folder on the Solution Explorer, if your nuget package is named as ThisProject.1.0.0.nupkg, you should name it as ThisProject.props so that it will work.
This is mine:
2) add these on the props file:
<Project>
<ItemGroup>
<Content Include="First.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Second.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
......
</ItemGroup>
</Project>
3) add a line on nuspec file to include the props file into the nupkg.
<file src="build\xxx.props(the physical, relative path of the file on your project folder)" target="build"></file>
4) then repack the nuget package, clean the nuget caches, then install this new one on the Net Framework project with packages.config.
Note: although the Properties window of the imported content file on the solution explorer does not show the changed value and still shows the old one, the files are already copied into the output folder of the project. And it is an UI display issue on Solution Explorer and the changed values are already be used and work well. So you do not have to care much about that.
Related
I have a wpf project for which the installer is created by wix setup project. the wix setup project is compiled to get the .msi. The .exe is generated from the .msi file using wix bootstrapper project.Now my question is how to get the assembly version [assembly: AssemblyFileVersion("x.x.x.xx")] form wpf .cs file?
Andy is right, you will not be able to pull the version number from a .cs file as WiX does not compile or know anything to do with the C# code.
What you want to do is version your main executable file (presumably the .csproj application) using the assembly version properties. (These can be found in the project properties)
1) In the Product.wxs add said main executable as a file in the installer.
<Component Id='MainExecutable' Guid='*'>
<File Id='MainExe' Name='MainExe.exe' Source='Path-to-exe' KeyPath='yes' />
</Component>
2) Bind the version of the .msi to this main executable. This is done in the Version attribute of the Product element.
<Product Id="*" Name="My Product Name" Language="1033" Version="!(bind.FileVersion.MainExe)" Manufacturer="Debabrata" UpgradeCode="PUT-GUID-HERE">
Not that the value after the FileVersion is the ID of your file. This is important.
Now to use this version number in the bootstrapper project - the process is very similar.
1) Add the MSI to the bootstrapper.
<MsiPackage SourceFile="Path-to-msi" Id="MyMSI">
2) In the Version attribute of the Bundle element the binding should be.
<Bundle Name="My Bundle" Version="!(bind.packageVersion.MyMSI)">
Again, note how the ID matches.
Hope this helps!
I have an app.config file in our WPF project that is transformed using the following build target in the .csproj
<!-- MSbuild Task for transforming app.config based on the configuration settings -->
<UsingTask TaskName="TransformXml"
AssemblyFile="$(SolutionDir)\packages\MSBuild.Microsoft.VisualStudio.Web.targets.12.0.4\tools\VSToolsPath\Web\Microsoft.Web.Publishing.Tasks.dll" />
<Target Name="AfterBuild">
<!-- Transform the app.config into the correct config file associated to the current build settings -->
<TransformXml Source="App.config" Transform="App.$(Configuration).config" Destination="$(OutputPath)\App.config" />
<!-- Bit of .Net to get all folders and subfolders that we want to delete post-build -->
<ItemGroup>
<FoldersToClean Include="$([System.IO.Directory]::GetDirectories("$(OutputPath)"))" />
</ItemGroup>
<!-- Delete all of our localization folders and .pdb symbols. We only delete PDB files for Release builds. Debug builds we will leave them. -->
<RemoveDir Directories="#(FoldersToClean)" />
<Exec Command="del $(OutputPath)*.pdb" Condition=" '$(Configuration)'=='Release' " />
</Target>
This correctly generates an App.config after the compilation, with my transformed QA or Production configuration files created. The issue I ran into however is that the following code uses AppName.exe.config.
string encryptedString = ConfigurationManager.AppSettings["SqlConnection"];
After doing a bit of reading, I understand why it's doing that. The App.config file ultimately becomes the AppName.exe.config for use during runtime. That's fine; my transformation happens to late though. When the compilation is completed, the AppName.exe.config file contains my base App.config file information, and none of the transformed settings. I assume that is due to the transform happening as a post-build step, where it transforms the App.config after the original App.config file was used to generate AppName.exe.config.
It looks like there isn't any thing preventing me from changing
<TransformXml Source="App.config"
Transform="App.$(Configuration).config"
Destination="$(OutputPath)\App.config" />
so that it replaces the AppName.exe.config file post-build.
<TransformXml Source="App.config"
Transform="App.$(Configuration).config"
Destination="$(OutputPath)\AppName.exe.config" />
Is there anything wrong with this? There isn't much in the way of help when using app.config and transforms for desktop applications. Everything I've read online is for transforming things into a web-config file. I assume this is safe and more or less is the same thing. However I wanted to make sure I'm not missing any glaring side-effects or issues i'll encounter by replacing the original AppName.exe.config with the transformed App.config.
Install this https://github.com/acottais/msbuild.xdt NuGet package and you will be able to create transforms like a web.config.
There are several other Nuget packages that will transform the app.config just like the web.config.
I used this one the other day and it worked great.
I'd like to create a nuget package (from some c# project), but I don't want to embed the generated dll, but just some static files instead.
I added a tag at the end of my nuspec file, but nuget pack command continues to embed the project.dll in the package.
The thing is I don't want this dll to be published.
Is there any way to do that?
Thanks,
Régis
Yes. You can create a .nuspec file that simply references the content files.
You must use nuget pack MyPackage.nuspec
Don't pack the .csproj file as that causes NuGet to include the built assembly.
See http://docs.nuget.org/create/nuspec reference for more info.
To package a file as content, you must use target=content when listing the file in your .nuspec document.
To create a 'content only' nuget package, you must use a <files> node to list the files.
A <files> node must be a sibling of the <metadata> node.
A <file> node must be a child of a <files> node.
To include a file as content, set the target attribute in a <file> node to 'content'.
Example:
<files>
<file src="{filePath}" target="content"/>
</files>
As previously mentioned, you must then pack the .nuspec file rather than a .csproj file:
nuget pack *.nuspec
I found the target=content trick here:
https://learn.microsoft.com/en-us/nuget/reference/nuspec#including-content-files
For contentFiles i use this way in the nuspec file :
<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
<metadata>
<id>DummyNuget</id>
<version>1.0.1-alpha</version>
<title>DummyNuget</title>
<authors>DummyNuget</authors>
<owners>DummyNuget</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>DummyNuget</description>
<releaseNotes></releaseNotes>
<copyright>2019</copyright>
<tags></tags>
<contentFiles>
<files include="**\*.*" buildAction="Content" copyToOutput="true" />
</contentFiles>
</metadata>
<files>
<file src="<path to files>\*.*" target="contentFiles\any\any" />
</files>
</package>
files to put the local files in the nuget package then contentFiles in the metadata to put all the files in the project as content copy to output
It's a WPF application, with Wix Installer.
I have resourceses folder and I want to include these files in the installer to put next to the executable. I solved generating a resources.wxs file with necessary information about the files under the resources folder using the heat tool. I managed to includ into the main wxs file. For that reason I modified the .wixproj file, adding a before build target action to generate the wxs and include it in the main wxs.
Concern: .wixproj is kind of hidden, there thing that you cannot modify from visual studio, like adding a before build action (pre build action is a different story)
Question: How can I extract the before build action into a separate file?
The before build action in the .wixproj:
<Target Name='BeforeBuild'>
<Exec Command='"%WIX%bin\heat" dir $(SolutionDir)resources -dr ResourcesDir -var var.ResourcesDir -cg ResourceFilesGroup -gg -g1 -sfrag -srd -out $(ProjectDir)Resources.wxs' />
<ItemGroup>
<Compile Include='$(ProjectDir)Resources.wxs' />
</ItemGroup>
You can extract it into a separate file—most project file types do that already. That's how they provide common targets to all projects of a type. A .wixproj has this:
<Import Project="$(WixVersionTargetsPath)" />
To augment your own, simply:
Create an XML file like:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name='BeforeBuild'>
<!-- tasks -->
</Target>
</Project>
Add an Import element inside the Project element and refer to that file:
<Import Project="custom.targets" />
If such a file primarily has Target elements, the convention is for it to have the file extension ".targets".
But there are two drawbacks with Visual Studio:
Visual Studio caches all the project file dependencies and runs the MSBuild internally. So, it you edit the external file, it won't be part of builds using Visual Studio until the project is next loaded. To quickly unload and reload a project, use the project context menu in the Solution Explorer. Workaround: Call MSBuild yourself.
When Visual Studio loads a project, if it includes non-standard external files, it gives a warning. (You can disable it per user by project file path, in the registry, if I recall.)
As an alternative to calling heat directly, you might want to look at the Harvest* targets that WiX provides. Note: As the documentation says, you don't invoke them directly (they're already invoked by the Build target); You simply add items to the ItemGroup they process and set properties they use.
I'm investigating to OpenNI SDK ant it's wrappers for .NET. So, I created MSBuild AfterBuild target to copy files from SDK folder (path from environment variable) to build output folder. Now build works on each computer (even if SDK isn't installed). But in this case build is very heavy.
Is there the way to create links to this files in solution? I need build to execute only for computers with installed SDK.
Add an Exists condition to the AfterBuild target, this would prevent the AfterBuild target from running.
<Target Condition="Exists('$(SdkLocation)')" Name="AfterBuild">
...
</Target>
You could also make a BeforeBuild target containing an Error task that will cause the build to break if the SDK is not detected.
<Target Name="BeforeBuild">
<Error Condition="!Exists('$(SdkLocation)')" Text="OpenNI SDK not found." />
</Target>
MsBuild should also be copying the SDK files to the output file if you've added References in the dependent projects. Are you copying extra files?