20200619のC#に関する記事は4件です。

型 'EventToReactiveCommand' の値は、型 'TriggerActionCollection' のコレクションまたは辞書に追加できません。

エラーメッセージ

型 'EventToReactiveCommand' の値は、型 'TriggerActionCollection' のコレクションまたは辞書に追加できません。

への対処。
System.Windows.Window.InteractivityではなくMicrosoft.Xaml.Behaviors.Wpfを使いましょう。

理由はこの辺みたいです。

WPF のビヘイビアーが入ってる Blend SDK for Visual Studio が Visual Studio 2019 で消えた件について

EventToReactiveCommandを使おうとしたけど例外!!

MVVM でイベント引数の値を ViewModel のコマンドに渡す方法を参考にやってみたらタイトルの例外で落ちてしまいました。

検索してみたら冒頭の情報とTwitterに辿り着きossの方のInteractivityを使うようにしたらすっと動きました。
地味に時間かかって悔しい。

具体的にはこんな感じです。

<Window x:Class="TestEventToReactiveCommand.Views.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:prism="http://prismlibrary.com/"

        xmlns:behaviours="http://schemas.microsoft.com/xaml/behaviors"
        xmlns:interactivity="clr-namespace:Reactive.Bindings.Interactivity;assembly=ReactiveProperty.WPF"

        xmlns:local="clr-namespace:TestEventToReactiveCommand"
        prism:ViewModelLocator.AutoWireViewModel="True"
        Title="{Binding Title}" Height="350" Width="525">

    <behaviours:Interaction.Triggers>
        <behaviours:EventTrigger EventName="MouseMove">
            <interactivity:EventToReactiveCommand Command="{Binding MouseMoveCommand}">
                <local:MouseMoveToMousePositionConverter />
            </interactivity:EventToReactiveCommand>
        </behaviours:EventTrigger>
    </behaviours:Interaction.Triggers>

    <Grid>
        <ContentControl prism:RegionManager.RegionName="ContentRegion" />
        <TextBlock
            HorizontalAlignment="Center"
            VerticalAlignment="Center"
            Text="{Binding Message.Value}" />
    </Grid>
</Window>

なんか私の場合はNugetで Microsoft.Xaml.Behaviors.Wpf を追加しないでも動いてますが、
ここによれば追加しろと書いてある??

ざっと動かしただけですが確認したソース
TestEventToReactiveCommand

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

VSCodeで「The .NET Core SDK cannot be located.」メッセージを抑止

概要

Visual Studio Code起動時に表示される以下のエラーを抑止する方法

The .NET Core SDK cannot be located. .NET Core debugging will not be enabled. Make sure the .NET Core SDK is installed and is on the path.

やり方

Disable this message in user settingsボタンを選択します。
vscd1-01.png

設定画面の検索ボックスにsuppressを入力して設定項目を絞り込みます。
Csharp:Suppress Dotnet Install Warningにチェックを入れます。
vscd1-02.png

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Windows Native C++でWinRTのOCR APIを使う方法

はじめに

こんにちは。Daddy's Officeの市川です。

私が10年以上開発を続けているWindowsPCを監視カメラシステムにする「LiveCapture3」。
先日、このソフトにOCR機能を追加して、カメラ映像内の数値を検出できるようにしました。
(この機能により、サーマルカメラを使用した自動温度計測&通知システムの構築が可能です)

「LiveCapture3」のコア機能はC++で実装しているので、C++でOCR機能を実装する必要がありました。
C++でのOCRといえば、「Tesseract」が有名ですが、今回は画像内の数値のみ検出すればよく、そこまで大掛かりにしたくありませんでした。

そこでWindowsのAPIを調べたところ、ありました!
Windows.Media.Ocr

しかし、よくよく見てみると、これはWinRTっぽい感じ。
つまり、UWPアプリやストアアプリであれば使えるのですが、デスクトップアプリから使うにはちょっと細工が必要そうです。

ということで

  • WinRTのWindows.Media.Ocrを.NetFrameworkのC#で使えるようにする
  • 上記のC# .NetFrameworkモジュールをC++から使えるようにする

という2段階で実装しました。

WinRTのWindows.Media.Ocrを.NetFrameworkで使う

言語としてはどちらもC#なので、参照を追加できれば基本はOKです。

まず、.NetFrameworkのクラスライブラリとしてプロジェクトを生成します。

OCRを使用する為には、下記のUWPライブラリが必要です。

  • Windows.Media.Ocr
  • Windows.Storage.Streams
  • Windows.Graphics.Imaging

これらを使えるようにするために、プロジェクトの参照で、直接ライブラリを追加します。
参照.jpg

追加するのは下記の2つです。

名前 パス
Windows.Foundation.UniversalApiContract C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Foundation.UniversalApiContract\8.0.0.0\Windows.Foundation.UniversalApiContract.winmd
Windows.Foundation.FoundationContract C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Foundation.FoundationContract\3.0.0.0\Windows.Foundation.FoundationContract.winmd

これで、準備はできました。

OCRエンジンの使い方は非常に簡単で、画像を渡すと認識結果の文字列が返却されるというものです。

using Windows.Graphics.Imaging;
using Windows.Media.Ocr;
using Windows.Storage.Streams;

async Task<OcrResult> detect(SoftwareBitmap bitmap)
{
     var ocrEngine = OcrEngine.TryCreateFromUserProfileLanguages();
     var ocrResult = await ocrEngine.RecognizeAsync(bitmap);
     return ocrResult;
}

ただ、面倒くさいのが

  • 引数の画像はSoftwareBitmap(WinRT)を使う必要がある
  • WinRTのAsyncは、デスクトップのasync/awaitとは違う形式になっている

というところを解決しないといけません。

色々調べた結果、以下に素晴らしい説明がありました!

Microsoft OCR をデスクトップのWFPアプリで動かす方法

参照追加の方法がちょっと違いますが、実装コードはこのまま行けました!

.NetFrameworkライブラリをC++からコールする

これは、以前私が投稿した下記のやり方で行います。

既存のC++ネイティブプロジェクトでC#マネージドコードを使う

これで、Native C++からWinRT用のOCR APIをコールしてOCR機能を実現することができました!

ソースコード

ソースコード一式(VisualStudio2019)はこちらに置いておきます。

ソースコード一式

参考

Microsoft OCR をデスクトップのWFPアプリで動かす方法
既存のC++ネイティブプロジェクトでC#マネージドコードを使う

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Windows 10 + C# + selenium で headless firefox を試してみる

Windows 10 + C# + selenium で headless firefox を試してみる

目的

FirefoxをC# + selenium からキックしてみる
OpenQA.Selenium.Support.UI.ExpectedConditions method is now deprecatedに対しては
SeleniumExtras.WaitHelpers.ExpectedConditionsで書き換えて対応してみる
※サイトの作成された時期によって修正の量が違うと思われる・・・・
PythonでのWebDriverWaitは

    element = WebDriverWait(driver, 10).until(
        EC.presence_of_element_located((By.TagName, 'h3'))
    )

を書き換えると以下になるのかいな??

    WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));            
    IWebElement firstResult = wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementExists(By.TagName("h3")));

追加パッケージ

.NETFramework 4.5でプロジェクトを作成後
プロジェクト -> NuGetパッケージの管理より以下を追加する

Selenium.WebDriver
Selenium.WebDriver.GeckoDriver
DotNetSeleniumExtras.WaitHelpers

サンプルコード

Seleniumブラウザー自動化プロジェクトのCS版を書き換えてみる

using OpenQA.Selenium;
using OpenQA.Selenium.Firefox;
using OpenQA.Selenium.Support.UI;
using SeleniumExtras.WaitHelpers;

private void btnChrome_Click(object sender, EventArgs e)
{
    var options = new FirefoxOptions();
    options.AddArgument("--headless");
    IWebDriver driver = new FirefoxDriver(options);

    try {
        WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));

        //Webページを開く
        driver.Navigate().GoToUrl("https://www.google.co.jp");

        //検索ボックスに検索ワードを入力
        IWebElement el = wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementExists(By.Name("q")));
        driver.FindElement(By.Name("q")).SendKeys("Selenium" + OpenQA.Selenium.Keys.Enter);

        //検索結果が出たという判定を何にするか?? は仕様依存??
        IWebElement firstResult = wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementExists(By.TagName("h3")));

        //ページソースの出力
        Console.WriteLine(driver.PageSource);
    }
    catch (Exception)
    {
        Console.WriteLine("Err");
    }
    finally
    {
        if (driver != null){
            driver.Quit();
        }
    }
}

参考にしたのは以下のサイト

Seleniumブラウザー自動化プロジェクト
C# Selenium 'ExpectedConditions is obsolete'
Selenium Web Driver, ExpectedConditions [deprecated] alternative
seleniumを使ってC#でGoogle Chromeの自動操作をする
【C#】Selenium ChromeDriverを使ってWebスクレイピング

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む