Custom Is64BitOperatingSystem预处理程序指令

问题描述 投票:0回答:1

我们可以像这样为Platform Conditional Compilation in .NET Core添加自定义预处理器指令

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp2.0</TargetFramework>
    <IsWindows Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true'">true</IsWindows>
    <IsOSX Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true'">true</IsOSX>
    <IsLinux Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true'">true</IsLinux>
  </PropertyGroup>
  <PropertyGroup Condition="'$(IsWindows)'=='true'">
    <DefineConstants>Windows</DefineConstants>
  </PropertyGroup>
  <PropertyGroup Condition="'$(IsOSX)'=='true'">
    <DefineConstants>OSX</DefineConstants>
  </PropertyGroup>
  <PropertyGroup Condition="'$(IsLinux)'=='true'">
    <DefineConstants>Linux</DefineConstants>
  </PropertyGroup>
</Project>

我已经测试过,它工作正常。

现在,我要检测我是否在64位操作系统上。这是我的.csproj

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netstandard2.1</TargetFramework>
    <Is64BitOperatingSystem Condition="'$([System.Environment]::Is64BitOperatingSystem)' == 'true'">true</Is64BitOperatingSystem>
  </PropertyGroup>

  <PropertyGroup Condition="'$(Is64BitOperatingSystem)'=='true'">
    <DefineConstants>Is64BitOperatingSystem</DefineConstants>
  </PropertyGroup>
</Project>

但是,当我运行此代码时,我的第一个if...else可以正常工作,但是我的Is64BitOperatingSystem预处理程序指令却没有运行

if (System.Environment.Is64BitOperatingSystem)
    Console.WriteLine(64);
else
    Console.WriteLine(32);

#if Is64BitOperatingSystem
    Console.WriteLine(64);
#else
   Console.WriteLine(32);
#endif

我在做什么错?我无法发现代码中的错误在哪里。

谢谢

编辑

要添加有关此内容的更多详细信息,我将此代码包含在.NET Core项目调用的.NET Standard库中。

我希望我的库检测它正在运行的当前体系结构(或已编译为,所以我可以做这样的事情

#if Is64BitOperatingSystem
    [DllImport(@"Resources/HIDAPI/x64/hidapi")]
#else
    [DllImport(@"Resources/HIDAPI/x32/hidapi")]
#endif

在调试之前,Visual Studio显然会编译我的应用程序,因此在此阶段使用System.Environment.Is64BitOperatingSystem或预处理程序指令检查体系结构应得出相同的结果,但事实并非如此。我在64位计算机上,我的预处理程序指令告诉我我在32位体系结构上,即使我在Visual Studio Configuration Manager中将AnyCPU更改为x64

请注意,this answer是Windows特定的,that one也是特定于Windows的,因为解决方案是从SetDllDirectory调用kernel32.dll函数

但是我希望我的代码能够在Linux上运行。

编辑2:

为了在此处共享最少的示例,我实际上删除了代码的错误部分。

看起来像这样可以得到预期的结果:

<PropertyGroup>
    <TargetFramework>netstandard2.1</TargetFramework>
    <Is64BitOperatingSystem Condition="'$([System.Environment]::Is64BitOperatingSystem)' == 'true'">true</Is64BitOperatingSystem>
</PropertyGroup>

<PropertyGroup Condition="'$(Is64BitOperatingSystem)'=='true'">
    <DefineConstants>Is64BitOperatingSystem</DefineConstants>
</PropertyGroup>

但是这会产生错误的行为:

<PropertyGroup>
    <TargetFramework>netstandard2.1</TargetFramework>
    <Is64BitOperatingSystem Condition="'$([System.Environment]::Is64BitOperatingSystem)' == 'true'">true</Is64BitOperatingSystem>
    <IsWindows Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true'">true</IsWindows>
</PropertyGroup>

<PropertyGroup Condition="'$(Is64BitOperatingSystem)'=='true'">
    <DefineConstants>Is64BitOperatingSystem</DefineConstants>
</PropertyGroup>

<PropertyGroup Condition="'$(IsWindows)'=='true'">
    <DefineConstants>Windows</DefineConstants>
</PropertyGroup>

[有人可以向我解释吗?我不明白为什么添加IsWindows条件会导致Is64BitOperatingSystem预处理程序指令上的行为不同

c# .net-core .net-standard preprocessor-directive
1个回答
1
投票

之所以在上次编辑中不起作用的原因是DefineConstants中的条件编译器常量不能单独定义,此属性的值是用分号分隔的值列表,应按以下方式定义

<PropertyGroup Condition="'$(IsWindows)'=='true'">
    <DefineConstants>Windows</DefineConstants>
</PropertyGroup>

<PropertyGroup Condition="'$(Is64BitOperatingSystem)'=='true' And '$(IsWindows)'=='true'">
    <DefineConstants>Windows;Is64BitOperatingSystem</DefineConstants>
</PropertyGroup>

并且以下代码将按预期工作

#if Windows
            Console.WriteLine("built in Windows!");
#endif

#if Is64BitOperatingSystem
            Console.WriteLine("built on x64");
#else
            Console.WriteLine("built on x86");
#endif
            Console.WriteLine(Environment.Is64BitOperatingSystem ? "running on x64" : "running on x86");

它将显示:

Windows内置!

基于x64构建

在x64上运行

但是它也会覆盖默认的DEBUGTRACE常量,您也需要手动管理它们(如果需要)。 [Linux常数

也是如此

enter image description here


0
投票

我希望我的库检测它正在运行(或已编译)的当前体系结构,因此我可以执行类似的操作

如果这是您的要求,那么我认为您在做错事。您尝试使用的方法将使库依赖于体系结构构建它的位置,而没有其他依赖。

编译指令,顾名思义,在编译时生效。它们在runtime无效。如果要为不同的体系结构使用不同的[DllImport],则将需要不同的版本。通常,解决方法是使用不同的构建配置。

在Configuration Manager中,创建两个单独的解决方案平台,以及相应的项目平台:

Configuration Manager Build Configurations

在“项目属性”->“构建”选项卡中,为两个条件之一指定条件编译指令:

Project Properties

在您的代码中,使用编译符号:

#if Is64Bit
    [DllImport(@"Resources/HIDAPI/x64/hidapi")]
#else
    [DllImport(@"Resources/HIDAPI/x32/hidapi")]
#endif
© www.soinside.com 2019 - 2024. All rights reserved.