我正在尝试使用 .NET Core 编写插件系统,我的要求之一是能够将插件 DLL 及其依赖项分发给用户进行安装。
但是,我不知道如何将我的 NuGet 依赖项包含为构建工件并将它们输出到构建文件夹,而不必使用 dotnet publish
作为 hack。有什么方法可以在 .csproj 文件(项目文件)中指定吗?
dotnet publish
是一种黑客行为?在您的 csproj 文件中包含该命令作为构建后脚本。
dotnet publish
将整个框架放在发布文件夹中,因为我正在编写插件,所以大部分文件都不是必需的,因为框架已经由引导程序加载。我正在寻找类似于构建在 .NET Framework 上的工作方式的东西。
<PackageReference/>
不支持 <CopyToOutputDirectory>
。
您可以将其添加到您的 csproj 文件中的 <PropertyGroup>
,以强制将 NuGet 程序集复制到构建输出:
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
但是,请注意,构建输出 (bin/Release/netcoreapp*/*
) 不应该是可移植和可分发的,dotnet publish
的输出是。但是在您的情况下,将程序集复制到构建输出对于测试目的可能非常有用。但请注意,您也可以使用 DependencyContext
api 来解析作为应用程序依赖关系图一部分的 DLL 及其位置,而不是枚举本地目录。
您可以使用 PostBuildEvent 在构建时自动部署模块。
要在构建文件夹中获取 NuGet 程序集,请添加模块的 csproj
<PropertyGroup>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
</PropertyGroup>
使用包含/排除定义您想要的模块文件(根据需要修改路径)
<ItemGroup>
<ModuleFiles
Include="$(TargetDir)*.dll"
Exclude="$(TargetDir)System*.dll;$(TargetDir)Microsoft*.dll"
DestinationPath="$(SolutionDir)src\MyProject\Modules\MyModule\%(Filename)%(Extension)">
</ModuleFiles>
</ItemGroup>
将您的构建文件夹重置为默认值并添加 PostbuildEvent
<Target Name="PublishModule" AfterTargets="PostBuildEvent" Inputs="@(ModuleFiles)" Outputs="@(ModuleFiles->'%(DestinationPath)')">
<WriteLinesToFile File="$(SolutionDir)src\[YOURAPP]\app_offline.htm" />
<Copy SourceFiles="@(ModuleFiles)" DestinationFiles="@(ModuleFiles->'%(DestinationPath)')" />
<Delete Files="$(SolutionDir)src\[YOURAPP]\app_offline.htm" />
</Target>
如果应用程序已经在运行,我将包括 app_offline 来回收应用程序,以避免文件使用中的错误。
添加
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
没用,但将其添加到 Framework .csproj 文件中:
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
做过。
我正在使用 .NET 5,这是我对类似问题的解决方案。
结构:Project-A(Contained Selenium Nuget References, and selenium code)Project-B(一个单元测试项目,调用Project-A中的方法)
问题:在构建解决方案时,chromedriver.exe 文件出现在 Project-A bin 文件夹中,但不会被复制到 Project-B bin 文件夹中,因此无法执行单元测试。抛出一个异常说 chromedriver.exe 没有找到。
解决方案:修改 Project-A 中 Selenium ChromeDriver NuGet 包引用的属性,仅将“contentfiles;analyzers”视为私有资产。未指定时,默认值为 'contentfiles;analyzers;build'。现在这意味着可以将构建的输出文件流向父引用项目,但不能流向内容文件或分析器,因为“构建”以前也被认为是私有资产,不会流向父项目。
之前(在 Project-A.csproj 中):
<ItemGroup>
<PackageReference Include="Selenium.Support" Version="3.141.0" />
<PackageReference Include="Selenium.WebDriver" Version="3.141.0" />
<PackageReference Include="Selenium.WebDriver.ChromeDriver" Version="87.0.4280.8800" />
</ItemGroup>
之后(在 Project-A.csproj 中):
<ItemGroup>
<PackageReference Include="Selenium.Support" Version="3.141.0" />
<PackageReference Include="Selenium.WebDriver" Version="3.141.0" />
<PackageReference Include="Selenium.WebDriver.ChromeDriver" Version="87.0.4280.8800">
<PrivateAssets>contentfiles;analyzers</PrivateAssets>
</PackageReference>
</ItemGroup>
希望这对某人有帮助!祝你好运。
我以更简单的方式“解决”(创建了解决方法)这个问题。
在后期构建中
dotnet publish "$(ProjectFileName)" --no-build -o pub
xcopy "$(ProjectDir)pub\3rdPartyProvider.*.dll" "$(OutDir)"
pub
是您希望发布的内容用于暂存的文件夹
注意:根据您使用的 dotnet.exe
版本,命令 --no-build
可能不可用。
例如,在 v2.0.3 中不可用;并在 v2.1.402 中可用。我知道 VS2017 Update4 有 v2.0.3。 Update8 有 2.1.x
更新:
上面的设置将在基本的调试环境中工作,但要将其放入构建服务器/生产环境中还需要更多。在我必须解决的这个特定示例中,我们分别构建 Release|x64
和 Release|x86
。所以我两个都占了。但是为了支持 post build dotnet publish
命令,我首先将 RuntimeIdentifier
添加到项目文件中。
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutputPath>..\..\lib\</OutputPath>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x86'">
<OutputPath>..\..\lib\</OutputPath>
<RuntimeIdentifier>win-x86</RuntimeIdentifier>
</PropertyGroup>
为什么我需要它,为什么没有它你可以逃脱?我需要这个,因为 我的 构建程序设置为拦截警告 MSB3270,如果出现则构建失败。此警告说,“嘿,您的依赖项中的某些文件格式错误”。但是你还记得这个练习的目标吗?我们需要提取包依赖 DLL。在许多情况下,是否存在此警告并不重要,因为后续构建无关紧要。同样,这是我关心的构建程序。因此,我只在生产构建期间使用的 2 个配置中添加了 RuntimeIdentifier
。
完整的后期构建
if not exist "$(ProjectDir)obj\$(ConfigurationName)" mkdir "$(ProjectDir)obj\$(ConfigurationName)"
xcopy "$(ProjectDir)obj\$(PlatformName)\$(ConfigurationName)" "$(ProjectDir)obj\$(ConfigurationName)" /E /R /Y
if $(ConfigurationName) == Release (
dotnet publish "$(ProjectFileName)" --runtime win-$(PlatformName) --no-build -c $(ConfigurationName) -o pub --no-restore --no-dependencies
) else (
dotnet publish "$(ProjectFileName)" --no-build -c $(ConfigurationName) -o pub --no-restore --no-dependencies
)
xcopy "$(ProjectDir)pub\my3rdPartyCompany.*.dll" "$(OutDir)" /Y /R
说明:dotnet publish 正在寻找 obj\Debug
或 obj\Release
。我们在构建期间没有它,因为构建会创建 obj\x64\Release
或 obj\x86\Release
。第 1 行和第 2 行缓解了这个问题。在第 3 行中,我告诉 dotnet.exe
使用特定的配置和目标运行时。否则,当这是调试模式时,我不关心运行时的东西和警告。在最后一行中,我只需将我的 dll 复制到输出文件夹中。任务完成。
dotnet publish "$(ProjectFileName)" -c Release --no-build -o bin\pub
xcopy "$(ProjectDir)pub\PostSharp.dll" "$(OutDir)"
结合上面的答案:我在生成后事件命令行中很好地工作:在 Visual Studio 中。它循环选择 dll(System*.dll 和 Microsoft.dll)*,然后跳过特定 dll 的删除。 System.Data.SqlClient.dll 和 System.Runtime.Loader.dll
for %%f in ($(OutDir)System*.dll $(OutDir)Microsoft*.dll) do if not %%f == $(OutDir)System.Data.SqlClient.dll if not %%f == $(OutDir)System.Runtime.Loader.dll del %%f
DependencyContext
?如何使用它来查找不在应用程序目录中的 DLL?它到底在哪里?dotnet new nunit
创建 NUnit 测试项目。