2013年6月26日水曜日

Delphiでの64bitアプリのデバッグ方法

大阪本社所属 Mです。

64bitの環境が普及し64bitアプリ開発の機会も増えてきた今日この頃
Delphiで64bitアプリのデバッグを行うためにはちょっとした準備が必要なので
その手順を投稿します。

Delphi自体は32bitアプリなので64bitアプリのデバッグは64bitリモートサーバと
通信して行うようです。DelphiのバージョンはXE3です。

①PAServer(プラットフォームアシスタントサーバー)のインストール

・ インストーラは setup_paserver.exe で、Delphiインストールディレクトリの
   PAServer フォルダ内にある。デフォルトでは以下の場所。

   C:\Program Files\Embarcadero\RAD Studio\バージョン番号\PAServer\setup_paserver.exe

・ setup_paserver.exe を実行してPAServerをインストール。
   UACがらみでC:\Program Files 以下ではないディレクトリにインストールすること!


②リモート プロファイルの準備

・ Delphiを起動し ツール→オプション→環境オプション→リモート プロファイルを選択
   [追加] ボタンを押してプロファイルを追加。




















・ テストプロファイル名(任意)を入力し、プラットフォームは 64ビット Windows を選択。


















・ 次の画面で接続先のホスト名またはIPアドレスを指定する
   ローカルでリモートデバッグを行う場合はループバック IP 127.0.0.1
   もしくはlocalhostと入力する。

   ポート番号はデフォルトの64211、パスワードは空白でOK。


・ 次の画面のC++情報は入力不要。


③ローカルルートディレクトリの指定

   「リモートデバッグ用のファイルが格納される場所」らしいが
   デバッグ時にも何も出力されないので何のための設定かよくわからない。
   ただ、設定しないとデバッグできないので設定する。
   ドロップダウンから選択できる。




















④リモートプロファイルの割り当て

・ プラットフォーム"64 ビット Windows "を右クリックして
   "リモート プロファイルの割り当て" を選択。




















・ 作成した 64bit Windows 用リモートプロファイルを選択。






















⑤デバッグの実行

・ PAServerの起動
  PAServerインストールディレクトリのpaserver.exe をダブルクリック、
  またはcmd.exeでPAServerインストールディレクトリに移動し「paserver」と入力してEnter。
  パスワードの入力が求められるので、そのままEnter。

















  これでアプリケーションを Debugでビルドした後、通常の32bitデバッグ時と同じように
  64bitアプリをデバッグできる。

  PAServerインストールディレクトリの"\scratch-dir" 以下に
  アプリケーションが出力され実行される。

  dllなどアプリ起動に必要なファイルがある場合は手動で実行ディレクトリに
  コピーが必要なので注意。




以上で手順の説明は終了です。

2013年2月25日月曜日

Windows7へのOracle10gインストール

Windows7へOracle10gインストールする場合、
「Oracle Database 10g Release 2 Client (10.2.0.3)」を使えばすんなりインストールできる。

・・・はずだったんですが、まったくインストールできず。

あらゆる常駐ソフトを終了させ、邪魔をしてそうなアプリをアンインストールしても
まったくできず。

最初のsetup.exeをたたいたあと、DOS窓が出たところで終わってしまう。。

まったく原因不明であきらめかけたところ、
ログファイルをよくよく見ると、dllの名前が書いてる。

ググって見るとディスプレイドライバ??
関係あるのか?と思いつつ、ドライバを最新にするも、やはり結果は一緒。

しかし、ここでふと気がつく。
まさか・・・USB接続のディスプレイアダプタのせい!?(←2面使うため)

USBを抜いてみると、、あっさりインストールできましたorz


Oracleをインストールするのに、こんなものが邪魔をするとは。。

2013年1月8日火曜日

SPOOLの罠【ORACLE】

こんにちは、大阪本社勤務のIです。

前回と同様ORACLEに関することなのですが、
今回はOracle8iとOracle10gの差による、
ちょっとした躓きがありましたので投稿します。

前回お話したとおり、現在、僕が携わっているシステムは、
メインのシステムのデータベースがOracle10g、
サブのシステムのデータベースがOracle8iです。

データの更新はサーバ上でコマンドプロンプトから
SQL Plusを起動して行うのですが、
その際に「SPOOL」コマンドを使用して、
処理内容をファイルに出力し、ログとして残す決まりになっています。

また、メインのシステムはデータ更新の機会が比較的多いのですが、
サブのシステムはデータ更新の機会はほとんどありません。

そんな中、先日サブのデータ更新を行うことになり、
いつもメインで入力しているとおり、
SPOOL "○○○○.LOG" ←と入力しENTERキーを入力すると、
「SP2-0332: スプール・ファイルを作成できません。」と表示されます。

ディレクトリに書き込み権限がないのか?
…などと、いろいろ試みてみましたが、状況は変わりません。

困って上司に尋ねたところ、Oracle8iではファイル名をダブルクォートで囲うと、
このエラーが発生するとのことでした。

その後
SPOOL ○○○○.LOG ←と入力しENTERキーを入力すると、
何事も無かったかのように、ファイルが出力されました。

知っていればどうってことない話ですが、
普段当たり前のように使っていた「SPOOL」コマンドで、
まさかこんな罠があるとは…といった感じでした。

ではまた次回。

スナップショットの罠【ORACLE】

こんにちは、大阪本社勤務のIです。

開発ブログということで、簡単ではありますが、
自分が開発時につまづいた内容などを投稿していきたいと思います。

現在、僕が携わっているシステムは、
メイン(仮にシステムAとします)のシステムがOracle10g、
サブ(仮にシステムBとします)のシステムがOracle8iで、
それぞれにデータベースが存在します。

また、システムA、システムBにて共通のテーブルがいくつかありますが、
夜間処理にて、システムAとシステムBの内容の同期をする仕組みになっています。

最近システムAで、あるテーブルのデータを日中に変更する必要があり、
システムAのデータを変更後、システムBに反映しようとしました。

手順としては、

①システムBのテーブルのデータを全件 DELETE する。

②データベースリンクを使用し、システムAのテーブルから SELECT し、
  システムBのテーブルに INSERT する。

…と考えていましたが、①を実行すると
「ORA-01732: このビューに対するデータ操作が無効です。」のエラーが出て、
データが削除できませんでした。

テーブルなのにビュー?…と思い、調べてみた結果、
システムBには、テーブル名と同名のスナップショットが存在していました。

□■□■□■□■□■ 調査メモ ■□■□■□■□■□
スナップショットとは、Oracleデータベース間で、データのバックアップを取る機能である。
スナップショットを作成すると、スナップショットと同名のテーブルが作成される。
そのテーブルに対して直接操作するには、スナップショットを作成する時に、
FOR UPDATE句を指定しないといけない。
スナップショットを同期するには下記のメソッドを使用。
DBMS_SNAPSHOT.REFRESH('スナップショット名','リフレッシュ方法')
リフレッシュ方法の内容
'F' ⇒ 高速リフレッシュ
'C' ⇒ 完全リフレッシュ
'?' ⇒ 強制リフレッシュ
'A' ⇒ 常にリフレッシュ
□■□■□■□■□■□■□■□■□■□■□■□■□

どうやらスナップショットが更新可能でなかったため、
DELETE 時にエラーが発生していたようです。

その後、当初考えていた手順ではなく、
DBMS_SNAPSHOT.REFRESH を実行することでテーブルの同期を行いました。

今回、スナップショットについて理解が乏しかったため、
このような現象に躓きましたが、良い勉強になりました。

この先、このようなことがあれば、投稿していきたいと思います。

2013年1月7日月曜日

ちょっとしたことで

こんにちは。
大阪本社勤務のMです。

今回初めてブログに記事を投稿します。
どうぞよろしくお願いします。

さて、今回はメールに関するちょっとしたテクニックを紹介します。

皆さんも仕事やプライベートでメールを送信する機会は多いと思います。
そして、メールでは返信期限を設定することがよくあります。
しかしその返信期限をメールにしっかり明記しているにもかかわらず
期限が過ぎてもちっとも返事が来ない…なんて経験ありませんか?

そんな時に役立つテクニック、それは

返信期限は日付だけではなく、具体的な時間まで指定する。

例えば
「○月×日 18:00までに返信お願いします。」
のように書くことで、期限までに返信が来る割合が3割もアップするのです。

ちょっとした工夫で、返事が来ないイライラを感じずに済むなら
やってみる価値ありですね!

2012年12月4日火曜日

文字列の定数をグループ化する方法?

いくつかの変数をグループ化したい場合、
レコード型を使えば済む話なのだが、
定数をグループ化するとなるとちょっと困る。

【例】
TGroup = record
  ItemA : string;
  ItemB : string;
  ItemC : string;
end;

var
  Grp : TGroup

定数なんてグループ化できなくていいよって場合は
どうでもいい話なのだが、個人的には定数もレコード型
みたいにして、コード補完で選択できたら便利だと思う。

というわけ、こんな手を使う。

【例】
TGroup = record
  ItemA : string;
  ItemB : string;
  ItemC : string;
end;

const
  GRP : TGroup = (ItemA:'AAA';ItemB:'BBB';ItemC:'CCC');

procedure TForm1.Button1Click(Sender: TObject);
begin
  ShowMessage(GRP.ItemA);
end;

TGroupを使って「型付き定数」を宣言し、
初期値をセットしておけば、グループ化された定数ができる。


こんな事しても、対して使い道ないよ!というかもしれないが、
こういう使い道もある。

【例】
TExample = record
  ColumnA : string;
  ColumnB : string;
  ColumnC : string;
end;

const
  EXAMPLE : TExample = (ColumnA:'NAME_A';ColumnB:'NAME_B';ColumnC:'NAME_C');

procedure TForm1.Button1Click(Sender: TObject);
begin

  with ClientDataSet1 do
  begin
    try
      Active := true;
      First;

      //***   列名をグループ化した定数で指定する   ***
      Edit1.Text := FieldByName(EXAMPLE.ColumnA).AsString;
      Edit2.Text := FieldByName(EXAMPLE.ColumnB).AsString;
      Edit3.Text := FieldByName(EXAMPLE.ColumnC).AsString;

    finally
      Active := false;
    end;
  end; 
end;

2012年11月5日月曜日

Delphiには値が変更できる定数があったりする話

「定数」とはその名の通り「あらかじめ定められた一定の数」
のはずなのだが、Delphiでは「定数」と呼ばれてるくせに
値を変更できるようにする方法が存在したりする。


まず普通の定数。

const
  TEST = 'てすと';

次に型付き定数。

const
  IDX : integer = 100;
  ARY : array[0..4] of string = ('A','B','C','D');

この2種類の定数のうち型指定のない「普通の定数」は
何をどうやろうと値の変わらない、正真正銘の定数なのだが、
「型付き定数」はコンパイルオプションを変更することで
「Static変数」に変身させることができてしまう。

【例】
procedure TForm1.Button1Click(Sender: TObject);
const
  IDX : integer = 1;
begin
  IDX := 2; ←通常はNG
  Inc(IDX); ←通常はNG
end;

ここでプロジェクトのオプションから
[Delphiコンパイラ]-[コンパイル]-[割り当て可能な型付き定数]
を選択しTrueにすると、上記の代入ができるようになる。

【例】
procedure TForm1.Button1Click(Sender: TObject);
const
  IDX : integer = 1;
begin
  IDX := 2; ←代入できる
  Inc(IDX); ←Static変数と同じなのでボタンクリックの度に値が加算される
end;

定数のくせに値が変更できていいのか?という思いはあるが
DelphiでどうしてもStatic変数が使いたいときはありかもしれない。