C#でイベントログを書き込みます。

環境:Vista, .NET Framework 3.5, Visual Studio 2008

 

イベントソースの確認・作成

イベントログを書き込むためには、事前にイベントソースを作成する必要があります。
※管理者権限がある場合、指定したソースが存在しなくても自動的に作成されます。

if (!System.Diagnostics.EventLog.SourceExists(source))
{
	System.Diagnostics.EventSourceCreationData data = 
		new System.Diagnostics.EventSourceCreationData(source, logName);
}

 

リモートコンピュータのソースを確認・作成する場合は、コンピュータ名を指定します。

if (!System.Diagnostics.EventLog.SourceExists(source, machineName))
{
	System.Diagnostics.EventSourceCreationData data = 
		new System.Diagnostics.EventSourceCreationData(source, logName);
	data.MachineName = machineName;
	System.Diagnostics.EventLog.CreateEventSource(data);
}

 

イベントログの書き込み(登録)

イベントログに書き込みます。ソースとメッセージは必須です。

System.Diagnostics.EventLog.WriteEntry(source, message);

 

全て指定した場合は、下記のようになります。

System.Diagnostics.EventLog.WriteEntry(source, message, System.Diagnostics.EventLogEntryType.Error, eventId, category, rowData);

 

リモートコンピュータへイベントログを書き込む場合は、静的メソッドではなく、EventLog オブジェクトを作成し、動的メゾットを使います。

System.Diagnostics.EventLog evtlog = new System.Diagnostics.EventLog(logName, machineName, source);
evtlog.WriteEntry(message, System.Diagnostics.EventLogEntryType.Error, eventId, category, rowData);

 

サンプルコード(ローカルPCにイベントログを書き込む)

using System;
using System.Windows.Forms;

namespace Test
{
	public partial class Form1 : Form
	{
		public Form1()
		{
			InitializeComponent();
		}

		private void button1_Click(object sender, EventArgs e)
		{
			string source = "Sample";
			string logName = "Application";
			string message = "イベントのメッセージ";
			int eventId = 1234;
			short category = 123;
			byte[] rowData = System.Text.Encoding.Unicode.GetBytes("ABCDEFGH");

			if (!System.Diagnostics.EventLog.SourceExists(source))
			{
				System.Diagnostics.EventSourceCreationData data = 
					new System.Diagnostics.EventSourceCreationData(source, logName);
				System.Diagnostics.EventLog.CreateEventSource(data);
			}

			System.Diagnostics.EventLog.WriteEntry(source, message, System.Diagnostics.EventLogEntryType.Error, eventId, category, rowData);

		}
	}
}

 

サンプルコード(リモートコンピュータにイベントログを書き込む)

using System;
using System.Windows.Forms;

namespace Test
{
	public partial class Form1 : Form
	{
		public Form1()
		{
			InitializeComponent();
		}

		private void button1_Click(object sender, EventArgs e)
		{
			string source = "Sample";
			string logName = "Application";
			string message = "イベントのメッセージ";
			int eventId = 1234;
			short category = 123;
			byte[] rowData = System.Text.Encoding.Unicode.GetBytes("ABCDEFGH");
			string machineName = "コンピュータ名";

			if (!System.Diagnostics.EventLog.SourceExists(source, machineName))
			{
				System.Diagnostics.EventSourceCreationData data = 
					new System.Diagnostics.EventSourceCreationData(source, logName);
				data.MachineName = machineName;
				System.Diagnostics.EventLog.CreateEventSource(data);
			}

			System.Diagnostics.EventLog evtlog = 
				new System.Diagnostics.EventLog(logName, machineName, source);
			evtlog.WriteEntry(message, System.Diagnostics.EventLogEntryType.Error, eventId, category, rowData);
		}
	}
}

 

実行結果(Vista)

001

002

 

Windows XP(Windows Server 2003)以降ならば、「Eventcreate」コマンドでイベントログを書き込むことが可能です。「Eventcreate /?」で詳しい説明が表示されるので、ご確認ください。

C#でイベントログを取得します。

2つの取得方法を記載していますが、共にロカールだけでなく、コンピュータ名を指定してリモートのイベントログを取得することができます。

 

1.取得するログが決まっている場合

取得するログが決まっている場合は、まずはログにインスタンスを関連付けます。

System.Diagnostics.EventLog log = 
	new System.Diagnostics.EventLog("Application");

 

上記のログ名(Application)を「Security」や「System」に変更したり、コンピュータ名を追加で指定することも可能です。

System.Diagnostics.EventLog log = 
	new System.Diagnostics.EventLog("Security", "コンピュータ名");

 

後は、関連付けた EventLog を使用してログを取得します。
※下記コードは実際に実行すると件数を制限していないため、かなり時間がかかるのでご注意ください。

for (int i = 0; i < log.Entries.Count; i++)
{
	//イベントを発生させたアプリケーションを取得
	Console.WriteLine("Source :{0}" , log.Entries[i].Source);
	Console.WriteLine("Message:{0}" , log.Entries[i].Message);
}

 

取得できる値などは、下記のサイトをご覧ください。

EventLog メンバ
http://msdn.microsoft.com/ja-jp/library/system.diagnostics.eventlog_members%28VS.80%29.aspx

 

サンプルコード

using System;
using System.Windows.Forms;

namespace Test
{
	public partial class Form1 : Form
	{
		public Form1()
		{
			InitializeComponent();
		}

		private void button1_Click(object sender, EventArgs e)
		{
			System.Diagnostics.EventLog log = 
				new System.Diagnostics.EventLog("Application");

			int max = Math.Min(5, log.Entries.Count);
			for (int i = 0; i < log.Entries.Count; i++)
			{
				textBox1.Text += "Source : " + log.Entries[i].Source + "\r\n";
				textBox1.Text += "Message: " + log.Entries[i].Message + "\r\n";
			}
		}
	}
}

 

2.すべてのイベント ログを取得する場合

すべてのイベント ログを取得する場合、EventLog の GetEventLogsメゾットを使用します。

まずは、EventLog の配列を取得します。

System.Diagnostics.EventLog[] logs = 
	System.Diagnostics.EventLog.GetEventLogs();

 

EventLogを取得するコンピュータ名を指定することも可能です。

System.Diagnostics.EventLog[] logs = 
	System.Diagnostics.EventLog.GetEventLogs("コンピュータ名");

 

後は EventLog の配列からをEventLogを取り出して、「1.取得するログが決まっている場合」と同じようにログを取得します。
※下記コードは実際に実行すると件数を制限していないため、かなり時間がかかるのでご注意ください。

foreach (System.Diagnostics.EventLog log in logs)
{
	textBox1.Text += "LogName: " + log.Log + "\r\n";

    for (int i = 0; i < log.Entries.Count; i++)
    {
		textBox1.Text += "Source: " + log.Entries[i].Source + "\r\n";
        textBox1.Text += "Entry : " + log.Entries[i].Message + "\r\n";
    }
}

 

サンプルコード

using System;
using System.Windows.Forms;

namespace Test
{
	public partial class Form1 : Form
	{
		public Form1()
		{
			InitializeComponent();
		}

		private void button1_Click(object sender, EventArgs e)
		{
			System.Diagnostics.EventLog[] logs = 
				System.Diagnostics.EventLog.GetEventLogs();
			foreach (System.Diagnostics.EventLog log in logs)
			{
				textBox1.Text += "LogName: " + log.Log + "\r\n";

				int max = Math.Min(10, log.Entries.Count);
				for (int i = 0; i < max; i++)
				{
					textBox1.Text += "Source: " + log.Entries[i].Source + "\r\n";
					textBox1.Text += "Entry : " + log.Entries[i].Message + "\r\n";
				}
			}
		}
	}
}

 

Vistaでユーザーアカウント制御 (UAC)が有効の場合、Windows フォームアプリケーションは「管理者として実行」しないと、例外(「System.Security.SecurityException: 要求されたレジストリ アクセスは許可されていません。」)が発生しますので、可能ならばVSを管理者として実行してください。

Windows 2008R2(RC版)とIISをインストールしただけでは、ACEのOLEDB プロバイダ(Microsoft.ACE.OLEDB.12.0)が入っていないため、IISでACE(accdb)を使用することができません。

何も考えないで、Provider に「Microsoft.ACE.OLEDB.12.0」を指定したところ
「'Microsoft.ACE.OLEDB.12.0' プロバイダはローカルのコンピュータに登録されていません。 」
というエラーが返ってきてしまいました。

ということで、IIS(64ビット版)でACEを使用する方法です。

1.「Access 2007 Runtime(AccessRuntime.exe)」をダウンロードし、インストールします。

Access 2007 Runtime(AccessRuntime.exe)
http://www.microsoft.com/downloads/details.aspx?displaylang=ja&FamilyID=d9ae78d9-9dc6-4b38-9fa6-2c745a175aed

 

2.ACEのOLEDB プロバイダは32ビットのため、IISで「32 ビット アプリケーションの有効化」をtrue(有効)にします。

32bit Application on 64bit IIS7
http://www.gine.jp/blog/kusa/post/32bit-Application-on-64bit-IIS7.aspx

上記でIISから使用可能になります。

 

今回の確認で使用したコードを記載します。前回のJETとProvider以外は同じです。
※コードは32ビットも64ビット関係ありません。

 

accdb.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="accdb.aspx.cs" Inherits="accdb" %;>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd";>

<html xmlns="http://www.w3.org/1999/xhtml";>
<head runat="server";>
    <title;></title;>
</head;>
<body;>
    <form id="form1" runat="server";>
    <div;>
        <asp:Repeater runat="server" ID="rep";>
            <ItemTemplate;>
                <p;>
                <%# DataBinder.Eval(Container.DataItem, "ID")%;>
                <%# DataBinder.Eval(Container.DataItem, "姓")%;>
                <%# DataBinder.Eval(Container.DataItem, "名")%;>
                </p;>
            </ItemTemplate;>
        </asp:Repeater;>
    </div;>
    </form;>
</body;>
</html;>

 

mdb.aspx.cs
using System;
using System.Data;
using System.Data.OleDb;

public partial class accdb : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        try
        {
            //string connString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\\inetpub\\wwwroot\\db\\Database1.mdb;User Id=admin;Password=;";
            //string queryString = "SELECT ID, UserName FROM table1;";

            string connString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=c:\\inetpub\\wwwroot\\db\\northwind.accdb;User Id=admin;Password=;";
            string queryString = "SELECT ID, 姓, 名 FROM 社員;";

            using (OleDbConnection con = new OleDbConnection(connString))
            {
                OleDbCommand cmd = con.CreateCommand();
                cmd.CommandText = queryString;

                con.Open();

                rep.DataSource = cmd.ExecuteReader();
                rep.DataBind();

                con.Close();
            }

        }
        catch (Exception ex)
        {
            Response.Write(ex.Message);
        }

    }
}

デフォルトではIISは32ビットアプリが動かない状態になっており、JET(mdb)のドライバーは 32 ビット しかないため、Windows Server 2008 64bit版のIISでJET(Microsoft.Jet.OLEDB.4.0)を使用すると、「'Microsoft.Jet.OLEDB.4.0' プロバイダはローカルのコンピュータに登録されていません。 」というエラーが返ってきます。

上記は、IISで「32 ビット アプリケーションの有効化」をtrue(有効)にすることにより解決できます。

「32 ビット アプリケーションの有効化」はアプリケーションプールにありますが、下記のページに設定方法が記載されています。

32bit Application on 64bit IIS7
http://www.gine.jp/blog/kusa/post/32bit-Application-on-64bit-IIS7.aspx

 

特にサンプルコードは不要なのですが、JETへのアクセスに使用したコードを記載します。
※コードは32ビットも64ビット関係ありません。

 

mdb.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="mdb.aspx.cs" Inherits="mdb" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:Repeater runat="server" ID="rep">
            <ItemTemplate>
                <p>
                <%# DataBinder.Eval(Container.DataItem, "ID")%>
                <%# DataBinder.Eval(Container.DataItem, "姓")%>
                <%# DataBinder.Eval(Container.DataItem, "名")%>
                </p>
            </ItemTemplate>
        </asp:Repeater>
    </div>
    </form>
</body>
</html>

 

mdb.aspx.cs
using System;
using System.Data;
using System.Data.OleDb;

public partial class mdb : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        try
        {
            string connString = "Provider=Microsoft.Jet.OLEDB.4.0;;Data Source=c:\\inetpub\\wwwroot\\db\\northwind.mdb;User Id=admin;Password=;";
            string queryString = "SELECT ID, 姓, 名 FROM 社員;";

            using (OleDbConnection con = new OleDbConnection(connString))
            {
                OleDbCommand cmd = con.CreateCommand();
                cmd.CommandText = queryString;

                con.Open();

                rep.DataSource = cmd.ExecuteReader();
                rep.DataBind();

                con.Close();
            }

        }
        catch (Exception ex)
        {
            Response.Write(ex.Message);
        }

    }
}

 

※Windows Server 2008R2(RC版)で作業を行ったため、製品版では違う可能性もあります。

Making Your Own Blocks にブロックの作成方法が書かれていたので、試しに Google Chart API を使ってQRコードを表示するブロックを作成してみます。作成したファイルは「UTF-8」で保存してください。

 

1.ブロックコントローラクラス(controller.php)を作成します。

<?php
class QRCodeBlockController extends BlockController {
	var $pobj;

	protected $btDescription = "Google Chart API でQRコードを表示します。";
	protected $btName = "QRコード表示";
	protected $btTable = 'btQRCode';
	protected $btInterfaceWidth = "350";
	protected $btInterfaceHeight = "300";
}
?>
btDescription ブロックの説明
btName ブロック名
btTable データベースのテーブル名
btInterfaceHeight 追加や編集時に表示されるポップアップダイアログの幅
btInterfaceWidth 追加や編集時に表示されるポップアップダイアログの高

 

2.ブロックで使用するデータベースのテーブル定義(db.xml)を作成します。

<?xml version="1.0">
<schema version="0.3">
	<table name="btQRCode">
		<field name="bID" type="I">
			<key />
			<unsigned />
		</field>
		<field name="chl" type="X2">
		</field>
		<field name="choe" type="X2">
		</field>
		<field name="chs" type="X2">
		</field>
	</table>
</schema>

 

3.ブロック追加時に実行されるプログラム(add.php)を作成します。

作成するQRコードの設定を入力してください。

<?php echo $form->label('chl', 'text');?> <?php echo $form->text('chl', array('style' => 'width: 320px'));?> <?php echo $form->label('choe', 'output encoding');?> <?php echo $form->text('choe', array('style' => 'width: 320px'));?> <?php echo $form->label('chs', 'size');?> <?php echo $form->text('chs', array('style' => 'width: 320px'));?>

 

4.ブロック編集時に実行されるプログラム(edit.php)を作成します。

作成するQRコードの設定を入力してください。

<?php echo $form->label('chl', 'text');?> <?php echo $form->text('chl', $chl, array('style' => 'width: 320px'));?> <?php echo $form->label('choe', 'output encoding');?> <?php echo $form->text('choe', $choe, array('style' => 'width: 320px'));?> <?php echo $form->label('chs', 'size');?> <?php echo $form->text('chs', $chs, array('style' => 'width: 320px'));?>

 

5.通常表示されるHTMLのプログラム(view.php)を作成します。

<?php echo sprintf('<img src="http://chart.apis.google.com/chart?cht=qr&chl=%s&choe=%s&chs=%s" />', urlencode($chl), $choe, $chs); ?>

 

6.ブロックを追加して、データを登録します。

 qr0

text http://www.yahoo.co.jp
output encoding Shift-JIS
size 200x200

 

7.問題なければ下記のような感じでQRコードが表示されます。

qr1