I'm using msbuild to automatically build and package a website ready for deployment. When I compile and then Publish my project through Visual Studio 2008 everything works fine.
However when I use msbuild I'm getting errors because AspNetCompiler is trying to compile aspx and ascx files that are not included in my .csproj, but still exist in version control.
I know I can just remove them from version control, but can anyone tell me why these files are being compiled?
Here is my msbuild task.
<AspNetCompiler
TargetPath="$(PackageDir)\Web"
VirtualPath="/"
PhysicalPath="$(buildDirectory)\Web"
Force="true"
/>
Thanks!
The AspNetCompiler task, which wraps _aspnet_compiler.exe_, compiles all "compilable" files in the application, rather than compiling only those files in the .csproj.
The giveaway is that none of the command-line parameters for the executable take a .csproj as input, only paths. (I suppose one could argue that it would look for a .csproj in the directory, but that is unlikely as it would introduce its own set of issues, such as what to do if someone had put two project files in one directory.)
Related
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.
I have an ASP.NET web package deployment using Visual Studios 2012 in which I would like to copy off files before deployment and then copy them back once deployment is completed. These files happen to be under Content\upload. If I just deploy.cmd the files are deleted and so currently I need to copy them off manually and then copy them back once deployment is complete. I have tried several examples of similar situations for adding tasks to the Project file as well as extra files added to the project, such as:
Adding tasks inside targets I have created called Name="BeforePublish" Name="AfterPublish" in the Project file.
<Target Name="BeforePublish">
<Message Text="BeforePublish"/>
<Copy/>
</Target>
Adding file called ProjectName.wpp.targets and adding
<Project>
<Target Name="CopyMyFiles" BeforeTargets="BeforePublish">
<Message Text="CopyMyFiles called"/>
<Copy/>
</Target>
</Project>
Neither of these techniques seem to be called. Any other ideas? Where and how should I put these tasks?
You can actually solve this using a skip rule. Try calling your command file like this:
deploy.cmd -skip:objectName=dirPath,absolutePath=Content\\uploads$
For more information on the skip directive, see Web Deploy Operation Settings.
I'm using MSBuild to build a web application project and adding parameters to create the package file. All of that is good. I get two folders in the _PublishedWebSites output:
AppName
AppName_Package
In the ApplicationName folder, the entire site is there and I can simply copy this folder over to the website and it will run.
In the Package folder I've got the expected 5 files:
AppName.deploy.cmd
AppName.-readme.txt
AppName.SetParameters.xml
AppName.SourceManifest.xml
AppName.zip
When deploying the package however, the web application dll (AppName.dll) is missing, as are a few other important referenced dependencies.
Inspecting the package itself does reveal that the files are in fact missing from the web applications bin directory.
This is very odd, considering the files are all in the root AppName folder, but not in the package found in AppName_Package folder.
The only MSDeploy related modification I've made is that I am overriding the CopyAllFilesToSingleFolderForPackageDependsOn target to copy in some handlers from a library project, and this all works nicely.
<PropertyGroup>
<CopyAllFilesToSingleFolderForPackageDependsOn>
CustomCollectFiles;
$(CopyAllFilesToSingleFolderForPackageDependsOn);
</CopyAllFilesToSingleFolderForPackageDependsOn>
</PropertyGroup>
<Target Name="CustomCollectFiles">
<ItemGroup>
<_CustomFiles Include="..\Libraries\CodeLibrary1\**\*.ashx" />
<FilesForPackagingFromProject Include="%(_CustomFiles.Identity)">
<DestinationRelativePath>$(ProjectDir)%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
</FilesForPackagingFromProject>
</ItemGroup>
</Target>
So, I'm not able to determine why the web application's DLL, and only a few other (referenced)DLLs are removed from the bin directory during the package creation process (but not all - maybe 3%).
Any ideas what I should be looking for in the log file?
EDIT: (Response to Sayed):
I truly appreciate you answering my post. Unfortunately I’m not sure we are on the same page. Like I said, I might not have explained my problem well enough to actually clue others in on exactly what my issue is. Let me try once more to clarify
Getting external files copied into my web application was not the problem. I understand that scanning over my post and seeing the all too common “CopyAllFilesToSingleFolderForPackageDependsOn” element set off a few red flags, alarms, bells and whisles. . It seems to be a common thing people are struggling with, and as you point out, there have been some issues with it being executed. That worked OK for me.
My problem has more to do with project referenced DLLs, AND most importantly the application DLL itself not being copied.
More tweaking around today has revealed something I was not aware of. For instance:
Kicking off a Build on TFS outputs a couple things:
The source from TFS is output to the Source Directory (SourceDir)
This only contains the output what is checked into TFS
This does not include project or file references, only what is committed in TFS
The output of the build is into two folders
Binaries (includes project and file references)
Sources (only what is included/committed in TFS)
Inside Binaries I find the _publishedWebsites folder, as well as all project and file references, while inside Sources there are just the files that are checked into TFS.
My problem, or confusion, was thinking that when I pass in the following parameters to MSBuild Arguments, it would take the output from the build (_PublishedWebsites) and use those files to create the package. It does not do that.
The actual process builds a package based on the files in the SOURCES folder. So, here is my dilemma/confusion, because I did not commit my application dll into source, it was not being included in the package, and therefore was not being sent off to the test site on the test server.
/p:DeployOnBuild=True /p:DeployTarget=MsDeployPublish /p:CreatePackageOnPublish=True /p:MSDeployPublishMethod=RemoteAgent /p:MSDeployServiceUrl=http://<mytestsite> /p:DeployIisAppPath="<AppName>" /p:UserName=<domain\user> /p:Password=<mypassword> /p:SkipExtraFilesOnServer=false /p:AllowUntrustedCertificate=True
To wrap this up, once I “checkout for edit” my application DLL on my dev machine, and them compile the solution, and finally commit the application DLL to source control, then it is included in the package because it is included as just another source item.
So, I guess this becomes my fault for not understanding how to get the output of the TFS BUILD into the sources folder, and get that included into the package used by msdeploy.
There is probably something very fundamental that I missed or just skimmed over - and not understood, that the package creation is from the Sources folder and not the _PublishedWebsites folder. Nor do I understand how to get the MSBuild compiled application dll, and project referenced dlls, into my package – replacing the committed source items in source control.
I hope this isn’t a complete waste of your time because I missed a
source=<some-parameter>
somewhere.
I appreciate it you can direct me to any existing sources out that already explain this to where I should be able to get my head around it and get this working. Or if it’s so easy to just tell me here.
The issue here is that the CopyAllFilesToSingleFolderForPackage target itself is not getting called from the VS2012 targets. We made a lot of changes and this may be a regression on our side. I will look into this to see if there is anything that we can do. Fortunately it should be pretty straight forward to update this to get the behavior that you are looking for. Instead of using CopyAllFilesToSingleFolderForPackageDependsOn you should be able to use PipelineCollectFilesPhaseDependsOn as an alternative. You should be able to change what you have above to
<PropertyGroup>
<PipelineCollectFilesPhaseDependsOn>
CustomCollectFiles;
$(PipelineCollectFilesPhaseDependsOn);
</PipelineCollectFilesPhaseDependsOn>
</PropertyGroup>
<Target Name="CustomCollectFiles">
<Message Text="Inside of CustomCollectFiles" Importance="high"/>
<ItemGroup>
<_CustomFiles Include="C:\Temp\_NET\WAP-AfterPublish\MvcApplication1\additional files\**\*" />
<FilesForPackagingFromProject Include="%(_CustomFiles.Identity)">
<DestinationRelativePath>additional files\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
</FilesForPackagingFromProject>
</ItemGroup>
</Target>
I just tried this for both VS2012 as well as VS2010 so this seems like a better to solution then the CopyAllFilesToSingleFolderForPackageDependsOn approach. Can you try that out and let me know what you find out?
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.
The following MSBuild invocation works great when used in an independent MSBuild project, LocalPublish.xml.
<MSBuild
Projects="MyProject.Web.csproj"
Targets="ResolveReferences;_CopyWebApplication"
Properties="WebProjectOutputDir=C:\Inetpub\MyProject\Website;OutDir=C:\Inetpub\MyProject\Website\bin\" />
In the past, we have invoked it using a Post-build event command line:
$(MSBuildBinPath)\msbuild "$(ProjectDir)LocalPublish.xml"
However I'm now trying to integrate the same into the AfterBuild event of MyProject.Web.csproj, and it fails to copy referenced project DLLs into the bin folder of the publish path. I tried adding BuildingProject=true to the Properties attribute as suggested here but it does not seem to make a difference.