雑記
 

WPFの機能を有効にする

2022/10/9

この記事が対象とする製品・バージョン

Visual Studio 2022 Visual Studio 2022 対象です。
VS2019 Visual Studio 2019 対象です。
VS2017 Visual Studio 2017 × 対象外です。
VS2015 Visual Studio 2015 × 対象外です。
VS2013 Visual Studio 2013 × 対象外です。
VS2012 Visual Studio 2012 × 対象外です。
VS2010 Visual Studio 2010 × 対象外です。
VS2008 Visual Studio 2008 × 対象外です。
VS2005 Visual Studio 2005 × 対象外です。
VS.NET 2003 Visual Studio 2003 × 対象外です。
VS.NET 2002 Visual Studio (2002) × 対象外です。
  Visual Studio Code × 対象外です。

 

目次

 

1.概要

.NETのアプリケーションで WPF の機能を使用する方法を説明します。

この記事では .NET 5 以上を対象にします。

コンソールアプリ や Windows フォームアプリ や ASP.NET Core Webアプリ など WPF以外のアプリケーションで WPF の機能が使用できるようになります。

この手順を実行すると、アプリケーションは Windows上でしか動作しなくなります。(WPFの機能はWindows上でしか実行できないため)

参考

Microsoft.NET.Sdk.Desktop の MSBuild プロパティ - .NET | Microsoft Learn

 

2.WPFの機能を有効にする方法

プロジェクトをダブルクリックして、TargetFramework に -windows を追加し、<UseWPF>true</UseWPF> を挿入すると WPF の機能を使用できるようになります。編集後に保存もお忘れなく。

 

TargetFrameworkの補足

たとえば、 <TargetFramework>net6.0</TargetFramework> となっている場合、<TargetFramework>net6.0-windows</TargetFramework> とします。

既に -windows が付いている場合は、不要です。

-windows以外の -xxxx が付いている場合(たとえば -ios 、- macos など)は、WPF を有効化できません。あきらめてください。(WPFはWindowsでしか動作しないため)。もし、Windowsでしか動作しなくなっても良いのであれば、-ios や - macos などを取り除いてその代わりに -windows を付けることで WPF を有効化することができます。

 

編集後すぐ実行するとエラーになるみたいです

なお、私が何度か試したところ、変更直後に間髪入れずに実行するとエラーになることがありました。もう1度実行すると正常に実行できました。

 

 

3.なぜこの手順が必要なのか?

通常、.NET では、既定ではない機能を使用するにはNuGetを使用するか、参照を使用しますが、WPFなど一部の機能は、この手順のように特別に用意された仕組みを使って有効化します。

 

次のC#のプログラムはWPFのMessageBoxクラスの機能を使って、画面にメッセージを表示します。

これを動作させるには、この記事で説明しているようにWPFの機能を有効化する必要があります。


System.Windows.MessageBox.Show("あいうえお");

(Windowsフォームアプリに慣れている方は、これが同じMessageBoxというクラスでもWindowsフォームアプリで使うMessageBoxではないことに注意してください。Windowsフォームアプリで使用するMessageBoxはSystem.Windows.Forms.MessageBoxです。)

 

この例の機能は特に魅力を感じませんが、WPFの機能を利用できれば、WPFが得意なグラフィック機能を使用してWebアプリで動的に画像を生成したりできるようになります(ただし、そのWebアプリはWindowsでしかホストできなくなるので、グラフィックが目的の場合 幅広く使える SkiaSharp から検討します)。もちろん、コンソールアプリやWindowsフォームアプリからWPFの機能を呼び出すこともできます。

 

4.困った場合

困った1.System.Threading.ThreadStateException: 'OLE を呼び出す前に、現在のスレッドをシングル スレッド アパートメント (STA) モードに設定しておく必要があります。'

使用する機能によっては この例外が発生することがあります。

解消するには、 Mainメソッドに [STAThread] 属性を付けます。(通常はmainですが、厳密にはアプリケーションのエントリーポイントであるメソッドです。)

 

たとえば、このプログラムはWPFのClipboardクラスの機能を使って文字列ABCをWindowsのクリップボードにコピーします。(マウスで文字を選択してコピーするのと同じ状態を作り出します。)


System.Windows.Clipboard.SetText("ABC");

コンソールアプリケーションでWPFを有効化しただけの状況でこの機能を呼び出すと、上記のエラーが発生します。

 

このエラーを解消するには Main メソッドに [STAThread]属性を適用します。通常コンソールアプリケーションでは Program.cs に Mainメソッドがあります。

internal class Program
{
    [STAThread]
    private static void Main(string[] args)
    {
        Console.WriteLine("Hello, World!");


        System.Windows.Clipboard.SetText("ABC");
    }
}

Mainメソッド以外の場所に問題となる処理がある場合でも、Mainメソッドに STAThread属性を適用することで解消します。

なお、STAThread属性をつけても通常は副作用はありません。COMコンポーネント という機能を使用している場合には影響がある場合があります。COMコンポーネントを自分のプログラムから明示的に使用していない場合でも、何かの機能の内部でCOMコンポーネントが呼び出されている場合はあります。

 

Mainメソッドがない場合

コンソールアプリケーションなどでは「最上位レベルのステートメント」という機能により Main メソッドの定義が隠されている場合があります。

その場合、最上位レベルのステートメントを解除して、Mainメソッドを明示的に使用する方式に切り替えます。

その方法はこちらで説明しています。

C# 最上位レベルのステートメントを適用/解除する