一人情シスのつぶやき

名古屋の中小企業で一人情シスをしている作者が、日々の業務で思うことをつぶやきます。

Microsoft Report使用時のビルド時の警告

Visual Studio 2017にてMicrosoft Reportを使用するために、Nugetで[Microsoft Rdlc Report Designer for Visual Studio]をインストールすると、ビルド時に「同じ依存アセンブリの異なるバージョン間での競合が見つかりました。」と警告が表示される。実行自体は問題なくできる。

qiita.com を参考に出力の詳細レベルを上げて確認すると、ReportのアセンブリSQLServer.Typesの12.0.0に依存している一方で、NugetでReportインストール時に一緒にインストールされるSQLServer.Typesは14.0.0であるためのようだ...

依存関係の解消方法が思い付かず、また動作には影響はないため以下のサイトを参考に

方法: 自動バインディング リダイレクトを有効/無効にする | Microsoft Docs 自動バインド リダイレクトを有効化したところ、警告は出なくなった。

ClickOnceでハマる

C#で開発したクライアントアプリケーションをClickOnceで配布する際にハマった2点

Windows10へのインストール

イントラのファイルサーバに置いてある証明書が設定されていないClickOnceWindows 10で実行すると、「コンピューターにセキュリティ上の問題を発生させるため、管理者がこのアプリケーションをブロックしました。...」と表示され、[閉じる]ボタンしか表示されないために、インストールができない。 Windows 7では普通にインストールできる。

answers.microsoft.com にあるレジストリの[LocaIntranet]の値をEnabledにする必要があった。 設定変更は直ちに反映される(OS再起動は不要)

関連アセンブリの添付

上記をクリアしたうえでClickOnceを公開し、クライアントで実行すると以下のエラーが表示される。

このアプリケーションをインストールまたは実行できません。このアプリケーションでは、まずグローバルアセンブリキャッシュ(GAC)にアセンブリ Microsoft.**** バージョン *** をインストールする必要があります。

****にはVisualStudio関連のアセンブリ各種が出力される。Visual Studio 2017 Express Desktopの時は発生しなかったのだが、2017 Professionalにしたら発生した。 どうも必要なアセンブリ(.dll)を添付できていないようで、事例は異なるが、

thinkami.hatenablog.com にあるように公開設定で全てのアセンブリを「必須コンポーネント(自動)」→「含む」に変更すると解消した。

アジャイル開発手法の適用を考える

最近、アジャイル開発手法に関するセミナーや勉強会に参加している。

同開発手法が既存の手法と比較して良い面を多数含んでいることは間違いないし、勉強会や記事などでの導入事例の多さがそれを物語っている。特にベンチャーであればアジャイル以外の手法は考えられないだろう。

一方で、過去のソフトウェア資産、開発スタイルがある企業ではそう簡単な話ではない、と思っている。勉強会の参加者の話を聞くと、未だにバージョン管理も満足にできていない、という話も聞く。

セミナーや勉強会で出てくる事例は、予算や人員をある程度確保できる環境だったり、前職でアジャイル開発していて獲得したノウハウを適用するような話だったりして、自分ができる気になるところまでいかない。 また、アジャイル手法のフルセットを紹介してここがゴールというような言われ方をしたり、あるいは自分で考えて取捨選択しなさいと言われることが多い。 開発者にとってバラ色の環境を構築するための実践的な方法を期待していって、がっかりして帰ってくることの繰り返して疲れてしまっている。

現時点の自分の認識だが、アジャイル開発とは先人がまとめた優れた複数のベストプラクティスとなる開発手法である。それぞれに適用領域があり、前提条件、向いていない環境がある。ウォーターフォール開発がベスト、という環境だってある。 なので、それぞれの手法が生まれた経緯、解決する問題、前提条件を理解して自分が置かれている環境が適用可能なのかを個別に検討する必要がある。 参加する勉強会によってはこれらのいずれも示さずに、ただただ成功事例だけを提示して導入すればバラ色の未来が開けるような言い方をするところがある。多い。

既存の資産、手法、人がいてスイッチング・コストが大きく、そのコストを小さくしてくれるような手法、事例をアドバイスしてくれる奇跡的な人でもいない限り、自分で考え抜くしかないのだと気付いた。今更だが...

実行順序に依存する複数LINQ実行時の遅延評価による副作用

例えば、LINQ1にて元データよりデータを抽出し、これをデータセット1とする。 次に、LINQ2にて、元データからデータセット1を除いたデータセットに対して抽出し、これをデータセット2とする。 これをLINQ3にて、元データからデータセット1とデータセット2を除いたデータセットに対して抽出し、これをデータ・セット3とする。 ....

上記のような処理を1メソッドで行う。 後続のLINQで除外するために、除外するためのデータセットを例えばListとして保持する。

LINQ2はLINQ1の結果が決まらないと決まらない。LINQ3はLINQ2, LINQ1の結果が決まらないと決まらない。だが、後続のLINQに対して結果を伝えるのは(LINQとは無関係の)Listオブジェクト。

このような場合に、上記LINQを順番にコードで記載したとしても、除外Listの値は後続に伝わらない(ことがある?)。おそらく、プログラムの動作として最初にLINQ3の結果を参照した場合にLINQ1,LINQ2の結果を行ってから、という動きはしてくれず、結果、空の除外Listに対してLINQ3を実行してしまっているためと思われる。

遅延されるのが問題なので、LINQの実行結果 IEnumerable型のオブジェクトに対してToList()を実行してやれば即時に確定してこのような副作用は発生しなくなる。遅延評価のメリットは当然なくなるが。

C#でExcelのバージョンに依存しないCOM経由での操作

C#での社内プログラムでExcelを操作する際、大部分はClosedXMLを利用しているのだが、ActiveXを使用しているなどでうまく動作しない場合にはCOM経由で操作している。

Visual Studioで参照ツリーにExcelのCOM参照を追加するのだが、その時点でPCにインストールされているOfficeのバージョンに対応したCOMを追加する形になる。
ビルド時に参照ツリーにあるCOMを参照するため、参照追加時のPCとビルド時のPCでインストールされているOfficeのバージョンが異なると、ビルド時に警告、またはエラーとなる。

参照追加時には2013、ビルド時に2016だったためにビルド時に警告が出て、そのまま実行すると該当箇所でRuntime Errorでコケる事象が発生した。 社内には、今後2013, 2016が混在する予定のため、どちらかだけしか対応できないとなると困るので、対応方法を調査した。

参照ツリーに追加して開発する形式を事前バインディング、実行時にCOMの名前から該当のCOMを参照する形式を遅延(動的)バインディングというらしい。

  • 事前バインディング
    • Visual StudioでCOMオブジェクトの仕様を把握しているため、補完が効いて開発効率が高い
    • 型情報なども取得済みでコンパイルするため、実行速度は遅延バインディングと比較して速い
    • 使用するOfficeのバージョンを指定する必要がある。
  • 遅延バインディング
    • 使用するOfficeのバージョンを指定する必要がない
    • Visual Studioでの補完は効かず、各オブジェクト、メソッドの情報を調べながら呼び出す必要がある。大変。
    • 実行時に型チェックを行うため、遅い。実行時エラーが出る可能性も。

遅延バインディングは、各メソッドをInvokeMemberで引数を調査しながら呼び出す必要があり、とても大変。以下のサイトにこの大変さをWrapするコードが公開されていた。

Excelの参照を追加せずにExcelを使う[C#]zenmai.wordpress.com とても素晴らしいのでぜひ利用しようと考えたのだが、(当然ながら)COMオブジェクトのすべてが実装されているわけではないので不足個所を追加実装する必要があり、結構大幅な追加が必要と思われた。

で、たどり着いたのがこちらの記事。

teratail.com

なんと、dynamicという宣言に変更するだけで、ビルド時のチェックはやめて実行時に動的に呼び出してくれるとのこと。 (COMオブジェクトの生成部分は固有の書き方への変更が必要)。素晴らしい!!

実際にdyamicに変更したところ、WorkbookオブジェクトへのReleaseComObject呼び出し時にエラーが発生。

hiro-syumi.ldblog.jp こちらの記事を参照させてもらってエラー箇所のみobject型へのキャスト処理を追加したところ、問題なく動作するようになった。

このdynamicの利用だが、最初からこれを前提に行うと上記の通りVisualStudioによるサポートが効かないので開発効率はかなり落ちると思われる。今回のようにCOM参照を追加して事前バインディングで実装したうえで、dynamicに書き換えるという形が効率が良いと感じた。

Windows 2016でプログラムが起動しない

当社で利用している手形管理のシステムにて、辞書の更新をしようとしたところ、なぜかexeをクリックしても起動しない症状が発生した。

イベントログにて、以下のような内容が出力されている

ProviderName : Microsoft-Windows-Immersive-Shell
Id           : 5973
Message      : アプリ Microsoft.Windows.Apprep.ChxApp_cw5n1h2txyewy:App.AppXc99k5qnnsvxj5szemm7fp3g7y08we5vm.mca のライセンス認証がエラーで失敗しました: このアプリは、ビルトイン Administrator ではアクティブ化できません。。詳しくは、Microsoft-Windows-TWinUI/Operational ログをご覧ください。

ググっては見たが、

https://support.microsoft.com/ja-jp/help/3064045/windows-store-apps-may-not-open-and-event-id-5973-is-logged-in-the-app

のように、ストアアプリを開くときの権限の問題しかヒットしない。 エクスプローラーからダブルクリックしているのだが、ひょっとしてストアアプリ起動と認識されてしまっているのかも、と思いコマンドプロンプトで起動したところ正常に起動した。

Windows 2016の不具合なのだろうか?

thinクライアントとして使える古いPCの限界

手元に、使わなくなったノートPCが2台あったため、Windowsにリモート接続するthinクライアントとして利用してみた。 1台はメモリ512MB, もう一台は768MBでPAE非対応というところからスペックはお察し...

Linuxを探したのだが、2018/5現在、PAE非対応という時点でインストールできるディストリビューションはかなり限られる。 2,3年前はOKだったLubuntu,XubuntuですらNG。 PuppyLinuxは日本語サイトは情報が古かったため本家を見たが、PAEまたはUEFI必須のようだ... 今回はKona LinuxのLightをインストールした。

時間はかかったがインストールは成功、最初からRemminaがインストールされていたためRDP接続もできた。 ...が、遅い。キーボードの入力が画面に反映されるのにワンテンポ、タイミングによっては数秒遅れるため、作業が止まってしまう。 さすがに、この程度のスペックでは、Thinクライアントにはスペック不足ということのようだ。10年前にはストレスなく動作したはずなので、kernelが重くなったのか、Remminaが軽くないのか、RDPの通信量がそもそも少なくないのか...

少なくともメモリは2GB、CPUは2つ以上、要は無印のKona Linuxがインストールできるくらいのスペックがないと再利用すらできないことを実感した。