I have a WinForms application which I am publishing via ClickOnce. This applciation includes the Accord FFMPEG libraries, which are included as references.
The FFMPEG NuGet package folder includes a .targets file, which includes a variety of dlls needed for proper operation of the FFMPEG library (avcodec.dll, avformat.dll, avutil.dll). These are copied to the \bin folder when building the project. This is done by including this line in the .csproj:
Import Project="..\packages\Accord.Video.FFMPEG.3.3.0\build\Accord.Video.FFMPEG.targets" Condition="Exists('..\packages\Accord.Video.FFMPEG.3.3.0\build\Accord.Video.FFMPEG.targets')"
However when publishing the application via ClickOnce, these files are not included in the published folder. Is there a way to run the Import Project task and add the files into the published folder?
Unfortunately I didn't manage to get this working using the .targets file. My solution in the end was to copy the required dlls to the deployment folder and include them in the manifest, as below.
<ItemGroup Label="FFMPEG DLL">
<ClickOnce Include="..\packages\Accord.Video.FFMPEG.3.3.0\build\*.dll">
<InProject>false</InProject>
<Visible>false</Visible>
</ClickOnce>
</ItemGroup>
<Target Name="BeforeBuild">
<CreateItem Include="#(ClickOnce)" AdditionalMetadata="TargetPath=%(FileName)%(Extension);IsDataFile=false">
<Output TaskParameter="Include" ItemName="_DeploymentManifestFiles" />
</CreateItem>
</Target>
<Target Name="BeforePublish">
<Touch Files="#(IntermediateAssembly)" />
</Target>
This is using .NET 4.6.1 and VS2017.
Related
I am creating a package for use in dotnet core web applications.
As of recent, it would appear that Powershell scripts are no longer used to populate and remove files on Nuget package installation/ uninstallation. It would appear that it is all managed using MsBuild. I have successful migrations on installation. The files are populated on a Build target like so:
<Target Name="CopyMyAssets" BeforeTargets="Build">
<ItemGroup>
<MyAssets Include="$(MyAssetsPath)" />
</ItemGroup>
<Copy SourceFiles="#(MyAssets)" DestinationFiles="#(MyAssets->'$(MSBuildProjectDirectory)\App_Plugins\MyPlugin\%(RecursiveDir)%(Filename)%(Extension)')" SkipUnchangedFiles="true" />
</Target>
And have a removal method with a clean target:
<Target Name="ClearMyAssets" BeforeTargets="Clean">
<ItemGroup>
<MyPluginDir Include="$(MSBuildProjectDirectory)\App_Plugins\MyPlugin\" />
</ItemGroup>
<RemoveDir Directories="#(MyPluginDir)" />
</Target>
My question is, on package uninstall through the Nuget package manager, how do I ensure that these files are removed during the uninstall process? The user may not remember to clean before uninstalling, which will leave these orphaned files, and with no package to tell the project what to do, they will no longer be removed on subsequent cleans. Do I need to somehow invoke a project clean on uninstallation, or is there a way of scripting file removal? I have read the MsBuild documentation and I see no uninstall target or replacement for the old uninstall.ps1 scripts that used to be used.
Edit: Additional context. This is a package designed for Umbraco CMS 9 and up. I generated the project using Umbraco templates, but it doesn't differ hugely from the usual template. You use a .targets file to determine file transfers on build.
I'm using Wix toolset v 3.11 in VS2019 to create a setup for our application. In order to ease maintenance, I need to copy the installer files to a folder with the version in its path.
Basically what I thought was to use a post build event where I would copy the files to a \$(BootstrapPackageVersion)\$(Configuration)\ directory, but I am not able to find such variable.
I tried to extract the version from the .exe package (since it gets its version from the MSI package that itself get its version from the original application, as intended) with the following code in the .wixproj file:
</PropertyGroup>
<Target Name="AfterBuild">
<GetAssemblyIdentity AssemblyFiles="$(TargetPath)">
<Output TaskParameter="Assemblies" ItemName="AssemblyVersions" />
</GetAssemblyIdentity>
<CreateProperty Value="$(TargetDir)/%(AssemblyVersions.Version)/">
<Output TaskParameter="Value" PropertyName="CustomTargetName" />
</CreateProperty>
<Copy SourceFiles="$(TargetDir)/*" DestinationFolder="$(CustomTargetName)"/>
</Target>
But it fails with the following error:
Cannot get assembly name for "[Path]\Setup.exe". Could not load file
or assembly 'Setup.exe' or one of its dependencies. The module was
expected to contain an assembly manifest.
I saw that there is a property, $(WixBundleVersion), but it doesn't seems to be available to use in build events.
Basically what I want to achieve is a fairly simple thing: take the output from the bootstrapper project and copy everything to another path that include the package version. It is possible?
The way I do this in my wix project is to output setup.exe into it's default folder and then run an AfterBuild and copy it to the final artifacts directory
in wixproj:
<Target>
...
<GetAssemblyIdentity AssemblyFiles="..\MyApp.App\bin\$(Configuration)\net5.0\FrameworkDep\win-$(Platform)\Publish\MyApp.App.dll">
<Output TaskParameter="Assemblies" ItemName="AssemblyVersion" />
</GetAssemblyIdentity>
<PropertyGroup>
<DefineConstants>BuildVersion=%(AssemblyVersion.Version)</DefineConstants>
</PropertyGroup>
...
</Target>
<Target Name="AfterBuild">
<Copy SourceFiles=".\bin\$(Configuration)\en-us\$(OutputName).msi" DestinationFiles=".\bin\$(Configuration)\$(OutputName)_%(AssemblyVersion.Version).msi" />
</Target>
This assigns
BuildVersion which you can then use in your wxs files
and
AssemblyVersion which you can use in the wixproj with %(AssemblyVersion.Version)
the AfterBuild section is copying the msi to
MyApp_1.2.3.msi
in my wxs file I can use:
<Product Id="*" Name="My App" Language="1033"
Version="$(var.BuildVersion)>
This is then using the build version from above so I just version control MyApp.App project.
We have a project (ProjectAbc) in a solution which is referencing a nuget package (which is our different project [ProjectXyz] from other solution). We use .net core framework and package reference to include nuget package (ProjectXyz) in .csproj file.
<PackageReference Include="ProjectXyz" Version="1.1.2.3" />
When the solution is build locally or in Prod, ProjectXyz.dll and ProjectXyz.xml gets generated in
ProjectAbc/bin/debug(locally) or release(inProd)/netcoreapp3.1
We want Only ProjectXyz.xml of Only ProjectXyz nuget package to get generated in following folder directly
ProjectAbc
I found various articles which directed me to do different things like copying file to output directory after building or using relative path. Though, tried different ways, I keep getting various errors. It may be because I am not aware of the syntax in .csproj file or also may be because I am not sure what I am doing.
What would be best way to copy file in above case or to generate file directly in the required folder?
for my comment response:
Since I am unable to paste the screenshot in my comment for #Perry Qian-MSFT. So pasting it here.
8/20/2020-----package screenshot---------------------------
You could use <package_name>.props file in nuget project ProjectXyz to copy such file into the project folder of ProjectAbc. You should use <package_id>.props.
1) First, in your ProjectXyz project, create a folder called build and then add a file called <package_id>.props, in your side, it is called ProjectXyz.props.
2) Add these in ProjectXyz.props file:
<Project>
<Target Name="CopyFilesToProject" BeforeTargets="Build">
<Message Text="Copying ProjectXyz.xml to project" />
<ItemGroup>
<SourceScripts Include="$(MSBuildThisFileDirectory)..\..\content\any\any\**\*.*"/> //file from the ProjectXyz nuget package
</ItemGroup>
<Copy
SourceFiles="#(SourceScripts)"
DestinationFiles="#(SourceScripts -> '$(MSBuildProjectDirectory)\%(RecursiveDir)%(Filename)%(Extension)')" //copy into the main ProjectAbc project folder
/>
</Target>
</Project>
3) Unload your ProjectXyz project and add these in ProjectXyz.csproj file:
<ItemGroup>
<Content Include="bin\Debug\xxx\ProjectXyz.xml(the path of the ProjectXyz.xml)" Pack="true"
PackagePath="content\any\any;contentFiles\any\any\;;">
<PackageCopyToOutput>true</PackageCopyToOutput>
</Content>
<None Include="build\ProjectXyz.props" Pack="true" PackagePath="build\$(TargetFramework)"/>
</ItemGroup>
4) Then you should pack your new ProjectXyz project.
5) Then you finish packing, you should first clean all nuget caches first.
Then in your ProjectAbc project, you should uninstall the old one and then install the new ProjectXyz nuget package.
After that, you should build ProjectAbc project first and then you will see that xml document from the nuget package is under the project folder of ProjectAbc.
====================================================================
Update 1
ProjectXyz project is net core or net standard while ProjectAbc is net core.
First, to help you understand the issue, instead, I try to pack ProjectXyz.xml file into other folder in the ProjectXyz.nupkg.
1) First, change to use these xml content in ProjectXyz.csproj file:
<ItemGroup>
<Content Include="bin\Debug\netcoreapp3.1\ProjectXyz.xml" Pack="true" PackagePath="XmlFolder">
<PackageCopyToOutput>true</PackageCopyToOutput>
</Content>
<None Include="build\ProjectXyz.props" Pack="true" PackagePath="build\$(TargetFramework)"/>
</ItemGroup>
The goal of it is to pack ProjectXyz.xml file into the folder called XmlFolder of XmlFolder.nupkg. And save ProjectXyz.xml file in the Nuget package.
Make sure that the file exists in the nuget package.
If the file does not exist, I think it is controlled by your git. Or you could put this ProjectXyz.xml in your project folder.
Try to right-click on your project-->Properties-->Build-->check this:
Just use <Content Include="ProjectXyz.xml" Pack="true" PackagePath="XmlFolder">
In our side, the file can be copied into nupkg nuget package so you should make sure that other tools like git will not interface it.
2) Then change to use these in ProjectXyz.props file:
<Project>
<Target Name="CopyFilesToProject" BeforeTargets="Build">
<Message Text="Copying ProjectXyz.xml to project" />
<ItemGroup>
//ProjectXyz.xml file from the ProjectXyz nuget package
<SourceScripts Include="$(MSBuildThisFileDirectory)..\..\XmlFolder\**\*.*"/>
</ItemGroup>
//copy ProjectXyz.xml file into the main ProjectAbc project folder
<Copy
SourceFiles="#(SourceScripts)"
DestinationFiles="#(SourceScripts -> '$(MSBuildProjectDirectory)\%(RecursiveDir)%(Filename)%(Extension)')"
/>
</Target>
</Project>
The goal of it is that when you install this nuget package, it will first run this target to copy the ProjectXyz.xml file from the nuget package into the main project ProjectAbc.
Note:
When you finishing installing nuget package, first build ProjectAbc project and the file will exists in ProjectAbc project folder.
3) Then right-click ProjectXyz-->Properties-->Pack to pack your project.
When you install the new ProjectXyz, you should first delete all files under
C:\Users\xxx(current user)\.nuget\packages.
Also, one more question I had is, the ProjectXyz is being referenced
in multiple projects like ProjectAbc, Project123. We dont want
ProjectXyz.xml file to show up in Project123 but only in ProjectAbc. I
guess with above solution, it might show in both of referencing
projects.
For this, you only need to add a condition in CopyFilesToProject target like this: $(ProjectXyz_Flag)==true and then create a property ProjectXyz_Flag and set its value to true in ProjectAbc.csproj file.
When you build ProjectAbc project, it will determine whether to copy the file based on the switch variable you are currently setting.
a) Add a condition called $(ProjectXyz_Flag) in ProjectXyz.props file:
Then repack your ProjectXyz project and do several clean steps as I said before.
When you install that package in ProjectAbc project, you should add such such property in ProjectAbc.csproj file:
<PropertyGroup>
<ProjectXyz_Flag>true</ProjectXyz_Flag>
</PropertyGroup>
Then when you build ProjectAbc project, it will execute the copy target and if you do not define that property, it will not copy that file in ProjectAbc.
And if those projects do not need ProjectXyz.xml file, you just do not define that switch property in those projects.
====================================================
Update 2
try to use nuget.exe cli to pack your project, you just need a custom nuspec file:
First, download nuget.exe cli and then configure its local path into PATH System Environment Variable. Then, you can call nuget in CMD.
Second, open CMD and cd xxx(project folder path), run nuget spec to generate the nuspec file and then modify the generated nuspec file:
<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<!-- ... -->
</metadata>
<files>
<file src="xxx\ProjectXyz.xml" target="XmlFolder" />
<file src="build\ProjectXyz.props" target="build\netcoreapp3.1" />
</files>
</package>
Third, run nuget pack to pack this project.
==============================================================
Update 3
Please first clean your nuget caches or just delete all nuget caches under C:\Users\xxx(current user)\.nuget\packages. Then reinstall your nuget package.
Also, make sure that the xxx.props name is the same as your nuget package_id.
If your nuget package calls ProjectXyz(package_id). Then the props file should be named as ProjectXyz.props.
Besides, you should set msbuild project build output verbosity to detailed under Tools-->Options-->Projects and Solutions-->Build and Run.
Then, rebuild your ProjectAbc to check whether the target executes.
======================================================
Update 4
You should make sure that when you pack your package project.mnop, make sure that the project.mnop.props file has no syntax errors.
For an example, I have incorrectly wrote something like asdczxcx in the props file, however, since the build action of the props file is Content or None, Vs will not automatically analyze its errors and will not show the errors.
And the error shows the same as yours.
So you should delete that Illegal characters. Make sure that project.mnop.props has no syntax errors. Then repack your project.
After that, first uninstall the old nuget package project.mnop on the ProjectAbc.
Then, delete the cache project.mnop folder under C:\Users\xxx(current user)\.nuget\packages.
Finally, delete bin and obj folder of ProjectAbc, install the new version project.mnop, then rebuild your project ProjectAbc.
=============================================
Update 5
Actually, this should be an easier way. And your inspiration can be done with a more concise Nuget package structure.
You should only change this:
1) change to use ProjectXyz.xml from the lib folder in your ProjectXyz.props:
<SourceScripts Include="$(MSBuildThisFileDirectory)..\..\lib\netcoreapp3.1\ProjectXyz.xml"/>
</ItemGroup>
<Copy
SourceFiles="#(SourceScripts)"
DestinationFiles="#(SourceScripts -> '$(MSBuildProjectDirectory)\%(RecursiveDir)%(Filename)%(Extension)')"
/>
2) change your xxx.nuspec file to:
<?xml version="1.0"?>
<package >
<metadata>
........
<copyright>Copyright 2020</copyright>
<tags>Tag1 Tag2</tags>
</metadata>
<files>
<file src="build\ProjectXyz.props" target="build\netcoreapp3.1" />
</files>
</package>
3) then pack your project and then you can get what you want.
Note: SourceScripts uses the path $(MSBuildThisFileDirectory).
$(MSBuildThisFileDirectory) means the full path where the ProjectXyz.props file of the nuget package exists.
In your side, the $(MSBuildThisFileDirectory) means
C:\Users\xxxxx\.nuget\packages\project.mnop\45.0.0\build\netcoreapp3.1
And then use this path to find the file address of ProjectXyz.xml in the lib folder of the nuget package.
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'm trying to update my (previously working) pdf-creating web application to use the ABCpdf.NET and ABCpdf.NET Gecko Runtime nuget packages.
I've installed both packages (both are version 8.1.1.6) however when I run my application, I get the following WebSupergoo.ABCpdf8.Internal.PDFException:
Failed to add HTML: Gecko engine hit an error it was unable to recover
from. Possible causes: XULRunner folder is corrupt or is from another
version of ABCpdf.
After installing the ABCpdf.NET Gecko Runtime package, I got a dialog telling me that I would need to manually copy the XULRunner folder into my output directory. In order to achieve this, I added the following to my applications .csproj file:
<Target Name="AfterBuild">
<CallTarget Targets="CopyAbcpdfToDeployFolder" />
</Target>
<Target Name="CopyAbcpdfToDeployFolder">
<ItemGroup>
<SourceDir Include="$(ProjectDir)XULRunner\**\*.*" />
</ItemGroup>
<Copy SourceFiles="#(SourceDir)" DestinationFolder="$(WebProjectOutputDir)\$(OutputPath)%(SourceDir.RecursiveDir)\XULRunner" />
</Target>
(This seems to be working correctly - the XULRunner folder and its contents are present in my bin folder after a build)
The line of code that is failing is as follows:
theDoc.AddImageUrl(url);
Can anyone help me get this working?
As it turns out, my changes to the .csproj file we not copying all files into the correct subfolders. In order to copy the folder structure and files recursively, the XML should have looked like this:
<Target Name="AfterBuild">
<CallTarget Targets="CopyXULRunnerToDeployFolder" />
</Target>
<Target Name="CopyXULRunnerToDeployFolder">
<ItemGroup>
<MyFiles Include="XULRunner\**\*.*" />
</ItemGroup>
<Microsoft.Build.Tasks.Copy SourceFiles="#(MyFiles)" DestinationFiles="#(MyFiles->'$(OutputPath)\XULRunner\%(RecursiveDir)%(Filename)%(Extension)')"/>
</Target>
I was able to accomplish the same outcome with the following MSBuild xml:
<ItemGroup>
<Content Include="XULRunner\**\*.*">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
I fell upon this setup after dealing with issues concerning the building of a package via MSDeploy not including the XULRunner files.
Not sure if there's anything patently wrong with this, but so far it works for me on a multiple staged deployment setup.