Open5

Visual Studio 2019 v16.8以降 で Windows 8.1 SDK を使用できない問題の解決方法

ピン留めされたアイテム
mugwort_rcmugwort_rc

解決策

  • Windows 8.1 SDKを窓から投げ捨てる
    • 良:最も健全な方法
    • 悪:Windows 8.1 は2023-01-10まで延長サポートされている
  • 「C/C++」/「言語」/「準拠モード」/「いいえ /permissive」運用を覚悟する
    • 良:古いコードの修正を先延ばしにできる
      • /std:c++latestだと/permissiveは働かないので/std:c++17で妥協する
      • 自らの書いたコードも知らぬうちに標準非準拠になりうることを許容する
  • /std:c++latestで未来に生きる or /permissive-で正しい運用を行う
    • 良:将来に負債を残さない
    • 悪:
      • C:\Program Files (x86)\Windows Kits\8.1\Include\umの以下のファイルを書き換えるので自己責任
        • combaseapi.h
        • gdiplusheaders.h
        • gidplusstringformat.h
      • 何らかの別のトラブルを生む可能性がゼロではない
      • (でも悪いのは私たちではない。これは正義である)
mugwort_rcmugwort_rc

Visual Studio 2019を最新に更新すると、従来コンパイルできていたソースが以下のようなエラーを吐いてコンパイルできなくなる。

1>C:\Program Files (x86)\Windows Kits\8.1\Include\um\combaseapi.h(229,21): error C2760: 構文エラー: 予期しないトークン '識別子 '、必要なトークン '型指定子'
1>C:\Program Files (x86)\Windows Kits\8.1\Include\um\combaseapi.h(229,21): error C2760: syntax error: unexpected token 'identifier', expected 'type specifier'

これはWindows 8.1 SDKのcombaseapi.hが寛容 /permissive(標準非準拠)ではコンパイルできるが、非寛容/permissive-(標準準拠)ではコンパイルできない形式になっているため。

mugwort_rcmugwort_rc

/permissive-だとそもそもgdiplusheaders.hgdiplusstringformat.hの2ファイルに致命的に頭の悪いメンバ関数宣言があるので、C:\Program Files (x86)\Windows Kits\8.1\Include\umの書き換えは避けられないことに気がついた。

--- a/gdiplusheaders.h	2013-06-18 05:23:06.000000000 +0900
+++ b/gdiplusheaders.h	2021-05-17 16:32:15.169658000 +0900
@@ -897,7 +897,7 @@
 
     UINT GetDownLevelRasterizationLimit() const;
 
-    static UINT Metafile::EmfToWmfBits(
+    static UINT EmfToWmfBits(
         _In_ HENHMETAFILE       hemf,
         _In_ UINT               cbData16,     
         _Out_writes_to_opt_(cbData16, return) LPBYTE            pData16,
--- a/gdiplusstringformat.h	2013-06-18 05:23:06.000000000 +0900
+++ b/gdiplusstringformat.h	2021-05-17 16:31:17.791940000 +0900
@@ -222,7 +222,7 @@
         ));
     }
 
-    StringTrimming StringFormat::GetTrimming() const
+    StringTrimming GetTrimming() const
     {
         StringTrimming trimming;
         SetStatus(DllExports::GdipGetStringFormatTrimming(