- 投稿日:2020-11-15T21:21:20+09:00
VS2019 C#でCOM DLLを作ってみた
はじめに
を参考にさせて頂きました。圧倒的感謝……!
環境
- Windows 10 Home (64bit)
- Visual Studio Community 2019
手順
プロジェクトの作成
プロジェクト テンプレート:クラス ライブラリ (.NET Framework) [C#]
プロジェクト名:ClassLibrary1
クラス ライブラリ (.NET Standard)
とは別なので注意。インタフェースとクラスの作成
Class1.csusing System; using System.Runtime.InteropServices; using System.Windows.Forms; namespace Sample { [ComVisible(true)] [Guid("EC463B16-E298-478E-A836-44585A30F806")] [InterfaceType(ComInterfaceType.InterfaceIsDual)] public interface ITest { void Hello(string msg); } [ComVisible(true)] [Guid("A81D546F-6F4E-49E0-9A2B-A9DCC725C489")] [ProgId("Sample.Test")] [ClassInterface(ClassInterfaceType.None)] public class Test : ITest { public void Hello(string msg) { MessageBox.Show(msg, "Test"); } } }Guid はツールから作成する。
MessageBox を使うのでプロジェクトにアセンブリ参照を追加する。
名前:System.Windows.Formsアセンブリに署名
プロジェクトのプロパティを開き、署名の「アセンブリに署名する」をチェックする。
キー ファイル:test署名しなくともRegAsmで警告は出るが登録は可能。
ビルド
ソリューション構成:Release
ソリューション プラットフォーム:Any CPU
ソリューションのビルド。レジストリに登録
管理者権限の PowerShell やコマンド プロンプトでレジストリに登録する。
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\RegAsm ClassLibrary1.dll /codebase
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\RegAsm ClassLibrary1.dll /codebase /u
で登録解除。
/tlb
を付けるとCOM一覧に表示されるがC#からは利用できない模様。
dllを直接参照する手もある。テストプログラム
JScript
test.jsvar test = new ActiveXObject("Sample.Test"); test.Hello("hello, JScript");というファイルを用意しダブルクリックする。
クラスに定義した ProgID を指定。
- 投稿日:2020-11-15T20:26:36+09:00
toio for Unity Editor Windows BLE対応
初めに
Unityでtoioの開発できるってことで飛びつきました。
https://toio.io/blog/detail/20200930-1.html
しかし、よく内容を見ているとUnity Editor内で確認できるのは
シュミレーターでのtoioの動き確認のみ。う~ん。やっぱUnity Editorでtoioコアキューブが動いてほしい
というわけでtoioの仕様についていろいろ調べ始めました。toio™コア キューブ 技術仕様2.2.0
https://toio.github.io/toio-spec/docs/ble_communication_overview.htmlBLEで接続してtoioコアキューブが動いているようなので
Unity EditorでBLE接続出来てしまえばいけちゃうのでは?
って事で調べ始めました。Uunity EitorでBLEを接続する
UnityでBLE接続するぞってって事でAssetstoreに行って検索を!
自分で作るんじゃないんだ。。。
無ければ自分で作るんですけどね。。ということで調べたら、あった!!神
Arduino Bluetooth Plugin $19
https://assetstore.unity.com/packages/tools/input-management/arduino-bluetooth-plugin-98960Arduino Bluetooth Pluginを使ってBLE接続
Arduino Unity Plugin.pdfの説明の最後のほうに
Setup BLE in unity editor for Windows 10の説明があるので手順書通りインストールします。BLEの通信するアプリ(BluetoothDesktopServer)を立ち上げて
アプリはBLEのサーバーと通信するものですが、コマンドでループバックで通信を行えるようにコマンドで実行しておきます。
CheckNetIsolation.exe LoopbackExempt -is -n=BluetoothDesktopServer_t05x7yb6e6yp0後はc#の方で
BluetoothHelper.BLE_AS_CLIENT = true;でBLEの接続の準備をしておきます。
Unity Editorで立ち上げて、toioのBLEを探すので接続したら
ServiceとCharacteristicsを指定して値を渡すと
toioがtoio™コア キューブ 技術仕様通りに値を送ると
値通り動いてくれます。※注意
Arduino Bluetooth PluginのwindowsのBLEの接続はまだ開発途中らしく、安定した接続はまだらしいです。この記事は2020/10に環境を作りました。
- 投稿日:2020-11-15T19:56:54+09:00
WebView2 Windows Form C#(.Net) の実装と詰まった点・困った点
今年(2020年)の8月にMicrosoftは.Netに対応させた「WebView2」のプレリリースを発表しました。
今回はその「WebView2」を Windows Form で実装していき、実装時の詰まった点・困った点について話していきます。WenView2とは?
「WenView2」とは、Windowsフォームに埋め込むことができるブラウザーコントロールの一種です。
Windowsフォームにブラウザーを埋め込むにはデフォルトの場合、「WebBrowser」を使用するのですが、「WebBrowser」は IE ベースとなっており、IE を使用すると一部 webページでは処理できない事象が発生します。
(先日、Rustでwasmを作成する記事を書いたのですが、IE ではwasmを処理できません)
今回使用する「WebView2」はEdgeベースとなっており、Edgeは「Chromium」ベースで作られてるため、IEで処理できないページを処理することができます。WenView2 の実装
基本的には、下記のMicrosoft公式ページを参照して頂ければ実装できます。
https://docs.microsoft.com/ja-jp/microsoft-edge/webview2/gettingstarted/winforms詰まった点・困った点
1.Canary チャネルをダウンロード
さあ、これから実装しようとなって、Nugetからプレリリース版の「Microsoft.Web.WebView2」をダウンロードし、WindowsフォームのデザイナーにWebView2を設置してブラウザーを表示しようとしたら、なぜかブラウザーがロードされない…
どういうことなのか?と思い迷うこと一時間。公式リファレンスを読み直してみたところ、前提条件に、「WebView2 Runtime または windows 10、windows 8.1、または windows 7 にインストールされている 非安定した Microsoft Edge (Chromium) カナリアチャネル 」とあります…
つまり、WebView2 Runtimeか、Microsoft Edge (Chromium) カナリアチャネルをダウンロードする必要があるということみたいです。
てっきり私は、最新の Edgeがダウンロードされているならば、「WebView2 Runtime」が取り込み済みとなっているのかと勘違いしてしまっていたのですが、そういうことではないそうです。
ということで、「Edge Canaryチャネル」をダウンロードして再度挑戦したところ、無事にロードさせることができました。
ちなみに、「Canaryチャネル」は下記サイト内で、画像の赤枠で囲った部分のやつです。
https://www.microsoftedgeinsider.com/ja-jp/download
まあ、こんなミス、自分だけかもしれませんが(笑)2.CoreWebView2がnull
まず、下記のコードを見てください。
このコードは正常に処理できる様に書いたコードですので、コピペしてもらってデバッグしても、エラーにならずに処理することができます。
(フォームのデザイナーは空の状態で大丈夫です。)
以降の話は、下記のコードを見比べながら読んで頂くとわかりやすいと思います。Form1.csusing Microsoft.Web.WebView2.Core; using Microsoft.Web.WebView2.WinForms; using System; using System.Windows.Forms; namespace SampleWebView2Form { public partial class Form1 : Form { /// <summary>webviewのコントロール(今回はわかりやすい様に、デザイナーを使わずにコード側で実装します。)</summary> private WebView2 WebView = new WebView2 { Source = new Uri("https://docs.microsoft.com/ja-jp/microsoft-edge/webview2/gettingstarted/winforms"), }; public Form1() { this.Controls.Add(WebView); InitializeComponent(); //WebView2のサイズをフォームのサイズに合わせる WebView.Size = this.Size; this.SizeChanged += Form1_SizeChanged; //WebView2のロード完了時のイベント WebView.NavigationCompleted += WebView_NavigationCompleted; } /// <summary>WebView2のロード完了時</summary> private void WebView_NavigationCompleted(object sender, CoreWebView2NavigationCompletedEventArgs e) { //WebView2のコントロールから CoreWebView2を取り出す //WebView2のロードが完了する前に CoreWebView2を取り出そうとすると nullになる。 if (WebView.CoreWebView2 != null) { //ブラウザーのポップアップ発生時のイベント WebView.CoreWebView2.NewWindowRequested += CoreWebView2_NewWindowRequested; } else MessageBox.Show("WebView.CoreWebView2 == null"); } /// <summary>WebView2でのポップアップを抑止したい</summary> private void CoreWebView2_NewWindowRequested(object sender, CoreWebView2NewWindowRequestedEventArgs e) { //本来なら、これでポップアップを抑止できるはず //だが、ロードの速度の都合で e.NewWindow(CoreWebView2)が nullになる場合があり、エラーが発生する if (e.NewWindow != null) { e.NewWindow.Stop(); MessageBox.Show("ポップアップを抑止しました"); } else { //ダミーのCoreWebView2を読み込ませてポップアップを抑止する //e.NewWindow = new Microsoft.Web.WebView2.Core.CoreWebView2(); //↑ちなみに、これはできない e.NewWindow = DummyWebView.CoreWebView2; e.NewWindow.Stop(); //これでJavaScriptが実行できる WebView.ExecuteScriptAsync("alert(\"ポップアップを抑止しました\");"); } } /// <summary>ポップアップ抑止に使用するダミーのWebView2(の中のCoreWebView2)</summary> private WebView2 DummyWebView = new WebView2 { Source = new Uri("https://www.google.co.jp/"), }; /// <summary>サイズ変更時のイベントでWebView2のサイズをフォームに合わせる</summary> private void Form1_SizeChanged(object sender, EventArgs e) { WebView.Size = this.Size; } } }WebView2には「CoreWebView2」というオブジェクトがあるのですが、この「CoreWebView2」に対してイベントを設定することで、ブラウザー側の動きに合わせて、C#側の処理を行っていくことができます。
ということで、ロードのタイミングでポップアップ時のイベントを設定します。
…するとどうなるかというと、例外回避のために設定した「CoreWebView2」の null判定に引っ掛かり、
"WebView.CoreWebView2 == null")
のメッセージが発生して、ポップアップ検知のイベントが設定されません。Form1.cspublic Form1() { this.Controls.Add(WebView); InitializeComponent(); if (WebView.CoreWebView2 != null) { //ブラウザーのポップアップ発生時のイベント WebView.CoreWebView2.NewWindowRequested += CoreWebView2_NewWindowRequested; } else MessageBox.Show("WebView.CoreWebView2 == null"); }原因は何かというと、この「CoreWebView2」というのがブラウザーのエンジン的な役割をしているため、読み込ませたいwebページのロードが終了しない限り、「CoreWebView2」がnullのまま、ということになってしまうからです。
それを解決するためには、下記の様にコードを修正します。Form1.cspublic Form1() { this.Controls.Add(WebView); InitializeComponent(); //WebView2のロード完了時のイベント WebView.NavigationCompleted += WebView_NavigationCompleted; } /// <summary>WebView2のロード完了時</summary> private void WebView_NavigationCompleted(object sender, CoreWebView2NavigationCompletedEventArgs e) { //WebView2のコントロールから CoreWebView2を取り出す //WebView2のロードが完了する前に CoreWebView2を取り出そうとすると nullになる。 if (WebView.CoreWebView2 != null) { //ブラウザーのポップアップ発生時のイベント WebView.CoreWebView2.NewWindowRequested += CoreWebView2_NewWindowRequested; } else MessageBox.Show("WebView.CoreWebView2 == null"); }「WebView2」のナビゲーションが完了時に「CoreWebView2」を取得することで nullを回避できるため、例外回避に引っ掛からず、正常にイベントを設定することができます。
ポップアップが止まらない
イベントも無事設定できたので、今度はポップアップを抑止したいと思います。
ポップアップを抑止したらタブコントロールの別のタブページにポップアップのページを表示する、というのが実装するならば自然な処理となるでしょうが、わざわざそれを書くと長くなるので、タブコントロールに関しては、今回は省きます。
ちなみに、ポップアップが発生する場合というのは、WebView2内でリンクを右クリックし、「リンクを新しいウィンドウで開く」を押下すると、Windowsフォームの外にリンク先のページが表示されます。
(今回の記事の最初に書いたコードで実行すると、既にポップアップが抑止されるようになっています。)
ポップアップを抑止するため、下記のコードを追加しました。
「CoreWebView2NewWindowRequestedEventArgs e」の「.NewWindow」が「CoreWebView2」なので、それを「.Stop()」すればポップアップを抑止できるでしょう。本当なら、e.Cancel みたいのがあるべきかと思いますが…
(ちなみに、e.Uri でポップアップのURLが取得できるので、ポップアップをタブコントロールの別タブにしたい場合は、このURLを使用して新規にWebView2を作成し、タブページを追加するというのが無難な処理なるかと思います。)Form1.cs/// <summary>WebView2のロード完了時</summary> private void WebView_NavigationCompleted(object sender, CoreWebView2NavigationCompletedEventArgs e) { if (WebView.CoreWebView2 != null) { //ブラウザーのポップアップ発生時のイベント WebView.CoreWebView2.NewWindowRequested += CoreWebView2_NewWindowRequested; } else MessageBox.Show("WebView.CoreWebView2 == null"); } /// <summary>WebView2でのポップアップを抑止したい</summary> private void CoreWebView2_NewWindowRequested(object sender, CoreWebView2NewWindowRequestedEventArgs e) { //ポップアップを抑止 if (e.NewWindow != null) { e.NewWindow.Stop(); MessageBox.Show("ポップアップを抑止しました"); } else MessageBox.Show("e.NewWindow == null"); }ということで実行してみると、またもや「null」…
原因は、さっきと同じでWebページ側がロード未完了なことです。
ならば、さっきみたいにナビゲーション完了で拾って.Stop()をかける、というのがやりたいわけですが、そもそもナビゲーション完了イベントを設定するためのWebView2コントロールが存在しません。(ポップアップ元のWebView2とは別の物が必要になるわけです)
「e.Navigatin」が nullならば作ればいい、というわけで= new CoreWebView2();
としようとしたんですが、それはダメらしい…
苦肉の策のとして下記の様な実装となりました。Form1.cs/// <summary>ポップアップ時のイベント_WebView2でのポップアップを抑止したい</summary> private void CoreWebView2_NewWindowRequested(object sender, CoreWebView2NewWindowRequestedEventArgs e) { //本来なら、これでポップアップを抑止できるはず //だが、ロードの速度の都合で e.NewWindow(CoreWebView2)が nullになる場合があり、エラーが発生する if (e.NewWindow != null) { e.NewWindow.Stop(); MessageBox.Show("ポップアップを抑止しました"); } else { //ダミーのCoreWebView2を読み込ませてポップアップを抑止する //e.NewWindow = new Microsoft.Web.WebView2.Core.CoreWebView2(); //↑ちなみに、これはできない e.NewWindow = DummyWebView.CoreWebView2; e.NewWindow.Stop(); //これでJavaScriptが実行できる WebView.ExecuteScriptAsync("alert(\"ポップアップを抑止しました\");"); } } /// <summary>ポップアップ抑止に使用するダミーのWebView2(の中のCoreWebView2)</summary> private WebView2 DummyWebView = new WebView2 { Source = new Uri("https://www.google.co.jp/"), };「CoreWebView2」を newで作成することができないため、ダミーの「WebView2」を用意して、そこから「CoreWebView2」を取得します。
「e.NewWindow」に当てはめることで nullじゃなくなるため、「.Stop()」が適用できます。
ついでに、この処理でポップアップを抑止した場合、「ExecuteScriptAsync()」で、JavaScriptのアラートが出力される様な処理にしてあります。
処理に納得がいかない…とは思いましたが、まあ、プレリリース版だとこんなもんですかね?
もっと良い方法があったら教えてください。 m(_ _)mまとめ
とりあえず今回はこんなところです。
プレリリース版ということもあるのか、処理が所々おかしいのが気になりますね。
贅沢言わなければ、ユーザー側に「IE」を使わせないという規制をかけることができるので、そこは良いところでしょうか?本当なら、開発者ツールが表示されない様に、
WebView.CoreWebView2.Settings.AreDevToolsEnabled = false;
とできるらしいのですが、それが反応しない…。
まあ、今だと日本語リファレンスも少ないし、処理も所々おかしいので、今後に期待、というところですかね。<2020.11.16 追記>
WebView2を使ったJavaScriptとC#の連携についての記事を書いたので、リンクを貼っておきます。
https://qiita.com/NagaJun/items/baf00494e0841a5e767e
- 投稿日:2020-11-15T05:36:37+09:00
.NET 5(C#9.0)を試してみた
2020/11/10 (日本時間11日 1:00)に、.NET 5が正式リリースされたそうなので試してみました。
.NET 5のインストール手順
Visual Studio 2019のインストール/アップデート
.NET 5をVisual Studioで扱う場合は、Visual Studio 2019 Version 16.8以降が必要とのことなので、
まずはアップデートを行います。
インストールがまだの場合は、最新のVisual Studioをインストールしましょう。
Download Visual Studio 2019 for Windows & Mac既にインストールされている場合は、Visual Studio Installerを起動し、更新ボタンをクリック
または、Visual Studioの [ヘルプ] -> [更新プログラムの確認] で更新します。
アップデートが完了したら、 [ヘルプ] -> [Microsoft Visual Studio のバージョン情報] とクリック
.NET 5をインストール
いよいよ.NET 5のインストールです。
まず、ダウンロードページにて、.NET 5のSDKインストーラをダウンロードします。
(種類がいろいろあるので、自分の使ってる端末にあったものをダウンロードします。)
ダウンロードが完了したら、インストーラを起動し、インストールボタンをクリック
しばらく待つと、インストール完了の旨が表示されます。
これで、.NET 5の環境が整いました。
意外と簡単だった。.NET 5(C#9.0)を使ってみる
さっそく新規プロジェクトを作って使ってみようと思います。
コンソールアプリの作成
とりあえずコンソールからやりたいと思います。
新しいプロジェクトの作成から、コンソール アプリ (.NET Core)
を選択1して、次へのボタンをクリック
適当なプロジェクト名を決め、作成ボタンをクリック
仮に、「Dotnet5Test」としました。
プロジェクトを作成したら、まずは、プロジェクトのプロパティを開きます。
これで.NET 5が使えるようになったので、さっそくコードを書いていきましょう。
個人的に目玉なのが、トップレベルステートメントというのが追加されたそうなので、試してみたいと思います。
最初に出力されたProgram.cs
のコードは、全てコメントアウトにします。
そしたら、1行だけ書きます。System.Console.WriteLine("Hello World!");えっメインメソッドとかコメントアウトしたけど実行できるの?
できちゃいました2
トップレベルステートメントというのは、メインメソッド相当のを自動生成してくれるらしいです。
なのでいきなり標準出力の処理を書いても、勝手にメインクラスとして認識してくれるというわけですね。
(なんか感動)
ちなみに以下のコードを実行すると...using System; Console.WriteLine("外側からHello World!"); namespace Dotnet5Test { class Program { static void Main(string[] args) { Console.WriteLine("内側からHello World!"); } } }こうなります。
Mainメソッドは無視されるようです。(たしか警告が出てたような...)
他の機能を試したい場合は、以下を参照してください。
What's new in .NET 5 (英語)
C# 9.0 の新機能 (日本語)Windows Formsの作成
今度はFormsアプリを作ってみます。
Windows Forms App (.NET)で作成(dotnet5Formsで作成しました。)
プロジェクトを作成したら、先程と同じように、プロパティから、対象のフレームワークを.NET 5に変更します。
すると、Formsの場合、以下のような警告が表示されます。
警告 NETSDK1137 Microsoft.NET.Sdk.WindowsDesktop SDK を使用する必要はなくなりました。ルート プロジェクト要素の SDK 属性を 'Microsoft.NET.Sdk' に変更することをご検討ください。検討してくださいとのことなので、.csprojのProject要素のSdk属性を、Microsoft.NET.Sdkに変更します。
(1行目のところ)
ビルドすると警告が消えるのでそのまま実行してみます。
この通り、普通に実行させることができました。VS Code(コマンド)でプロジェクト作成/実行
.NET 5をインストールすると、
dotnet
というコマンドが使えるようになっています。dotnet --versionプロジェクト作成dotnet new console -o Dotnet5Test実行dotnet run感想
- .NET 5のインストールが以外と簡単だった。
- コンソールアプリに関しては、.NET 5だと入門しやすい、とっつきやすいのかなと思った。
参考サイト