Why does MSBuild ignore ProjectReference Private=False if OutputPath is specified - reference

I have a project with a non-private ProjectReference item:
<ItemGroup>
<ProjectReference Include="..\..\RProcessConfig\RProcessConfig.csproj">
<Private>false</Private>
</ProjectReference>
</ItemGroup>
Using "C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\MSBuild\Current\Bin\Msbuild.exe" %cd%\Modules\AreaArithmetics\AreaArithmetics.csproj from the command line works like a charm. The dependency dll is not copied to the output directory and i am happy.
But if i use "C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\MSBuild\Current\Bin\Msbuild.exe" %cd%\Modules\AreaArithmetics\AreaArithmetics.csproj /p:OutputPath=%cd%\RProcessService\RProcessServiceCore\bin\publish\Modules to specify another output path than specified in AreaArithmetics.csproj, the <Private>false</Private> part seems to be ignored and my dependency appears in the output folder
The only difference between the two calls is that the second one specifies an OutputPath to MSBuild. How can this break Reference Configurations?

In this case OutputPath set via the CLI invocation is going to be a global property and thus also apply in all referenced project, so RProcessConfig.csproj will also build to the same output directory, the main project would not copy it, but it is already there.
Recent versions of MSBuild (16.8+) have a way to suppress the flowing of this global property by also passing -p:PassOutputPathToReferencedProjects=False as well (introduced by this PR).

Related

How do I copy my dll and other binaries from bin folder in asp.net website to azure devops pipeline

I just created an azure pipeline from bitbucket cloud and using the default generated yaml file, when i run the Run New pipeline, I am getting errors in VsBuild saying
Error CS0246: The type or namespace name 'RestSharp' could not be found (are you missing a using directive or an assembly reference?)
The RestSharp.dll is located in my bin folder in asp.net website.
Looking at the raw logs, it says
2020-07-10T03:35:57.7771564Z Considered "d:\a\1\s\mywebsite\Bin\RestSharp.dll", but it didn't exist.
2020-07-10T03:35:57.7772002Z For SearchPath "{TargetFrameworkDirectory}".
2020-07-10T03:35:57.7772374Z Considered "C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6\RestSharp.winmd", but it didn't exist.
2020-07-10T03:35:57.7772874Z Considered "C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6\RestSharp.dll", but it didn't exist.
...
However, when I build in VS 2019, there are no build errors, since I am referencing my dlls and binaries.
How do I fix this missing dlls or referenced binaries? If I need to copy files from bin folder to the build directory, how?
Error CS0246: The type or namespace name 'RestSharp' could not be found
Tested using .dll file path in bin folder as HintPath. I encountered the same issue.
It seems that the root cause of this issue is that the RestSharp.dll doesn't exist in the Bin folder at the time of reference.
This is my solution to solve this issue:
Step1: Add the package reference in Packages.config file.
For example:
<?xml version="1.0" encoding="utf-8"?>
<packages>
.....
<package id="RestSharp" version="106.11.4" targetFramework="net472" />
</packages>
Step2: Change the RestSharp HintPath in .csproj file. Since you add the package reference, you could directly get the RestSharp.dll in the package path.
For example:
<Reference Include="RestSharp">
<Private>True</Private>
<HintPath>..\packages\RestSharp.106.11.4\lib\net452\RestSharp.dll</HintPath>
</Reference>
Then the RestSharp.dll could be used in the build.
By the way, I recommend that you could turn them into packages, and restore them during build. Then you could get the dll files in the package path. This can avoid the error above.

How can I import a .props file that gets generated by a Target?

Background
I am attempting to build a C++ Visual Studio project. My project is Importing an MSBuild .targets file that specifies a single Target, "SetupConanDependencies". This Target uses the conan tool to install dependencies for a project based on a "conanfile.txt" file located in the project root directory.
The output of this Target consists of several files, including a "conanbuildinfo.props" property file. I can Import the generated .props file in my project in order to tell it how to resolve dependencies that have been installed via conan.
Here is a stripped down version of my Target definition (I have tested and verified that it does produce a "conanbuildinfo.props" file):
<Target Name="SetupConanDependencies"
Inputs="$(SolutionDir)conanfile.txt"
Outputs="$(OutDir).conan/conanbuildinfo.props"
BeforeTargets="ClCompile">
<Message Importance="High" Text="Installing project dependencies with conan..." />
<Exec Command="conan install $(ProjectDir)conanfile.txt --install-folder=$(OutDir).conan"/>
</Target>
For my question, the only relevant information is that I have a Target that is generating a .props property file. I would like to Import the generated property file in my project before building. However, I also want the Target to run automatically as part of the build process.
Question
I cannot simply Import the generated .props file inside the .targets file, because it has not yet been built by the Target.
<Import Project="$(OutDir).conan/conanbuildinfo.props"/>
<!-- Adding this line after my Target definition results in the following error, because
the file doesn't exist on disk at the time the .targets file is imported. -->
<!-- Error MSB4019 The imported project "D:\CustomBuildToolExample\Debug\.conan\conanbuildinfo.props" was not
found. Confirm that the path in the <Import> declaration is correct, and that the file exists on disk. -->
Furthermore, from my current understanding of MSBuild, .props files are supposed to be Imported before .targets files. This seems to imply that I cannot Import the .props file that gets created by my Target at all, because by the time the Target generates the .props file, the project has already imported all of the Properties it will use as part of the build process.
Is there a way to include a .props file that is generated by a Target, so that my project will use the properties defined in that .props file as part of its build process?

The target "PipelineTransformPhase" does not exist in the project

I'm trying to create an azure package via tfs build server.
my project is an Azure MVC web api project. when i trigger a build I get the error "The target "PipelineTransformPhase" does not exist in the project."
But I've added the Microsoft.WebApplication.targets file to the appropriate folder in my build server.
this is the line mentioned in my csproj file
Import Project="$(VSToolsPath)\WebApplications\Microsoft.WebApplication.targets" Condition="'$(VSToolsPath)' != ''" />
Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" Condition="'$(VSToolsPath)' == ''" />
even without condition I get the same error.
could someone help to resolve this issue .
many thanks in advance
First, read these SO posts, they might have your answer:
Package / Publish error on Azure
MSBuild target package not found
Is it possible that the .targets file was never found? (If you're on a machine without Visual Studio it won't be there). That would produce an error somewhat like:
The imported project
"...\WebApplications\Microsoft.WebApplication.targets" was not found.
Confirm that the path in the <Import> declaration is correct, and that
the file exists on disk.
I'll assume that isn't the problem. I would run the build with logging enabled and look at where your targets are coming from (or not coming from in this case). It might add some light to your problem. You can use the /fl switch something like my example below to get a detailed (not diagnostic -- which you could do) log from a build:
msbuild /fl /flp:logfile=<yourpath>\yourLog.log;verbosity=detailed
The lines you should be most interested in are around targets. Lines like
Target "Clean" in file "..." from project "..." (entry point): and
Overriding target "Clean" in project "..." with target "Clean" from project "..."

Visual Studio Express 2012 and Typescript output directory

I've successfully installed the typescript plugin into the VS.
I would like to change to compiled js files output directory. Currently the js files are being in the same directory with the ts files.
I found a solution that said I should install web essentials and with that I can modify the compiler settings. Unfortunately, the free VS express don't let me to install 3rdparty things. It's ok, but is there any other solution to change the output directory of js files?
In command line it IS a simple --out flag.
I'm not familiar with the limitations of Express, but here's how you do it in the Pro edition without Web Essentials:
Open up the .csproj file inside your project with your favorite text editor. Look for the property groups that look like:
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
...
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
...
</PropertyGroup>
and inside both of those add a property like so:
<TypeScriptOutDir>my/dir</TypeScriptOutDir>
If you open up C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v11.0\TypeScript\Microsoft.TypeScript.targets you can see how those properties map to the command line flags and how I figured it out.
Like I said I don't know Express and whether it places any limitations on modifying .csproj files so let me know if this works.
not need edit .csproj file, just go to project properties and set "Redirect JavaScript output to directory"
The TypeScript compiler has a flag to redirect output to a directory:
tsc --outDir "Path" app.ts
Finally, I've solved the problem.
The solution:
I added these lines into the csproj file:
<ItemGroup>
<TypeScriptCompile Include="$(ProjectDir)\**\*.ts" />
</ItemGroup>
<Target Name="BeforeBuild">
<Exec Command=""$(PROGRAMFILES)\Microsoft SDKs\TypeScript\tsc" #(TypeScriptCompile ->'"%(fullpath)" --outDir myoutputdirectory', ' ')" />
</Target>
I have this problem in typescript 1.8, after google a little I discovered that the following Output options in the typescript properties project page are incompatible.
If you select Combine Javascript output into file then if you
want to put the .js and .map file in other file, you must to put here
the directory, and do not select Redirect Javascript output
directory
In the other hand if you want to have individual .js files and move
them to a specific directory, then select Redirect Javascript
output directory and maintain deselected Combine Javascript
output into file
For example in my case I want to have a combined .js in a specific directory then may setting are as show in the picture:

InstallShield 2011 Standalone Builder does not include SetupPrerequisites required for .NET 3.5

The 2011 InstallShield Standalone Builder does not include the SetupPrerequisites required for .NET 3.5; when building with the Full installation, it completes successfully, but when building with the SAB, it gives the following set of errors:
ISDEV : error -1007: Cannot copy source 'c:\Program Files\InstallShield\2011 SAB\SetupPrerequisites\Microsoft .net\3.5\Full\dotnetfx35.exe' to target '[path]\Release\DiskImages\DISK1\ISSetupPrerequisites{2B692A0F-7172-44B2-B0CB-9991078AFD31}\dotnetfx35.exe'
ISDEV : error -5054: Could not determine the size of the file "[path]\Release\DiskImages\DISK1\ISSetupPrerequisites{2B692A0F-7172-44B2-B0CB-9991078AFD31}\dotnetfx35.exe"
ISDEV : error -1007: Cannot copy source 'c:\Program Files\InstallShield\2011 SAB\SetupPrerequisites\Microsoft .net\3.5\Full\Helper.exe' to target '[path]\Release\DiskImages\DISK1\ISSetupPrerequisites{2B692A0F-7172-44B2-B0CB-9991078AFD31}\Helper.exe'
ISDEV : error -5054: Could not determine the size of the file "[path]\Release\DiskImages\DISK1\ISSetupPrerequisites{2B692A0F-7172-44B2-B0CB-9991078AFD31}\Helper.exe"
It is somewhat strange that after not being able to copy (from SRC to DEST), it still tries to determine the file size of DEST!
But anyway, the root cause is that the "Microsoft .net" folder under SetupPrerequisites in the install directory (c:\Program Files\InstallShield\2011 SAB) is missing. It should have a folder "3.5", which should have a folder "Full", which should contain two files: dotnetfx35.exe and Helper.exe.
We have fixed this in our SAB installations by copying these files from the Full installation to the SAB installation.
Actually, we already had an InstallShield folder with the ISM in it, so we just created a SetupPrerequisites folder under there, put the same structure as should have been installed, and then added logic to the build such that if it sees this folder, it will copy everything in it down to the SAB install folder so that the build will succeed.
I'm answering my own question in the above paragraph; I wanted to put this out there for anyone else who might experience this issue.
Your observations are correct and I don't like the way InstallShield works ( by default ) as it encourages the magical (build) machine antipattern.
Instead, I prefer to edit the PRQ files and the ISM references to the PRQs ( ISSetupPrerequisites table, ISBuildSourcePath column ) and make everything use relative paths based on the ISPROJECTDIR path variable. I check then check all the PRQ files and redist files into my source control so that when my build pulls the tree everything can be found. This pattern can be made more complex if you are reusing redists across multiple builds but the concept is the same.

Resources