.Net言語(C#,VB.Net)でCOMを実装する

もしかしたら常識なのかも知れないけれど…(^^;

あまり雑誌などでも紹介されていないと思うのですが,.Net言語でも簡単に COM を実装することができます。知らなかった…

自分のために(^^)手順をメモ。なお,ここで紹介する操作は,VS2005で行ったものです。

1. プロジェクト生成ウィザードでは「クラスライブラリ」を選択。

2. クラスの実装は次のようにします。これは C# の場合ですが,VB.Netでもほとんど同じです。

(1) System.Runtime.InteropServices をインポート。
(2) インターフェースを明示的に定義。従ってインターフェースとそれを実装するクラスの2つを記述します。
(3) クラスには ClassInterfaceAttribute で ClassInterface.None を指定して,外部へ公開しないようにしておきます。

例として作成したコードはこんな感じ。

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace ScriptLib {

public interface CsInterface {
void Message(string msg);
}

[ClassInterface(ClassInterfaceType.None)]
public class CsClass : CsInterface {
public void Message(string msg) {
MessageBox.Show(msg, "C# COM");
}
}
}

3. プロジェクトのプロパティから「アプリケーション」タブの[アセンブリ情報]を開きます。

4.「アセンブリをCOM公開可能にする」チェックボックスをONにします。ここが重要。

memo2.gif

5. プロパティ「ビルドイベント」タブの[ビルド後に実行するコマンドライン]に次のコマンドを定義します。

regasm $(TargetFileName) /tlb:$(TargetName).tlb /codebase

6. ビルドすれば出来上がり!!

ATLよりずっと簡単で,以外と使えそうです。


タグ:C# .net com

NHibernate の設定(QuickStart)

最近になって“NHibernate ( Hibernate の .Net版)”というのがあるのを,初めて知りました。さっそく,QuickStart!!

  1. NHibernate を SourceForge からダウンロードする。この記事を書いている時点での最新バージョンは 1.2.1。

  2. VisualStudio 2005 でプロジェクトを作成する。ここではC#を選択。

  3. Hibernate アセンブリをプロジェクトに追加。ソリューションエクスプローラの「参照設定」を右クリック,メニューから「参照の追加」でアセンブリ NHibernate.dll を選択して追加する。VS2005 の場合はインストールディレクトリ下の bin/net-2.0 にあるものを使用。

  4. hibernate.cfg.xml という設定ファイルを新規作成し,コンフィギュレーションを記述。

    この例は MySQL を使用する場合。その他の例は,リファレンスマニュアルに詳しく記載している。リファレンスマニュアル(nhibernate_reference.pdf)は,インストールした場所の doc/ ディレクトリにある。
    <?xml version="1.0" encoding="utf-8" ?>
    <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
    <!-- an ISessionFactory instance -->
    <session-factory>
    <property name="connection.provider">
    NHibernate.Connection.DriverConnectionProvider
    </property>
    <property name="connection.driver_class">
    NHibernate.Driver.MySqlDataDriver
    </property>
    <property name="connection.connection_string">
    Database=test;Data Source=localhost;User Id=TEST;Password=TEST
    </property>
    <property name="dialect">
    NHibernate.Dialect.MySQLDialect
    </property>

    <mapping file="config/Project.hbm.xml"/>

    </session-factory>
    </hibernate-configuration>
    これはlocalhost上のMySQLにあるtestデータベースへ,ユーザ名/パスワード=TEST/TESTで接続する例。

  5. 設定ファイルの参照をプログラム記述する。ここではリファレンスマニュアルで紹介されている方法を参考に,簡単なヘルパクラスを作成してみる。
    using System;
    using NHibernate;
    using NHibernate.Cfg;
    using log4net;

    namespace NHibernateTest {

    public sealed class NHibernateHelper {
    private static readonly string configfile = "hibernate.cfg.xml";
    private static ISessionFactory sessionFactory;
    private static ISession currentSession = null;

    static NHibernateHelper() {
    sessionFactory =
    new Configuration().Configure(configfile).BuildSessionFactory();
    }

    public static ISession GetCurrentSession() {
    if(sessionFactory != null && currentSession == null) {
    currentSession = sessionFactory.OpenSession();
    }
    return currentSession;
    }

    public static void CloseSession() {
    if(currentSession != null) {
    currentSession.Close();
    currentSession = null;
    }
    }
    }
    }

  6. 永続化対象にするクラスは,基本的に普通の定義をすればよいが,少し制限もある。
    (1) デフォルトコンストラクタを持っていること
    (2) 各メンバはプロパティ(アクセサ)を定義し,かつそれがvirtualであること
    簡単な定義をしてみる。
    namespace NHibernateTest {

    public class Project {
    public virtual int Id {
    get { return id; }
    set { id = value; }
    }
    private int id;

    public virtual string Name {
    get { return name; }
    set { name = value; }
    }
    private string name;
    }
    }

  7. 永続化クラスに対応するテーブルも作る。
    CREATE TABLE PROJECTS (
    ID BIGINT PRIMARY KEY NOT NULL AUTO_INCREMENT,
    NAME VARCHAR(40)
    );

  8. .Netクラスとテーブルを対応付けるマップファイルを作成する。
    <?xml version="1.0" encoding="utf-8" ?>
    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
    namespace="HibTest1" assembly="HibTest1">
    <class name="Project" table="Project">
    <id name="Id" column="id" type="Int32">
    <generator class="identity"/>
    </id>
    <property name="Name">
    <column name="NAME" length="40" />
    </property>
    </class>
    </hibernate-mapping>

  9. アクセスはこんな感じで。
      ISession session = NHibernateHelper.GetCurrentSession();
    ITransaction tx = session.BeginTransaction();

    Project project = new Project();
    project.Name = "test";
    session.Save(project);

    tx.Commit();
    これを実行すると,レコードが1つできる(はず)。

  10. log4net の定義も必要かもしれないので,。アプリケーション側で定義する。必要ならNHibernateに関する定義も行う。
    設定の詳細はlog4netの説明を参考にしてください。

タグ:Hibernate .net

NUnit の設定(QuickStart)

ユニットテストフレームワークJUnitの.Net移植版 NUnit のQuickStartです。


  1. Nunit を公式サイトからダウンロードする。この記事を書いている時点では,最新バージョンは 2.4.7。対象となる .Net のバージョン(1.1 or 2.0)によってバイナリが違うので注意。
  2. VisualStudio2005 でプロジェクトを生成する。またはユニットテスト対象にするプロジェクトを開く。
    namespace UnitTest {
    public class Program {
    static void Main(string[] args) {
    Console.WriteLine(new Program().sum(1, 10));
    }
    public int sum(int n1, int n2) {
    int sum = 0;
    for(int n = n1; n <= n2; ++n) {
    sum += n;
    }
    return sum;
    }
    }
    }

  3. プロジェクトの「参照の追加」→「参照」で Nunit インストールディレクトリのbin/下にある,次のアセンブリを指定して追加する。
    • nunit.core.dll
    • nunit.fixtures.dll
    • nunit.framework.dll

  4. テストクラスを記述する。JUnitと違って,テストクラス・メソッドは Attribute で指定する。



    [TestFixture]テストクラス
    [SetUp]SetUpメソッド
    [TearDown]TearDownメソッド
    [Test]テストメソッド

    テストメソッド内では Assert クラスの静的メソッドを使用する。
    namespace UnitTest {

    [TestFixture]
    public class Test {
    private Program prog = null;

    [SetUp]
    public void setup() {
    prog = new Program();
    }

    [Test]
    public void SubTest() {
    Assert.AreEqual(prog.sum(1, 2), 3);
    }

    [TearDown]
    public void tearDown() {
    prog = null;
    }
    }
    }

  5. プロジェクトをビルドする。
  6. UnitTestを実行する。ここでは NUnit GUI を使ってテストする。

    • NUnit GUI を起動。
    • File->Openメニューで,5.のビルド結果(exe, dll)ファイルを開く。ファイルが開くと,テストクラス/メソッドが認識され,ツリー表示される。
    • テストを実施するクラス・メソッドなどをツリー上で選択し,Run を実行。
    • テスト結果がグラフィカルに表示される。
タグ:.net NUnit

Windowsのユーザ一覧を取得するには(.Net)

.Net環境のプログラムからWindowsのユーザ一覧を取得するには DirectoryEntryクラスを使用します。

このクラスは,オンラインヘルプなどでは“ActiveDirectoryのノード・オブジェクトを参照する”と説明されていますが,実際には ActiveDirectoryを使用していないWorkGroup環境やDomain管理環境でも動作します。

DirectoryEntryクラスを使用して,ActiveDirectory で管理される各種のシステム情報を検索・取得することができます。
using System;
using System.Reflection;
using System.DirectoryServices;
using System.Collections.Generic;

namespace UserInfoTest {

class UserInfo {

// プロパティ値を格納するフィールド

public string Name = null;
public Byte[] objectSid = null;
public string Description = null;

/*
他に"User" エントリは以下のフィールドを
保持しています:
MaxStorage
PasswordAge
PasswordExpired
LoginHours
Description
BadPasswordAttempts
LastLogin
HomeDirectory
LoginScript
Profile
HomeDirDrive
Parameters
PrimaryGroupID
MinPasswordLength
MaxPasswordAge
MinPasswordAge
PasswordHistoryLength
AutoUnlockInterval
LockoutObservationInterval
MaxBadPasswordsAllowed
RasPermissions
objectSid
*/

// コンストラクタ

public UserInfo(DirectoryEntry userEntry) {

// フィールドと同じ名称のプロパティがあれば
// その内容をフィールドに設定します

Type myType = GetType();
foreach(FieldInfo fi in myType.GetFields()) {
PropertyValueCollection pvc
= userEntry.Properties[fi.Name];
if(pvc != null && pvc.Count > 0) {
fi.SetValue(this, pvc.Value);
}
}
}

// ユーザリストを取得します

public static List GetList(string dirpath) {

DirectoryEntry de = new DirectoryEntry(dirpath);
List userInfoList = new List();

foreach(DirectoryEntry node in de.Children) {
if(node.SchemaClassName == "User") {
userInfoList.Add(new UserInfo(node));
}
}
return userInfoList;
}

// 確認用

public static void Main(string[] args) {

// パスの指定方法は"DirectoryEntry.Path プロパティ"
// のオンラインヘルプを参照して下さい

string dirpath = "WinNT://hostname";

// 全ローカルユーザを表示します

foreach(UserInfo ui in UserInfo.GetList(dirpath)) {
Console.WriteLine(ui.Name + "," + ui.Description);
}
}

}
}
タグ:.net C#

.Net でのクエリ引数のエンコードについて

VB.Net などで HTTP を使用してファイル送受信を行いたい場合,System.Net.WebClientクラスを利用するのが最も手軽です。

WebClient.UploadFile()
ファイル送信(アップロード)
WebClient.DownloadFile()
ファイル受信(ダウンロード)

.Net の WebClientクラスを使用して HTTP ファイル転送を行う場合,クエリ引数を QueryStringプロパティを用いて次のように指定します。
Using webClient As new WebClient
webClient.QueryString("UserName") = "UserName"
webClient.QueryString("Password") = "Password"
webClient.UploadFile(uploadURI, uploadFilePath)
End Using
クエリパラメータに日本語(2バイトコード)が含まれている場合,いくつかのプログラム例では
webClient.QueryString("UserFullName") =
System.Web.HttpUtility.UrlEncode(userFullName)
のようにURLエンコードするように紹介されていますが,実際に行った結果では(少なくとも 2.0 では)最初の例のように代入するだけでエンコードが行われるようです。

なおWebClientクラスはクエリ文字列を常にUTF-8でエンコードします。受信側がこれ以外のコードを前提としている場合,例えば Tomcat のサーブレットでパラメータを取得するような場合には,コード処理に多少の工夫が必要です。

VB.Net のクライアントから Tomcat 上で動作するサーブレットにクエリ引数を渡す場合のコード例を示します。
--- VB.Net ---
Using webClient As new WebClient
webClient.QueryString("UserName") = "UserName"
webClient.QueryString("Password") = "Password"
webClient.UploadFile(servletURI, uploadFilePath)
End Using

--- Tomcat Servlet ---
protected void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
...............................................
String userName = getRequestParameter(request, "UserName");
String password = getRequestParameter(request, "Password");
...............................................
}

private String getRequestParameter(HttpServletRequest request,
String parname)
throws UnsupportedEncodingException {
String param = request.getParameter(parname);
if(param == null) {
return null;
} else {
return new String(param.getBytes("ISO-8859-1"), "UTF-8");
}
}

WEBサービスの参照先アドレスの変更(VisualStudio2005)

VisualStudio2005(VS2005)でWebサービスを使用するプログラム開発を行う場合,WSDLファイルのURLを指定した「WEB参照」をプロジェクトに定義します。

WSDLファイルが参照されるのはこの定義時のみです。プログラム実行時に参照されるWEBサービスのアドレスも,このときプロジェクトに記録されます。

しかし実際の業務では,開発環境と実行環境でWEBサービスのアドレスが異なることも多く,これでは不都合です。この場合,次のような手順を行うと,参照アドレス定義をプログラムコードの外に配置して,実行時に変更することが可能になります。
  1. 定義したWEB参照のプロパティ「URLの動作」として“ダイナミック”を指定する

  2. アプリケーションビルド時に自動生成される設定ファイルxxx.exe.configに,WEB参照URLが記録される(xxx.exeはアプリケーションの実行ファイル名)。

  3. このファイルのURLを変更すれば,プログラム起動時の参照先を指定することができる。


なお,設定ファイルxxx.exe.configはビルド実行毎に上書きされてしまいます。これを回避するためには,元ファイルであるアプリケーションのapp.configファイルの内容を,上記と同じように更新しておけばOKです。

ClickOnceアプリケーションにパラメータを渡す方法

ClickOnceで起動されるアプリケーションには,通常のプログラムのようにコマンド引数などを使用してパラメータを渡すことができません。

以下のようにClickOnceを起動するURLのクエリ文字列を使用すれば,引数を渡すことが可能です。
http://host/clickonce/ClickApp.application¶m1=value1¶m2=value2

起動されたプログラムでは,System.Deployment.Application.Deployment クラスを使用してURIを取得します。VB.Net でのプログラム例を示します。
Private Function getQueryParameters() As Dictionary(Of String, String)
Dim url As String = _
ApplicationDeployment.CurrentDeployment.ActivationUri.AbsoluteUri
Dim queryString As String = New Uri(url).Query
Dim params As String() = queryString.Replace("?", "").Split("&")
Dim result As Dictionary(Of String, String) = _
New Dictionary(Of String, String)

For Each param As String In params
Dim token As String() = param.Split("=")
If token.Length = 2 Then
result.Add(token(0), token(1))
End If
Next
Return result
End Function
タグ:ClickOnce .net

VB.Net で ini ファイルを操作する

Windowsアプリケーションの設定情報の保存方法としては,すでに過去のものになった感もあるiniファイルですが,意外な場面で必要になったりもします。

.Net ではiniファイルを直接扱うことができないため,アクセスを行うコードを書く必要がありますが,WIN32APIを使って結構簡単に実装できます。

具体的なコード例を VB.Net で書いてみます。まずは使用する WIN32API を DllImport 宣言します。
<dllimport("kernel32.dll", CharSet:=CharSet.Auto)> _
Protected Shared Function GetPrivateProfileString( _
ByVal sectionName As String, _
ByVal keyName As String, _
ByVal defaultValue As String, _
ByVal returnValue As StringBuilder, _
ByVal bufferSize As Integer, _
ByVal fileName As String) As Integer
End Function

<dllimport("kernel32.dll")> _
Protected Shared Function WritePrivateProfileString( _
ByVal sectionName As String, _
ByVal keyName As String, _
ByVal strValue As String, _
ByVal fileName As String) As Integer
End Function

後はごく普通に呼び出すだけでOKです。

デフォルトプロパティを使用して操作するクラスを作ると,連想配列的に参照・更新ができて,プログラムがシンプルになります。
Public class IniFileHandler

Private fileName As String

Public Sub New(ByRef fileName as String)
Me.fileName = fileName
End Sub

<dllimport("kernel32.dll", CharSet:=CharSet.Auto)> _
Protected Shared Function GetPrivateProfileString( _
ByVal sectionName As String, _
ByVal keyName As String, _
ByVal defaultValue As String, _
ByVal returnValue As StringBuilder, _
ByVal bufferSize As Integer, _
ByVal fileName As String) As Integer
End Function

<dllimport("kernel32.dll")> _
Protected Shared Function WritePrivateProfileString( _
ByVal sectionName As String, _
ByVal keyName As String, _
ByVal strValue As String, _
ByVal fileName As String) As Integer
End Function

Default Public Property Item(ByVal section As String, _
ByVal key As String) As String
Get
Return GetPrivateProfileString(section, key, Me.filename)
End Get
Set(ByVal value As String)
  WritePrivateProfileString(section, key, value, Me.fileName)
End Set
End Property

End Class

このクラスを使うときは,以下のようなコードになります。
Dim iniFile As IniFileHandler
iniFile = New IniFileHandler("testapp.ini")

iniFile("Section1", "key1") = "value1" '' WRITE
Dim sValue As String = iniFile("Section2", "key2") '' READ
タグ:VB.NET .net

Log4Netの設定( QuickStart

Log4Net の簡単な設定方法です。

Log4Net は Java アプリケーションで広く使用されている Jakarta/Log4J の .Net 移植版で,柔軟な設定機能とパフォーマンスのよさ(オーバーヘッドの少なさ)を特徴とするログ処理機構です。

1. ダウンロード

Log4net を Apache サイトからダウンロードします。この記事を書いている時点での最新バージョンは 1.2.10 です。

2. プロジェクト作成

VisualStudio2005 でプロジェクトを生成します。ここではVB.Netでの開発について説明しますが,その他の言語でも基本は同じです。

3. アセンブリの登録

プロジェクトの「参照の追加」→「参照」で,Log4net アセンブリを指定します。アセンブリにはいくつか種類があるので,net/2.0 にあるものを選択します。

4. AssenblyInfo の修正

VBプロジェクトにある MyProject/AssemblyInfo.vb を開きます。IDEからは選択できなくなっていますで,Explorer から直接クリックします。

AssemblyInfo に以下の指定を追記します。
<Assembly: log4net.Config.XmlConfigurator(
ConfigFile:="log4net.conf", Watch:=True)>

"ConfigFile"には設定ファイル名を指定します。ファイル指定は絶対パス・相対パスともに可能で,相対パスを指定すると,実行ディレクトリ(DEBUG時は.EXEがあるディレクトリ)からの相対パスとして解釈されます。

またここで Watch = True としておくと,ファイル更新時にプログラムを再起動しなくても読込してくれるため,オンラインでの設定変更が可能になります。

5. Configuration の記述

こんな感じで,適当に設定を書いてみます。
<log4net>
<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionpattern
value="%date [%thread] %-5level %logger [%ndc] - %message%newline">
</conversionpattern>
</layout>
</appender>

<root>
<level value="INFO">
<appender-ref ref="ConsoleAppender">
</appender-ref>
</level>
</root>
</log4net>


6. プログラムからのログ出力

次のような形式で,プログラムから Log を呼び出してみます。
Imports log4net
Imports Log4NetTestModule Log4NetTest
Private logger As ILog = LogManager.GetLogger(GetType(Log4NetTest))

Sub Main()
logger.Info("test")
End Sub

次のように,コンソールにログが出力されました。

log4net
タグ:log4net .net

ClickOnceアプリケーションをApache HTTP Serverに配置する

ClickOnceアプリケーションをホストする場合,通常は IIS を HTTPサーバとして使用すると思います。

ここでは,IIS の代わりに Apache HTTP Server を使用するための設定を紹介します。Apache を稼動するサーバは Windows 以外(Linuxなど)でも構いません。

Apacheの標準設定では,MIMEタイプのデフォルトが“text/plain”になっています。このため,ClickOnce配布ファイルをブラウザから参照すると,アプリケーションがインストールされずに配置マニフェストファイルの内容がテキスト表示されてしまいます。

Apache 側に以下のMIMEタイプ定義を追加すれば,ClickOnde アプリケーションを正常にインストールできるようになります。

 application/x-ms-application  application
 application/x-ms-manifest manifest
 application/octet-stream deploy


デフォルト設定でインストールされた Apache であれば,conf/mime.type に上の3行を追記すればOKです。

FireFoxでClickOnce を実行する

ClickOnceの起動処理には,Internet Explorer(IE) 独自のコンテント処理に依存している部分があります。そのためIE以外のブラウザでは,ClickOnceを起動することができません。

ClickOnceで配布するアプリケーションは,通常は(セキュリティ上の理由で)イントラネットを対象とすることが多いと思いますが,最近の FireFox などの普及率を考えると,他ブラウザも無視できない部分があります。

FireFoxであれば,以下の場所で配布されているAddOn を使用してClickOnceアプリを実行することができます。
https://addons.mozilla.org/firefox/1608/

ClickOnce をプログラムから起動する

ClickOnceで配布されるアプリの起動は,通常はVisualStudio2005などで生成した起動用 Web ページを使用してブラウザから実行します。

しかしクライアント上で実行されるプログラムをClickOnceで配信管理したいような場合は,この起動方法ではちょっと不便です。

そこでClickOnceプログラムから起動する方法をいくつか考案して,それぞれテストをしてみました。プログラム例はVisualBasic.Netです。

1. プログラムからsetup.exe を起動する。

次のようなプロシージャを用意して setup を実行します。
Private Sub ExecClickOnceApp()
Dim prog As String = "http:\\host\clickonce\setup.exe"
System.Diagnostics.Process.Start(prog)
End Sub

・実行毎にWebブラウザが毎回起動します。
・ダウンロード後,EXEを直接実行するための承認入力が必要になります。
p1.jpg
・規定のWebブラウザ」としてIE以外(Firefox等)が設定してある場合,インストールが自動実行されません。

※ 実用性に問題あり。

2. 配置マニフェスト(*.applicationファイル)を起動する。

setup.exe の代わりに,マニュフェストファイルでもプログラムを起動できます。
Private Sub ExecClickOnceApp()
Dim prog As String = "http:\\host\clickonce\TestWebApp.application"
System.Diagnostics.Process.Start(prog)
End Sub

※ EXE実行の承認入力が不要となる以外は,setup.exe を起動するのと同じ。

3. 配置マニフェスト(.applicationファイル)をWebBrowser で取得する。

WebBrowser コントロールを使って,配置マニュフェストを取得します。
Private Sub ExecClickOnceApp()
Dim apUrl As String = "http:\\host\clickonce\TestWebApp.application"
Dim webBrowser As New WebBrowser
webBrowser.Navigate(apUrl)
End Sub

・コントロールでファイル取得するので,ブラウザは起動されない。
・firefoxなど,IE以外のブラウザが設定されている環境でも起動できる。

※ この方法が一番都合がよさそうです。
タグ:ClickOnce .net
rank← ランキングはこちらをクリック!

×

この広告は180日以上新しい記事の投稿がないブログに表示されております。