最近のトラックバック

2017年4月
            1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30            

Google AdSense2

« 2009年3月 | トップページ | 2009年6月 »

2009年5月

Web APIのレスポンスXML形式データをJSONに変換

WebAPIから送られたXML形式データをJSONに変換について記述する。
「XML→JSONへのデータ変換」および「プロキシサーバアクセス」に「JKL.ParseXML」というJavaScriptライブラリを利用している。


■JKL.ParseXMLの入手
Kawa.net xpJKL.ParseXML/ajax通信処理ライブラリからダウンロード出来る。
同ページにはライブラリの使用方法も記述されている。
ライセンスは「修正BSD」。


■サンプル
このサンプルソースには以下の注意点がある。
①fnProxyXml2Json()メソッド内では本ブログの別記事の「ASP.NET(C#)でWeb API中継用プロキシサーバを作ってみた」で紹介したプロキシサーバを利用している。
このサーバはインターネット上に存在しないため、各自で利用するプロキシサーバに書き直す必要がある。
②価格調査で有名な価格.comが提供している「価格.com Webサービス」、および文字コード変換するJavaScriptライブラリ「Escape Codec Library: ecl.js」を利用している。
サンプルを試す場合、事前に「ecl.js」を入手する必要がある。
「ecl.js」は「価格.com Webサービス」で検索条件をSJISでエンコードするために利用している。


<!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>
<title>ASP.NET Webサービスプロキシ&XML→JSON変換テスト</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<script src="jkl-parsexml.js" type="text/jscript"></script>
<script src="ecl.js" type="text/jscript"></script>
<script type="text/javascript">

/// <summary>
/// 価格.com Webサービスのキー(貴方のIDを設定してください)
/// </summary>
var g_sKakakuApiKey = "XXXXXXXXXXXXXXXXXXXX";

/// <summary>
/// REST通信&取得したXMLデータをJSON変換
/// </summary>
/// <param name="url">REST対象のURL</param>
/// <param name="callbackFnc">コールバックファンクション</param>
function fnProxyXml2Json(url, callback)
{
    //---------------------------------------------------------------------------------------------
    // 自鯖プロキシサーバのURL作成(ASP.NET向け)
    // ※ここは各自で利用しているプロキシサーバのURLに書き換えてね。
    //---------------------------------------------------------------------------------------------
    // 自分のサーバ+仮想フォルダのURLを取得
    var sVirtualUrl = window.location.href;
    var i = sVirtualUrl.indexOf('/', "http://".length);
    i = sVirtualUrl.indexOf('/', i+1);
    sVirtualUrl = sVirtualUrl.substr(0, i+1);
    // URLのクロスドメイン対策の自鯖にPROXYサーバURL作成 
    var sProxyUrl = sVirtualUrl + "Service.asmx/fnCallUrl?sUriEncodingURL=" + encodeURIComponent(url);
    //---------------------------------------------------------------------------------------------
    // jkl-parsexml.js経由でPROXYサーバにアクセス&XMLをJSON変換
    //---------------------------------------------------------------------------------------------
    var xml = new JKL.ParseXML(sProxyUrl);
    xml.async(callback , true)
    var data = xml.parse();
}
/// <summary>
/// プロキシサーバからの受信先メソッド
/// <summary>
function fnReturnJson(res)
{
    var divResult = document.getElementById("divResult");
    //---------------------------------------------------------------------------------------------
    // 受信したresオブジェクトはXML→JSONに変換されている。
    //---------------------------------------------------------------------------------------------
    // 該当製品なし
    if (typeof(res.ProductInfo) == "undefined")
    {
        divResult.innerHTML = "該当製品は見つかりませんでした。";
        return;
    }
    // 検索結果表示
    divResult.innerHTML =
        "<span style=\"background-color:red; color: white; ;font-size:large;\">" + 
        "検索件数: " + 
        res.ProductInfo.NumOfResult + "件中、" + res.ProductInfo.Item.length + "件表示" + 
        "</span><br />";
    for (var i = 0; i < res.ProductInfo.Item.length; i++) {
        var sRecord = "";
        sRecord += "製品名:" + res.ProductInfo.Item[i].ProductName + "<br />";
        sRecord += "最低価格:" + res.ProductInfo.Item[i].LowestPrice + "<br />";
        sRecord += "<img src=\"" + res.ProductInfo.Item[i].ImageUrl + "\" />";
        sRecord += "<hr />";
        divResult.innerHTML += sRecord;
    }
}
/// <summary>
/// [プロキシサーバ通信]ボタン押下
/// <summary>
function evSendRequest()
{
    //---------------------------------------------------------------------------------------------
    // XML形式のデータをレスポンスする価格.com Webサービスにアクセス
    //---------------------------------------------------------------------------------------------
    var sKeyword = document.getElementById("txtSearch").value;
    var sKakakuRestUrl = "http://api.kakaku.com/WebAPI/ItemSearch/Ver1.0/ItemSearch.aspx";
    sKakakuRestUrl += "?Keyword=" + EscapeSJIS(sKeyword);    // ← ecl.jsを使っているのはここだけ
    sKakakuRestUrl += "&ApiKey=" + g_sKakakuApiKey;
    fnProxyXml2Json(sKakakuRestUrl, fnReturnJson);
}
</script>
</head>
<body>
    <h1>ASP.NET Webサービスプロキシ&XML→JSON変換テスト</h1>
    <span style="font-size:x-small; color:Gray;">
        自鯖プロキシを経由して価格.comのWebAPIからデータ取得&XMLデータをJSON化:
    </span>
    <br />
    <input type="text" id="txtSearch" value="Intel Core 2 Quad" />
    <input type="button" onclick="evSendRequest();" value="検索" />
    <hr />
    <br />
    <div id="divResult" style="background-color:#f0f0f0;"></div>
</body>
</html>

価格.com Webサービスで「Intel Core 2 Quad」を検索したときの検索結果XML


検索結果イメージ


■参考URL


■関連ページ

ASP.NET(C#)でWeb API中継用プロキシサーバを作ってみた

ASP.NET(C#)でWeb API中継用プロキシサーバを作ってみた。
※本内容はWebAPI利用時に問題となるクロスドメイン対策のためのプロキシサーバ作成を目的としてます。
※WebAPIから取得したXML形式のデータをJSON変換に利用したい場合、別記事の Web APIのレスポンスXML形式データをJSONに変換を参照してほしい。


■最初に
開発環境は以下の通り

  • Visual Studio 2008 SP1
  • .NET Framework 3.5 SP1
  • ASP.NET3.5 (ASP.NET Webサービス)

※本内容だけでは不正アクセスへの対応は不十分です。


■中継サーバ作成
1.「ASP.NET Webサービス」プロジェクト作成


フォルダ/ファイル構成


2.web.configの変更
web.configにwebServicesタグを加える。


<configuration>
  <system.web>
    :
    :
    <!--  WebServiceアクセスを許可する。(*.asmxを使ったWebサービス通信) -->
    <webServices>
      <protocols>
        <add name="HttpPost" />
        <add name="HttpGet" />
      </protocols>
    </webServices>
  </system.web>
</configuration>

3.プロキシサーバ作成
プロジェクトに最初から存在するService.csを変更。

using System;
using System.IO;
using System.Net;
using System.Text;
using System.Web;
using System.Web.Script.Services;
using System.Web.Services;

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
// この Web サービスを、スクリプトから ASP.NET AJAX を使用して呼び出せるようにするには、次の行のコメントを解除します。 
[System.Web.Script.Services.ScriptService]
public class Service : System.Web.Services.WebService
{
    /// <summary>
    /// コンストラクタ
    /// </summary>
    public Service () {

        //デザインされたコンポーネントを使用する場合、次の行をコメントを解除してください 
        //InitializeComponent(); 
    }
    /// <summary>
    /// 外部サーバURLのREST呼び出し
    /// </summary>
    /// <param name="sUriEncodingURL">URIエンコードされた外部サーバURL</param>
    /// <remarks>
    /// クロスドメイン対策プロキシ<br />
    /// 常に安全対策を考慮すること<br />
    /// </remarks>
    [WebMethod]
    [ScriptMethod]
    public void fnCallUrl(string sUriEncodingURL)
    {
        HttpRequest req = HttpContext.Current.Request;
        HttpResponse res = HttpContext.Current.Response;
        //-----------------------------------------------------------------------------------------
        // 不正アクセス対策
        //-----------------------------------------------------------------------------------------
        // 別ホストサーバ経由のアクセスの場合は何もしない
        if (req.UrlReferrer.Authority != req.Url.Authority)
        {
            return;
        }
        // Basic認証、ログインパスワード、ワンタイムパスワードなど
        ;
        //-----------------------------------------------------------------------------------------
        // 外部サーバからデータを取り出す。
        //-----------------------------------------------------------------------------------------
        WebRequest wrGETURL = WebRequest.Create(sUriEncodingURL);
        WebProxy myProxy = new WebProxy("call_proxy", 80);
        myProxy.BypassProxyOnLocal = true;
        string sContent;
        using (Stream objStream = wrGETURL.GetResponse().GetResponseStream())
        using (StreamReader objReader = new StreamReader(objStream, Encoding.GetEncoding("UTF-8")))
        {
            sContent = objReader.ReadToEnd();
            objReader.Close();
            objStream.Close();
        }
        //-----------------------------------------------------------------------------------------
        // レスポンスにコンテンツ内容を書き出す
        //-----------------------------------------------------------------------------------------
        res.Clear();
        //res.AddHeader("Content-Type",~);
        //res.AddHeader("Pragma", "no-cache");
        res.Write(sContent);
    }
}

4.テスト用XML作成
動作確認用にXMLFile.xmlを作成。
内容は何でもよい。

<?xml version="1.0" encoding="utf-8" ?>
<address>
  <item>
    <country>日本</country>
    <city>東京</city>
  </item>
  <item>
    <country>日本</country>
    <city>大阪</city>
  </item>
  <item>
    <country>日本</country>
    <city>名古屋</city>
  </item>
</address>

5.テスト用HTML作成
稼働確認用のHTMLファイルtest.htmを作成。
非同期通信で中継プロキシにアクセス。

<!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>
<title>Proxyテスト</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<script type="text/javascript">

/// <summary>
/// 価格.com Webサービスのキー(貴方のIDを設定してください)
/// </summary>
var g_sKakakuApiKey = "XXXXXXXXXXXXXXXXXXXX";

/// <summary>
/// 非同期リクエスト
/// <summary>
function fnAjaxRequest(sUrl, fnCallback)
{
    var res;
    //---------------------------------------------------------------------------------------------
    // 非同期リクエストオブジェクト作成
    //---------------------------------------------------------------------------------------------
    if (window.XMLHttpRequest) {
        res = new XMLHttpRequest();
    }
    else {
        try {
            res = new ActiveXObject("Msxml2.XMLHTTP");
        } catch(e)
        {
            res = new ActiveXObject("Microsoft.XMLHTTP");
        }
    }
    //---------------------------------------------------------------------------------------------
    // 非同期リクエスト
    //---------------------------------------------------------------------------------------------
    // リクエスト準備
    res.open("GET", sUrl, true);
    res.setRequestHeader("Content-Type","application/x-www-form-urlencoded; charset=UTF-8");
    // レスポンス呼出の準備
    res.onreadystatechange = function() {
        if (res.readyState == 4) {
            fnCallback(res);
        }
    }
    // リクエスト
    res.send(null);
}
/// <summary>
/// プロキシサーバからの受信先メソッド
/// <summary>
function fnSendResponse(res)
{
    var divResult = document.getElementById("divResult");
    divResult.innerText = res.responseText;
}
/// <summary>
/// [プロキシサーバ通信]ボタン押下
/// <summary>
function evSendRequest()
{
    var sVirtualUrl;
    var sCallUrl;
    //---------------------------------------------------------------------------------------------
    // サーバURLおよびフォルダ取得
    //---------------------------------------------------------------------------------------------
    sVirtualUrl = window.location.href;
    var i = sVirtualUrl.indexOf('/', "http://".length);
    i = sVirtualUrl.indexOf('/', i+1);
    sVirtualUrl = sVirtualUrl.substr(0, i+1);
    //---------------------------------------------------------------------------------------------
    // 呼び出し先URL取得
    //---------------------------------------------------------------------------------------------
    var selCallUrl = document.getElementById("selCallUrl");
    switch(selCallUrl.value)
    {
        // 価格.com WEBサービス(REST)
        case "kakaku":
            sCallUrl = "http://api.kakaku.com/WebAPI/ItemSearch/Ver1.0/ItemSearch.aspx";
            sCallUrl += "?Keyword=%83o%83C%83I&CategoryGroup=pc&ResultSet=medium&SortOrder=pricerank&PageNum=1";
            sCallUrl += "&ApiKey=" + g_sKakakuApiKey;
            break;
        // Yahoo!トップページ
        case "yahoo":
            sCallUrl = "http://yahoo.co.jp";
            break;
        // 自鯖XMLファイル
        case "xml":
            sCallUrl = sVirtualUrl + "XMLFile.xml";
            break;
    }
    //---------------------------------------------------------------------------------------------
    // 作成したプロキシサーバに非同期リクエスト
    //---------------------------------------------------------------------------------------------
    // プロキシサーバURL作成
    var sProxyUrl = sVirtualUrl + "Service.asmx/fnCallUrl?sUriEncodingURL=";
    // リクエストURL作成
    var sRequestUrl = sProxyUrl + encodeURIComponent(sCallUrl);
    // 非同期リクエスト
    fnAjaxRequest(sRequestUrl, fnSendResponse);
}
</script>
</head>
<body>
    <select id="selCallUrl">
        <option value="kakaku" selected="selected">価格.com WEBサービス(REST)</option>
        <option value="yahoo">Yahoo!トップページ</option>
        <option value="xml">自鯖XMLファイル</option>
    </select>
    <input type="button" onclick="evSendRequest();" value="プロキシ通信" />
    <div id="divResult" style="background-color:#f0f0f0;"></div>
</body>
</html>

6.稼働確認
・価格.com Webサービス(REST)への中継結果

・Yahoo!トップページへの中継結果

・自分のサーバのXMLFile.xlsに中継した結果


■中継サーバ運用時の注意
  • セキュリティ(不正アクセスの温床になったり、踏み台にされないこと)
  • 文字コードはWebAPIでは主にUTF-8だがShift-JIS等の他の文字コードもあるので注意。


■参考URL


■関連ページ

「Google Maps」「Yahoo!地図」「Virtual Earth」の共通インタフェース作成

題名も本文もソースコードも長いので注意してね!

2つ以上の地図系WebAPIを使ったことがある人は「表示も操作も似ているんだからAPIをインタフェース化できないか?」と 考える人も多いと思う。
そんな他愛もないことに挑戦してみました。

なお本インタフェースは「デュアルマップサービス」で使った機能だけのため網羅度は非常に低い。
情報ウィンドウやポリゴンなど基本的な機能ですら対応していないので注意してほしい。
興味のある人は機能補完をよろしく!


■利用した地図API
利用した地図APIは以下の通り(※2009/05/23時点では各API共に最新だと思う。)

  • Google Maps API(GMap2オブジェクト)
  • Yahoo!地図Web API(Ver.2?)
  • Windows Virtual Earth SDK(ver.6.2)



■基本方針
「各地図で固有機能がある」「バージョンアップも活発」等の理由で全APIの共通化は無理。
他に「測地系」「表示スケール」「ズーム範囲」等、同じ機能でも地図ごとに違いがある。
「Virtual Earth」に至っては地図の種類が違うだけで設定値や利用不可になるAPIも存在する。

というわけで以下の基本方針を作った。

  • 全ての地図で対応している「世界測地系」を利用。
  • 表示スケールの違いは視認判定で作り込み。
    (Yahooは最小スケール60mだからGoogleの最小スケール50mに合わせる等)
  • ズーム範囲の違いは視認判定で作り込み。
  • 同じ機能だけインタフェース化。なくても必要かつ簡単に作れる機能は自作。
  • 必要機能だけインタフェース化。
  • 可能な限り固有機能も使えるようにする。


■インタフェース
上でも書いたけど機能の網羅度は非常に低い。
興味のある人は機能補完をよろしく!

クラス・列挙型

クラス名 概要
OmYMap 「Yahoo!地図Web API」のYahooMapsCtrlクラスを共通インタフェース化したクラス
OmGMap 「Google Maps API」のGMap2クラスを共通インタフェース化したクラス
OmVMap 「Windows Virtual Earth SDK」のVEMapクラスを共通インタフェース化したクラス
OmLatLng 各種APIの緯度・経度クラスの差異を吸収した緯度・経度クラス
OmMapKind 地図の識別オブジェクト(列挙:YMap/GMap/VMap)

OmYMap・OmGMap・OmVMapのコンストラクタ
関数名 シグニチャ 備考
コンストラクタ function(sDivId, iLat, iLng,
  iZoom, enMapMode)
シグニチャは共通。
引数sDivId:DIVタグID、
引数:iLat, iLngには世界測定系の緯度・経度
引数iZoom・enMapModeは各API固有値を設定。

OmYMap・OmGMap・OmVMap共通イベント
イベント名 シグニチャ 備考
マウスドラッグ中 evMoving(fnc) 引数fncにはfunction()型のコールバック関数を渡す。
マウスドラッグ終了 evMoved(func) 引数fncにはfunction()型のコールバック関数を渡す。
ズーム終了 evZoomed(fnc) 引数fncにはfunction(iZoom)型のコールバック関数を渡す。

OmYMap・OmGMap・OmVMap共通メソッド
メソッド名 シグニチャ 備考
マップオブジェクト取得 fnGetMapObj() 各APIの地図オブジェクトを返す。
マップDIVタグID取得 fnGetMapDivId() マップで利用しているDIVタグのIDを返す。
マップ種別取得 fnGetMapDivId() 各API別のOmMapKindの列挙値を返す。
中心マークを表示する? fnSetVisibleCentermark(bShow) 中心マークの表示/非表示切り替え。
地図モード取得 fnGetMapMode() 各APIの現在の地図モードを返す。
地図モード設定 fnSetMapMode(enMapMode) 各APIの現在の地図モードを設定する。引数enMapModeには各API固有値を渡す。
中心座標設定 fnSetCenter(objLatLng) 中心座標の設定。引数objLatLngにはOmLatLngオブジェクトを渡す。
中心座標取得 fnGetCenter() 中心座標の取得。戻り値はOmLatLngオブジェクト。
ズーム設定 fnSetZoom(iZoom) ズーム設定。引数iZoomには各API用のズーム値を渡す。
ズーム取得 fnGetZoom() ズーム値の取得。戻り値には各API用のズーム値を返す。
地図の移動 fnMoveTo(objLatLng) 地図の移動。引数objLatLngにはOmLatLngオブジェクトを渡す。
地図のサイズ変更 fnResize(width, height) 地図の幅・高さをリサイズする。
Yahoo!地図のズーム取得 fnGetYMapZoom(iZoom) 引数未設定なら現在の地図オブジェクトのズーム値を基にYahoo!地図のズーム値を返す。
引数が設定されていれば引数を基にYahoo!地図のズーム値を返す。
Google Mapsのズーム取得 fnGetGMapZoom(iZoom) 引数未設定なら現在の地図オブジェクトのズーム値を基にGoogle Mapsのズーム値を返す。
引数が設定されていれば引数を基にGoogle Mapsのズーム値を返す。
Virtual Earthのズーム取得 fnGetVMapZoom(iZoom) 引数未設定なら現在の地図オブジェクトのズーム値を基にVirtual Earthのズーム値を返す。
引数が設定されていれば引数を基にVirtual Earthのズーム値を返す。

OmLatLngコンストラクタ
メソッド名 シグニチャ 備考
コンストラクタ function(obj1, obj2) 引数obj1:はYLLPoint、GLatLng、VELatLongオブジェクトまたは緯度(数値)のいずれか。
引数obj2:経度(数値)。

OmLatLngメソッド
メソッド名 シグニチャ 備考
緯度取得 fnGetLat() 世界測地系の緯度を返す。
経度取得 fnGetLng() 世界測地系の経度を返す。

OmMapKind列挙型
定数 シグニチャ
Yahoo!地図 OmMapKind.YMap
Google Maps OmMapKind.GMap
Virtual Earth OmMapKind.VMap


> ■JavaScriptソースコード
かなり長いけど...
Oncemail Labの 「デュアルマップサービス」からサンプルの起動確認ができる。

map.js


///////////////////////////////////////////////////////////////////////////////////////////////////
/// ASP.NET for AJAXを使っている場合、不要
///////////////////////////////////////////////////////////////////////////////////////////////////

function $get(id)
{
	return document.getElementById(id);
}

///////////////////////////////////////////////////////////////////////////////////////////////////
/// 地図の識別オブジェクト
///////////////////////////////////////////////////////////////////////////////////////////////////

var OmMapKind =
{
    YMap:0, // Yahoo!地図
    GMap:1, // Google Maps
    VMap:2  // Virtual Earth
};

///////////////////////////////////////////////////////////////////////////////////////////////////
/// 緯度・経度クラス(各種APIの緯度・経度クラスの差異を吸収)
///////////////////////////////////////////////////////////////////////////////////////////////////

/// <summary>
/// コンストラクタ
/// </summary>
/// <param name="obj1">緯度/YLLPointオブジェクト/GLatLngオブジェクト</param>
/// <param name="obj2">経度</param>
var OmLatLng = function(obj1, obj2)
{
    // YLLPointオブジェクト
    if (typeof(obj1.lat) != "undefined" && typeof(obj1.lon) != "undefined")
    {
        this.m_iLat = obj1.lat;
        this.m_iLng = obj1.lon;
    }
    // GLatLngオブジェクト
    else if (typeof(obj1.lat) != "undefined" && typeof(obj1.lng) != "undefined")
    {
        this.m_iLat = obj1.lat();
        this.m_iLng = obj1.lng();
    }
    // VELatLongオブジェクト
    else if (typeof(obj1.Latitude) != "undefined" && typeof(obj1.Longitude) != "undefined")
    {
        this.m_iLat = obj1.Latitude;
        this.m_iLng = obj1.Longitude;
    }
    // 数値の場合
    else if (typeof(obj1) != "undefined" && typeof(obj2) != "undefined")
    {
        this.m_iLat = obj1;
        this.m_iLng = obj2;
    }
}
/// <summary>
/// 緯度取得
/// </summary>
/// <returns>緯度</returns>
OmLatLng.prototype.fnGetLat = function()
{
    return this.m_iLat;
}
/// <summary>
/// 経度取得
/// </summary>
/// <returns>経度</returns>
OmLatLng.prototype.fnGetLng = function()
{
    return this.m_iLng;
}

///////////////////////////////////////////////////////////////////////////////////////////////////
/// Yahoo!地図APIラッパークラス
///////////////////////////////////////////////////////////////////////////////////////////////////

/// <summary>
/// コンストラクタ
/// </summary>
/// <param name="sDivId">divタグのID</param>
/// <param name="iLat">緯度</param>
/// <param name="iLng">経度</param>
/// <param name="iZoom">ズーム値(1~11)</param>
/// <param name="enMapMode">地図モード:YMapMode.MAP[地図]、YMapMode.AERO[航空写真]</param>
var OmYMap = function(sDivId, iLat, iLng, iZoom, enMapMode)
{
    // マップオブジェクト生成
    var latlng = new YLLPoint(iLat, iLng);
    this.m_objMap = new YahooMapsCtrl(sDivId, latlng, iZoom, enMapMode, YDatumType.WGS84);
    this.m_objMap.setVisibleModeButton(false);
    this.m_objMap.setVisibleHomeButton(false);
    this.m_sDivId = sDivId;
}
/// <summary>
/// マップオブジェクト取得
/// </summary>
/// <returns>YahooMapsCtrlオブジェクト</returns>
OmYMap.prototype.fnGetMapObj = function()
{
    return this.m_objMap;
}
/// <summary>
/// マップDIVタグID取得
/// </summary>
/// <returns>DIVタグID</returns>
OmYMap.prototype.fnGetMapDivId = function()
{
    return this.m_sDivId;
}
/// <summary>
/// マップ種別
/// </summary>
/// <returns>OmMapKind列挙体</returns>
OmYMap.prototype.fnGetMapKind = function()
{
    return OmMapKind.YMap;
}
/// <summary>
/// イベントMoving
/// </summary>
/// <param name="fnc">関数オブジェクト[void func()]</param>
OmYMap.prototype.evMoving = function(fnc)
{
    this.m_objMap.addEvent(YEventType.MAP_MOVING, function(){ fnc(); });
}
/// <summary>
/// イベントMoved
/// </summary>
/// <param name="fnc">関数オブジェクト[void func()]</param>
OmYMap.prototype.evMoved = function(fnc)
{
    this.m_objMap.addEvent(YEventType.MAP_MOVED, function(){ fnc(); });
}
/// <summary>
/// イベントZoomed
/// </summary>
/// <param name="fnc">関数オブジェクト[void func(iZoom)]</param>
OmYMap.prototype.evZoomed = function(fnc)
{
    var refMap = this.m_objMap;
    this.m_objMap.addEvent(YEventType.LAYER_CHANGED, function(){ fnc(refMap.getCurrentLayer()); });
}
/// <summary>
/// 中心マークを表示する?
/// </summary>
/// <param name="bShow">true:表示、false:非表示</param>
OmYMap.prototype.fnSetVisibleCentermark = function(bShow)
{
    this.m_objMap.setVisibleCentermark(bShow);
}
/// <summary>
/// マップモードボタンを表示する?
/// </summary>
/// <param name="bShow">true:表示、false:非表示</param>
OmYMap.prototype.fnSetVisibleMapModeButton = function(bShow)
{
    this.m_objMap.setVisibleModeButton(bShow);
}
/// <summary>
/// ホームボタンUIを表示する?
/// </summary>
/// <param name="bShow">true:表示、false:非表示</param>
OmYMap.prototype.fnSetVisibleHomeButton= function(bShow)
{
    this.m_objMap.setVisibleHomeButton(bShow);
}
/// <summary>
/// 地図モード取得
/// </summary>
/// <returns>地図モード/returns>
OmYMap.prototype.fnGetMapMode = function()
{
    return this.m_objMap.getCurrentMode();
}
/// <summary>
/// 地図モード設定
/// </summary>
/// <param name="enMapMode">地図モード:YMapMode.MAP[地図]、YMapMode.AERO[航空写真]</param>
OmYMap.prototype.fnSetMapMode = function(enMapMode)
{
    this.m_objMap.changeMode(enMapMode);
}
/// <summary>
/// 中心座標設定
/// </summary>
/// <param name="objLatLng">座標オブジェクト</param>
OmYMap.prototype.fnSetCenter = function(objLatLng)
{
    var latlng = new YLLPoint(objLatLng.fnGetLat(), objLatLng.fnGetLng());
    this.m_objMap.moveTo(latlng);
}
/// <summary>
/// 中心座標取得
/// </summary>
/// <returns>座標オブジェクト/returns>
OmYMap.prototype.fnGetCenter = function()
{
    return new OmLatLng(this.m_objMap.getCenter());
}
/// <summary>
/// ズーム設定
/// </summary>
/// <param name="iZoom">ズーム値(1~11)</param>
OmYMap.prototype.fnSetZoom = function(iZoom)
{
    this.m_objMap.setLayer(iZoom);
}
/// <summary>
/// ズーム取得
/// </summary>
/// <returns>ズーム値(1~11)</returns>
OmYMap.prototype.fnGetZoom = function()
{
    return this.m_objMap.getCurrentLayer();
}
/// <summary>
/// 地図の移動
/// </summary>
/// <param name="objLatLng">座標オブジェクト</param>
OmYMap.prototype.fnMoveTo = function(objLatLng)
{
    var latlng = new YLLPoint(objLatLng.fnGetLat(), objLatLng.fnGetLng());
    // 指定マップの経度/緯度を移動
    this.m_objMap.moveTo(latlng);
}
/// <summary>
/// 地図のサイズ変更
/// </summary>
/// <param name="width">幅</param>
/// <param name="height">高さ</param>
OmYMap.prototype.fnResize = function(width, height)
{
    // divタグのサイズ変更
    var map = $get(this.m_sDivId);
    map.style.width = width + "px";
    map.style.height = height + "px";
    // リサイズ通知
    this.m_objMap.resizeMap();
}
/// <summary>
/// Yahoo!地図のズーム取得
/// </summary>
/// <param name="iYMapZoom">ズーム値(1~11)</param>
/// <returns>Yahoo!地図のズーム</returns>
OmYMap.prototype.fnGetYMapZoom = function(iYMapZoom)
{
    return this.fnGetZoom();
}
/// <summary>
/// Google Mapsのズーム取得
/// </summary>
/// <param name="iYMapZoom">ズーム値(1~11)</param>
/// <returns>Google Mapsのズーム</returns>
OmYMap.prototype.fnGetGMapZoom = function(iYMapZoom)
{
    if (typeof(iYMapZoom) == "undefined")
    {
        iYMapZoom = this.fnGetZoom();
    }
    switch(iYMapZoom) {
        case 0:
            return 16;
        case 1:
            return 18;
        case 2:
            return 17;
        case 3:
            return 16;
        case 4:
            return 14;
        case 5:
            return 12;
        case 6:
            return 11;
        case 7:
            return 10;
        case 8:
            return 9;
        case 9:
            return 8;
        case 10:
            return 5;
        case 11:
            return 3;
        default:
            return 1;
    }
}
/// <summary>
/// Virtual Earthのズーム取得
/// </summary>
/// <param name="iYMapZoom">ズーム値(1~11)</param>
/// <returns>Virtual Earthのズーム</returns>
OmYMap.prototype.fnGetVMapZoom = function(iYMapZoom)
{
    if (typeof(iYMapZoom) == "undefined")
    {
        iYMapZoom = this.fnGetZoom();
    }
    switch(iYMapZoom) {
        case 1:
            return 18;
        case 2:
            return 17;
        case 3:
            return 16;
        case 4:
            return 14;
        case 5:
            return 12;
        case 6:
            return 11;
        case 7:
            return 10;
        case 8:
            return 9;
        case 9:
            return 8;
        case 10:
            return 5;
        case 11:
            return 2;
        default:
            return 19;
    }
}

///////////////////////////////////////////////////////////////////////////////////////////////////
/// Google Map APIラッパークラス
///////////////////////////////////////////////////////////////////////////////////////////////////

/// <summary>
/// コンストラクタ
/// </summary>
/// <param name="sDivId">divタグのID</param>
/// <param name="iLat">緯度</param>
/// <param name="iLng">経度</param>
/// <param name="iZoom">ズーム値(1~19)</param>
/// <param name="enMapMode">地図モード:G_NORMAL_MAP[地図]、G_SATELLITE_MAP[航空写真]、G_HYBRID_MAP[地図+写真]</param>
var OmGMap = function(sDivId, iLat, iLng, iZoom, enMapMode)
{
    // マップ作成
    this.m_objMap = new GMap2($get(sDivId));
    // 各種コントロール追加
    this.m_objScaleControl = new GScaleControl();
    this.m_objLargeMapControl = new GLargeMapControl();
    this.m_objMap.setCenter(new GLatLng(iLat, iLng), iZoom);
    this.m_objMap.addControl(this.m_objScaleControl);
    this.m_objMap.addControl(this.m_objLargeMapControl);
    this.m_objMap.setMapType(enMapMode);
    //// ホイールの有効化
    //this.m_objMap.enableScrollWheelZoom();
    // メンバー変数追加 
    this.m_sDivId = sDivId;
    // 中心マークオブジェクト
    this.m_divCenterMark = document.createElement("div");
}
/// <summary>
/// マップオブジェクト取得
/// </summary>
/// <returns>YahooMapsCtrlオブジェクト</returns>
OmGMap.prototype.fnGetMapObj = function()
{
    return this.m_objMap;
}
/// <summary>
/// マップDIVタグID取得
/// </summary>
/// <returns>DIVタグID</returns>
OmGMap.prototype.fnGetMapDivId = function()
{
    return this.m_sDivId;
}
/// <summary>
/// マップ種別
/// </summary>
/// <returns>OmMapKind列挙体</returns>
OmGMap.prototype.fnGetMapKind = function()
{
    return OmMapKind.GMap;
}
/// <summary>
/// イベントMoving
/// </summary>
/// <param name="fnc">関数オブジェクト[void func()]</param>
OmGMap.prototype.evMoving = function(fnc)
{
    GEvent.addListener(this.m_objMap, "drag", function(){ fnc(); });
}
/// <summary>
/// イベントMoved
/// </summary>
/// <param name="fnc">関数オブジェクト[void func()]</param>
OmGMap.prototype.evMoved = function(fnc)
{
    GEvent.addListener(this.m_objMap, "dragend", function(){ fnc(); });
}
/// <summary>
/// イベントZoomed
/// </summary>
/// <param name="fnc">関数オブジェクト[void func(iZoom)]</param>
OmGMap.prototype.evZoomed = function(fnc)
{
    GEvent.addListener(this.m_objMap, "zoomend", function(oldLevel, newLevel){ fnc(newLevel); });
}
/// <summary>
/// 中心マークを表示する?
/// </summary>
/// <param name="bShow">true:表示、false:非表示</param>
OmGMap.prototype.fnSetVisibleCentermark = function(bShow)
{
    // 一度中心マークを削除
    try {
        this.m_objMap.getContainer().removeChild(this.m_divCenterMark);
    }catch(e) {
        // this.m_divCenterMarkがaddされていない時に例外処理が走るが無視
    }
    // 中心マークを設定
    if (bShow) {
        var mapW = parseInt(this.m_objMap.getContainer().style.width);
        var mapH = parseInt(this.m_objMap.getContainer().style.height);
        var markW = 33; // センターマークの横幅(ピクセル数)
        var markH = 33; // センターマークの縦幅(ピクセル数)
        var x = (mapW - markW) / 2; // センターマークの中心位置(X座標)
        var y = (mapH - markH) / 2; // センターマークの中心位置(Y座標)
        this.m_divCenterMark.style.position = "absolute";
        this.m_divCenterMark.style.top = y+"px";
        this.m_divCenterMark.style.left = x+"px";
        this.m_divCenterMark.style.backgroundImage = "url(../img/gmap_centermark.gif)";
        this.m_divCenterMark.style.width = markW+"px";
        this.m_divCenterMark.style.height = markH+"px";
        //this.m_divCenterMark.style.opacity = 0.5;
        this.m_objMap.getContainer().appendChild(this.m_divCenterMark);
    }
}
/// <summary>
/// マップモードボタンを表示する?
/// </summary>
/// <param name="bShow">true:表示、false:非表示</param>
OmGMap.prototype.fnSetVisibleMapModeButton = function(bShow)
{
    if (bShow)
    {
        this.m_objMap.addControl(this.m_objScaleControl);
        this.m_objMap.addControl(this.m_objLargeMapControl);
    }
    else
    {
        this.m_objMap.removeControl(this.m_objScaleControl);
        this.m_objMap.removeControl(this.m_objLargeMapControl);
    }
}
/// <summary>
/// ホームボタンUIを表示する?
/// </summary>
/// <param name="bShow">true:表示、false:非表示</param>
OmGMap.prototype.fnSetVisibleHomeButton= function(bShow)
{
    // APIが存在しない
    ;
}
/// <summary>
/// 地図モード取得
/// </summary>
/// <returns>地図モード/returns>
OmGMap.prototype.fnGetMapMode = function()
{
    return this.m_objMap.getCurrentMapType();
}
/// <summary>
/// 地図モード設定
/// </summary>
/// <param name="enMapMode">地図モード:G_NORMAL_MAP[地図]、G_SATELLITE_MAP[航空写真]、G_HYBRID_MAP[地図+写真]</param>
OmGMap.prototype.fnSetMapMode= function(enMapMode)
{
    this.m_objMap.setMapType(enMapMode);
}
/// <summary>
/// 中心座標設定
/// </summary>
/// <param name="objLatLng">座標オブジェクト</param>
OmGMap.prototype.fnSetCenter = function(objLatLng)
{
    var latlng = new GLatLng(objLatLng.fnGetLat(), objLatLng.fnGetLng());
    this.m_objMap.setCenter(latlng);
}
/// <summary>
/// 中心座標取得
/// </summary>
/// <returns>座標オブジェクト/returns>
OmGMap.prototype.fnGetCenter = function()
{
    return new OmLatLng(this.m_objMap.getCenter());
}
/// <summary>
/// ズーム設定
/// </summary>
/// <param name="iZoom">ズーム値(1~11)</param>
OmGMap.prototype.fnSetZoom = function(iZoom)
{
    this.m_objMap.setZoom(iZoom);
}
/// <summary>
/// ズーム設定
/// </summary>
/// <returns>ズーム値(1~19)</returns>
OmGMap.prototype.fnGetZoom = function()
{
    return this.m_objMap.getZoom();
}
/// <summary>
/// 地図の移動
/// </summary>
/// <param name="objLatLng">座標オブジェクト</param>
OmGMap.prototype.fnMoveTo = function(objLatLng)
{
    var latlng = new GLatLng(objLatLng.fnGetLat(), objLatLng.fnGetLng());
    // 指定マップの経度/緯度を移動
    this.m_objMap.panTo(latlng);
}
/// <summary>
/// 地図のサイズ変更
/// </summary>
/// <param name="width">幅</param>
/// <param name="height">高さ</param>
OmGMap.prototype.fnResize = function(width, height)
{
    // divタグのサイズ変更
    var map = $get(this.m_sDivId);
    map.style.width = width + "px";
    map.style.height = height + "px";
    // リサイズ通知
    this.m_objMap.checkResize();
}
/// <summary>
/// Yahoo!地図のズーム取得
/// </summary>
/// <param name="iGMapZoom">ズーム値(1~19)</param>
/// <returns>Yahoo!地図のズーム</returns>
OmGMap.prototype.fnGetYMapZoom = function(iGMapZoom)
{
    if (typeof(iGMapZoom) == "undefined")
    {
        iGMapZoom = this.fnGetZoom();
    }
    switch(iGMapZoom) {
        case 19:
        case 18:
            return 1;
        case 17:
            return 2;
        case 16:
        case 15:
            return 3;
        case 14:
            return 4;
        case 13:
        case 12:
            return 5;
        case 11:
            return 6;
        case 10:
            return 7;
        case 9:
            return 8;
        case 8:
            return 9;
        case 7:
        case 6:
        case 5:
        case 4:
            return 10;
        case 3:
        case 2:
        case 1:
        case 0:
            return 11;
        default:
            return 11;
    }
}
/// <summary>
/// Google Mapsのズーム取得
/// </summary>
/// <param name="iGMapZoom">ズーム値(1~19)</param>
/// <returns>Google Mapsのズーム</returns>
OmGMap.prototype.fnGetGMapZoom = function(iGMapZoom)
{
    return this.fnGetZoom();
}
/// <summary>
/// Virtual Earthのズーム取得
/// </summary>
/// <param name="iGMapZoom">ズーム値(1~19)</param>
/// <returns>Virtual Earthのズーム</returns>
OmGMap.prototype.fnGetVMapZoom = function(iGMapZoom)
{
    if (typeof(iGMapZoom) == "undefined")
    {
        iGMapZoom = this.fnGetZoom();
    }
    switch(iGMapZoom) {
        case 1:
            return 2;
        case 2:
            return 3;
        case 3:
            return 4;
        case 4:
            return 5;
        case 5:
        case 6:
            return 6;
        case 7:
            return 7;
        case 8:
            return 8;
        case 9:
            return 9;
        case 10:
            return 11;
        case 11:
            return 11;
        case 12:
            return 13;
        case 13:
            return 14;
        case 14:
            return 15;
        case 15:
            return 16;
        case 16:
        case 17:
            return 17;
        case 18:
            return 18;
        case 19:
            return 19;
        default:
            return 1;
    }
}

///////////////////////////////////////////////////////////////////////////////////////////////////
/// Virtual Earth APIラッパークラス
/// http://msdn.microsoft.com/ja-jp/library/bb412546.aspx
/// 注意:複数の外部ファイルを読み込む場合、Virtual Earthの<script>を先頭に書かないとfirefoxでバグる?
/// http://ongmap.com/blog/?p=54
///////////////////////////////////////////////////////////////////////////////////////////////////

/// <summary>
/// コンストラクタ
/// </summary>
/// <param name="sDivId">divタグのID</param>
/// <param name="iLat">緯度</param>
/// <param name="iLng">経度</param>
/// <param name="iZoom">ズーム値(1~19)</param>
/// <param name="enMapMode">地図モード:VEMapStyle.Road[道路地図]、VEMapStyle.Shaded[影付きマップ道路地図]、
/// VEMapStyle.Aerial[航空写真]、VEMapStyle.Hybrid[ハイブリッド]、VEMapStyle.Oblique[斜角マップ]、
/// VEMapStyle.Birdseye[概観図 (斜角) ]、VEMapStyle.BirdseyeHybrid[概観ハイブリッド]</param>
var OmVMap = function(sDivId, iLat, iLng, iZoom, enMapMode, enMapView)
{
    // マップ作成
    this.m_objMap = new VEMap(sDivId);
    // 各種コントロール追加
    this.m_objMap.SetDashboardSize(VEDashboardSize.Tiny);
    this.m_objMap.LoadMap(new VELatLong(iLat, iLng), iZoom, enMapMode, false, VEMapMode.Mode2D);
    this.m_objMap.SetScaleBarDistanceUnit(VEDistanceUnit.Kilometers);
    // メンバー変数追加 
    this.m_sDivId = sDivId;
    // 中心マークオブジェクト
    this.m_divCenterMark = document.createElement("div");
}
/// <summary>
/// マップオブジェクト取得
/// </summary>
/// <returns>YahooMapsCtrlオブジェクト</returns>
OmVMap.prototype.fnGetMapObj = function()
{
    return this.m_objMap;
}
/// <summary>
/// マップDIVタグID取得
/// </summary>
/// <returns>DIVタグID</returns>
OmVMap.prototype.fnGetMapDivId = function()
{
    return this.m_sDivId;
}
/// <summary>
/// マップ種別
/// </summary>
/// <returns>OmMapKind列挙体</returns>
OmVMap.prototype.fnGetMapKind = function()
{
    return OmMapKind.VMap;
}
/// <summary>
/// イベントMoving
/// </summary>
/// <param name="fnc">関数オブジェクト[void func()]</param>
OmVMap.prototype.evMoving = function(fnc)
{
    this.m_objMap.AttachEvent("onmousemove", function(e) { fnc(); });
}
/// <summary>
/// イベントMoved
/// </summary>
/// <param name="fnc">関数オブジェクト[void func()]</param>
OmVMap.prototype.evMoved = function(fnc)
{
    this.m_objMap.AttachEvent("onmouseup", function(e) { fnc(); });
}
/// <summary>
/// イベントZoomed
/// </summary>
/// <param name="fnc">関数オブジェクト[void func(iZoom)]</param>
OmVMap.prototype.evZoomed = function(fnc)
{
    this.m_objMap.AttachEvent("onendzoom", function(e) { fnc(e.zoomLevel); });
}
/// <summary>
/// 中心マークを表示する?
/// </summary>
/// <param name="bShow">true:表示、false:非表示</param>
OmVMap.prototype.fnSetVisibleCentermark = function(bShow)
{
    var divMap = $get(this.m_sDivId);
    // 一度中心マークを削除
    try {
        this.m_objMap.DeleteControl(this.m_divCenterMark);
    }catch(e) {
        // this.m_divCenterMarkがaddされていない時に例外処理が走るが無視
    }
    // 中心マークを設定
    if (bShow) {
        var mapW = parseInt(divMap.style.width);
        var mapH = parseInt(divMap.style.height);
        var markW = 33; // センターマークの横幅(ピクセル数)
        var markH = 33; // センターマークの縦幅(ピクセル数)
        var x = (mapW - markW) / 2; // センターマークの中心位置(X座標)
        var y = (mapH - markH) / 2; // センターマークの中心位置(Y座標)
        this.m_divCenterMark.style.position = "absolute";
        this.m_divCenterMark.style.top = y+"px";
        this.m_divCenterMark.style.left = x+"px";
        this.m_divCenterMark.style.backgroundImage = "url(../img/gmap_centermark.gif)";
        this.m_divCenterMark.style.width = markW+"px";
        this.m_divCenterMark.style.height = markH+"px";
        //this.m_divCenterMark.style.opacity = 0.5;
        this.m_objMap.AddControl(this.m_divCenterMark, 1);
    }
}
/// <summary>
/// マップモードボタンを表示する?
/// </summary>
/// <param name="bShow">true:表示、false:非表示</param>
OmVMap.prototype.fnSetVisibleMapModeButton = function(bShow)
{
    if (bShow)
    {
        this.m_objMap.AddControl(this.m_objScaleControl, 1);
        this.m_objMap.AddControl(this.m_objLargeMapControl, 1);
    }
    else
    {
        this.m_objMap.DeleteControl(this.m_objScaleControl);
        this.m_objMap.DeleteControl(this.m_objLargeMapControl);
    }
}
/// <summary>
/// ホームボタンUIを表示する?
/// </summary>
/// <param name="bShow">true:表示、false:非表示</param>
OmVMap.prototype.fnSetVisibleHomeButton= function(bShow)
{
    // APIが存在しない
    ;
}
/// <summary>
/// 地図モード取得
/// </summary>
/// <returns>地図モード/returns>
OmVMap.prototype.fnGetMapMode = function()
{
    return this.m_objMap.GetMapStyle();
}
/// <summary>
/// 地図モード設定
/// </summary>
/// <param name="enMapMode">地図モード:VEMapStyle.Road[道路地図]、VEMapStyle.Shaded[影付きマップ道路地図]、
/// VEMapStyle.Aerial[航空写真]、VEMapStyle.Hybrid[ハイブリッド]、VEMapStyle.Oblique[斜角マップ]、
/// VEMapStyle.Birdseye[概観図 (斜角) ]、VEMapStyle.BirdseyeHybrid[概観ハイブリッド]</param>
OmVMap.prototype.fnSetMapMode= function(enMapMode)
{
    this.m_objMap.SetMapStyle(enMapMode);
}
/// <summary>
/// 中心座標設定
/// </summary>
/// <param name="objLatLng">座標オブジェクト</param>
OmVMap.prototype.fnSetCenter = function(objLatLng)
{
    var latlng = new VELatLong(objLatLng.fnGetLat(), objLatLng.fnGetLng());
    this.m_objMap.SetCenter(latlng);
}
/// <summary>
/// 中心座標取得
/// </summary>
/// <returns>座標オブジェクト/returns>
OmVMap.prototype.fnGetCenter = function()
{
    return new OmLatLng(this.m_objMap.GetCenter());
}
/// <summary>
/// ズーム設定
/// </summary>
/// <param name="iZoom">ズーム値(1~19)</param>
OmVMap.prototype.fnSetZoom = function(iZoom)
{
    this.m_objMap.SetZoomLevel (iZoom);
}
/// <summary>
/// ズーム設定
/// </summary>
/// <returns>ズーム値(1~11)</returns>
OmVMap.prototype.fnGetZoom = function()
{
    return this.m_objMap.GetZoomLevel();
}
/// <summary>
/// 地図の移動
/// </summary>
/// <param name="objLatLng">座標オブジェクト</param>
OmVMap.prototype.fnMoveTo = function(objLatLng)
{
    var latlng = new VELatLong(objLatLng.fnGetLat(), objLatLng.fnGetLng());
    // 指定マップの経度/緯度を移動
    this.m_objMap.PanToLatLong(latlng);
}
/// <summary>
/// 地図のサイズ変更
/// </summary>
/// <param name="width">幅</param>
/// <param name="height">高さ</param>
OmVMap.prototype.fnResize = function(width, height)
{
    // divタグのサイズ変更
    var map = $get(this.m_sDivId);
    map.style.width = width;
    map.style.height = height;
    // 指定マップのサイズ変更
    this.m_objMap.Resize(width, height);
}
/// <summary>
/// Yahoo!地図のズーム取得
/// </summary>
/// <param name="iVMapZoom">ズーム値(1~19)</param>
/// <returns>Yahoo!地図のズーム</returns>
OmVMap.prototype.fnGetYMapZoom = function(iVMapZoom)
{
    if (typeof(iVMapZoom) == "undefined")
    {
        iVMapZoom = this.fnGetZoom();
    }
    switch(iVMapZoom) {
        case 1:
        case 2:
        case 3:
        case 4:
            return 11;
        case 5:
        case 6:
            return 10;
        case 7:
        case 8:
            return 9;
        case 9:
            return 8;
        case 10:
        case 11:
            return 7;
        case 12:
            return 6;
        case 13:
            return 5;
        case 14:
            return 4;
        case 15:
        case 16:
        case 0:
            return 3;
        case 17:
            return 2;
        case 18:
        case 19:
            return 1;
        default:
            return 11;
    }
}
/// <summary>
/// Google Mapsのズーム取得
/// </summary>
/// <param name="iVMapZoom">ズーム値(1~19)</param>
/// <returns>Google Mapsのズーム</returns>
OmVMap.prototype.fnGetGMapZoom = function(iVMapZoom)
{
    if (typeof(iVMapZoom) == "undefined")
    {
        iVMapZoom = this.fnGetZoom();
    }
    switch(iVMapZoom) {
        case 1:
        case 2:
            return 1;
        case 3:
            return 2;
        case 4:
            return 3;
        case 5:
            return 4;
        case 6:
            return 5; // or 6
        case 7:
            return 7;
        case 8:
            return 8;
        case 9:
            return 9;
        case 10:
        case 11:
            return 10;
        case 12:
            return 11;
        case 13:
            return 13;
        case 14:
            return 14;
        case 15:
            return 15;
        case 16:
            return 16;
        case 17:
            return 17;
        case 18:
            return 18;
        case 19:
            return 19;
        default:
            return 1;
    }
}
/// <summary>
/// Virtual Earthのズーム取得
/// </summary>
/// <param name="iVMapZoom">ズーム値(1~19)</param>
/// <returns>Virtual Earthのズーム</returns>
OmVMap.prototype.fnGetVMapZoom = function(iVMapZoom)
{
    return this.fnGetZoom();
}

test.htm

<!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>
<title>マップインタフェーステスト</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<script src="http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.2" type="text/javascript"></script>
<script src="http://map.yahooapis.jp/MapsService/js/V2/?appid=(あなたのID)" type="text/javascript"></script>
<script src="http://maps.google.com/maps?file=api&key=(あなたのキー)" type="text/javascript"></script>
<script src="../js/Map.js" type="text/javascript"></script>
<script type="text/javascript">
var gYMap;
var gGMap;
var gVMap;
window.onload = function()
{
    if (GBrowserIsCompatible()) {
        gYMap = new OmYMap("ymap", 35.681382, 139.766084, 3, YMapMode.MAP);
        gGMap = new OmGMap("gmap", 35.681382, 139.766084, 16, G_NORMAL_MAP);
        gVMap = new OmVMap("vmap", 35.681382, 139.766084, 16, VEMapStyle.Road);
    }
}
window.onunload = function()
{
    GUnload();
}
</script>
</head>
<body>
    <div id="ymap" style="position: relative; width:300px; height:200px;"></div><br />
    <div id="gmap" style="position: relative; width:300px; height:200px;"></div><br />
    <div id="vmap" style="position: relative; width:300px; height:200px;"></div><br />
</body>
</html>

■参考URL


■関連ページ

サービスアプリ拡張(デュアルマップサービス)

公開済みサービス「 デュアルマップサービス」 をVirtual Earthにも対応。
他に「中心マーク対応」「現在の住所」等の機能拡張と各種不具合修正。


■サービス公開先
Oncemail Lab


■サンプル
こんな感じで2つの地図を並べて表示・同期操作できる。

・東京駅を「Yahoo!地図」と「Googleマップ」で表示。


・清水寺を「Yahoo!地図(航空写真)」と「Virtual Earth」で表示。



■2009/05/23時点での公開サービス

サービス名 概要
OfficeファイルのPDFファイル変換サービス Excel・Word・PowerPointファイルをPDFファイルに変換します。
複数ファイルの一括変換も可能です。
Officeファイルバージョン変換サービス Excel・Word・PowerPointファイルのファイルバージョンを変換します。
複数ファイルの一括変換も可能です。
PDFのファイル結合サービス 2つのPDFファイルを1つのPDFファイルに結合します。
PDFのファイル分割サービス PDFファイルを2つのファイルに分割します。
PDFファイルにパスワード設定サービス PDFファイルにパスワードを設定します。
デュアルマップサービス 「Yahoo!地図」「Googleマップ」「Virtual Earth」を2つ並べ表示・同期操作できます。
ランダムパスワード生成サービス ランダムなパスワードを生成します。
重複なしの複数パスワードを作成できます。
CAPCHA作成サービス CAPCHA(キャプチャ)を作成・ダウンロードできます。
重複なしの複数ファイルをダウンロードできます。
画像ファイル一括変換サービス 画像ファイル(JPEG、GIF、PNG、ビットマップ)の画像形式・サイズ・透過等の変換を行います。
複数ファイルの一括変換も可能です。
ファイルのZIP圧縮サービス ファイルをZIP圧縮します。
ファイルのLZH圧縮サービス ファイルをLZH圧縮します。
ファイルの7z圧縮サービス ファイルを7z圧縮します。
テキストの正規表現置換サービス テキストを正規表現で置換します。

NET Frameworkアプリケーションを64bit OS上で32bitモードで動かす方法(その2)

.NET Frameworkアプリケーションを64bit OS上で32bitモードで動かす方法の紹介。



■最初に
前回はWindowsアプリケーションとASP.NETを32bitアプリケーションとして動かすための設定を書いてみた。
しかし心情としては、例えライブラリが32ビットにしか対応していなくても64ビットOS上では64ビットアプリケーションで動かしたいのが本音だと思う。
今回は折衷案として以下の方式を考えてみた。

①64bitで動く部分は64bitアプリケーションとして作成する。
②32bitしか対応していないライブラリ(dll,ActiveX等)を利用した処理を切り出し、32ビットアプリケーションとして作成する。
③64bitアプリケーションから32bitアプリケーションをプロセス起動する。処理に必要な値はコマンドライン引数かファイルで渡す。

なお本ページの環境構成は以下の通り。
・Windows Server 2008 64bit
・Visual Studio 2008
・.NET Framework 3.5 SP1



■32ビットアプリケーション作成サンプル
まず32ビットアプリケーションの作成だ。

手順1
新規プロジェクトを「コンソールアプリケーション」として作成。
プロジェクト名はとりあえず「proc32」とする。


手順2
コマンドライン引数を取得するコードを記述する。
※このサンプルではMessageBox.Show()を利用するためプロジェクト参照から「System.Windows.Forms」を追加している。


using System;
using System.Windows.Forms;

class CProc32
{
    static void Main(string[] args)
    {
        if (args.Length > 0)
        {
            MessageBox.Show(args[0]);
        }
    }
}


手順3
プロジェクトのプロパティから「出力の種類」を"Windowsアプリケーション"に設定。


手順4
「ビルド」タブを選択し、「プラットフォーム ターゲット」を"x86"に設定する。


■ASP.NET32ビットプリケーションを64ビットアプリケーションから起動サンプル
今度は64bitアプリケーションの作成だ。
「プラットフォーム ターゲット」の既定値は"Any CPU"のためOSに合わせてアプリケーション動作を32ビット・64ビットに切り替えるが、今回は強制的に64bitアプリとして作成する。

手順1
新規プロジェクトを「Windows フォーム アプリケーション」を作成。
プロジェクト名はとりあえず「Win64」とする。


手順2
フォームにボタンを作成し、ボタンイベントに以下のソースを記述。
ポイントは「Process.StartInfo.WindowStyleプロパティ」と「Process.WaitForExit()メソッド」だ。


using System;
using System.Diagnostics;
using System.Windows.Forms;

namespace Win64
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        /// <summary>
        /// [32bitアプリを起動]ボタン押下
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            //-------------------------------------------------------------------------------------
            // 32bitアプリを起動
            //-------------------------------------------------------------------------------------
            Process ps = new Process();
            // プロセス起動引数設定
            ps.StartInfo.FileName = "proc32.exe";
            ps.StartInfo.Arguments = "\"ビット64アプリからから32ビットアプリを起動しました。\"";
            // プロセルのウィンドウは非表示
            ps.StartInfo.WindowStyle =ProcessWindowStyle.Hidden;
            // プロセス起動
            ps.Start();
            // プロセスが終了するまで最大10秒(=10 * 1000ミリ秒)待機
            ps.WaitForExit(10 * 1000);
            //-------------------------------------------------------------------------------------
            // 終了メッセージ
            //-------------------------------------------------------------------------------------
            MessageBox.Show("ボタン処理が終了");
        }
    }
}


手順3
プロジェクトのプロパティから「プラットフォーム ターゲット」を"x64"に設定する。


手順4
先の手順で作成した「proc32.exe」を「Win64.exe」と同じフォルダに配置。


手順5
「Win64.exe」を起動しボタンを押すと「proc32.exe」内のMessagBox処理が呼び出される。


手順6
このときのタスクマネジャーは以下の通りだ。



■関連ページ


サービスアプリ拡張(「Office→PDF変換」「Officeバージョン変換」の一括変換)

公開済みサービス「OfficeファイルのPDFファイル変換サービス」および「Officeファイルバージョン変換サービス」を、複数ファイル一括変換できるように機能拡張。

■サービス公開先
Oncemail Lab


■2009/05/17時点での公開サービス

サービス名概要
OfficeファイルのPDFファイル変換サービス Excel・Word・PowerPointファイルをPDFファイルに変換します。
複数ファイルの一括変換も可能です。
Officeファイルバージョン変換サービス Excel・Word・PowerPointファイルのファイルバージョンを変換します。
複数ファイルの一括変換も可能です。
PDFのファイル結合サービス 2つのPDFファイルを1つのPDFファイルに結合します。
PDFのファイル分割サービス PDFファイルを2つのファイルに分割します。
PDFファイルにパスワード設定サービス PDFファイルにパスワードを設定します。
デュアルマップサービス 「Yahoo!地図」「Googleマップ」の異なるタイプの地図を2つ同時に表示・操作できます。
ランダムパスワード生成サービス ランダムなパスワードを生成します。
CAPCHA作成サービス CAPCHA(キャプチャ)を作成・ダウンロードできます。
画像ファイル一括変換サービス 画像ファイル(JPEG、GIF、PNG、ビットマップ)の画像形式・サイズ・透過等の変換を行います。
複数ファイルの一括変換も可能です。
ファイルのZIP圧縮サービス ファイルをZIP圧縮します。
ファイルのLZH圧縮サービス ファイルをLZH圧縮します。
ファイルの7z圧縮サービス ファイルを7z圧縮します。
テキストの正規表現置換サービス テキストを正規表現で置換します。

サービスアプリ追加(テキストの正規表現置換サービス)

Oncemail Labテキストの正規表現置換サービスを追加。

※高性能エディタには一般装備している正規表現置換機能だけど各種制約で利用不可なこともあるので...

■サービス公開先
Oncemail Lab


■2009/05/16時点での公開サービス

サービス名概要
OfficeファイルのPDFファイル変換サービス Excel・Word・PowerPointファイルをPDFファイルに変換します。
Officeファイルバージョン変換サービス Excel・Word・PowerPointファイルのファイルバージョンを変換します。
PDFのファイル結合サービス 2つのPDFファイルを1つのPDFファイルに結合します。
PDFのファイル分割サービス PDFファイルを2つのファイルに分割します。
PDFファイルにパスワード設定サービス PDFファイルにパスワードを設定します。
デュアルマップサービス 「Yahoo!地図」「Googleマップ」の異なるタイプの地図を2つ同時に表示・操作できます。
ランダムパスワード生成サービス ランダムなパスワードを生成します。
CAPCHA作成サービス CAPCHA(キャプチャ)を作成・ダウンロードできます。
画像ファイル一括変換サービス 複数の画像ファイルを一括で画像形式・サイズ・透過等の変換を行います。
ファイルのZIP圧縮サービス ファイルをZIP圧縮します。
ファイルのLZH圧縮サービス ファイルをLZH圧縮します。
ファイルの7z圧縮サービス ファイルを7z圧縮します。
テキストの正規表現置換サービス テキストを正規表現で置換します。

サービスアプリ追加(デュアルマップサービス)

Oncemail Labデュアルマップサービスを追加。


■サービス公開先
Oncemail Lab


■サンプル
こんな感じで、「Yahoo!地図」と「Googleマップ」を2つ並べて地図を表示・操作できる。



■2009/05/10時点での公開サービス

サービス名概要
OfficeファイルのPDFファイル変換サービス Excel・Word・PowerPointファイルをPDFファイルに変換します。
Officeファイルバージョン変換サービス Excel・Word・PowerPointファイルのファイルバージョンを変換します。
PDFのファイル結合サービス 2つのPDFファイルを1つのPDFファイルに結合します。
PDFのファイル分割サービス PDFファイルを2つのファイルに分割します。
PDFファイルにパスワード設定サービス PDFファイルにパスワードを設定します。
デュアルマップサービス 「Yahoo!地図」「Googleマップ」の異なるタイプの地図を2つ同時に表示・操作できます。
ランダムパスワード生成サービス ランダムなパスワードを生成します。
CAPCHA作成サービス CAPCHA(キャプチャ)を作成・ダウンロードできます。
画像ファイル一括変換サービス 複数の画像ファイルを一括で画像形式・サイズ・透過等の変換を行います。
ファイルのZIP圧縮サービス ファイルをZIP圧縮します。
ファイルのLZH圧縮サービス ファイルをLZH圧縮します。
ファイルの7z圧縮サービス ファイルを7z圧縮します。

ASP.NETでPDFファイルのファイル分割

ASP.NET(C#)でPDFファイルのファイル分割を行うサンプルを紹介する。
このサンプルではiText#(iTextSharp)というフリーライブラリーを利用する。


■iTextSharpの準備方法
iTextSharpはSourceForgeここからダウンロードできる。
必要な物は以下の通り。

DLL 説明
itextsharp.dll iTextSharpのDLL
iTextAsian.dll 日本語リソースのDLL
これらDLLファイルをASP.NETプロジェクトのBinフォルダに配置すればOK。
詳しくはここを参照。


■ASP.NET(C#)サンプル
利用サンプル概要は以下の通り。
OnceMail Labから実行結果及び全ソースを確認できる。


using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;

 :
 :
 :

/// <summary>
/// PDF分割
/// </summary>
/// <param name="sSourceFilePath">入力ファイルパス</param>
/// <param name="sDestFilePath1">出力ファイルパス1</param>
/// <param name="sDestFilePath2">出力ファイルパス2</param>
/// <param name="iSplitPageNumber">分割ページ番号</param>
public void fnSplitPdf(string sSourceFilePath, string sDestFilePath1, string sDestFilePath2, int iSplitPageNumber)
{
    PdfReader reader = null;
    try
    {
        // リーダー作成
        reader = new PdfReader(sSourceFilePath);
        // 1つめ分割ファイル作成
        fnCreateSplitPdfFile(reader, sDestFilePath1, 1, iSplitPageNumber - 1);
        // 2つめ分割ファイル作成
        fnCreateSplitPdfFile(reader, sDestFilePath2, iSplitPageNumber, reader.NumberOfPages);
    }
    finally
    {
        // 終了処理
        if (reader != null)
            reader.Close();
    }
}
/// <summary>
/// 分割PDFファイル作成
/// </summary>
/// <param name="reader">リーダー</param>
/// <param name="sDestFilePath">出力ファイルパス</param>
/// <param name="iStartPageNumber">読込開始位置</param>
/// <param name="iEndPageNumber">読込終了位置</param>
private void fnCreateSplitPdfFile(PdfReader reader, string sDestFilePath, int iStartPageNumber, int iEndPageNumber)
{
    Document doc = null;
    try
    {
        // ドキュメント作成
        doc = new Document(reader.GetPageSizeWithRotation(iStartPageNumber));
        // writer作成
        PdfWriter writer = PdfWriter.GetInstance(doc, new FileStream(sDestFilePath, FileMode.Create));
        // ドキュメントオープン
        doc.Open();
        // ContentByte作成
        PdfContentByte cb = writer.DirectContent;
        // readerから指定ページのPDFファイルをコピー→出力ドキュメントに出力
        for (int i = iStartPageNumber; i <= iEndPageNumber; i++)
        {
            // ページサイズ設定
            doc.SetPageSize(reader.GetPageSizeWithRotation(i));
            // ページ作成
            doc.NewPage();
            // ページ取得
            PdfImportedPage page = writer.GetImportedPage(reader, i);
            // ページ向きに合わせてページ追加
            int iRotation = reader.GetPageRotation(i);
            if (iRotation == 90 || iRotation == 270)
            {
                cb.AddTemplate(page, 0, -1f, 1f, 0, 0, reader.GetPageSizeWithRotation(i).Height);
            }
            else
            {
                cb.AddTemplate(page, 1f, 0, 0, 1f, 0, 0);
            }
        }
    }
    finally
    {
        // オブジェクト破棄
        if (doc != null)
            doc.Close();
    }
}


■関連ページ

サービスアプリ追加(PDFのファイル分割サービス)

Oncemail LabPDFのファイル分割サービスを追加。


■サービス公開先
Oncemail Lab


■2009/05/07時点での公開サービス

サービス名概要
OfficeファイルのPDFファイル変換サービス Excel・Word・PowerPointファイルをPDFファイルに変換します。
Officeファイルバージョン変換サービス Excel・Word・PowerPointファイルのファイルバージョンを変換します。
PDFのファイル結合サービス 2つのPDFファイルを1つのPDFファイルに結合します。
PDFのファイル分割サービス PDFファイルを2つのファイルに分割します。
PDFファイルにパスワード設定サービス PDFファイルにパスワードを設定します。
ファイルのZIP圧縮サービス ファイルをZIP圧縮します。
ファイルのLZH圧縮サービス ファイルをLZH圧縮します。
ファイルの7z圧縮サービス ファイルを7z圧縮します。
ランダムパスワード生成サービス ランダムなパスワードを生成します。
CAPCHA作成サービス CAPCHA(キャプチャ)を作成・ダウンロードできます。
画像ファイル一括変換サービス 複数の画像ファイルを一括で画像形式・サイズ・透過等の変換を行います。

サービスアプリ追加(ファイルの7z圧縮サービス)

Oncemail Labファイルの7z圧縮サービスを追加。


■サービス公開先
Oncemail Lab


■2009/05/06時点での公開サービス

サービス名概要
OfficeファイルのPDFファイル変換サービス Excel・Word・PowerPointファイルをPDFファイルに変換します。
Officeファイルバージョン変換サービス Excel・Word・PowerPointファイルのファイルバージョンを変換します。
PDFファイルにパスワード設定サービス PDFファイルにパスワードを設定します。
PDFをファイル結合サービス 2つのPDFファイルを1つのPDFファイルに結合します。
ファイルのZIP圧縮サービス ファイルをZIP圧縮します。
ファイルのLZH圧縮サービス ファイルをLZH圧縮します。
ファイルの7z圧縮サービス ファイルを7z圧縮します。
ランダムパスワード生成サービス ランダムなパスワードを生成します。
CAPCHA作成サービス CAPCHA(キャプチャ)を作成・ダウンロードできます。
画像ファイル一括変換サービス 複数の画像ファイルを一括で画像形式・サイズ・透過等の変換を行います。

C#で7zの圧縮・解凍

C#で7z(セブンゼット)の圧縮・解凍を行うサンプルを紹介する。
本サンプルでは7-zip32.dllというフリーライブラリー(C言語DLL)を利用。


■DLLの準備方法
7-zip32.dllは統合アーカイバプロジェクトからダウンロードできる。

DLL 説明 備考
7-zip32.dll 7z圧縮・解凍用ライブラリ。 GNU Lesser General Public License準拠
7-zip32.dllファイルをC:\Windows等パスの通ったフォルダに配置すればOK。


■C#サンプル
7-zip32.dllの利用メソッドは以下の通り。
C言語ライブラリのためDllImport宣言が必要。


■7z圧縮・解凍
[DllImport("7-zip32.dll", CharSet = CharSet.Ansi)]
int SevenZip(
    IntPtr hwnd,            // ウィンドウハンドル
    string szCmdLine,       // コマンドライン
    StringBuilder szOutput, // 処理結果文字列
    int dwSize);            // 引数szOutputの文字列サイズ

第2引数のコマンドラインの様式は7-zip32.dll付属の「7-zipCMD.txt」によるとこんな感じ。

<command> [<switch>...] <archive_name> [<base_dir>\] [<arguments>...]

command      : コマンド。
switch       : スイッチ。(<'/' | '-'><switch_characters>[<option>])
archive_name : 基本となる書庫名。
base_dir     : 基準ディレクトリ。\ で終わる必要があります。
arguments    : switch、wildcard、filename、list_file。

wildcard     : ワイルドカード。
filename     : ファイル名。
list_file    : ファイルのリストを書いたファイル。(@{filename})

[ ] は省略可能。
... は複数指定可能。

本サンプル内で利用したコマンドラインは以下の通り。
コマンドライン 説明
a -t7z -hide -mmt=on -y archive.7z <ファイルパス1> <ファイルパス2>... ファイルパス1、ファイルパス2...をarchive.7zファイルに圧縮。
a -t7z -hide -mmt=on -y -p{パスワード} archive.7z <ファイルパス1> <ファイルパス2>... ファイルパス1、ファイルパス2...をarchive.7zファイルにパスワード指定で圧縮。
a -t7z -hide -mmt=on -y -r archive.7z <フォルダパス> サブフォルダごとarchive.7zファイルに圧縮。
a -t7z -hide -mmt=on -y -r -p{パスワード} archive.7z <フォルダパス> サブフォルダごとパスワード指定でarchive.7zファイルに圧縮。
x -aoa -hide -y -r archive.7z -o{出力フォルダパス}\* archive.7zファイルを圧縮時と同じフォルダ構成で出力フォルダパスに解凍。
x -aoa -hide -y -r archive.7z -o{dust_folder}\* -p{パスワード} パスワードの掛ったarchive.7zファイルを圧縮時と同じフォルダ構成で出力フォルダパスに解凍。

コマンド
a:書庫にファイルを追加
x:フォルダ付きで書庫を解凍。

スイッチ
-t7z:7形式を指定
-hide:処理状況ダイアログ表示の抑止
-mmt=on:マルチスレッドモードの設定
-y:全ての質問に yes を仮定
-r:サブディレクトリの再帰的検索
-aoa:確認なしで上書き
-p{password}:パスワードの設定
-o{dir_path}:出力先ディレクトリの設定

詳細についてはDLL付属の7-zipCMD.txt、あるいはサンプルソース内のコメントを参照。


サンプルソースの7z操作クラス(SevenZManager)の公開機能は以下の通り
機能概要 メソッド名
7z圧縮[複数ファイル] fnCompressFiles()
7z圧縮[複数ファイル・パスワード指定] fnCompressFilesWithPassword()
7z圧縮[フォルダ指定] fnCompressFolder()
7z圧縮[フォルダ指定・パスワード指定] fnCompressFolderWithPassword()
7z解凍 fnExtract()
7z解凍[パスワード指定] fnExtractWithPassword()
Oncemail LabからASP.NETから利用したときの実行結果及びソースを確認できる。
※Oncemail Labでは「7z圧縮[複数ファイル]」サンプルのみ実行可能。


using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;

/// <summary>
/// 7z操作クラス(7-zip32.dllのラッパークラス)
/// </summary>
/// <remarks>
/// 【注意】
/// 7-zip32.dllをC:\Windows\などパスの通った場所に保存していること!!
///  DLL取得元:統合アーカイバプロジェクト
/// http://www.madobe.net/archiver/index.html
/// </remarks>
public static class SevenZManager
{
    /// <summary>
    /// [DLL Import] SevenZipのコマンドラインメソッド
    /// </summary>
    /// <param name="hwnd">ウィンドウハンドル(=0)</param>
    /// <param name="szCmdLine">コマンドライン</param>
    /// <param name="szOutput">実行結果文字列</param>
    /// <param name="dwSize">実行結果文字列格納サイズ</param>
    /// <returns>
    /// 0:正常、0以外:異常終了
    /// </returns>
    [DllImport("7-zip32.dll", CharSet = CharSet.Ansi)]
    private static extern int SevenZip(IntPtr hwnd, string szCmdLine, StringBuilder szOutput, int dwSize);

    /// <summary>
    /// 7z圧縮[複数ファイル]
    /// </summary>
    /// <param name="aryFilePath">圧縮対象ファイル一覧(フルパス指定)</param>
    /// <param name="s7zFilePath">7zファイル名</param>
    public static void fnCompressFiles(List<string> aryFilePath, string s7zFilePath)
    {
        lock (typeof(SevenZManager))
        {
            StringBuilder sbCmdLine = new StringBuilder(1024);   // コマンドライン文字列
            StringBuilder sbOutput = new StringBuilder(1024);    // 7-zip32.dll出力文字
            //---------------------------------------------------------------------------------
            // コマンドライン文字列の作成
            //---------------------------------------------------------------------------------
            // a:書庫にファイルを追加
            // -t7z:7形式を指定
            // -hide:処理状況ダイアログ表示の抑止
            // -mmt=on:マルチスレッドモードの設定
            // -y:全ての質問に yes を仮定
            sbCmdLine.AppendFormat("a -t7z -hide -mmt=on -y \"{0}\"", s7zFilePath);
            // 圧縮対象ファイルをコマンドライン化
            foreach (string sFilePath in aryFilePath)
            {
                sbCmdLine.AppendFormat(" \"{0}\"", sFilePath);
            }
            string sCmdLine = sbCmdLine.ToString();
            //---------------------------------------------------------------------------------
            // 圧縮実行
            //---------------------------------------------------------------------------------
            int iSevenZipRtn = SevenZip((IntPtr)0, sCmdLine, sbOutput, sbOutput.Capacity);
            //---------------------------------------------------------------------------------
            // 成功判定
            //---------------------------------------------------------------------------------
            fnCheckProc(iSevenZipRtn, sbOutput);
        }
    }
    /// <summary>
    /// ZIP圧縮[複数ファイル・パスワード指定]
    /// </summary>
    /// <param name="aryFilePath">圧縮対象ファイル一覧(フルパス指定)</param>
    /// <param name="s7zFilePath">7zファイル名</param>
    /// <param name="sPassword">パスワード(半角英数字)</param>
    public static void fnCompressFilesWithPassword(List<string> aryFilePath, string s7zFilePath, string sPassword)
    {
        lock (typeof(SevenZManager))
        {
            StringBuilder sbCmdLine = new StringBuilder(1024);   // コマンドライン文字列
            StringBuilder sbOutput = new StringBuilder(1024);    // 7-zip32.dll出力文字
            //---------------------------------------------------------------------------------
            // コマンドライン文字列の作成
            //---------------------------------------------------------------------------------
            // a:書庫にファイルを追加
            // -t7z:7形式を指定
            // -hide:処理状況ダイアログ表示の抑止
            // -mmt=on:マルチスレッドモードの設定
            // -y:全ての質問に yes を仮定
            // -p{password}:パスワードの設定
            sbCmdLine.AppendFormat(
                "a -t7z -hide -mmt=on -y -p{1} \"{0}\"", s7zFilePath, sPassword);
            // 圧縮対象ファイルをコマンドライン化
            foreach (string sFilePath in aryFilePath)
            {
                sbCmdLine.AppendFormat(" \"{0}\"", sFilePath);
            }
            string sCmdLine = sbCmdLine.ToString();
            //---------------------------------------------------------------------------------
            // 圧縮実行
            //---------------------------------------------------------------------------------
            int iSevenZipRtn = SevenZip((IntPtr)0, sCmdLine, sbOutput, sbOutput.Capacity);
            //---------------------------------------------------------------------------------
            // 成功判定
            //---------------------------------------------------------------------------------
            fnCheckProc(iSevenZipRtn, sbOutput);
        }
    }
    /// <summary>
    /// 7z圧縮[フォルダ指定]
    /// </summary>
    /// <param name="sFolderPath">圧縮対象フォルダ(フルパス指定)</param>
    /// <param name="s7zFilePath">7zファイル名</param>
    public static void fnCompressFolder(string sFolderPath, string s7zFilePath)
    {
        lock (typeof(SevenZManager))
        {
            StringBuilder sbOutput = new StringBuilder(1024);   // 7-zip32.dll出力文字
            //---------------------------------------------------------------------------------
            // sFolderPathの最後が\の場合、\を取り払う
            //---------------------------------------------------------------------------------
            while (sFolderPath[sFolderPath.Length - 1] == '\\')
            {
                sFolderPath = sFolderPath.Substring(0, sFolderPath.Length - 1);
            }
            //---------------------------------------------------------------------------------
            // コマンドライン文字列の作成
            //---------------------------------------------------------------------------------
            // a:書庫にファイルを追加
            // -t7z:7形式を指定
            // -hide:処理状況ダイアログ表示の抑止
            // -mmt=on:マルチスレッドモードの設定
            // -y:全ての質問に yes を仮定
            // -r:サブディレクトリの再帰的検索
            string sCmdLine = string.Format(
                "a -t7z -hide -mmt=on -y -r \"{0}\" \"{1}\\*\"", s7zFilePath, sFolderPath);
            //---------------------------------------------------------------------------------
            // 圧縮実行
            //---------------------------------------------------------------------------------
            int iSevenZipRtn = SevenZip((IntPtr)0, sCmdLine, sbOutput, sbOutput.Capacity);
            //---------------------------------------------------------------------------------
            // 成功判定
            //---------------------------------------------------------------------------------
            fnCheckProc(iSevenZipRtn, sbOutput);
        }
    }
    /// <summary>
    /// 7z圧縮[フォルダ指定・パスワード指定]
    /// </summary>
    /// <param name="sFolderPath">圧縮対象フォルダ(フルパス指定)</param>
    /// <param name="s7zFilePath">7zファイル名</param>
    /// <param name="sPassword">パスワード(半角英数字)</param>
    public static void fnCompressFolderWithPassword(string sFolderPath, string s7zFilePath, string sPassword)
    {
        lock (typeof(SevenZManager))
        {
            StringBuilder sbOutput = new StringBuilder(1024);   // 7-zip32.dll出力文字
            //---------------------------------------------------------------------------------
            // sFolderPathの最後が\の場合、\を取り払う
            //---------------------------------------------------------------------------------
            while (sFolderPath[sFolderPath.Length - 1] == '\\')
            {
                sFolderPath = sFolderPath.Substring(0, sFolderPath.Length - 1);
            }
            //---------------------------------------------------------------------------------
            // コマンドライン文字列の作成
            //---------------------------------------------------------------------------------
            // a:書庫にファイルを追加
            // -t7z:7形式を指定
            // -hide:処理状況ダイアログ表示の抑止
            // -mmt=on:マルチスレッドモードの設定
            // -y:全ての質問に yes を仮定
            // -r:サブディレクトリの再帰的検索
            // -p{password}:パスワードの設定
            string sCmdLine = string.Format(
                "a -t7z -hide -mmt=on -y -r -p{2} \"{0}\" \"{1}\\*\"",
                s7zFilePath, sFolderPath, sPassword);
            //---------------------------------------------------------------------------------
            // 圧縮実行
            //---------------------------------------------------------------------------------
            int iSevenZipRtn = SevenZip((IntPtr)0, sCmdLine, sbOutput, sbOutput.Capacity);
            //---------------------------------------------------------------------------------
            // 成功判定
            //---------------------------------------------------------------------------------
            fnCheckProc(iSevenZipRtn, sbOutput);
        }
    }
    /// <summary>
    /// 7z解凍
    /// </summary>
    /// <param name="s7zFilePath">7zファイル名</param>
    /// <param name="sDustFolder">出力先フォルダ</param>
    public static void fnExtract(string s7zFilePath, string sDustFolder)
    {
        lock (typeof(SevenZManager))
        {
            StringBuilder sbOutput = new StringBuilder(1024);   // 7-zip32.dll出力文字
            //---------------------------------------------------------------------------------
            // sDustFolderの最後が\の場合、\を取り払う
            //---------------------------------------------------------------------------------
            while (sDustFolder[sDustFolder.Length - 1] == '\\')
            {
                sDustFolder = sDustFolder.Substring(0, sDustFolder.Length - 1);
            }
            ////---------------------------------------------------------------------------------
            //// 出力先フォルダが存在しなければ作成
            ////---------------------------------------------------------------------------------
            //if (!Directory.Exists(sDustFolder))
            //{
            //    Directory.CreateDirectory(sDustFolder);
            //}
            //---------------------------------------------------------------------------------
            // コマンドライン文字列の作成
            //---------------------------------------------------------------------------------
            // x:解凍
            // -aoa:確認なしで上書き
            // -hide:処理状況ダイアログ表示の抑止
            // -y:全ての質問に yes を仮定
            // -r:サブディレクトリの再帰的検索
            // -o{dir_path}:出力先ディレクトリの設定
            string sCmdLine = string.Format(
                "x -aoa -hide -y -r \"{0}\" -o\"{1}\"\\*", s7zFilePath, sDustFolder);
            //---------------------------------------------------------------------------------
            // 解凍実行
            //---------------------------------------------------------------------------------
            int iSevenZipRtn = SevenZip((IntPtr)0, sCmdLine, sbOutput, sbOutput.Capacity);
            //---------------------------------------------------------------------------------
            // 成功判定
            //---------------------------------------------------------------------------------
            fnCheckProc(iSevenZipRtn, sbOutput);
        }
    }
    /// <summary>
    /// 7z解凍[パスワード指定]
    /// </summary>
    /// <param name="s7zFilePath">7zファイル名</param>
    /// <param name="sDustFolder">出力先フォルダ</param>
    /// <param name="sPassword">パスワード(半角英数字)</param>
    public static void fnExtractWithPassword(string s7zFilePath, string sDustFolder, string sPassword)
    {
        lock (typeof(SevenZManager))
        {
            StringBuilder sbOutput = new StringBuilder(1024);   // 7-zip32.dll出力文字
            //---------------------------------------------------------------------------------
            // sDustFolderの最後が\の場合、\を取り払う
            //---------------------------------------------------------------------------------
            while (sDustFolder[sDustFolder.Length - 1] == '\\')
            {
                sDustFolder = sDustFolder.Substring(0, sDustFolder.Length - 1);
            }
            //---------------------------------------------------------------------------------
            // コマンドライン文字列の作成
            //---------------------------------------------------------------------------------
            // x:解凍
            // -aoa:確認なしで上書き
            // -hide:処理状況ダイアログ表示の抑止
            // -y:全ての質問に yes を仮定
            // -r:サブディレクトリの再帰的検索
            // -o{dir_path}:出力先ディレクトリの設定
            // -p{password}:パスワードの設定
            string sCmdLine = string.Format(
                "x -aoa -hide -y -r \"{0}\" -o\"{1}\"\\* -p{2}",
                s7zFilePath, sDustFolder, sPassword);
            //---------------------------------------------------------------------------------
            // 解凍実行
            //---------------------------------------------------------------------------------
            int iSevenZipRtn = SevenZip((IntPtr)0, sCmdLine, sbOutput, sbOutput.Capacity);
            //---------------------------------------------------------------------------------
            // 成功判定
            //---------------------------------------------------------------------------------
            fnCheckProc(iSevenZipRtn, sbOutput);
        }
    }
    /// <summary>
    /// SevenZipメソッド成功判定
    /// </summary>
    /// <param name="iSevenZipRtn">SevenZipメソッドの戻り値</param>
    /// <param name="sbLzhOutputString">SevenZipメソッドの第3引数</param>
    private static void fnCheckProc(int iSevenZipRtn, StringBuilder sbLzhOutputString)
    {
        //-------------------------------------------------------------------------------------
        // メソッドの戻り値=0なら正常終了
        //-------------------------------------------------------------------------------------
        if (iSevenZipRtn == 0)
            return;
        //-------------------------------------------------------------------------------------
        // 例外スロー
        //-------------------------------------------------------------------------------------
        string sMsg = string.Format(
            "7z圧縮/解凍処理に失敗:\nエラーコード={0}:\n{1}", iSevenZipRtn, sbLzhOutputString);
        throw new ApplicationException(sMsg);
    }
}



using System;
using System.IO;
using System.Collections.Generic;
using System.Text;

class Program
{
    static void Main(string[] args)
    {
        //-------------------------------------------------------------------------------------
        // ファイル圧縮
        //-------------------------------------------------------------------------------------
        List<string> aryFiles1 = new List<string>();
        aryFiles1.Add(@"c:\temp\file1.gif");
        aryFiles1.Add(@"c:\temp\file1.txt");
        string s7zFilePath1 = 
            string.Format(@"c:\temp\{0:yyyyMMddHHmmss}files.7z", DateTime.Now);
        SevenZManager.fnCompressFiles(aryFiles1, s7zFilePath1);
        //-------------------------------------------------------------------------------------
        // ファイル圧縮(パスワード付)
        //-------------------------------------------------------------------------------------
        List<string> aryFiles2 = new List<string>();
        aryFiles2.Add(@"c:\temp\file2.png");
        aryFiles2.Add(@"c:\temp\file2.xls");
        string s7zFilePath2 =
            string.Format(@"c:\temp\{0:yyyyMMddHHmmss}filesP.7z", DateTime.Now);
        string sPassword2 = "abc";
        SevenZManager.fnCompressFilesWithPassword(aryFiles2, s7zFilePath2, sPassword2);
        //-------------------------------------------------------------------------------------
        // フォルダ圧縮
        //-------------------------------------------------------------------------------------
        string sFolder3 = @"c:\temp\arc";
        string s7zFilePath3 =
            string.Format(@"c:\temp\{0:yyyyMMddHHmmss}folders.7z", DateTime.Now);
        SevenZManager.fnCompressFolder(sFolder3, s7zFilePath3);
        //-------------------------------------------------------------------------------------
        // フォルダ圧縮(パスワード付)
        //-------------------------------------------------------------------------------------
        string sFolder4 = @"c:\temp\arc";
        string s7zFilePath4 =
            string.Format(@"c:\temp\{0:yyyyMMddHHmmss}foldersP.7z", DateTime.Now);
        string sPassword4 = "123";
        SevenZManager.fnCompressFolderWithPassword(sFolder4, s7zFilePath4, sPassword4);
        //-------------------------------------------------------------------------------------
        // 解凍
        //-------------------------------------------------------------------------------------
        string sDustDir5 = @"c:\temp\7zDust";
        SevenZManager.fnExtract(s7zFilePath1, sDustDir5);
        //-------------------------------------------------------------------------------------
        // 解凍(パスワード付)
        //-------------------------------------------------------------------------------------
        string sDustDir6 = @"c:\temp\7zDustP";
        SevenZManager.fnExtractWithPassword(s7zFilePath2, sDustDir6, sPassword2);
    }
}

■注意点
7-zip32.dllを使う際に気がついた注意点は以下の通り。

  • 7-zip32.dll利用時にはGNU Lesser General Public Licenseについて良く調べること。
  • 64BitOSで動かす際にはアプリケーションを32Bitモードで動かさないとDLLリンクでエラーになる。(.NETアプリのデフォルトはAnyCPUなので設定変更しないとアウト)

7zについては7-Zip - Wikipediaおよび7z - Wikipediaを参照。
GNU Lesser General Public License(LGPL)についてはGNU General Public License - WikipediaおよびGNU Lesser General Public License - Wikipediaを参照。

64bitOSで動かしたい場合、NET Frameworkアプリケーションを64bit OS上で32bitモードで動かす方法を参照。

■クレジット
念のため...

  • 7-zip ファイルの圧縮、解凍の基本部分の著作権は Igor Pavlov 氏にあります。
  • 7z 圧縮方式の BZip2 アルゴリズムはJulian Seward 氏が作成し、 PPMD アルゴリズムは Dmitry Shkarin 氏が作成しています。
  • 7-zip32.dll つまり統合アーカイバ仕様の DLL 作成部分に関しては秋田 稔 氏が著作権を保有します。
  • 本ページサンプルソースはページ管理者が著作権を保有します。


■関連ページ

Windows 7 RCを使ってみた

Windows 7 RCを使ってみた

■最初に
2009年5月7日(開発者向けは4月30日)にWindows 7 RCをリリース。

<Windows 7: ホーム ページ>
Windows 7: ホーム ページ

<ダウンロード先>
Windows 7 製品候補版(Release Candidate): ダウンロードの手順

<テスト環境>

OS Windows 7 RC Ultimate 評価コピー ビルド 7100(32ビット版)
CPU Intel Core 2 QUAD 9550s 2.83GHz
メモリー 2GB
HDD 120GB
画面解像度 1280×1024
本テストでは仮想環境(Hyper V)のGuest OSとしてWindow 7をインストールしている。
このためAero等、ハードウエアに依存する機能が無効になっている。
イメージはリモートデスクトップ接続経由で取得している。


起動画面


ビルド番号


インストール直後のHDD容量


インストール直後のパフォーマンス

■起動・ログイン・終了
仮想環境のためAeroが無効状態...。

起動中


ログオン...この画面が表示されるまで約30秒。


デスクトップ...ログオン画面から約10秒。


シャットダウン...約10秒ぐらい。

■スタートメニュー

全体イメージ


デフォルト


すべてのプログラム


最近使った項目...アプリケーション毎に設定されるようになった。

■タスクバー
仮想環境のためAeroが無効状態...。

全体イメージ


タスクアイコン...タスクバーにはアイコンだけが表示されるようになった。


デスクトップの表示...タスクバーの右端に移動した。

■コントロールパネル

カテゴリ


小さなアイコン...幾つか新しい項目が増えている。

■エクスプローラ
左側が変わった。アイコン毎にツリー表示できる。

■ガジット
自由配置できるようになった。

■アクセサリツール
見た目が一番変わったのがアクセサリかも。

スタートメニュー...幾つか新しいものが増えた。


付箋...新規追加?


数式入力パネル...新規追加?計算は出来ないみたい。


ペイント...大幅修正。リボン化。
フリー・市販ツールと比べると機能不足だがトリミング・ブラシ・オートシェープ・グリッド・ルーラ等が追加された。
お手軽な画像加工では十分使える。
個人的にペイント利用頻度が高いので一押しの機能拡張。




ワードパッド...リボン化。機能はあまり変わっていない。


電卓...大幅修正。普通の電卓・関数電卓・プログラマ・統計の4種に分割&機能拡張。

通常の電卓
関数電卓
統計
プログラマ

■Windows Live メール(インストール手順付)
スタートメニューにWindows メール(旧 Outlook Express)が見つからなかった。
「Windows 7」に、電子メールや画像編集ソフトは非搭載と判明:ニュース - CNET Japanで紹介されているように標準搭載しないらしいが、Windows Liveから追加インストールできる。
名前も「Windows Live メール」に変わった。
簡単なインストール手順を含め以下の通り。








■Internet Explorer 8
Internet Explorer 8(IE8)が標準搭載。Vista版とリビジョンが違う以外の変更点は見られない。



「IE8がアンインストールできる」という話題があったが、これかな?

■Windows Media Player 12
Windows Media Player 12を搭載。

■標準インストール済ライブラリ
簡単に調べてみた。以下の通り

NO.ライブラリ対応バージョン
1 .NET Framework 2.0, 3.0, 3.5
2 C,C++,MFCランタイム VC6以前なら動きそう。VC7以降なら追加インストールっぽい。
msvcirt.dll,msvcp60.dll,msvcrt.dll,msvcrt20.dll,msvcrt40.dll,mfc40.dll,mfc40u.dll,mfc42.dll,mfc42u.dllを確認。
3 VB6.0ランタイム日本語版 入ってない。
4 Direct X 11

Visual Studio 2003以前の開発者およびVisual Studio 2002以降のVC++開発者には不親切な気がする。

■簡単に使ってみた印象

○Vistaから違和感がない程度にUIが向上している。
○RCの割にシステムダウンもアプリケーション異常終了もしない。
○アクセサリツール関連が向上。
×XP以前のユーザだとVistaと同じくUIに違和感がある。

セキュリティやPC管理機能は向上しているみたいだけど個人的にはXP・VistaからWindows7への移動はメリットが薄いと感じた。
今回試していない機能と対応ソフト次第って感じかなぁ~。
まぁ発売当日にはインストールしちゃうんだろうけどね...。

試していないけど期待している機能。

機能名所感
Aero 期待したいかな。
Windows XP Mode 仮想OS(Virtual PC)としてXPを動かすらしい。
グラフィックカード等のハードウエアをバリバリ使うゲームは多分恩恵を受けられないと思う。

サービスアプリ追加(画像ファイル一括変換サービス)

Oncemail Lab画像ファイル一括変換サービスを追加。


■サービス公開先
Oncemail Lab


■2009/05/04時点での公開サービス

サービス名概要
OfficeファイルのPDFファイル変換サービス Excel・Word・PowerPointファイルをPDFファイルに変換します。
Officeファイルバージョン変換サービス Excel・Word・PowerPointファイルのファイルバージョンを変換します。
PDFファイルにパスワード設定サービス PDFファイルにパスワードを設定します。
PDFをファイル結合サービス 2つのPDFファイルを1つのPDFファイルに結合します。
ファイルのZIP圧縮サービス ファイルをZIP圧縮します。
ファイルのLZH圧縮サービス ファイルをLZH圧縮します。
ランダムパスワード生成サービス ランダムなパスワードを生成します。
CAPCHA作成サービス CAPCHA(キャプチャ)を作成・ダウンロードできます。
画像ファイル一括変換サービス 複数の画像ファイルを一括で画像形式・サイズ・透過等の変換を行います。

C#でCAPCHA画像作成

C#でCAPCHA(キャプチャ)画像を作成する方法を紹介する。



※本サンプルは、CodeProject: CAPTCHA Image. Free source code and programming helpのサンプルソースをベースに作成している。
※本サンプルではCAPCHAに表示する文字は固定の値を設定している。 ランダムな文字列を利用する場合、C#でパスワード文字列作成も併せて検討してほしい。


■C#サンプル
サンプルソース「キャプチャジェネレータクラス(CaptchaGenerator)」の公開機能は以下の通り

No. 機能概要 メソッド名
1 イメージの保存(Stream出力) fnSaveImage()
2 イメージの保存(ファイル出力) fnSaveImage()

本ソースはOncemail LabからASP.NETから利用したときの実行結果が確認できる。


using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;

/// <summary>
/// CAPCHAジェネレータ
/// </summary>
public static class CaptchaGenerator
{
    /// <summary>
    /// フォントファミリー名のデフォルト値
    /// </summary>
    const string CST_DEFALUT_FONT_FAMILY_NAME = "MS ゴシック";

    /// <summary>
    /// イメージの保存
    /// </summary>
    /// <param name="sText"></param>
    /// <param name="sText">テキスト</param>
    /// <param name="iWidth">幅</param>
    /// <param name="iHeight">高さ</param>
    /// <param name="imgFormat">イメージタイプ</param>
    public static void fnSaveImage(Stream stream, string sText, int iWidth, int iHeight, ImageFormat imgFormat)
    {
        // 枠作成
        Rectangle rect = new Rectangle(0, 0, iWidth, iHeight);
        // CAPCHA作成
        using (Bitmap bmpImage = fnGenerateImage(sText, rect, CST_DEFALUT_FONT_FAMILY_NAME))
        {
            bmpImage.Save(stream, imgFormat);
        }
    }    
    /// <summary>
    /// イメージの保存
    /// </summary>
    /// <param name="sOutputFilePath">出力ファイルパス</param>
    /// <param name="sText">テキスト</param>
    /// <param name="iWidth">幅</param>
    /// <param name="iHeight">高さ</param>
    public static void fnSaveImage(string sOutputFilePath, string sText, int iWidth, int iHeight)
    {
        ImageFormat imgFormat = ImageFormat.Jpeg;
        // イメージフォーマットの作成
        switch (Path.GetExtension(sOutputFilePath).ToLower())
        {
            case ".bmp": imgFormat = ImageFormat.Bmp; break;
            case ".gif": imgFormat = ImageFormat.Gif; break;
            case ".png": imgFormat = ImageFormat.Png; break;
        }
        // 枠作成
        Rectangle rect = new Rectangle(0, 0, iWidth, iHeight);
        // CAPCHA作成
        using (FileStream fs = new FileStream(sOutputFilePath, FileMode.CreateNew))
        using (Bitmap bmpImage = fnGenerateImage(sText, rect, CST_DEFALUT_FONT_FAMILY_NAME))
        {
            bmpImage.Save(fs, imgFormat);
            fs.Flush();
            fs.Close();
        }
    }
    /// <summary>
    /// CAPTCHAイメージ作成
    /// </summary>
    /// <param name="sText">CAPCHAテキスト</param>
    /// <param name="rect">枠サイズ</param>
    /// <param name="sFamilyName">フォント名</param>
    /// <returns>Bitmapオブジェクト</returns>
    private static Bitmap fnGenerateImage(string sText, Rectangle rect, string sFamilyName)
    {
        Random rnd = new Random();                          // 乱数オブジェクト
        HatchStyle hsBackground = HatchStyle.SmallConfetti; // 背景ハッチパターン
        HatchStyle hsText = HatchStyle.LargeConfetti;       // テキストハッチパターン
        Color colBackgroundForeColor = Color.White;         // 背景色
        Color colTextForeColor = Color.White;               // テキスト色
        //---------------------------------------------------------------------------------
        // ランダムなハッチパターンを取得
        //---------------------------------------------------------------------------------
        string[] aryHatchStyleName = Enum.GetNames(typeof(HatchStyle));
        // 背景ハッチパターン取得
        int iHatchStyleIndex = rnd.Next(aryHatchStyleName.Length);
        hsBackground = (HatchStyle)Enum.Parse(typeof(HatchStyle), aryHatchStyleName[iHatchStyleIndex]);
        // テキストハッチパターン取得
        iHatchStyleIndex = rnd.Next(aryHatchStyleName.Length);
        hsText = (HatchStyle)Enum.Parse(typeof(HatchStyle), aryHatchStyleName[iHatchStyleIndex]);
        // 背景色ハッチパターンの前景色取得
        int iRed, iGreen, iBlue;
        iRed = 0xFF - rnd.Next(2);
        iGreen = 0xFF - rnd.Next(2);
        iBlue = 0xFF - rnd.Next(2);
        colBackgroundForeColor = Color.FromArgb(iRed, iGreen, iBlue);
        // テキストハッチパターンの前景色取得
        do
        {
            iRed = rnd.Next(0xFF);
            iGreen = rnd.Next(0xFF);
            iBlue = rnd.Next(0xFF);
            colTextForeColor = Color.FromArgb(iRed, iGreen, iBlue);
        } while (iRed > 0xD0 && iGreen > 0xD0 && iBlue > 0xD0);
        //---------------------------------------------------------------------------------
        // Bitmapイメージ作成
        //---------------------------------------------------------------------------------
        Bitmap bitmap = new Bitmap(rect.Width, rect.Height, PixelFormat.Format32bppArgb);
        // グラフィックオブジェクト
        using (Graphics g = Graphics.FromImage(bitmap))
        // 背景ハッチブラシ
        using (HatchBrush hbBackground = new HatchBrush(hsBackground, Color.LightGray, colBackgroundForeColor))
        // テキストハッチブラシ
        using (HatchBrush hbText = new HatchBrush(hsText, Color.LightGray, colTextForeColor))
        using (StringFormat format = new StringFormat())
        using (GraphicsPath path = new GraphicsPath())
        {
            int iFontSize;  // フォントサイズ
            SizeF size;     // サイズ
            //-----------------------------------------------------------------------------
            // グラフィックの初期化
            //-----------------------------------------------------------------------------
            // アンチエイリアスモード
            g.SmoothingMode = SmoothingMode.AntiAlias;
            //-----------------------------------------------------------------------------
            // 背景イメージ作成
            //-----------------------------------------------------------------------------
            // グラフィックオブジェクトを紙吹雪背景でハッチング
            g.FillRectangle(hbBackground, rect);
            //-----------------------------------------------------------------------------
            // テキストイメージ作成
            //-----------------------------------------------------------------------------
            // イメージに収まるフォントサイズ算出
            iFontSize = rect.Height + 1;
            do
            {
                iFontSize--;
                using (Font f = new Font(sFamilyName, iFontSize, FontStyle.Bold))
                {
                    size = g.MeasureString(sText, f);
                }
            } while (size.Width > rect.Width);
            using (Font font = new Font(sFamilyName, iFontSize, FontStyle.Bold))
            {
                //-------------------------------------------------------------------------
                // ゆがんだテキストのグラフィックパス作成
                //-------------------------------------------------------------------------
                // テキストフォーマット設定
                format.Alignment = StringAlignment.Center;
                format.LineAlignment = StringAlignment.Center;
                // パスにテキスト情報を設定、ワープ変換を利用しランダムにゆがめる。
                path.AddString(sText, font.FontFamily, (int)font.Style, font.Size, rect, format);
                // ワープ変換
                float v = 4F;
                PointF[] points =
                {
                    new PointF(rnd.Next(rect.Width) / v, rnd.Next(rect.Height) / v),
                    new PointF(rect.Width - rnd.Next(rect.Width) / v, rnd.Next(rect.Height) / v),
                    new PointF(rnd.Next(rect.Width) / v, rect.Height - rnd.Next(rect.Height) / v),
                    new PointF(rect.Width - rnd.Next(rect.Width) / v, rect.Height - rnd.Next(rect.Height) / v)
                };
                Matrix matrix = new Matrix();
                matrix.Translate(0F, 0F);
                path.Warp(points, rect, matrix, WarpMode.Perspective, 0F);
            }
            // テキスト描画
            g.FillPath(hbText, path);
            //-----------------------------------------------------------------------------
            // ランダムなノイズ作成
            //-----------------------------------------------------------------------------
            int m = Math.Max(rect.Width, rect.Height);
            for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++)
            {
                int x = rnd.Next(rect.Width);
                int y = rnd.Next(rect.Height);
                int w = rnd.Next(m / 80);
                int h = rnd.Next(m / 80);
                g.FillEllipse(hbBackground, x, y, w, h);
            }
        }
        return bitmap;
    }
}



using System;
using System.Collections.Generic;

class Program
{
    static void Main(string[] args)
    {
        string sJpegFilePath = string.Format(@"c:\temp\{0:yyyyMMddHHmmss}.jpg", DateTime.Now);
        string sGifFilePath = string.Format(@"c:\temp\{0:yyyyMMddHHmmss}.gif", DateTime.Now);
        string sPngFilePath = string.Format(@"c:\temp\{0:yyyyMMddHHmmss}.png", DateTime.Now);
        // JPEGでCAPCHAイメージファイル作成
        CaptchaGenerator.fnSaveImage(sJpegFilePath, "CAPCHA IMAGE JPEG", 300, 50);
        // GIFでCAPCHAイメージファイル作成
        CaptchaGenerator.fnSaveImage(sGifFilePath, "CAPCHA IMAGE GIF", 300, 50);
        // PNGでCAPCHAイメージファイル作成
        CaptchaGenerator.fnSaveImage(sPngFilePath, "CAPCHA IMAGE PNG", 300, 50);
    }
}
【作成結果】
JEPEGイメージ

GIFイメージ

PNGイメージ


※本サンプルではCAPCHAに表示する文字は固定の値を設定している。 ランダムな文字列を利用する場合、C#でパスワード文字列作成も併せて検討してほしい。



■関連ページ

サービスアプリ追加(CAPCHA作成サービス)

Oncemail LabCAPCHA作成サービスを追加。


■サービス公開先
Oncemail Lab


■2009/05/02時点での公開サービス

サービス名概要
OfficeファイルのPDFファイル変換サービス Excel・Word・PowerPointファイルをPDFファイルに変換します。
Officeファイルバージョン変換サービス Excel・Word・PowerPointファイルのファイルバージョンを変換します。
PDFファイルにパスワード設定サービス PDFファイルにパスワードを設定します。
PDFをファイル結合サービス 2つのPDFファイルを1つのPDFファイルに結合します。
ファイルのZIP圧縮サービス ファイルをZIP圧縮します。
ファイルのLZH圧縮サービス ファイルをLZH圧縮します。
ランダムパスワード生成サービス ランダムなパスワードを生成します。
CAPCHA作成サービス CAPCHA(キャプチャ)を作成・ダウンロードできます。

NET Frameworkアプリケーションを64bit OS上で32bitモードで動かす方法

.NET Frameworkアプリケーションを64bit OS上で32bitモードで動かす方法の紹介。


※続編としてNET Frameworkアプリケーションを64bit OS上で32bitモードで動かす方法(その2)も書いてみた。


■最初に
最近64bit Windows OSの利用機会が増えているが、ActiveXやC言語DLLが64bitに対応していないことは多い。
.NET FrameworkアプリケーションはOSに応じて32bit・64bitアプリケーションと自動で切り替えて動作するが、 64bit OSで32bitにしか対応していないライブラリを内部利用したアプリケーションを動かすと以下の例外発生する。

BadImageFormatException
間違ったフォーマットのプログラムを読み込もうとしました。 (HRESULT からの例外: 0x800xxxxx)
この回避方法の1つとして64bit OS環境上で.NET Frameworkアプリケーションを32bitモードで動かす設定方法を紹介する。

なお本ページの環境構成は以下の通り。
・Windows Server 2008 64bit
・IIS 7.0
・Visual Studio 2008
・.NET Framework 3.5 SP1



■コンソールアプリケーション・Windowsアプリケーションの32bit化
コンソールアプリケーション・Windowsアプリケーションの設定方法は以下の通り。(Windowsサービスも?)

手順1
ソリューションエクスプローラから該当プロジェクトを右クリック、プロパティを選択する。


手順2
「ビルド」タブを選択し、「プラットフォーム ターゲット」を"x86"に設定する。


結果
タスクマネジャーから該当アプリケーションが32bitで起動していることが確認できる。




■ASP.NETアプリケーションの32bit化
ASP.NETはIIS6.0以降、デフォルトではIISの一部として動くため、ワーカプロセス自体を32bitに設定する必要がある。
設定方法は以下の通り。

手順1
インターネットインフォメーションサービス(IIS)マネージャを起動し、該当アプリケーションで利用しているアプリケーション プールを選択、右クリックで「詳細設定」を選択する。


手順2
「全般」の「32 ビット アプリケーションの有効化」を"true"に設定後、IISを再起動する。


結果
タスクマネジャーからワーカープロセス(w3wp.exe)が32bitアプリケーションとして起動していることが確認できる。



■関連ページ


サービスアプリ追加(ランダムパスワード生成)

Oncemail Labランダムパスワード生成を追加。


■サービス公開先
Oncemail Lab


■2009/05/01時点での公開サービス

サービス名概要
OfficeファイルをPDFファイル変換 Excel・Word・PowerPointファイルをPDFファイルに変換します。
Officeファイルバージョン変換 Excel・Word・PowerPointファイルのファイルバージョンを変換します。
PDFファイルにパスワード設定 PDFファイルにパスワードを設定します。
PDFをファイル結合 2つのPDFファイルを1つのPDFファイルに結合します。
ファイルをZIP圧縮 ファイルをZIP圧縮します。
ファイルをLZH圧縮 ファイルをLZH圧縮します。
ランダムパスワード生成 ランダムなパスワードを生成します。

C#でパスワード文字列作成

C#でランダムなパスワード文字列を作成する方法を紹介する。


■前提知識
本サンプルはASCIIコードの印字可能な文字コードを利用している。
本サンプルで利用している文字コードは以下の通り。

 203040506070
00SP0@P`p
01!1AQaq
02"2BRbr
03#3CScs
04$4DTdt
05%5EUeu
06&6FVfv
07'7GWgw
08(8HXhx
09)9IYiy
0A*:JZjz
0B+;K[k{
0C,<L\l|
0D-=M]m}
0E.>N^n~
0F/?O_oDL

ASCIIコードの詳細はwikipediaあたりで詳しく紹介している。

より強固なパスワードを作りたい場合、
System.Security.Cryptography.RNGCryptoServiceProviderクラス
System.Web.Security.Membership.GeneratePassword()メソッド
等も参考にしてほしい。


■C#サンプル
サンプルソースパスワードジェネレータクラス(PasswordGenerator)の公開機能は以下の通り

No. 機能概要 メソッド名 備考
1 「数値」パスワード取得 fnGetNumber()  
2 「英小文字」パスワード取得 fnGetAlphabetLower()  
3 「英大文字」パスワード取得 fnGetAlphabetUpper()  
4 「英文字・数字」パスワード取得 fnGetNumberAlphabet()  
5 「英文字・数字」パスワード取得
※形の似た文字は除く
fnGetNumberAlphabetWithoutResembleShape() 0とO、1とlとI、iとjを外している
6 「英数記号文字」パスワード取得 fnGetNumberAlphabetSymbol() あまりパスワードで使われない文字」HTML特殊文字等を外している
7 「英数記号文字」パスワード取得
※形の似た文字は除く
fnGetNumberAlphabetSymbolWithoutResembleShape() あまりパスワードで使われない文字」HTML特殊文字・0とO、1とlとI、iとj等を外している
なおNo.5~7は処理共通化の為fnGetSpecialCondition()を呼び出す際に匿名メソッドを使っているため一見難しそうに感じるかもしれないが、やっていることはNo.4とほとんど同じである。

本ソースはOncemail LabからASP.NETから利用したときの実行結果及びソースを確認できる。


using System;
using System.Text;

/// <summary>
/// パスワードジェネレータ
/// </summary>
public class PasswordGenerator
{
    /// <summary>
    /// 乱数
    /// </summary>
    private static Random m_Rnd = new Random();
    /// <summary>
    /// パスワードに含める文字コードの判定デリゲート
    /// </summary>
    private delegate bool fnCheckIncludCharCode(int iCharCode);
    
    /// <summary>
    /// 「数値」パスワード取得
    /// </summary>
    /// <param name="iLength">パスワード長</param>
    /// <returns>パスワード文字列</returns>
    public static string fnGetNumber(int iLength)
    {
        lock (typeof(PasswordGenerator))
        {
            const int CHAR_CODE_MAX = ((int)('9' - '0')) + 1;   // 文字コード範囲
            byte[] aryBytePassword = new byte[iLength];         // パスワード文字コード配列
            int iCharCode;                                      // 文字コード
            //---------------------------------------------------------------------------------
            // パスワード文字コード配列の作成
            //---------------------------------------------------------------------------------
            for (int i = 0; i < aryBytePassword.Length; i++)
            {
                // 乱数で'0'~'9'の文字コード生成
                // ※先頭文字に"0は認めない"
                do
                {
                    iCharCode = m_Rnd.Next(CHAR_CODE_MAX);
                    iCharCode += (int)'0';
                } while (i == 0 && iCharCode == 0x30);
                // 文字コードをバイト配列に設定
                aryBytePassword[i] = (byte)iCharCode;
            }
            //---------------------------------------------------------------------------------
            // バイト配列をASCII文字列に置換
            //---------------------------------------------------------------------------------
            return Encoding.GetEncoding("ASCII").GetString(aryBytePassword);
        }
    }
    /// <summary>
    /// 「英小文字」パスワード取得
    /// </summary>
    /// <param name="iLength">パスワード長</param>
    /// <returns>パスワード文字列</returns>
    public static string fnGetAlphabetLower(int iLength)
    {
        lock (typeof(PasswordGenerator))
        {
            const int CHAR_CODE_MAX = ((int)('z' - 'a')) + 1;   // 文字コード範囲
            byte[] aryBytePassword = new byte[iLength];         // パスワード文字コード配列
            int iCharCode;                                      // 文字コード
            //---------------------------------------------------------------------------------
            // パスワード文字コード配列の作成
            //---------------------------------------------------------------------------------
            for (int i = 0; i < aryBytePassword.Length; i++)
            {
                // 乱数で'a'~'z'の文字コード生成
                iCharCode = m_Rnd.Next(CHAR_CODE_MAX);
                iCharCode += (int)'a';
                // 文字コードをバイト配列に設定
                aryBytePassword[i] = (byte)iCharCode;
            }
            //---------------------------------------------------------------------------------
            // バイト配列をASCII文字列に置換
            //---------------------------------------------------------------------------------
            return Encoding.GetEncoding("ASCII").GetString(aryBytePassword);
        }
    }
    /// <summary>
    /// 「英大文字」パスワード取得
    /// </summary>
    /// <param name="iLength">パスワード長</param>
    /// <returns>パスワード文字列</returns>
    public static string fnGetAlphabetUpper(int iLength)
    {
        return fnGetAlphabetLower(iLength).ToUpper();   
    }
    /// <summary>
    ///「英文字・数字」パスワード取得
    /// </summary>
    /// <param name="iLength">パスワード長</param>
    /// <returns>パスワード文字列</returns>
    public static string fnGetNumberAlphabet(int iLength)
    {
        lock (typeof(PasswordGenerator))
        {
            const int CHAR_CODE_MAX = ((int)('z' - '0')) + 1;   // 文字コード範囲
            byte[] aryBytePassword = new byte[iLength];         // パスワード文字コード配列
            int iCharCode;                                      // 文字コード
            //---------------------------------------------------------------------------------
            // パスワード文字コード配列の作成
            //---------------------------------------------------------------------------------
            for (int i = 0; i < aryBytePassword.Length; i++)
            {
                // 乱数で'0'~'9'・'A'~'Z'・'a'~'z'の文字コード生成
                // ※:;<=>?@[\]^′なら再取得
                do
                {
                    iCharCode = m_Rnd.Next(CHAR_CODE_MAX);
                    iCharCode += (int)'0';
                } while (((0x3A <= iCharCode) && (iCharCode <= 0x40)) ||    // :;<=>?@
                         ((0x5B <= iCharCode) && (iCharCode <= 0x60)));     // [\]^′
                // 文字コードをバイト配列に設定
                aryBytePassword[i] = (byte)iCharCode;
            }
            //---------------------------------------------------------------------------------
            // バイト配列をASCII文字列に置換
            //---------------------------------------------------------------------------------
            return Encoding.GetEncoding("ASCII").GetString(aryBytePassword);
        }
    }
    /// <summary>
    ///「英文字・数字」パスワード取得
    /// ※形の似た文字は除く(0とO、1とlとI、iとj)は外す
    /// </summary>
    /// <param name="iLength">パスワード長</param>
    /// <returns>パスワード文字列</returns>
    public static string fnGetNumberAlphabetWithoutResembleShape(int iLength)
    {
        return fnGetSpecialCondition(
                iLength,                    // パスワード長
                ((int)('z' - '0')) + 1,     // 文字コード範囲
                '0',                        // 文字コードの先頭文字
                delegate(int iCharCode)     // パスワードに含める文字コード判定(匿名)メソッド
                {
                    // '0''O'の場合
                    if (iCharCode == '0' || iCharCode == 'O')
                        return false;
                    // '1''l''I'の場合
                    if (iCharCode == '1' || iCharCode == 'l' || iCharCode == 'I')
                        return false;
                    // 'i''j'の場合
                    if (iCharCode == 'i' || iCharCode == 'j')
                        return false;
                    // '0'~'9'の場合
                    if (('0' <= iCharCode && iCharCode <= '9'))
                        return true;
                    // 'A'~'Z'の場合
                    if (('A' <= iCharCode && iCharCode <= 'Z'))
                        return true;
                    // 'a'~'z'の場合
                    if (('a' <= iCharCode && iCharCode <= 'z'))
                        return true;
                    // その他の場合
                    return false;
                });
    }
    /// <summary>
    ///「英数記号文字」パスワード取得
    /// </summary>
    /// <param name="iLength">パスワード長</param>
    /// <returns>パスワード文字列</returns>
    public static string fnGetNumberAlphabetSymbol(int iLength)
    {
        return fnGetSpecialCondition(
                iLength,                    // パスワード長
                ((int)('z' - '!')) + 1,     // 文字コード範囲
                '!',                        // 文字コードの先頭文字
                delegate(int iCharCode)     // パスワードに含める文字コード判定(匿名)メソッド
                {
                    switch ((char)iCharCode)
                    {
                        case '"':
                        case '&':
                        case '\'':
                        case '(':
                        case ')':
                        case ',':
                        case '.':
                        case ':':
                        case ';':
                        case '<':
                        case '>':
                        case '\\':
                        case '[':
                        case ']':
                        case '^':
                        case '`':
                        case '{':
                        case '|':
                        case '}':
                        case '~':
                            return false;
                        default:
                            return true;
                    }
                });
    }
    /// <summary>
    ///「英数記号文字」パスワード取得
    /// ※形の似た文字は除く
    /// </summary>
    /// <param name="iLength">パスワード長</param>
    /// <returns>パスワード文字列</returns>
    public static string fnGetNumberAlphabetSymbolWithoutResembleShape(int iLength)
    {
        return fnGetSpecialCondition(
                iLength,                    // パスワード長
                ((int)('z' - '!')) + 1,     // 文字コード範囲
                '!',                        // 文字コードの先頭文字
                delegate(int iCharCode)     // 文字コード判定メソッド
                {
                    switch ((char)iCharCode)
                    {
                        case '"':
                        case '&':
                        case '\'':
                        case '(':
                        case ')':
                        case ',':
                        case '.':
                        case ':':
                        case ';':
                        case '>':
                        case '<':
                        case '\\':
                        case '[':
                        case ']':
                        case '^':
                        case '`':
                        case '{':
                        case '|':
                        case '}':
                        case '~':
                        case '0':
                        case 'O':
                        case '1':
                        case 'l':
                        case 'I':
                        case 'i':
                        case 'j':
                            return false;
                        default:
                            return true;
                    }
                });
    }        
    /// <summary>
    /// 「特殊条件指定」パスワードの取得
    /// </summary>
    /// <param name="iLength">パスワード長</param>
    /// <param name="iCharCodeRange">文字コード範囲</param>
    /// <param name="cStartCharCode">文字コードの先頭文字</param>
    /// <param name="check">指定文字コードがパスワード対象となるか判定で利ゲート</param>
    /// <returns>パスワード文字列</returns>
    private static string fnGetSpecialCondition(
        int iLength, int iCharCodeRange, char cStartCharCode, fnCheckIncludCharCode check)
    {
        lock (typeof(PasswordGenerator))
        {
            byte[] aryBytePassword = new byte[iLength]; // パスワード文字コード配列
            int iCharCode;                              // 文字コード
            //---------------------------------------------------------------------------------
            // パスワード文字コード配列の作成
            //---------------------------------------------------------------------------------
            for (int i = 0; i < aryBytePassword.Length; i++)
            {
                // 特殊条件に一致した文字コードだけ生成
                do
                {
                    iCharCode = m_Rnd.Next(iCharCodeRange);
                    iCharCode += (int)cStartCharCode;
                } while (!check(iCharCode));
                // 文字コードをバイト配列に設定
                aryBytePassword[i] = (byte)iCharCode;
            }
            //---------------------------------------------------------------------------------
            // バイト配列をASCII文字列に置換
            //---------------------------------------------------------------------------------
            return Encoding.GetEncoding("ASCII").GetString(aryBytePassword);
        }
    }
}



using System;
using System.IO;
using System.Collections.Generic;
using System.Text;

class Program
{
    static void Main(string[] args)
    {
        string sPassword;   // パスワード
        // 
        Console.WriteLine("数値");
        sPassword = PasswordGenerator.fnGetNumber(7);
        Console.WriteLine(sPassword);
        // 
        Console.WriteLine("英大文字");
        sPassword = PasswordGenerator.fnGetAlphabetUpper(7);
        Console.WriteLine(sPassword);
        // 
        Console.WriteLine("英小文字");
        sPassword = PasswordGenerator.fnGetAlphabetLower(7);
        Console.WriteLine(sPassword);
        // 
        Console.WriteLine("英数字");
        sPassword = PasswordGenerator.fnGetNumberAlphabet(7);
        Console.WriteLine(sPassword);
        //
        Console.WriteLine("英数字(形の似た文字は除)");
        sPassword = PasswordGenerator.fnGetNumberAlphabetWithoutResembleShape(7);
        Console.WriteLine(sPassword);
        // 
        Console.WriteLine("英数記号");
        sPassword = PasswordGenerator.fnGetNumberAlphabetSymbol(7);
        Console.WriteLine(sPassword);
        //
        Console.WriteLine("英数記号※形の似た文字は除く");
        sPassword = PasswordGenerator.fnGetNumberAlphabetSymbolWithoutResembleShape(7);
        Console.WriteLine(sPassword);
    }
}


--出力結果--
数値
8494099
英大文字
VLDJJDK
英小文字
aiwkhhc
英数字
po1KfMl
英数字(形の似た文字は除)
oE3Latm
英数記号
HF1+cbf
英数記号※形の似た文字は除く
-3g3Lh!


■関連ページ


« 2009年3月 | トップページ | 2009年6月 »

Google AdSense


  • ---

Amazon ウィジェット

  • ウィジェット

@niyo_naのツイート

無料ブログはココログ

Google Analytics