I have a solution with 20+ projects. Pretty much every project references two third party assemblies called foo.v.4.5.dll. I got a new version of the third party application today called foo.v.5.0.dll. I have to visit every project and change the references to the new assemblies. If they don't work well then I have to revisit and undo the change. This is time consuming and a pain.
Is there an easier way to do this? Are there any tools that can help me change the project references globally or is this the only way?
Each project has a .csproj file.
These files contains the references to the assemblies.
You can create a code to open all those files, search for the current assembly text and substitute for the new assembly text.
There goes an example:
<Reference Include="Autodesk.AutoCAD.Interop.Common, Version=18.1.0.0, Culture=neutral, PublicKeyToken=eed84259d7cbf30b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<EmbedInteropTypes>True</EmbedInteropTypes>
<HintPath>..\..\..\..\..\..\ObjectARX 2011\inc-win32\Autodesk.AutoCAD.Interop.Common.dll</HintPath>
</Reference>
So a XML parsing would be probably the best way
Related
I've got a plugin for a third party software, and I reference their assembly - let's call it Api.dll.
Each year, Api.dll is updated. I'd like to support versions from past years.
Since the assembly name is the same, I can't just add them all and use a compile time flag - I have to manually remove, add, rebuild.
How can I automate this build process better, so I can build all the versions that I need at the same time, pointing to the appropriate version of the same-named .dll?
I would do this with build configurations. If you create a config for each version, you can edit your csproj file like this:
<Reference Include="v1/Api.dll" Condition="'$(Configuration)'=='Release Api v1'" />
<Reference Include="v2/Api.dll" Condition="'$(Configuration)'=='Release Api v2'" />
<Reference Include="v3/Api.dll" Condition="'$(Configuration)'=='Release Api v3'" />
Doing this will change the library being referenced depending on the configuration.
Additionally, if you need specific code per version, you could add in some compilation symbols for each configuration and use #if ...
I'm converting my project from MVC 4 to MVC 5 (and .Net 4 to .Net 4.5.2, which is the real driver of the changes.)
When I run one of my pages I get this error (blank space added by me for easier reading)
[A]System.Web.WebPages.Razor.Configuration.HostSection cannot be cast
to [B]System.Web.WebPages.Razor.Configuration.HostSection.
Type A originates from 'System.Web.WebPages.Razor, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=31bf3856ad364e35' in the context
'Default' at location
'C:\windows\Microsoft.Net\assembly\GAC_MSIL\System.Web.WebPages.Razor\v4.0_1.0.0.0__31bf3856ad364e35\System.Web.WebPages.Razor.dll'.
Type B originates from 'System.Web.WebPages.Razor, Version=3.0.0.0,
Culture=neutral, PublicKeyToken=31bf3856ad364e35' in the context
'Default' at location
'C:\Windows\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET
Files\studentportal3g\2204bad2\aece9b3b\assembly\dl3\ad80387c\91adbf51_fc73d101\System.Web.WebPages.Razor.dll'.
When I first saw this is though, Ah easy! Not so much :)
I've gone over every project and made sure it's version is upgraded to MVC 5 which has the 3.0.0.0 version of System.Web.WebPages.Razor.dll.
Clean rebuild, still get the error. No problem , I'll delete the cached temp files.
Clean rebuild, still get the problem. I go back, manually check each version of System.Web.WebPages.Razor.dll, in the references of each project that has a reference to it. I check my folder where I copy dlls to make references to them manually, it's not there.
If my solution doesn't' contain a copy of the DLL or a reference to the DLL, and I've manually deleted the cache folders in 'C:\Windows\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET
Files\studentportal3g...
Where is the old bad dll coming from? How do I fix this error? How do I prevent it happening again?
Thanks,
Eric-
Visual Studio is a great tool, but it doesn't always make the right choices when it comes to upgrading dependencies, nor does it support every possible option available in MSBuild. Whenever you find yourself in a bind such as this you should manually review and (if necessary) edit your .csproj file in order to resolve it.
The problem isn't that your file exists in the GAC or that it has not been installed by NuGet, the issue is most likely that one of your project files still has a reference to the old version of System.Web.WebPages.Razor version 1.0.0.0, and you need to find all references to it and change them to 3.0.0.0 accordingly.
Right-click on your project node in Solution Explorer and click Unload Project.
Right-click the project node again and click Edit <projectName>.csproj.
Search the file for references to System.Web.WebPages.Razor and update the version and the HintPath accordingly (as shown below). Make sure the HintPath you use actually points to an existing file.
Repeat these steps for all dependent projects in the solution (and any that are in DLLs that are not part of the solution).
Old Reference
<Reference Include="System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Private>True</Private>
<HintPath>..\packages\Microsoft.AspNet.WebPages.1.0.20105.408\lib\net40\System.Web.WebPages.Razor.dll</HintPath>
</Reference>
Updated Reference
<Reference Include="System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Private>True</Private>
<HintPath>..\packages\Microsoft.AspNet.WebPages.3.0.0\lib\net45\System.Web.WebPages.Razor.dll</HintPath>
</Reference>
You should also go through the web.config and /Views/web.config files to ensure that they are not referencing any old versions of this assembly.
NOTE: If the above instructions don't solve your issue, the issue likely is outside of your solution. Most likely there is a 3rd party library that is referencing the old version of the file somewhere. If so, you could attempt to get an updated version of the DLL.
You may also want to check out this question.
It looks like the old DLL is in the Global Assembly Cache (GAC). The GAC is a place where you can store assemblies that can be referenced from several applications on the machine. Click here to read more about GAC.
Use the tool gacutil to update the assembly in the GAC.
The tool is located somewhere under "Microsoft SDKs" folder in Program Files. For me, it was located in
C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.1 Tools\
Open cmd and navigate to the place where gacutil i stored. Then use it like this:
gacutil.exe -i [path to your assebly] -f.
The -i parameter is for indicating where your assembly is located. The -f parameter is used to force an update of the assembly, if it was already there.
Example
Say your DLL is located in
C:\temp\System.Web.WebPages.Razor.dll
Then you would run gacutil.exe -i "C:\temp\System.Web.WebPages.Razor.dll" -f
I have a Visual Studio C# solution which consists of some projects. One of the projects needs to reference another project which is not part of the solution.
At the beginning I was referencing dlls:
<ItemGroup>
<Reference Include="ExternalProj1, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Proj1\ExternalProj1.dll</HintPath>
</Reference>
</ItemGroup>
However I must reference projects so that those will generate their dlls. In fact If I reference dlls and they have not been created, I need to build those projects separately.
However when referencing projects:
<ItemGroup>
<ProjectReference Include="..\..\Proj1\ExternalProj1">
<Project>{3341b552-a569-4313-aabc-34452fff60ac}</Project>
<Name>ExternalProj1</Name>
</ProjectReference>
</ItemGroup>
However when building the compiler cannot find those assemblies. The strange thing is that building process is reported as completed successfully but the error window reports one warning:
The referenced component ExternalProj could not be found.
So, what am I doing wrong? Thank you
I see you are using ProjectReference, which is what I'm familiar with in plain (non-NET) C++ projects. The Include attribute needs to name the file, not just the base name; e.g.
<ProjectReference Include="..\..\Proj1\ExternalProj1.vcxproj">
That is, ProjectReference is not Reference. See Common MSBuild Project Items
Also, the metadata that determines whether to link the LIB automatically is determined via the supplied props files if it is not specified for that item. Is a managed project even producing a LIB? So this should (with the filename correct) cause the nominated project to be built also as a dependent, doing something with its products is another issue altogether.
Try building from MSBuild.exe command line, not the IDE, to see the pure behavior before the IDE messes things up or adds more issues to figure out. And, feed it the specific proj file you are wanting, not the "solution" file. The .sln file is a strange beast and not only is it possible to have project references not present in the sln, there is no inherent concept of a sln file at all. Other than a list of projects to show in the IDE, it is a magic file converted into a master proj on the fly that lets you name various targets individually without having to know which proj file (or the path to it) which is handy enough, but mainly there for compatibility with VSBuild according to The Books. So avoid it, at least to simplify things to get the behavior you want during the exploration stage. Then add any complications back in if you still want them :) .
I have various projects which reference assemblies within C:\Program Files (x86). I have installed the assemblies on my build controller in the exact same way and the files are in the C:\, however whenever I trigger a build my controller doesn't find the assemblies.
<Reference Include="GrapeCity.ActiveReports.Diagnostics.v7, Version=7.0.6163.0, Culture=neutral, PublicKeyToken=..., processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
</Reference>
The reference in the project looks like the above, which in my opinion I can understand why the build controller can't find the reference because there are no hint paths.
I have tried changing Copy Local to true and Specific Version to false, this also didn't work. What should I change in my project, build controller or build definition to make the server have scope of the assemblies?
So one way to solve this is to not reference from the GAC.
<Reference Include="GrapeCity.ActiveReports.Diagnostics.v7, Version=7.0.6163.0, Culture=neutral, PublicKeyToken=..., processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
</Reference>
Find this GrapeCity.ActiveReports.Diagnostics.v7.dll.
Where your .sln file resides, create a .\ThirdPartyReferences\ folder.
Copy GrapeCity.ActiveReports.Diagnostics.v7.dll to that directory.
Remove the "gac" reference.
Add the more local .\ThirdPartyReferences\ reference.
Check .\ThirdPartyReferences\ folder into source control.
Make sure .\ThirdPartyReferences\ is "pull down" from source control during the build.
OR
Get "GrapeCity.ActiveReports" installed on the build-server using their install tools.
Which should get into correctly into the GAC on the build server.
I usually choose the first option (my first option above).
I like having a very good handle on what my ThirdParty dependcies are for my build.
I'm working with a large (270+ project) VS.Net solution. Yes, I know this is pushing the friendship with VS but it's inherited and blah blah. Anyway, to speed up the solution load and compile time I've removed all projects that I'm not currently working on... which in turn has removed those project references from the projects I want to retain. So now I'm going through a mind numbing process of adding binary references to the retained projects so that the referenced Types can be found.
Here's how I'm working at present;
Attempt to compile, get thousands of
errors, 'type or namespace missing'
Copy the first line of the error
list to the clipboard
Using a perl script hooked up to a
hotkey (AHK) I extract the type name from
the error message and store it in the windows clipboard
I paste the type name into source
insight symbol browser and note the
assembly containing the Type
I go back to VS and add that
assembly as a binary reference to
the relevant project
So now, after about 30 mins I'm thinking there's just got to be a quicker way...
These solutions come to my mind:
You can try to use Dependency Walker or similar program to analyze dependecies.
Parse MSBuild files (*.csproject) to get list of dependencies
EDIT:
Just found 2 cool tools Dependency Visualizer & Dependency Finder on codeplex I think they can help you greatly.
EDIT:
#edg, I totally misread your question, since you lose references from csproj files you have to use static analysis tool like NDepend or try to analyze dependencies in run time.
No, there currently isn't a built-in quicker way.
I would suggest not modifying the existing solution and create a new solution with new projects that duplicate (e.g. rename and edit) the projects you want to work on. If you find that the solution with the hundreds of projects is an issue for you then you'll likely just need to work on a subset. Start with a couple of new projects, add the binary (not project) reference and go from there.
One thing you can try is opening up the old .csproj file in notepad and replacing the ProjectReference tags with Reference tags. If you can write a parser, feel free to share. :)
Entry in .csproj file if it is a project reference
<ItemGroup>
<ProjectReference Include="..\WindowsApplication2\WindowsApplication2.csproj">
<Project>{7CE93073-D1E3-49B0-949E-89C73F3EC282}</Project>
<Name>WindowsApplication2</Name>
</ProjectReference>
</ItemGroup>
Entry in .csproj file if it is an assembly reference
<ItemGroup>
<Reference Include="WindowsApplication2, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<ExecutableExtension>.dll</ExecutableExtension>
<HintPath>..\WindowsApplication2\bin\Release\WindowsApplication2.dll</HintPath>
</Reference> </ItemGroup>
Instead of removing the project files from the solution, you could unload the projects you aren't working on (right-click the project and select Unload Project). As long as the unloaded project has been built once, any other project with a reference to it will be able to find the assembly in the project's output directory and build with it.