Azure DevOps: publish self-contained .net Core app with Chocolatey - .net-core

I need to create a self-contained .net core (3.1 in my case) app and to pack & publish using chocolatey so it can be installed and used.
I'm using Azure DevOps and have a feed on my own where I'm supposed to publish the chocolatey package.
The objective is to do this in the build pipeline, so, among other tasks I have:
dotnet publish task: creates the self-contained executable
chocolatey pack task: creates the .nupkg from a very simplistic .nuspec (only mandatory fields) I created.
My current problem is that the .nupkg file created contains always the project files and not the executable generated.
To try and work around it I even made the chocolatey pack's task work directory the same as the dotnet publish's task output one.
What am I missing? Is there another approach?

Azure DevOps: publish self-contained .net Core app with Chocolatey
It depends on whether you include the contained executable file in your .nuspec file.
If we include the contained executable file in the .nuspec file, chocolatey will create the .nupkg include the contained executable file, like:
<files>
<file src="IngestCanonicLtesConsole\ContainedExecutable.exe" target="Tools\ContainedExecutable.exe" />
</files>
We could add this contained executable file in the package:
So, if we are only include the mandatory fields without the <files>contained executable </files>, it will not include the contained executable file.
Besides, we need to include the contained executable file in the .nuspec file, we could change the output of the dotnet build to $(System.DefaultWorkingDirectory)\IngestCanonicLtesConsole, so that we could use the relative path in the .nuspec file.
Please check the document .nuspec reference for some more details.

After a few tests I realized that the chocolatey pack will "pack" all files that in exist in the same folder as the ".nuspec". Not sure this is because I don't set anything on tool.
Basically, my solution was to copy my ".nuspec" file to the folder where my executable was.

Related

How to use my own DLLs instead of the one referenced by a dependent package

I'm using a nuget package (let's call it A) which has dependency to another package, let's call it B.
To include A in my project, I changed .csproj file to:
<ItemGroup>
<PackageReference Include="A" Version="2.0.5" />
</ItemGroup>
When I run nuget restore package B is consumed from some nuget source too.
I want to replace dlls of package B with my own DLLs, I've created myself.
I can do it on my local machine by just copy pasting the desired dlls in bin folder. But how can I do the same on Azure Websites? Is there anyway to automate this process?
Is there any way to tell nuget not to fetch DLLs of B from nuget source and instead use my desired ones?
Update:
Thanks to Shahryar's contribution, we can also choose to add the dll file and set it to be copied to the compilation folder for implementation (define properties in the .csproj file).
In fact, it is mainly to change the content of final compiled files, because after the final deployment, it runs according to the compiled files.
Original Answer:
You can compile the web app locally first, and then replace your dll file with the corresponding file in bin. Use zip to package the entire compiled file, and then use zip deployment to directly upload the final compiled file to Azure (the operation of the web app deployed to Azure depends on the file uploaded in this way)
Have a look of Zip Deploy.

Can .Net Core 3 self-contained single executable be decompiled?

I tried using Dotpeek and ILSpy.Net to decompile (my own code), they failed.
Do I need special obfuscation on distributed binaries of .Net Core 3 self-contained single executable ?
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.0</TargetFramework>
<PublishTrimmed>true</PublishTrimmed>
<PublishReadyToRun>true</PublishReadyToRun>
<PublishSingleFile>true</PublishSingleFile>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
</PropertyGroup>
</Project>
The single-file exe is really an unmanaged wrapper and ILSpy doesn't support decompiling this. But when you run the exe, it unwraps its contents to a temp folder. So you can find the managed dll there and decompile it using ILSpy.
To find the temp folder, you can use any tool that shows locations of assemblies loaded by a process. SysInternals Process Monitor (procmon) is a good one.
You can setup procmon to filter by your exe name, and when you launch your exe, procmon should show some events for assemblies being loaded from a temp folder:
You can browse to that folder and find your managed dll there. And you can decompile using ILSpy from that location.
I wrote a blog entry: https://eersonmez.blogspot.com/2020/02/ilspy-decompiling-net-core-self.html
I wrote a small dotnet tool after I stumbled upon this question and couldn't find a lightweight tool myself other than ILSpy.
You can install it using the following dotnet command: dotnet tool install -g sfextract.
After installing it, run it using the following command: sfextract application.exe -o output-dir
The bundle format for .NET 5.0 (bundle version 2) is identical to previous versions. .NET 6.0 (bundle version 6) has an additional field for each file entry containing the compressed size, since single-file applications can now be compressed using gzip by setting EnableCompressionInSingleFile to true.
https://www.nuget.org/packages/sfextract/
https://github.com/Droppers/SingleFileExtractor
Update 07/2022: .Net 5 single-file does not automatically unpack to the same temporary location as before. to force it to be unpacked you would need to add the following:
in the project file add these properties (according to theseMicrosoft docs):
<PublishSingleFile>true</PublishSingleFile>
<IncludeAllContentForSelfExtract>true</IncludeAllContentForSelfExtract>
Add an environment variable DOTNET_BUNDLE_EXTRACT_BASE_DIR with the location you want the files extracted to.
Update: One of the announcements made regarding .Net 5 states that the way single-file executables will be made would change, so this method will not work for them.
I wanted to add on #Eren Ersönmez's answer, that while ILSpy DotPeek don't support this at the time, since the self-contained single file is just a wrapper that contains all your DLLs and gets extracted on runtime, simply knowing where it is extracted to can save you using ProcMon or ProExp or windbg.
If you use windows you can go to c:\Users\{Local Username}\AppData\local\temp\.net\{Name of executable}
which should lead to somewhere similar to
c:\Users\alenros\AppData\Local\Temp.net\MyTestApplication
Launch your exe, and a folder with the same name will be created in that location.
The folder will contain randomly named folders. open the latest one and there you will find all your extracted DLLs, which can then be decompiled.

.nupkg does not contains dll of project instead it copies whole project in package after vsts build

****i'm building the nuget package using vsts build, once the build is created it does not contains dll of project instead it's just copying whole project in nuget packages.which is not expected****
Based on the code of nuspec file, you include all files, so all files will be in the package, you need to specify the files/folders that you want to include into the package.
The simple way is that you can specify the project file instead of nuspec file to package.

Visual Studio Team Services dotnet publish

My build completes with no errors, but it creates a randomly named zip file (s.zip) for the release step.
After the release step, I end up with that s.zip in inetpub/wwwroot/admin-tool/ folder. I'm almost there, but I want it to unzip and dump all the contents in here. This should be automatic, shouldn't it?
My dotnet publish looks like this:
and cause this to run, which is how I get the s.zip:
C:\Program Files\dotnet\dotnet.exe publish C:\agent\_work\3\s\Angular.AdminTool.csproj -c release --output C:\agent\_work\3\a\s
If I try to edit the -o argument and make it -o $(Build.ArtifactStagingDirectory)/admin-tool I will just end up with C:\agent\_work\3\a\admin-tool\s.zip
Is getting the name of my zip to be the same as the name of my web-site (admin-tool) the key to getting the zip to automatically extract in the release step?
In case it help others, I used the simple command line tools rather than the pre-canned "dotnet core" ones:
and for the Archive files task, be sure to include a hard-coded name for the zip to be used in the build process:
And for the release, in the "Deploy IIS App" task, be sure to include the full path for the zip file:
I also ran into this issue but solved it another way.
In my case I have a single project to build and deploy.
The $(Parameters.RestoreBuildProjects) value is set to a single project
MyProjectFolder/MyProject.csproj.
In the .Net Core Publish task, this value is used in the Path to Project(s) field.
Then I tick both the boxes for
I saved and queued this pipeline.
The zip file created seems to be derived from the name of the folder
so I ended up with a zip file in the artifact staging directory with the name of the project. Then the Publish Artifact task placed this zip file into the Artifact that is named in that task.

How To Run MSBuild scripts in .wixproj?

Im trying to learn to make a web installer using Windows Installer XML (WIX 3.5). I found this blog about using msbuild in .wixproj files to avoid the scenario where the installer ends up dropping the web project assemblies right in the root of the app instead of keeping them in the bin folder like they're supposed to be.
Here is the link to that:
<http://www.paraesthesia.com/archive/2010/07/30/how-to-consume-msdeploy-staged-web-site-output-in-a.aspx>
But after adding the MSBuild scripts in the .wixproj file, I don't know what to do anymore. According to the instruction after adding the MSBuild script:
"When that target runs, you'll see a .wxs file pop out in the .wixproj project folder. Add the generated .wxs to your .wixproj project so it knows to include it in the build."
I really don7t know what this means. How can I run the target? I tried to build it but there was no .wxs file generated in the .wixproj folder.
Am I missing something? Please help...
Assuming you have added the section from the tutorial:
<Target Name="BeforeBuild">
...
</Target>
The target will be run automatically when you build the project. The "BeforeBuild" target is one of the standard entry-points to add your own modifications to the build. The target will then generate a file (named [WebProjectName].wxs that is placed in the same directory as your wixproj file. Click on the show all files button in visual studio and right-click on the file and "Include in project" That will then include the wxs is your installer and when you next build it will have the correct folder/file structure.

Resources