Where does Ionide + Fake put the output executable? - f#

I am trying to use .NET Core + Ionide + VS Code + Fake + Paket on macOS High Sierra.
Using the project generator, I have created a Suave application called Test. Ionide seems to have generated the appropriate files. After tweaking the TargetFramework to .NET Core, I can build successfully:
$ ./build.sh
...
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:03.72
Finished Target: Build
---------------------------------------------------------------------
Build Time Report
---------------------------------------------------------------------
Target Duration
------ --------
Clean 00:00:00.0026904
InstallDotNetCLI 00:00:01.2292511
Restore 00:00:04.2731055
Build 00:00:07.1234434
Total: 00:00:12.7035334
---------------------------------------------------------------------
Status: Ok
---------------------------------------------------------------------
There are now some files in Test/bin, but none of them are .exe, which is what I would expect as output from fsharpc.
Where does Ionide + Fake put the output executable?
My project has OutputType executable:
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Include="Test.fs" />
</ItemGroup>
<Import Project="..\.paket\Paket.Restore.targets" />
</Project>

.Net Core compiles all projects (even executable applications) to .dll not .exe that can be run with dotnet PATH_TO_DLL. In the bin folder, in the subfolder for given framework target there should be file YOUR_PROJECT_NAME.dll that can be run with dotnet CLI.

To generate an exe you need to supply a run-time identifier. You can include this in the fsproj with
<PropertyGroup>
<RuntimeIdentifiers>win10-x64</RuntimeIdentifiers>
</PropertyGroup>
but you don't need to do that. You can use VSCode's tasks.json file to set up a build task.
My suggestion is just to run the dotnet CLI:
dotnet build -c Release -r win10-x64
This will create an exe in the bin\release\netcoreapp2.0\win10-x64 folder. You can also dotnet publish if you want a self-contained directory to deploy (this can get large). The id for OSX will be something like osx-x64.
By default ionide generates an fsproj file that is targetting net461, and you might also need Fake 5 for dotnetcore. I also suggest you use paket in magic-mode, and commit the .exe to github (if you use git).

Related

Dotnet command failed with non-zero exit code on the following projects :

I am trying to build on TFS an API which contains several projects in dotnet.core3.1
When I run the dotnet build Api.sln command on TFS here is the result
[error] Dotnet command failed with non-zero exit code on the following projects: D: \ TFS \ Agent01 \ _work \ 18 \ s \ PMTApi.sln
Context:
TFS 2017
Dotnet Core 3.1 projects
Source code management on TFS git
Agents unable to connect to the outside (internet)
The dependency imports are done from a private server thanks to the NuGet.Config file set up to redirect the dependency imports not on the https://api.nuget.org/v3/index.json server but well on that of our private company.
Explanation:
On the TFS git source manager, the PMTApi.sln project contains 7 .csproj files
But in the PMTApi.sln file there are only 4 .csproj which are included
Local result:
Is good dotnet build completes the 5 successful projects.
Result on TFS:
Not good.
[error] Dotnet command failed with non-zero exit code on the following projects: D: \ TFS \ Agent01 \ _work \ 18 \ s \ PMTApi.sln
Observation:
I have the impression that TFS is based on all the .csproj files from the TFS git source manager and not from PMTApi.sln
Conclusion the projects which are not referenced in PMTApi.sln still try to restore the dependencies which causes the top error.
Test:
I tried to exclude these 3 .csproj projects in my NuGet.Config file like this, but it doesn't work
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="XXX NuGet Packages" value="http://privateServer/nuget" />
</packageSources>
<ItemGroup>
<ProjectReference Exclude="..\folderName1\projectName1.csproj" />
<ProjectReference Exclude="..\folderName2\projectName2.csproj" />
<ProjectReference Exclude="..\folderName3\projectName3.csproj" />
</ItemGroup>
</configuration>
Do you have any ideas for a successful dotnet build task?
The construction:
TFS Return:
Local configuration:
1- here you have to right click on the solution
2- manage package Nuget for solution
3- add the url of your private server
4- and uncheck the server of api.NuGet.org
for my case I also uncheck the visual studio packages
You should specify the csproj file(s) to use in the Project(s) argument, not sln file. Check the description of this argument:
The path to the csproj file(s) to use. You can use wildcards (e.g.
**/*.csproj for all .csproj files in all subfolders). This field follows glob pattern, and is run against root of the repository at all
times irrespective of Working Directory.
https://learn.microsoft.com/en-us/azure/devops/pipelines/tasks/build/dotnet-core-cli?view=azure-devops

MSbuild error while chekout : exited with code 9009

I am try to chekout my file from TFS using MSBuild script. But I am getting "exited with code 9009"
My code is bellow :
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
<PropertyGroup>
<TfCommand>
"C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\tf.exe"
</TfCommand>
</PropertyGroup>
<Target Name="Build">
<Exec Command="$(TfCommand) checkout "$/ApplicationSharedServices/release/dev_branch/renderer/bin/MIME.dll""/>
</Target>
</Project>
As per Just TFS's answer, you need to be in the folder that is in your workspace before you run TF. it might work fine with VS but with MSBuild pure you need to be in the folder. Now you technically don't need to put the full path when doing the get then. just MIME.dll.
Just out of curiosity, why are you running an MSBuild TF get command? is this in you automated build? You should start using PowerShell and run a pre-build script to get the info you need. You could also use Nuget with package restore to get any DLLs needed for compilation.
Cheers,
ET

Adding files to the bin directory at Build and Publish

I have two license files that I would like to include in my \bin directory both when I build and publish.
Both files are in the App_Data directory (their initial location doesn't matter, they just need to end up in the \bin) and have the following properties set:
Build Action = Content
Copy to Output Directory = Copy Always
They are in not the \bin when I build or publish.
What is wrong with my setup: the settings, the folders, the files, something else...?
UPDATE
I moved the files out of the App_Data directory and placed them in the project root and now they are copied to the \bin on build.
I've done this in a few projects by expanding my .csproject file slightly. The following code should be put directly beneath the Project node in your WebProject.csproj.
The AfterBuild target simply copies a set of files ("unreferenced DLLs" in this case) to the bin-folder when building normally from Visual Studio. The CustomCollectFiles basically do the same thing when deploying.
<PropertyGroup>
<UnreferencedDlls>..\lib\Unreferenced\**\*.dll</UnreferencedDlls>
</PropertyGroup>
<PropertyGroup>
<CopyAllFilesToSingleFolderForPackageDependsOn>
CustomCollectFiles;
$(CopyAllFilesToSingleFolderForPackageDependsOn);
</CopyAllFilesToSingleFolderForPackageDependsOn>
</PropertyGroup>
<Target Name="AfterBuild">
<Message Text="Copying unreferenced DLLs to bin" Importance="High" />
<CreateItem Include="$(UnreferencedDlls)">
<Output TaskParameter="Include" ItemName="_UnReferencedDLLs" />
</CreateItem>
<Copy SourceFiles="#(_UnReferencedDLLs)" DestinationFolder="bin\%(RecursiveDir)" SkipUnchangedFiles="true" />
</Target>
<Target Name="CustomCollectFiles">
<Message Text="Publishing unreferenced DLLs" Importance="High" />
<ItemGroup>
<_CustomFiles Include="$(UnreferencedDlls)" />
<FilesForPackagingFromProject Include="%(_CustomFiles.Identity)">
<DestinationRelativePath>bin\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
</FilesForPackagingFromProject>
</ItemGroup>
</Target>
The part you need to modify is basically the UnreferencedDlls node to match your folder structure. The **\*.dll part simply means "every DLL file at any level beneath here".
If you're using Visual Studio:
Show your file properties (Click on your file or Right-click on it then choose Properties)
At the Copy to Output Directory property choose Copy always or Copy if newer.
At build time, the file is going to be copied at the bin directory: Debug or Release...
not necessarily a direct answer, but I highly suggest not using the baked in "publish" mechanism, but rather wire up a build script (probably in powershell) that will do everything you need. It's really easy to hook into MSBuild as well as nUnit and also copy files and move them around.
POWERSHELL (rough) example.
# Get Directory Location
$invocation = (Get-Variable MyInvocation).Value
$directorypath = Split-Path $invocation.MyCommand.Path
# Build the application using MSBuild
cmd /c C:\Windows\Microsoft.NET\Framework\$v4_net_version\msbuild.exe "$directorypath\MyProject.sln" /p:Configuration=Release
# Run the tests using nUnit
cmd /c $directorypath\build\nunit\nunit-console.exe $solutionPath\MyProject.Tests\bin\debug\MyProject.Tests.dll
# Copy the license to the appropriate directory
Copy-Item -LiteralPath "$directorypath\mylicensefile.txt" "$directorypath\bin\release" -Force
# NOTE: You are going to have to adjust this to match your solution and projects.
In this post on Microsoft Connect the answer is much simpler:
Referenced assemblies in Unit Test are not copied in TestResults/Out
So what I did was the following:
[TestClass]
[DeploymentItem("Some.dll")]
public class SomeTests
{
...
}
It works fine for me.
Hope it help.

Use MSDeploy to copy buildresult to targetserver

There is a webproject with a batchfile that generates all files needed on the targetserver and puts them in a folder "/Deployable" .
The batch file is quite involved because the project contains a pluginsystem and all plugins need to be copied to a certain location.
When I use webdeploy to deploy to the targetserver it happens what you expect: there are some of the needed assemblies copied over, but not the files as specified in the batchfile.
My plan is now to first execute the batchfile and then use webdeploy to copy the folder "/Deployable" to the targetserver. Can this be done with webdeploy?
This is what I see in Visual Studio deploy menue:
This is the resulting publish profile
<?xml version="1.0" encoding="utf-8"?> <publishData>
<publishProfile publishUrl="http://myserver/msdeployagentservice"
deleteExistingFiles="False"
ftpAnonymousLogin="False"
ftpPassiveMode="True"
msdeploySite="mysite/"
msdeploySiteID=""
msdeployRemoteSitePhysicalPath=""
msdeployAllowUntrustedCertificate="False"
msdeploySkipExtraFilesOnServer="False"
msdeployMarkAsApp="False"
profileName="publish_to_myserver"
publishMethod="MSDeploy"
replaceMatchingFiles="True"
userName="myuser"
savePWD="True" userPWD="xxx" SelectedForPublish="True" />
</publishData>>
I think there is an ability to add third-party files into webdeploy package by modifying .csproj file, however, I have never had to use it.
Alternatively, you can easily achieve the same result by using MSDeploy's command-line client and its sync verb, by specifying your /Deployable folder as the -source argument and your target server's msdeploy service as the -dest, e.g.:
$(WebDeployToolPath)\msdeploy -verb:sync -source:dirPath='Deployable\' -dest:dirPath='$(DeployDirectoryLocalPath)',computerName=$(DeployTargetURL),userName='$(DeployUserName)',password='$(Password)',authType='Basic' -verbose -allowUntrusted
Substitutions:
$(WebDeployToolPath) - full path to folder with msdeploy executable (e.g. c:\Program Files (x86)\IIS\Microsoft Web Deploy V3\msdeploy.exe )
Deployable\ - full path to the folder you wnat to copy to the target server.
$(DeployDirectoryLocalPath) - full local path to the target folder on the target server.
$(DeployTargetURL) - web deploy service URL (e.g. https://192.168.142.55:8172/MsDeploy.axd or http://myserver/msdeployagentservice)
$(DeployUserName) - username to be used for deployment (should be admin for Win 2003)
$(Password) - user's password.
That's it - this command will synchronize Deployable\ folder with $(DeployDirectoryLocalPath) folder (i.e. make the content exactly match).
You can wrap it into an msbuild target in your .csproj file:
<PropertyGroup>
<DeployTargetURL Condition="'$(DeployTargetURL)'==''">https://192.168.142.55:8172/MsDeploy.axd</DeployTargetURL>
<DeployUserName Condition="'$(DeployUserName)'==''">tergetServer\Administrator</DeployUserName>
<Password Condition="'$(Password)'==''">AdminPassword</Password>
<WebDeployToolPath Condition="'$(WebDeployToolPath)'==''">c:\Program Files (x86)\IIS\Microsoft Web Deploy V3\msdeploy.exe</WebDeployToolPath>
<Target Name="Deploy">
<Exec Command=""$(WebDeployToolPath)"\msdeploy -verb:sync -source:dirPath='Deployable\' -dest:dirPath='$(DeployDirectoryLocalPath)',computerName=$(DeployTargetURL),userName='$(DeployUserName)',password='$(Password)',authType='Basic' -verbose -allowUntrusted " />
</Target>
And than run it from the command-line in the following way:
%windir%\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe MyProject.proj /t:Deploy*

How do I build when Tfs Read-only files block assembly and config file updates (via ccnet)

What are the work-arounds for builds failing when moved to TFS because now each file is set to read-only?
Using CC.net, TFS2008 (TFS 2010 within 2 months), target framework 3.5, msbuild 3.5.
You can use an exec command to do this in the AfterGet target:
<PropertyGroup>
<MyProperty>D:\BuildSource</MyProperty>
</PropertyGroup>
....
<Exec Command="Attrib -r -s *.* /S /D" WorkingDirectory="$(MyProperty)" />

Resources