C# + NuGet + NuGet Package Explorerで、ローカルや共有フォルダにある既存のexeやdllを参照し、クラスを利用する

WPFでいろいろと作成していると、既存の秘伝のタレのexeやdllに含まれるクラスを使いたくなる時があります。

どうするのが一番手間がかからないかなと考えたところ、以下のようにしてローカルや共有フォルダ(以下、両方をまとめて「ローカル」と表現)でNuGetを使ってみるのが一番良さそうでした。

 
そこで、ローカルでNuGetパッケージを使ってみたときのメモを残しておきます。

 
2015/12/10 追記 ここから

公式Blogに以下の記事が掲載されましたので、Microsoft.TeamFoundation.MVVMの使用前に記事を確認してみてください。
Microsoft.TeamFoundation.MVVM 名前空間の利用について - Visual Studio サポート チーム blog - Site Home - MSDN Blogs

2015/12/10 追記 ここまで

 

環境

  • Windows7
  • .NET Framework 4.5
  • 以下を含む、ローカルNuGetパッケージ*1
    • クラスライブラリ(*.dll)
    • Windowsフォーム(*.exe)
    • WPF(*.exe)
  • ローカルNuGetパッケージ使う側: WPFアプリ (Microsoft.TeamFoundation.MVVM名前空間を使用)
  • NuGet Package Explorer 3.9.0.0

 

ローカルNuGetパッケージで管理するソリューションを作成

NuGet Package Explorerにて使うため、事前に作成しておきます。

 

ローカルNuGetパッケージの作成

手動でも作成できますが、「NuGet Package Explorer」を使ったほうがいろいろと手間が省けそうなので、そちらを使ってみました。
Nugetの使い方とパッケージの作り方 - Qiita

 
「NuGet Package Explorer」の使い方については以下が参考になりましたが、想定するケースが異なっているので、ローカルでしか使わない場合のメモを残しておきます。

 
なお、誤りやより良いやり方ががあればご指摘ください。

 

NuGet Package Explorerのダウンロード

公式サイトに行き、click here and you’re done!のリンクから、ClickOnceアプリであるNuGet Package Explorerをダウンロード・インストールします。
Using A Gui To Build Packages

 
発行者が不明みたいですが、今回はインストールを進めます。

f:id:thinkAmi:20141030060224p:plain

 

ローカルNuGetパッケージの作成

NuGet Package Explorerを起動すると以下の画面となるため、新規作成の「Create a new package」を選択します。

f:id:thinkAmi:20141030060235p:plain

 
メイン画面が表示されるため、左上の「Edit Metadata」ボタンを押します。

f:id:thinkAmi:20141030060241p:plain

 
Metadataの編集画面になるため、必要最低限のIdAuthorsを変更し、Edit assembly referencesボタンを押します。

f:id:thinkAmi:20141030060250p:plain

 
左上のGroupsの隣にある「+」(Add a new group)ボタンを押します。

f:id:thinkAmi:20141030060258p:plain

 
右下の欄が入力可能になるため、ローカルNuGetパッケージに入れるファイル名を入力し、右下の「+」(Add new reference)ボタンを押します。

f:id:thinkAmi:20141030060305p:plain

 
必要なdllやexeを追加したら、OKボタンを押します。

f:id:thinkAmi:20141030060312p:plain

 
よければ、左上の「Save」ボタンを押します。

f:id:thinkAmi:20141030060324p:plain

 
これでPackage metadataの設定が終わったため、続いて、Package contentsの設定をします。

 
Package contentsエリアの上で右クリックし、「Add Lib Folder」を選択します。

f:id:thinkAmi:20141030060333p:plain

 
Package contentsエリアにlibが表示されます。

その「lib」の上で右クリック、「Add Existing File...」を選択します。

f:id:thinkAmi:20141030060340p:plain

 
ファイルの選択画面が開くため、ローカルNuGetパッケージに入れるファイルを指定します。必要なdllやexeの追加が終わると、以下のような表示になります。

f:id:thinkAmi:20141030060348p:plain

 
よければ、左上の「FILE」 > 「Save As ...」より、NuGetパッケージを保管するフォルダを指定して、*.nupkgファイルを保存します。

f:id:thinkAmi:20141030060356p:plain

 
試しに保存された*.nupkgファイルを7zなどで解凍してみると、以下のようなものが出てきます。libフォルダの中には、ローカルNuGetパッケージのdllやexeが保存されています。

f:id:thinkAmi:20141030060404p:plain

 
これでローカルNuGetパッケージの作成が終わりました。

 

ローカルNuGetパッケージの使用

これ以降はVisualStudioでの作業になります。

 

NuGetパッケージソースの追加

ツール」 > 「NuGetパッケージマネージャー」 > 「パッケージマネージャーの設定」を選択し、その中の「パッケージソース」にて、パッケージソースを追加します。

パッケージソースはローカルや共有フォルダも指定できるため、今回は上記で作成した*.nupkgファイルのあるフォルダを指定します。

 

NuGetパッケージの追加

「プロジェクト」 > 「NuGetパッケージの管理...」を選択し、「オンライン」で先ほど追加したNuGetパッケージソースを選択すると、作成したNuGetパッケージが表示されるので、「インストール」ボタンを押します。

f:id:thinkAmi:20141030060415p:plain

 

プログラムでの使用

ローカルNuGetパッケージに含まれる名前空間が参照設定へ追加されるため、あとは他のライブラリと同様にして使います。

// WindowsFormウィンドウを開く
// WindowsFormを直接Show()できないので、
// WPFのView(WindowsFormView)のWindowsFormsHostの中にWindowsFormを貼付し、
// そのWPFウィンドウを開く
WindowDisplayService.Show("WindowsForm", new WindowsFormViewModel());


// WPFウィンドウを開く
WindowDisplayService.Show("WPF", new WPFProject.MainViewModel());


// クラスライブラリのメソッドを使ってメッセージボックスを表示
MessageBoxService.ShowInformation(DllProject.Class1.Say());

 

WPFアプリでWindowsフォームを開く方法

参考までに、WPFアプリでWindowsフォームを開く場合、以下を参考にしてひと手間をかける必要があります。

 
まずは、プロジェクトに対し、アセンブリ > フレームワークにあるWindowsFormsIntegrationへの参照を追加します。

次に、WPFのウィンドウを新規作成し、以下の設定を行います。

  • ローカルNuGetパッケージの名前空間(WindowsFormProject)を追加
  • WindowsFormsHostタグを追加
    • そのタグの子として、WindowsFormのクラスと、TopLevelFormBorderStyleプロパティを設定

 

<Window x:Class="NuGetUser.WindowsFormView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:form="clr-namespace:WindowsFormProject;assembly=WindowsFormProject"
        Title="WindowsFormView" Height="300" Width="300">
    <Grid>
        <WindowsFormsHost>
            <form:Form1 TopLevel="False" FormBorderStyle="None"/>
        </WindowsFormsHost>
    </Grid>
</Window>

 
これで、新規WPFアプリからローカルNuGetパッケージに含まれるWindowsフォームを表示することができるようになります。

 

ローカルNuGetパッケージの更新

いろいろとプログラムを書いてゆくうちに、ローカルNuGetパッケージを時々更新することがあるかもしれません。

ただ、上記で見た通り、*.nupkgファイルにはdllやexeが含まれています。そのため、ローカルNuGetパッケージ用のソリューションをリビルドしても、ローカルNuGetパッケージへは反映されません。

そこで、ローカルNuGetパッケージ更新時の作業もメモとして残しておきます。

こちらも、誤りやより良い方法があればご指摘ください。

 

NuGet Package Explorerでの作業
Package contentsにてlib中のdllやexeを更新

ローカルNuGetパッケージをリビルドなどした時に、NuGet Package Explorerを開いたままであれば、以下のようなウィンドウが出て、libの中身が削除されます。

f:id:thinkAmi:20141030060426p:plain

そのため、再度上記の手順にてdllやexeを指定します。

 
もし、NuGet Package Explorerを開いていない場合には、リビルド後に*.nupkgファイルを開き、各dllやexeの上で右クリック、「Replace with...」を選択して再度exeやdllを指定します。

f:id:thinkAmi:20141030060434p:plain

 

Package metadataの修正と保存

Package metadataの「Edit metadata」ボタンを押し、Versionを更新して、「Save」ボタンを押します。

f:id:thinkAmi:20141030060442p:plain

 
そして、ファイルを保存します。 ただし、「FILE」 > 「Save」とすると以下の画面が出るため、誤らないためにも「Save As...」の方が良いかもしれません。

f:id:thinkAmi:20141030060452p:plain

 
保存しようとすると、すでにファイル名にバージョンが付加された状態になっているので、そのまま適切な場所へと保存します。

f:id:thinkAmi:20141030060500p:plain

 

ローカルNuGetパッケージを使う側の作業

NuGetパッケージの管理を開くと、更新に新しいバージョンが登場しているため、更新ボタンで更新を行います。

f:id:thinkAmi:20141030060509p:plain

 
その後、使う側のプログラムを実行すると、ローカルNuGetパッケージの内容が更新されていることが分かりました。

 

ソースコード

GitHubに上げました。

ローカルNuGetパッケージ

*.nupkgファイルも同梱してあります。
CSharp-Sample/LocalNuGetPackage at master · thinkAmi/CSharp-Sample

ローカルNuGetパッケージを使う側

CSharp-Sample/LocalNuGetUser at master · thinkAmi/CSharp-Sample

 

参考

VisualStudioを使って手作業で行う場合には、以下が参考になりました。
neue cc - NuGetパッケージの作り方、或いはXmlエディタとしてのVisual Studio

あとは公式ドキュメントです。
Creating And Publishing A Package

*1:都合上、今回は1つのソリューションにまとめ、プロジェクトを分けました