NETCore SDK プロジェクトでnugetパッケージを作成する

NETCore SDK プロジェクトでnugetパッケージを作成してみたのでその手順をまとめたいと思います。(VisualStudioなどは予めインストールされていることとします。)

nuspecファイルを作成する

nugetパッケージを作成するためnuget specコマンドを実行してnuspecファイルを作成します。

> cd /path/to/project
> nuget spec

nuspecファイルを編集する

作成したnuspecファイルの内容を編集します。が、VisualStudioを利用している場合には特に編集する必要はない気がします。

<?xml version="1.0"?>
<package >
  <metadata>
    <id>$id$</id>
    <version>$version$</version>
    <title>$title$</title>
    <authors>$author$</authors>
    <owners>$author$</owners>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>$description$</description>
    <releaseNotes>Summary of changes made in this release of the package.</releaseNotes>
    <copyright>Copyright 2017</copyright>
  </metadata>
</package>

nugetパッケージを作成する

NETCore SDK プロジェクトではnuget pack {プロジェクト名}を実行すると型 'System.String' のオブジェクトを型 'NuGet.Frameworks.NuGet.Frameworks1051960.NuGetFramework' にキャストできません。というエラーが発生しパッケージを作成することができません。

NuGet pack Unable to cast object of type 'System.String' to type 'NuGet.Frameworks.NuGetFramework' · Issue #4808 · NuGet/Home

上記のIssueに書いているとおりmsbuild /t:packで実行すればうまく作成できます。

$ msbuild /t:pack
.NET Framework 向け Microsoft (R) Build Engine バージョン 15.4.8.50001
Copyright (C) Microsoft Corporation.All rights reserved.

このソリューション内のプロジェクトを 1 度に 1 つずつビルドします。並行ビルドを有効にするには、"/m" スイッチを追加してください。
2017/12/09 13:24:13 にビルドを開始しました。

....

ビルドに成功しました。
    0 個の警告
    0 エラー

経過時間 00:00:01.37

おわりに

はじめてnugetパッケージを作成してみたのですが、とてもかんたんにできました。MS製品は製品内の完結度が高くて何かを始めるのが楽なのが素敵です。

C#実践開発手法 (マイクロソフト公式解説書)

C#実践開発手法 (マイクロソフト公式解説書)

Resharperで参照しているクラスのソースコードを表示する

ResharperではNugetなどで参照しているライブラリのソースコードをでコンパイルするなどして表示してくれます。その設定についてまとめたいと思います。

設定方法

Resharperの設定は メニューバーのResharper からOptionsを表示します。Tools - External Sourcesを選択し、Navigation to Sourcesを選択します。

image.png (195.6 kB)

利用不法

NuGetなどで参照しているクラスを右クリックし、Go To Implementationをクリックします。

image.png (112.0 kB)

これにより対象となるクラスのソースコードが表示されます。

image.png (150.4 kB)

以前と違ってNuGetを参照するライブラリについても内容を手軽に確認できると開発が捗るのでおすすめです。

ASP.NET MVCプログラミング入門 (マイクロソフト関連書)

ASP.NET MVCプログラミング入門 (マイクロソフト関連書)

Azure FunctionsでOpenCVSharpを利用したアプリケーションを作ったときにハマったこと

Azure FunctionsでOpenCVSharpを利用した画像の加工を行おうとしたのですが、以下の点でうまく動作しませんでした。

最初の構成

OpenCV3.2 All-in-one package - bundles native OpenCV DLLs: .NET Framework wrapper for OpenCVを利用してx86またはx64でアプリケーションをビルドし、ローカル環境で正常に動作することを確認しました。

そこでAzureFunctionsへデプロイして実行したところ、以下の通りエラーが発生し動作しないことがわかりました。

Exception while executing function: IneiConvertFunction
Microsoft.Azure.WebJobs.Host.FunctionInvocationException : Exception while executing function: IneiConvertFunction ---> System.TypeInitializationException : The type initializer for 'OpenCvSharp.NativeMethods' threw an exception. ---> System.DllNotFoundException : Unable to load DLL 'OpenCvSharpExtern': The specified module could not be found. (Exception from HRESULT: 0x8007007E)
   at OpenCvSharp.NativeMethods.redirectError(CvErrorCallback errCallback,IntPtr userdata,IntPtr& prevUserdata)
   at OpenCvSharp.NativeMethods.LoadLibraries(IEnumerable`1 additionalPaths)
   at OpenCvSharp.NativeMethods..cctor() 
   End of inner exception
   at OpenCvSharp.NativeMethods.imgcodecs_imread(String filename,Int32 flags)
   at OpenCvSharp.Mat..ctor(String fileName,ImreadModes flags)
   at ReportFunctions.IneiConvertUtils.IneiConverter.Convert(String filePath)
   at ReportFunctions.IneiConvertFunction.Run(Stream ineiFileBlob,String name,TraceWriter log)
   at lambda_method(Closure ,IneiConvertFunction ,Object[] )
   at Microsoft.Azure.WebJobs.Host.Executors.VoidMethodInvoker`2.InvokeAsync(TReflected instance,Object[] arguments)
   at async Microsoft.Azure.WebJobs.Host.Executors.FunctionInvoker`2.InvokeAsync[TReflected,TReturnValue](Object instance,Object[] arguments)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at async Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.InvokeAsync(IFunctionInvoker invoker,ParameterHelper parameterHelper,CancellationTokenSource timeoutTokenSource,CancellationTokenSource functionCancellationTokenSource,Boolean throwOnTimeout,TimeSpan timerInterval,IFunctionInstance instance)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at async Microsoft.Azur…

この時点ではデプロイする時に何かファイルが不足しているなどが原因かと思っていました。KuduのDebug Consoleでデプロイされたファイルなどを比較してみたのですが、特に不足しているファイルなどは見当たりませんでした。

とりあえず何か足りないらしい…

さて、とりあえずこの段階でAzureFunctionsの利用をやめてVMにでも環境を構築してお茶を濁そうかとも思ったのですが、せっかくここまで作ったのでもうちょっと調べてみようと思いました。

とりあえずデプロイされているファイルの一式は特に変わりないのでアプリケーションの実行環境に差異があるのではと思い、OpenCVShapの動作環境を確認しました。

shimat/opencvsharp: .NET Framework wrapper for OpenCV

OpenCV 3.2 Visual C++ 2015 Redistributable Package .NET Framework 2.0 or later / .NET Core / Mono

とりあえず、NuGetパッケージを利用しているのでOpenCV本体については考える必要はなさそうでした。またKuduのDebug Consoleでインストールされている.NET Frameworkのバージョンを確認しましたが以下の通り問題ないことがわかりました。

D:\home>dotnet --version
2.0.3

ということで、3つの前提条件の打ち2つは問題ないことがわかったのですが、最後のVisual C++ 2015 Redistributable Packageをどのように確認するかです。

Visual C++ 2015 Redistributable Packageはインストールされていない

ここからはGoogleでいろいろなキーワードで検索する以外にい方法が思いつきませんでした。そう、私はC++での開発経験はないのでこの辺はさっぱりわからないからです(´ω`)

とはいえ、10分位アレヤコレヤと調べたところ以下のサイトに辿り着きました。

Visual C++ Redistributable Packages for Visual Studio Azure App Service – benjamin perkins

Azure Functionsは Azure App Serviceで動作しているので多分同じようにすれば調べられるだろうと思い早速試してみることにしました。

// Visual C++ Redistributable Packages for Visual Studio 2015
// x64
D:\home>reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Installer\Dependencies\{d992c12e-cab2-426f-bde3-fb8c53950b0d} "
ERROR: The system was unable to find the specified registry key or value.

// x86
D:\home>reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Installer\Dependencies\{e2803110-78b3-4664-a479-3611a381656a}"
ERROR: 
The system was unable to find the specified registry key or value.

// Visual C++ Redistributable Packages for Visual Studio 2013
// x64
D:\home>reg query "HKLM\SOFTWARE\Classes\Installer\Dependencies\{050d4fc8-5d48-4b8f-8972-47c82c46020f}"

HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Installer\Dependencies\{050d4fc8-5d48-4b8f-8972-47c82c46020f}
    (Default)    REG_SZ    {050d4fc8-5d48-4b8f-8972-47c82c46020f}
    Version    REG_SZ    12.0.30501.0
    DisplayName    REG_SZ    Microsoft Visual C++ 2013 Redistributable (x64) - 12.0.30501

HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Installer\Dependencies\{050d4fc8-5d48-4b8f-8972-47c82c46020f}\Dependents

// x86
D:\home>reg query "HKLM\SOFTWARE\Classes\Installer\Dependencies\{f65db027-aff3-4070-886a-0d87064aabb1}"

HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Installer\Dependencies\{f65db027-aff3-4070-886a-0d87064aabb1}
    (Default)    REG_SZ    {f65db027-aff3-4070-886a-0d87064aabb1}
    Version    REG_SZ    12.0.30501.0
    DisplayName    REG_SZ    Microsoft Visual C++ 2013 Redistributable (x86) - 12.0.30501

HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Installer\Dependencies\{f65db027-aff3-4070-886a-0d87064aabb1}\Dependents

どうやらVisual C++ Redistributable Packages for Visual Studio 2015についてはインストールされておらずVisual C++ Redistributable Packages for Visual Studio 2013であればインストールされているようです。

OpenCVSharp2.4を利用する

ここまででとりあえず現状のままだとOpenCVSharp3をAzure Functionsで動作させるのは無理そうだということになります。いや、ひょっとしたらVisual C++ Redistributable Packages for Visual Studio 2015をインストールするような方法があるのかもしれませんが、ちょっとわかりませんでした。

そこで、Visual C++ Redistributable Packages for Visual Studio 2013で動作するOpenCVSharpのバージョンを確認したところ2.4.10であれば動作することがわかりました。

shimat/opencvsharp_2410: .NET Framework wrapper for OpenCV 2.4.10

OpenCV 2.4.10 Visual C++ 2013 Redistributable Package .NET Framework 2.0 or later / Mono

これまで作っていたものを少し修正する必要がありますが、環境面ではこのバージョンで動作させることができそうだということがわかりました。

最終的に…

最終的にOpenCVSharp2.4.10を利用してAzure FunctionsでOpenCVを利用した画像加工処理を実装することができました。やりたいことが非常に単純なことで、Azure Storage のBlobContainerにファイルがアップロードされたら処理をしたいというだけだったので、この方法は最適でした。

Azure Functionsについては昨日始めて触ったのですが、一日位で一つの処理を動かすことができて満足しています。責務が明確な小さな処理は積極的に利用していこうかなと思いました。

Azureテクノロジ入門 2018

Azureテクノロジ入門 2018

  • 作者: 久森達郎、真壁徹、大田昌幸、藤本浩介、佐藤直生、安納順一、松崎剛、高添修,日本マイクロソフト株式会社
  • 出版社/メーカー: 日経BP社
  • 発売日: 2017/11/17
  • メディア: 単行本
  • この商品を含むブログを見る