6

我有一个 .NET Core 控制台应用程序。我的目标是能够有条件地DLLImport调用一个函数并调用它,但仅限于 Windows 运行时。

我想也许如果我可以访问csproj文件中的运行时标识符,我可以有条件地为该运行时定义一个常量,然后在我的 c# 中我可以包围 DLLImport 并调用#if/#endif块。

csproj是否可以根据构建项目的运行时在 a 中设置编译常量?这专门针对面向 .NET Core 的 SDK 样式的项目格式(以 开头<Project Sdk="Microsoft.NET.Sdk">)。

注意:这个问题很接近,但适用于project.json风格项目。

或者,是否有更好的方法来实现我的目标?

4

2 回答 2

12

如果您通过传递不同的--runtime选项(MSBuild 属性RuntimeIdentifier)为不同的运行时构建和发布,您可以在 csproj 文件中以该属性为条件(允许您#if BUILT_FOR_WINDOWS在 C# 代码中使用):

<PropertyGroup>
  <DefineConstants Condition="'$(RuntimeIdentifier)' == 'win-x64'">$(DefineConstants);BUILT_FOR_WINDOWS</DefineConstants>
</PropertyGroup>

但是,您也可以使用以下方法在运行时测试当前操作系统:

using System.Runtime.InteropServices;
…

if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
    // call windows function here
}
else
{
    // do something else here
}

只要[DllImport(…)]没有在找不到库/方法的操作系统上调用标记为的函数,就不会有任何问题。请注意,DllImport()它还可以根据操作系统探测不同的库 - 所以DllImport("foo")会检查foo.dll,foo.dyliblibfoo.so

于 2018-05-04T06:15:26.530 回答
1

添加到 Martin Ullrich 的答案:如果您想基于RuntimeIdentifier引用的库项目而不是具有应用程序入口点的项目定义常量,请确保RuntimeIdentifiers在项目的 .csproj 文件中包含您在属性中使用的标识符列表, 例如:

<PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
    <RuntimeIdentifiers>linux-x64;linux-arm</RuntimeIdentifiers>
</PropertyGroup>

如果你不这样做,那么常量将不会被定义为RuntimeIdentifier属性不会被传递给 csproj,就像我的情况一样。

来源:https ://github.com/dotnet/core/issues/2678#issuecomment-498967871

于 2021-09-15T20:54:21.480 回答