Gon*_*ing 8 project-reference visual-studio-2010 envdte
当您添加特定DLL时,我们需要使用DTE复制"添加引用"对话框的行为(它将Hint路径条目添加到CSProj文件中的引用).
**注意:此处有另一篇相关但未重复的帖子:https://stackoverflow.com/questions/6690655/visual-studio-2010-add-in-how-to-get-a-references-提示路径属性请阅读该提示以获取有关此问题的更多信息.我现在已经添加了一个不错的赏金来得到答案,并且很乐意在任何体面的答案上分散投票:)*
我正在使用DTE以编程方式将项目引用转换为直接DLL引用.
假设我有一个简单的解决方案Project2(在父项目),它引用Project1(该子项目),我作出这样的变化:
project1Reference = FindProjectReference(project2.References, project1);
project1Reference.Remove();
Reference dllReference = project2.References.Add(project1DllPath);
Run Code Online (Sandbox Code Playgroud)
其中project1DllPath引用该"c:\somewhere\Project1\Bin\Debug\Project1.dll"文件.
我还不能解决的问题是,新的参考是不是对
"c:\somewhere\Project1\Bin\Debug\Project1.dll",而是指向
"c:\somewhere\Project2\Bin\Debug\Project1.dll"(文件被复制那里).
如果我使用"添加引用"菜单直接/手动添加DLL,则不会执行此复制.
如何在没有复制和引用它的情况下将DLL引用添加到现有项目的DLL中?
我尝试dllReference.CopyLocal = false;在Add之后添加,但除了设置标志之外没有任何区别.创建后似乎没有选项可以修改路径.
更新:我还尝试以编程方式从Project2中删除Project1上的任何Build依赖项,但这没有任何效果.
以下是csproj文件之间的区别:
<ItemGroup>
<ProjectReference Include="..\ClassLibrary1\ClassLibrary1.csproj">
<Project>{86B3E118-2CD1-49E7-A180-C1346EC223B9}</Project>
<Name>ClassLibrary1</Name>
</ProjectReference>
</ItemGroup>
Run Code Online (Sandbox Code Playgroud)
<ItemGroup>
<Reference Include="ClassLibrary1, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<Private>False</Private>
</Reference>
...
</ItemGroup>
Run Code Online (Sandbox Code Playgroud)
<ItemGroup>
<Reference Include="ClassLibrary1, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\ClassLibrary1\bin\Debug\ClassLibrary1.dll</HintPath>
</Reference>
...
</ItemGroup>
Run Code Online (Sandbox Code Playgroud)
看起来能够指定DLL引用的提示路径是关键.如何在DLL引用上设置提示路径(假设您只有Reference属性的句柄)?
来自下面的Muse VSExtensions的建议不会影响有问题的DLL,因为已经从DLL的项目BIN到父项目的BIN文件夹进行了复制.父项目不打算使用引用路径,因为它已在其输出文件夹中具有子DLL.
Reference Paths项目的另外还保存到项目 .csproj.user文件中,而不保存到项目 .csproj文件中.
bdr*_*jer 10
我确信这是VS 2010中的一个新bug /功能,因为我有一个加载项,几天前我从VS 2008迁移后开始显示类似的行为...基本上,如果你添加一个引用在VS的汇编搜索路径中的任何内容,它都将在没有路径提示的情况下添加.
我设法找到解决这个问题的其他VS加载项(Power Tools,NuGet等),他们似乎都使用了MsBuild.我不知道MsBuild是否会提高资源使用率 - 我自己没有看到太大的减速,可能是因为References.Add()开始很慢.但请注意,要获取MsBuild项目的实例,将使用名为"GetLoadedProjects"的方法,这可能意味着它适用于已存在于内存中的数据.
下面是我用来修复我的插件的代码,它是我在网上找到的简化版本......基本上,想法是像往常一样添加引用,然后使用MsBuild设置路径提示.设置提示是一项简单的操作,但找到MsBuild项目项的实例以添加提示是非常复杂的.我试图仅使用MsBuild破解替代方案,但遇到了其他问题...这个似乎有效.
另一件可能感兴趣的事情是:代码包含一种优化 - 如果引用的路径等于我们想要添加的路径,它不会将提示添加到新引用.这对于有问题的情况来说已经足够了,并且当VS决定使用输出文件夹中的dll而不是我们告诉它时,它会正确检测到.但是当我尝试在输出文件夹中添加对dll的引用时(我对许多相关项目使用单个输出文件夹),加载项没有设置提示路径,项目似乎切换到使用其他一些dll在路径中(在我的情况下是来自其PublicAssemblies文件夹中的那个)...因此,删除"if(!newRef.Path.Equals(..."行)并始终添加提示可能很有用.我是仍在调查此案例,因此欢迎任何额外的 - 代码,提示或改进代码.
string newFileName = "the path to your.dll";
VSLangProj.VSProject containingProject = yourProject;
VSLangProj.Reference newRef;
newRef = containingProject.References.Add(newFileName);
if (!newRef.Path.Equals(newFileName, StringComparison.OrdinalIgnoreCase))
{
Microsoft.Build.Evaluation.Project msBuildProj = Microsoft.Build.Evaluation.ProjectCollection.GlobalProjectCollection.GetLoadedProjects(containingProject.Project.FullName).First();
Microsoft.Build.Evaluation.ProjectItem msBuildRef = null;
AssemblyName newFileAssemblyName = AssemblyName.GetAssemblyName(newFileName);
foreach(var item in msBuildProj.GetItems("Reference"))
{
AssemblyName refAssemblyName = null;
try
{
refAssemblyName = new AssemblyName(item.EvaluatedInclude);
}
catch {}
if (refAssemblyName != null)
{
var refToken = refAssemblyName.GetPublicKeyToken();
var newToken = newFileAssemblyName.GetPublicKeyToken();
if
(
refAssemblyName.Name.Equals(newFileAssemblyName.Name, StringComparison.OrdinalIgnoreCase)
&& ((refAssemblyName.Version != null && refAssemblyName.Version.Equals(newFileAssemblyName.Version))
|| (refAssemblyName.Version == null && newFileAssemblyName.Version == null))
&& (refAssemblyName.CultureInfo != null && (refAssemblyName.CultureInfo.Equals(newFileAssemblyName.CultureInfo))
|| (refAssemblyName.CultureInfo == null && newFileAssemblyName.CultureInfo == null))
&& ((refToken != null && newToken != null && Enumerable.SequenceEqual(refToken, newToken))
|| (refToken == null && newToken == null))
)
{
msBuildRef = item;
break;
}
}
}
if (msBuildRef != null)
{
Uri newFileUri = new Uri(newFileName);
Uri projectUri = new Uri(Path.GetDirectoryName(containingProject.Project.FullName).TrimEnd(Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar);
Uri relativeUri = projectUri.MakeRelativeUri(newFileUri);
msBuildRef.SetMetadataValue("HintPath", relativeUri.ToString());
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
8025 次 |
| 最近记录: |