We have an internal NuGet Package that consists of some .NET Code and a TypeScript Definition File (*.d.ts). This is the content of the package:
After installing the package into a new .NET Core project, the folder structure in the solution explorer looks like this.
So far, everything went as expected. But note the small arrow symbols on the "i18n" folder and the "Index.d.ts" file. It looks like they're just links to the actual file. When I click on the d.ts file the content seems correct. But Visual Studio fails to recognize the declarations in it, so I can't use it in my TypeScripts.
One idea was to include the path to the packages in the tsconfig.json, but that can't be the solution... Any other ideas how to do that?
How to add TypeScript Definitions to .NET Core Nuget Packages
As far as I know, Definitely Typed packages are not compatible with .NET Core projects. That because the script files should be included in <contentFiles> element. You can refer to the Including content files for more detail info.
Besides, just as Martin comment, npm is the recommended method of installing Definitely Typed packages:
https://github.com/DefinitelyTyped/DefinitelyTyped#how-do-i-get-them
So, after seeing the replies here and not giving up, I have to put in my approach to this.
As I'm working on a large solution with over 100 subprojects - many of them fast moving NuGets, I couldn't give up. I wanted to have my .NET object models including their interface/class representations in TS, being able to have both imported by including one NuGet (and thereby reduce dependency hell a little bit). I have to mention, I tested this only with my own object model, which has no external dependencies - and I tested only on VS2022.
But in this restricted scenario it works without any issues.
On the project containing the TS definitions
Set the build action for the ts definitions you need to be included in the NuGet to "content". This will include them into the NuGet package.
On the consumer side
Adjust your package reference, add the following property/value:
<GeneratePathProperty>True</GeneratePathProperty>
This will create an MsBuild property/variable referencing the path to the local presence of the restored NuGet file (important if your building on multiple, different machines - like on CI pipelines, build servers etc.) and allowing you to avoid any hardcoded absolute paths.
The generated property has the following format
$(Pkg<PackageNameWithDotsBeingReplacedByUnderlines>)
So a package named "MyPackage.Hello" would result in the variable $(PkgMyPackage_Hello)
Now we create a new build target to copy the files from the restored package's contentfiles folder (as it's restored, and we have the restored and thereby extracted path, we can finally target them).
<Target Name="CopyImportedTypes" BeforeTargets="Build">
<ItemGroup>
<TsTypesToCopy Include="$(PkgMyPackage_Hello)\contentFiles\any\net6.0-windows10.0.20348\*.ts" />
</ItemGroup>
<Copy SourceFiles="#(TsTypesToCopy)" DestinationFolder="$(MSBuildProjectDirectory)\AnyProjectSubFolderIfDesired" SkipUnchangedFiles="true" OverwriteReadOnlyFiles="true" />
</Target>
Make sure to adjust the "Include" path to your package (TFM, Platform etc.). An easy way to get the relative path is to open up the solution explorer, expand your consuming project, expand dependencies and then packages, expand the package with your ts definitions and open up the properties of the contentfiles.
This target is being executed before the actual build (so we can use the imported types on the build being happening right this moment) (BeforeTargets property). The ItemGroup is nothing else than a definition of items (in our case, source files) we want to use, being stored into #(TsTypesToCopy) which is being used by the copy task.
Thankfully, VS does automatically set new files to the right build action (in most cases), so the brand new ts files should be in the right mode automatically - so we don't have to tweak anything manually.
I have a solution where there is a dependency on 7zip's sfx. Out of desire to keep the entire solution (plus the sfx) managed and coordinated, I want to create a new project to house all the source files that is used by sfx, and when building, execute a command line that tells 7zip to build a sfx from the source files, and place into the output so that it can be then referenced by actual Visual Studio projects within the same solution.
I think I can figure the command line by using Build events and providing the appropriate macros to ensure that the 7zip's output is placed into the target folder with appropriate name so that it can be then correctly referenced by other VS projects. But what I am not sure about is what Visual Studio project I need to use or steps to take to tell Visual Studio that there isn't going to be any code to be compiled in this project and it just has to execute this script I give it.
The closest thing I can come up with is VS's Make project but I don't know if that is the right thing since this has nothing to do with Make at all.
So, what is the Visual Studio project template I need to use? If empty, then what configuration do I need to perform so that it won't try and look for some code files to compile but instead just execute scripts as part of the solution's build?
For now, it seems that using C++ Makefile Project works. I had to make few configurations:
1) I had to specify the project's "Configuration Type" as "Utility"
2) I used Pre-Build event and provided a command to invoke a batch file included in the project. The batch file then takes care of everything.
3) Normally, non C++ files are not considered for determining whether build is needed or if it's already up to date. To ensure that a new build is perform if the batch file or other key files are edited, I set the file's "File Type" to "MakeFile". Even though it isn't actually a Make file, it ensures that any edits made to the file will cause a new build.
The downsides I've found so far are:
1) C++ uses "Filters", not folders. Therefore, keeping the files in same directory structure is a big PITA. One can "include" files and get a one-to-one mapping between "Filters" and the actual directory structure on disk but it's annoying and tedious. Wish it was a C# project
2) I'm a bit wary about how it will detect new files or other changes for files that I didn't explicitly set to "MakeFile". I expect the source to be stable but I worry that when I realize I need a new file and add it, I might forget and not notice that the build is not correctly including the new file.
I'm not sure if this is the best method but this works for my purpose - having a project to manage external tools as part of bigger build process.
How specifically should my command line be written as to copy the output from one project into the output of another project? The list of macros that are avaliable does not list anyway of accessing OTHER project directories under the same solution:
http://msdn.microsoft.com/en-us/library/42x5kfw4(v=vs.80).aspx
Here is what I currently have:
copy "$(TargetDir)FILE_TO_MOVE.EXE" ""
What should I put in the second quote to complete this command?
NOTE: A similar question does NOT actually show you HOW to do it, which is what I am asking: Visual Studio 2008: How do I include project output as an embedded resource in another project?
It is much easier to do it the other way around, have the project that has the dependency on the file also copy the file. Which you can do in the IDE without pre/post buid event or macro trickery.
Ensure the source project is built. Right click the target project, Add Existing Item and select the file. Click the added file in the Solution Explorer window and set the properties to Build Action = Content, Copy to Output Directory = Copy if newer. And right-click the target project, Project Dependencies, tick the source project to ensure that it always gets built first.
I am assuming that yout are copying the "FILE_TO_MOVE.EXE" in the post build events of your project.
The thing about the build events in Visual Studio is that they are run just like a batch file, therefore I beileve that the easiest way to solve your problem is to use a system environment variable in your project... This way your code would be similar to the one below.
copy "$(TargetDir)FILE_TO_MOVE.EXE" "$(MyVariable)"
Note: Visual Studio doesn't let you use your environment variable like this: %MyVariable%.
I think the correct way now would be to simply add your secondary project, i.e a Windows Service, to the References of the main project.
For example if you have a main GUI project (that the solution was created with), and a second Service project added to the solution, adding it to References of the GUI project will cause the EXE and the PDB of the service to be placed in the Debug/Release folder of you main project.
I am not sure if you still need to add the Project Dependancy as Hans suggested . This is probably automatic thanks to the reference.
I have two projects in one Visual Studio 2008 solution. I'd like to use the primary output from one of the projects as an embedded resource in the other, but for the life of me I can't find any way to accomplish this.
If I simply add the output file as a resource, then it doesn't seem to change when its source project is rebuilt. I even have the project dependencies/build order set up properly and this does not seem to help.
Anyone have any hints for me?
Thanks!
the best option is to "reference" the other project as if it were a class library.
that way you make sure the whole references tree is copied to your output dir.
When you add an existing file to a project, Visual Studio copies the file into the project's directory.
Any subsequent changes to the original file are ignored.
There are two workarounds:
Add a post-build action to the first project that copies its output file to the second project, and edit the dependencies so that the first project is always built first.
Add the output file to the second project as a link (Click the down arrow next to the Add button in the open dialog).
This will reference the file from its original location without making any copies.
Set the output directory of the project that generates the resource to point to the resource directory in the project that uses it.
If that's not possible for some reason, use a post-build command (also available in the project settings) to copy the file there.
I have four projects in my Visual Studio solution (everyone targeting .NET 3.5) - for my problem only these two are important:
MyBaseProject <- this class library references a third-party DLL file (elmah.dll)
MyWebProject1 <- this web application project has a reference to MyBaseProject
I added the elmah.dll reference to MyBaseProject in Visual studio 2008 by clicking "Add reference..." → "Browse" tab → selecting the "elmah.dll".
The Properties of the Elmah Reference are as follows:
Aliases - global
Copy local - true
Culture -
Description - Error Logging Modules and Handlers (ELMAH) for ASP.NET
File Type - Assembly
Path - D:\webs\otherfolder\_myPath\__tools\elmah\Elmah.dll
Resolved - True
Runtime version - v2.0.50727
Specified version - false
Strong Name - false
Version - 1.0.11211.0
In MyWebProject1 I added the reference to Project MyBaseProject by:
"Add reference..." → "Projects" tab → selecting the "MyBaseProject". The Properties of this reference are the same except the following members:
Description -
Path - D:\webs\CMS\MyBaseProject\bin\Debug\MyBaseProject.dll
Version - 1.0.0.0
If I run the build in Visual Studio the elmah.dll file is copied to my MyWebProject1's bin directory, along with MyBaseProject.dll!
However if I clean and run MSBuild for the solution (via D:\webs\CMS> C:\WINDOWS\Microsoft.NET\Framework\v3.5\MSBuild.exe /t:ReBuild /p:Configuration=Debug MyProject.sln)
the elmah.dll is missing in MyWebProject1's bin directory - although the build itself contains no warning or errors!
I already made sure that the .csproj of MyBaseProject contains the private element with the value "true" (that should be an alias for "copy local" in Visual Studio):
<Reference Include="Elmah, Version=1.0.11211.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\mypath\__tools\elmah\Elmah.dll</HintPath>
**<Private>true</Private>**
</Reference>
(The private tag didn't appear in the .csproj's xml by default, although Visual Studio said "copy local" true. I switched "copy local" to false - saved - and set it back to true again - save!)
What is wrong with MSBuild? How do I get the (elmah.dll) reference copied to MyWebProject1's bin?
I do NOT want to add a postbuild copy action to every project's postbuild command! (Imagine I would have many projects depend on MyBaseProject!)
I just deal with it like this. Go to the properties of your reference and do this:
Set "Copy local = false"
Save
Set "Copy local = true"
Save
and that's it.
Visual Studio 2010 doesn't initially put:
<private>True</private> in the reference tag and setting "copy local" to false causes it to create the tag. Afterwards it will set it to true and false accordingly.
I'm not sure why it is different when building between Visual Studio and MsBuild, but here is what I have found when I've encountered this problem in MsBuild and Visual Studio.
Explanation
For a sample scenario let's say we have project X, assembly A, and assembly B. Assembly A references assembly B, so project X includes a reference to both A and B. Also, project X includes code that references assembly A (e.g. A.SomeFunction()). Now, you create a new project Y which references project X.
So the dependency chain looks like this: Y => X => A => B
Visual Studio / MSBuild tries to be smart and only bring references over into project Y that it detects as being required by project X; it does this to avoid reference pollution in project Y. The problem is, since project X doesn't actually contain any code that explicitly uses assembly B (e.g. B.SomeFunction()), VS/MSBuild doesn't detect that B is required by X, and thus doesn't copy it over into project Y's bin directory; it only copies the X and A assemblies.
Solution
You have two options to solve this problem, both of which will result in assembly B being copied to project Y's bin directory:
Add a reference to assembly B in project Y.
Add dummy code to a file in project X that uses assembly B.
Personally I prefer option 2 for a couple reasons.
If you add another project in the future that references project X, you won't have to remember to also include a reference to assembly B (like you would have to do with option 1).
You can have explicit comments saying why the dummy code needs to be there and not to remove it. So if somebody does delete the code by accident (say with a refactor tool that looks for unused code), you can easily see from source control that the code is required and to restore it. If you use option 1 and somebody uses a refactor tool to clean up unused references, you don't have any comments; you will just see that a reference was removed from the .csproj file.
Here is a sample of the "dummy code" that I typically add when I encounter this situation.
// DO NOT DELETE THIS CODE UNLESS WE NO LONGER REQUIRE ASSEMBLY A!!!
private void DummyFunctionToMakeSureReferencesGetCopiedProperly_DO_NOT_DELETE_THIS_CODE()
{
// Assembly A is used by this file, and that assembly depends on assembly B,
// but this project does not have any code that explicitly references assembly B. Therefore, when another project references
// this project, this project's assembly and the assembly A get copied to the project's bin directory, but not
// assembly B. So in order to get the required assembly B copied over, we add some dummy code here (that never
// gets called) that references assembly B; this will flag VS/MSBuild to copy the required assembly B over as well.
var dummyType = typeof(B.SomeClass);
Console.WriteLine(dummyType.FullName);
}
If you are not using the assembly directly in code then Visual Studio whilst trying to be helpful detects that it is not used and doesn't include it in the output. I'm not sure why you are seeing different behaviour between Visual Studio and MSBuild. You could try setting the build output to diagnostic for both and compare the results see where it diverges.
As for your elmah.dll reference if you are not referencing it directly in code you could add it as an item to your project and set the Build Action to Content and the Copy to Output Directory to Always.
Take a look at:
This MSBuild forum thread I started
You will find my temporary solution / workaround there!
(MyBaseProject needs some code that is referencing some classes (whatever) from the elmah.dll for elmah.dll being copied to MyWebProject1's bin!)
I had the same problem.
Check if the framework version of your project is the same of the framework version of the dll that you put on reference.
In my case, my client was compiled using "Framework 4 Client" and the DLL was in "Framework 4".
The issue I was facing was I have a project that is dependent on a library project. In order to build I was following these steps:
msbuild.exe myproject.vbproj /T:Rebuild
msbuild.exe myproject.vbproj /T:Package
That of course meant I was missing my library's dll files in bin and most importantly in the package zip file. I found this works perfectly:
msbuild.exe myproject.vbproj /T:Rebuild;Package
I have no idea why this work or why it didn't in the first place. But hope that helps.
I just had the exact same problem and it turned out to be caused by the fact that 2 projects in the same solution were referencing a different version of the 3rd party library.
Once I corrected all the references everything worked perfectly.
As Alex Burtsev mentioned in a comment anything that’s only used in a XAML resource dictionary, or in my case, anything that’s only used in XAML and not in code behind, isn't deemed to be 'in use' by MSBuild.
So simply new-ing up a dummy reference to a class/component in the assembly in some code behind was enough convince MSBuild that the assembly was actually in use.
Using deadlydog's scheme,
Y => X => A => B,
my problem was when I built Y, the assemblies (A and B, all 15 of them) from X were not showing up in Y's bin folder.
I got it resolved by removing the reference X from Y, save, build, then re-add X reference (a project reference), and save, build, and A and B started showing up in Y's bin folder.
Changing the target framework from .NET Framework 4 Client Profile to .NET Framework 4 fixed this problem for me.
So in your example: set the target framework on MyWebProject1 to .NET Framework 4
I had the same problem and the dll was a dynamically loaded reference.
To solve the problem I have added an "using" with the namespace of the dll.
Now the dll is copied in the output folder.
This requires adding a .targets file to your project and setting it to be included in the project's includes section.
See my answer here for the procedure.
Referencing assemblies that are not used during build is not the correct practice. You should augment your build file so it will copy the additional files. Either by using a post build event or by updating the property group.
Some examples can be found in other post
MSBuild to copy dynamically generated files as part of project dependency
VS2010 How to include files in project, to copy them to build output directory automatically during build or publish
Another scenario where this shows up is if you are using the older "Web Site" project type in Visual Studio. For that project type, it is unable to reference .dlls that are outside of it's own directory structure (current folder and down). So in the answer above, let's say your directory structure looks like this:
Where ProjectX and ProjectY are parent/child directories, and ProjectX references A.dll which in turn references B.dll, and B.dll is outside the directory structure, such as in a Nuget package on the root (Packages), then A.dll will be included, but B.dll will not.
I had a similar issue today, and this is most certainly not the answer to your question. But I'd like to inform everyone, and possibly provide a spark of insight.
I have a ASP.NET application. The build process is set to clean and then build.
I have two Jenkins CI scripts. One for production and one for staging. I deployed my application to staging and everything worked fine. Deployed to production and was missing a DLL file that was referenced. This DLL file was just in the root of the project. Not in any NuGet repository. The DLL was set to do not copy.
The CI script and the application was the same between the two deployments. Still after the clean and deploy in the staging environment the DLL file was replaced in the deploy location of the ASP.NET application (bin/). This was not the case for the production environment.
It turns out in a testing branch I had added a step to the build process to copy over this DLL file to the bin directory. Now the part that took a little while to figure out. The CI process was not cleaning itself. The DLL was left in the working directory and was being accidentally packaged with the ASP.NET .zip file. The production branch never had the DLL file copied in the same way and was never accidentally deploying this.
TLDR; Check and make sure you know what your build server is doing.
Make sure that both projects are in the same .net version also check copy local property but this should be true as default
Using Visual Studio 2015 adding the additional parameter
/deployonbuild=false
to the msbuild command line fixed the issue.
I just ran into a very similar issue. When compiling using Visual Studio 2010, the DLL file was included in the bin folder. But when compiling using MSBuild the third-party DLL file was not included.
Very frustrating. The way I solved it was to include the NuGet reference to the package in my web project even though I'm not using it directly there.
I dont think #deadlydog answer is valid with the current Nuget system. I recreated the scenario with Y => X => A => B in visual studio 2022 and all I had to do was run the command in terminal
msbuild -t:clean,rebuild,pack
Including all referenced DLL files from your projectreferences in the Website project is not always a good idea, especially when you're using dependency injection: your web project just want to add a reference to the interface DLL file/project, not any concrete implementation DLL file.
Because if you add a reference directly to an implementation DLL file/project, you can't prevent your developer from calling a "new" on concrete classes of the implementation DLL file/project instead of via the interface. It's also you've stated a "hardcode" in your website to use the implementation.