2012年10月19日金曜日

[Apache][Tomcat][Java]環境作成

[共通] 当 Blog の投稿に関する基本事項について
→ http://fuunyan.blogspot.jp/2012/09/blog.html


以前いくつか類似投稿をしているが自分自身わかりづらかったので一つにまとめてみる。

環境を整えるのに参考にしたサイトリンク
@IT総合トップ > Java Agile > やり直し「JSPとTomcat」(1)
●Tomcat-1.インストール(Windows環境)


01)javaのダウンロード
http://www.oracle.com/technetwork/java/javase/downloads/index.html
上記アドレスから最新の JDK をダウンロードする。
ダウンロードするバージョンを選択すると、選択したバージョンが提供されているプラットフォームの選択リストが表示される。
そこでまずライセンスへの同意意思を示すために「Accept License Agreement」を選択後、ダウンロードしたいプラットフォームのリンクを選択する。
これをしないと警告メッセージが表示されるだけでダウンロードできません(よく引っ掛かるトラップ)


02)インストール
インストール先をデフォルトの program files 配下から C:\Java\~ に変更しただけ。
windows7 などではセキュリティ系の問題とかでめんどくさいことが発生する場合もあるので私はここに変更しています(フルパスにスペースが入るのも回避したいですし)

あとはウィザード通りです。


03)システム変数追加
以下の二つを追加
  JAVA_HOME=C:\Java\jdk1.7.0_07
  PATH=%PATH%;%JAVA_HOME%\Bin


04)Apache Tomcat のダウンロード
http://tomcat.apache.org/download-70.cgi
上記アドレスから最新版を取得する。
「32-bit/64-bit Windows Service Installer」というやつね。


05)インストール
基本ウィザード通りに進行。
変更がある手順は3か所。

1か所目:Configuration
以下の項目を追加

  User Name  admin
  Password  root

2か所目:インストール先
例によって program files 直下回避です。
あとスペースがやたら入っているので、めんどくさいですが全てなくしています。
(確かにスペースあるほうが見やすいとは思います)

  C:\ApacheSoftwareFoundation\Tomcat7.0

3か所目:完了画面
チェックを両方とも外す。
普段常用するならつけていてもいいですが、そうだとしても設定が完了するまでは起動されても困るので外した方がいいかと。


05)システム変数追加
以下を追加
  CATALINA_HOME=C:\Apache Software Foundation\Tomcat 7.0


06)Tomcat起動
スタートメニューから Configure Tomcat を起動
サービスをスタートする
動作確認のため http://localhost:8080/ にアクセス


 これで正しくインストールできたらしく問題なく動作しておりまする。


余談:
テスト中などに発生する問題。
こんなメッセージが表示された場合(主に Win7 とか Vista など UAC が原因らしく)

unable to open the service 'tomcat7'

Tomcat インストール先直下内 Bin 配下にある Tomcat7w.exe のプロパティで互換性タブを選択。
特権レベルグループ内の「管理者としてこのプログラムを実行する」を選択状態にする。

2012年10月15日月曜日

[C#] 非同期処理

[共通] 当 Blog の投稿に関する基本事項について
→ http://fuunyan.blogspot.jp/2012/09/blog.html


ファイルの比較処理をテストで作ったのだが、処理が長くなると UI が固まるため、対策として非同期処理を導入することにしました。
今回は web 上で公開されているサンプルなども充実していたので苦労しませんでした。
っと言いたいのですが VisualStudio (っと言うか .NET のバージョンですかね)の違いなどにより使える機能が限定されているため最新の解説ページの情報が役に立たず。
何だかんだと調べてみた結果 VS2008 + C# の組み合わせでは最適と思われる方法で作ってみました。
環境制限などで必要に迫られているようでしたら参考にどうぞ。

今回のテストフォーム上は少しコントロール多めです。
TextBox x 2
Label x 2
Button x 1
ListBox x 1
TextBox に比較対象となるファイルのフルパスを入力しておきます(実行時に入力してもいいですがめんどくさい)
そしてボタンを押すと処理開始となります。
処理結果は ListBox に出力、途中経過は Label に出力します。

とりあえず using 宣言。
using System.IO;            // ファイル操作で使用
using System.Threading;     // スレッド系で使用

次にデリゲートの宣言。
スレッド対象のメソッド(って言う言い方が正しいのか?)を宣言します。
ちなみに宣言位置はクラス内です。
// 非同期処理に利用するデリゲートの定義宣言
private delegate int checkDlgt(string file1, string file2);

// 非同期側スレッド内からフォーム上のコントロールを操作するために利用するデリゲートの定義宣言
private delegate void addStrLog3dlgt(int tgt, string str);

そして非同期側からフォームコントロールを操作するためのメソッド
フォームコントロールは別スレッドからは操作できないため、デリゲート経由で操作することになります。
今回は途中経過を表示したいので、作成しました。
// 非同期側(子プロセス)から listBox3 に追記するためのメソッド
private void addStrLog3(int tgt, string str)
{
    switch (tgt)
    {
        case 1:
            label1.Text = str;      // 処理位置
            break;
        case 2:
            label2.Text = str;      // ファイルサイズ
            break;
        case 3:
        default:
            listBox3.Items.Add(str);
            break;
    }
}

やっとサブスレッドの本体です。
この中でファイルの比較を行います。
// 非同期処理の本体
private int binaryChecking(string file1, string file2)
{
    // もろもろメッセージ出力のための処理
    if (!this.InvokeRequired)
        return 0;

    addStrLog3dlgt asl3 = new addStrLog3dlgt(addStrLog3);

    if (File.Exists(file1) && File.Exists(file2))
    {
        // 指定された2ファイルをバイナリ形式で開く
        byte[] f1 = File.ReadAllBytes(file1);
        byte[] f2 = File.ReadAllBytes(file2);
        // 進捗率表示用
        int iProgress = f1.Count() / 10;

        // 比較元のファイルサイズを表示
        this.Invoke(asl3, 2, f1.Count().ToString());
        this.Invoke(asl3, 3, "start   :" + DateTime.Now.ToLongDateString() + " " + DateTime.Now.ToLongTimeString());
        for (int i = 0; f1.Count() > i; i++)
        {
            if (!(f1[i] == f2[i]))
                break;

            // 進捗状況表示
            if (i % iProgress == 0)
                this.Invoke(asl3, 3, i.ToString("D8") + ":" + DateTime.Now.ToLongDateString() + " " + DateTime.Now.ToLongTimeString());

            // 処理状況表示(非常に処理速度に影響を与えるので下記値を参考に変更)
            //   1=トイレ休憩可能、10=遅い、1000=まぁ待てる、10000=実用範囲
            if( i % 1000 == 0)
                this.Invoke(asl3, 1, i.ToString());
        }
    }
    else
    {
        return 0;
    }

    return 1;
}

そしてコールバックメソッドです。
呼び出したのはいいですが、非同期なのでスレッドいつ終わるかわかりません。
メインスレッドでサブスレッドの終了監視を行うことも可能ですが、それでは結局 UI が固まり本末転倒。
そんなわけで、終わったら自分から申告してもらう必要があります。
そのために利用します。
// コールバックメソッド
private void CallBackMethod(IAsyncResult iAR)
{
    addStrLog3dlgt asl3 = new addStrLog3dlgt(addStrLog3);
    checkDlgt cDlgt = (checkDlgt)iAR.AsyncState;

    string strWork;
    int ret = cDlgt.EndInvoke(iAR);

    if (ret == 1)
        strWork = "finish  :";
    else
        strWork = "abort   :";
    
    this.Invoke(asl3, 3, strWork + DateTime.Now.ToLongDateString() + " " + DateTime.Now.ToLongTimeString());
}

最後にイベント起動部分。
ボタン押下イベントです。
// バイナリファイルの比較
private void button4_Click(object sender, EventArgs e)
{
    // 非同期で動作させるメソッドを指定
    checkDlgt cDlgt = new checkDlgt(binaryChecking);

    // 非同期処理の起動(先方で利用する引数値もここで指定)
    IAsyncResult iAR = cDlgt.BeginInvoke(textBox1.Text, textBox2.Text, new AsyncCallback(CallBackMethod), cDlgt);
}

本当は別途テストプログラムを作成するつもりだったのですが、なんとなく勢いで考えていた処理をそのまま作ってしまいました。
サブスレッドの処理状況表示 if 文の数値を小さくすると格段に処理が遅くなるため、メインスレッド(画面側)の UI が死んでいる様、もしくは死なない様の比較がしやすいかと思います。

余談ですが VS2012 など投稿時点での最新バージョンでは atwait などの処理を利用することで、もっと簡単に高機能な処理を実現できるようです。
バージョン制約が無い方は、その辺も調べられてみてはどうでしょうか。

今回はこれまで。

2012年10月10日水曜日

[C#] App.config の利用方法

[共通] 当 Blog の投稿に関する基本事項について
→ http://fuunyan.blogspot.jp/2012/09/blog.html


C#で開発を行っていてアプリの固有情報を保存するにあたり、何の制約もないのに ini ファイルを使うことも無かろう・・・って事で C# スタンダードらしい「アプリケーション構成ファイル( App.config )」を利用することにした。
しかし探し方が下手なのか、もっとも単純な使用例(書いて読む)が見当たらなかったので、自分で書いておく。

コードを書く前に
事前準備として system.configuration.dll への参照を追加する必要がある。
ソリューション エクスプローラで右クリック →「参照の追加(R)...」で表示される「参照の追加」ウィンドウが開く。
.NET タブの中から「System.Configuration」を選択して「 OK 」を押下。

お試し環境は、いつもの Button x 2 と ListBox があるフォーム画面です。

// 下記宣言を追加
using System.Configuration;

// app.config の appSettings に情報を設定
private void button1_Click(object sender, EventArgs e)
{
    // System.Configuration.ConfigurationManager を利用するにあたり
    // System.Configuration.dll への参照を追加する必要がある
    // (ソリューション エクスプローラで右クリック → 参照の追加)

    // Configuration オブジェクトを開く(対象ユーザーは「全てのユーザー」を指定)
    Configuration conf = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);

    // 登録情報の作成
    // キー名:KeyName の後ろに通番を付与した書式
    // データ:日付と時間を登録する
    string keyStr = "KeyName" + ConfigurationManager.AppSettings.Count.ToString();
    string valueStr = DateTime.Now.ToLongDateString() + " " + DateTime.Now.ToLongTimeString();

    // 情報の登録 → 保存 → 情報更新(次回アクセス時)
    conf.AppSettings.Settings.Add(keyStr, valueStr);
    conf.Save(ConfigurationSaveMode.Modified);
    ConfigurationManager.RefreshSection("appSettings");
}

// app.config の appSettings から情報を取得
private void button2_Click(object sender, EventArgs e)
{
    listBox1.Items.Add("--- start reading ----------");

    // App.Config からの読み込み
    // AllKeys は全てのキー名を取得してくれる
    foreach (string keyStr in ConfigurationManager.AppSettings.AllKeys)
        // ピンポイントで取得するだけなら下記1行だけで ok (取得先のキー名がわかっている時など)
        listBox1.Items.Add(ConfigurationManager.AppSettings[keyStr]);

    listBox1.Items.Add("--- end reading ----------");
    listBox1.SelectedIndex = listBox1.Items.Count - 1;
}

Button1 を押すことでデータを登録します。
Button2 を押すことで appSettings よりデータを取得します。
取得したデータは ListBox に追加されます。

データが膨大になった場合のセクション分けもできるらしいのですが、時間なので今回はこれまで。

2012年9月18日火曜日

[C++/CLI] イベント関数の引数についてくるobjectを各コンポーネントにしてみる

[共通] 当 Blog の投稿に関する基本事項について
→ http://fuunyan.blogspot.jp/2012/09/blog.html


たとえば DateTimePicker を使用して期間を指定できるデザインの画面の場合・・・
2種類あったら合計4イベント書くことになるけど、これを使えば1つのイベントを使いまわせる。

System::Void DateValueChanged(System::Object^  sender, System::EventArgs^  e)
{
    System::Windows::Forms::DateTimePicker^  dtWork;
    System::Windows::Forms::DateTimePicker^  dtFrom;
    System::Windows::Forms::DateTimePicker^  dtTo;

    dtWork = safe_cast(sender);

    // 呼び出し元のコンポーネントを判断し、処理対象となるコンポーネントを選定する
    if((dtWork->Name == Date1From->Name) || (dtWork->Name == Date1To->Name))
    {
        dtFrom = Date1From;
        dtTo = Date1To;
    }

    if((dtWork->Name == Date2From->Name) || (dtWork->Name == Date2To->Name))
    {
        dtFrom = Date2From;
        dtTo = Date2To;
    }

    // ・From, To 共に有効な場合 From < To となるように入力後にデータ確認を行う。
    // ・どちらか片方のみ有効の場合は入力制約を設けない。
    // ・片側入力から両側入力になった場合、後から有効になったコンポーネントの指定日付を
    //  先に有効であったコンポーネントの指定日付と合わせる。
    if((dtFrom->Checked && dtTo->Checked) && (dtFrom->Value > dtTo->Value))
        if(dtWork->Name == dtFrom->Name)
            dtFrom->Value = dtTo->Value;
        else
            dtTo->Value = dtFrom->Value;
}

[C++/CLI] 別のプロセスにメッセージを送信する


[共通] 当 Blog の投稿に関する基本事項について
→ http://fuunyan.blogspot.jp/2012/09/blog.html


例によって経過などはリストボックスに追加する方向で

・投げるほう
FindWindow で対象画面を見つけて SendMessage でメッセージを送信。
// stdafx.h に追加したやつら
#include <windows.h>
#pragma comment(lib, "user32.lib")

// 対象ウィンドウの検索
HWND  hWND;
hWND = FindWindow(nullptr, L"送信先画面名");
if(hWND == nullptr)
{
    LBox->Items->Add("not find...");
    return;
}
else
    LBox->Items->Add("find...");

// メッセージ送信
COPYDATASTRUCT cds;

cds.dwData = 0;
cds.cbData = sizeof("送信文字列 ") + 1;
cds.lpData = L"送信文字列";
::SendMessage(hWND, WM_COPYDATA, 0, (LPARAM)&cds);

・受けるほう
WndProc をオーバーライドして独自処理を作成。
その中で送信メッセージを処理する。
// stdafx.h に追加したやつら
#include <windows.h>

// protectedに追加(デストラクタの後ろとか?)
protected:
virtual void WndProc(Message% m) override
{
    switch(m.Msg)
    {
        case WM_COPYDATA:
            // 処理記述
            COPYDATASTRUCT *cds = (COPYDATASTRUCT*)m.LParam.ToInt32();
            String^ str = gcnew String( (wchar_t*)cds->lpData);
            listBox1->Items->Insert(0, str);
            break;
    }
    Form::WndProc(m);
}

[共通] 当 Blog の投稿に関する基本事項について

当 Blog 内に投稿されているすべての記事に適用する基本事項を記載します。

この投稿の内容は当 Blog 内のすべての投稿に適用されます。

特に断りがない限り、投稿主である「AL(ある)」は本投稿の条件を適用した状態で記事を投稿しているとお考えください。
この投稿の内容は状況変化に応じ随時変更いたします。
変更後の内容は(変更以前に投稿したものを含め)すべての投稿に適用いたします。

1)記載内容の真偽について
この Blog は技術系情報の個人的メモ書きサイトとして立ち上げました。
この性質上、投稿内に記載されているコード類は動作確認をしたうえで記載しているはずですが、まれに最終的なコードが反映されていない(=間違っている)可能性があります。
このため記載コードについては参照程度に留め、最終的な動作確認等は閲覧者個人でお願いいたします。

2)事故について
閲覧者が投稿内容を参照し、自身のプログラム等に反映後、結果としてリカバリ不能な事態が発生したとしても投稿主は責任を持ちません。
閲覧した投稿の内容を反映される場合は、閲覧者個人の責任で行ってください。

3)意見・要望について
投稿内容に関する質問や指摘、要望は受け付けております。
もしこれらの連絡を取りたい場合はコメント欄に記載していただくか、投稿主宛にメールを送ってください。
ただし頂いた質問や要望についての回答義務は負わないものとします。
(公開する以上、読みやすい、意味のあるものにしたいため前向きに対応はいたします)

2012年8月25日土曜日

[C++/CLI] いろいろメモ


[共通] 当 Blog の投稿に関する基本事項について
→ http://fuunyan.blogspot.jp/2012/09/blog.html


え~新作業場にてVC++で画面作成をすることになり四苦八苦しならが作成しているときに使った、非常に個人的なメモ投稿となっております。
まぁそれでも似たような事を知りたい人がいるかもしれないと公開しました。
この辺の事情を察して、ご覧ください。
当分の間、随時更新されていくはずです。
後付けし続けると大変長い投稿になるので項目ごとに投稿するように修正予定。
そんなわけで追加分は下書きとして保存中・・・。

●関連・面白そうサイトメモ
http://www.plustarnet.com/aspil/Programming/

http://www.atmarkit.co.jp/fdotnet/special/cppcli/cppcli_03.html

・前田稔(Maeda Minoru)の超初心者のプログラム入門
http://www.eonet.ne.jp/~maeda/index.html

方法 : System::String を wchar_t* または char* に変換する
http://msdn.microsoft.com/ja-jp/library/d1ae6tz5(v=vs.80)


公式に面白そうな企画があったっぽい
Visual Studio 2008 でゲームを作ろう 第 1 回プロジェクトファイル
http://www.microsoft.com/ja-jp/download/details.aspx?id=14288


・C++/CLI: とある文字列の相互変換(コンバージョン)
http://codezine.jp/article/detail/4774

・Programing Enlightened 文字列操作
http://vene.wankuma.com/prog/CppCli_strings.aspx


・方法 : さまざまな文字列型間で変換する
http://msdn.microsoft.com/ja-jp/library/ms235631(v=vs.80).aspx

●さすがに個別記事化するほどでもない技術情報

マネージ?アンマネージ?
#pragma unmanaged
#pragma managed


コマンドライン引数の値を取得
// 以下の順で指定されているのを想定
// [1] iniファイルへのフルパス
// [2] 
// [3] 
array<String^>^ args = System::Environment::GetCommandLineArgs();

if(args->Length > 1)
    iniPath = args[1];