Delphi Programming / Object Pascal
[掲載 2017年04月06日] [更新 2018年08月28日] Delphi 一般・その他
Indy コンポーネントのインストール
動作確認等
主に Windows 7 U64(SP1 + Delphi 6(UP2) Pro + Indy 10.6.2
Indy コンポーネントのインストール - Delphi 6 の例
Delphi 6 に Indy 10.6.2 をインストールする手順です。
Delphi 6 の Indy のバージョンはデフォルトで 8 です。Delphi 7 では 9 です。本ページの方法でインストールすれば、2017年04月06日現在の最新のバージョンの Indy を利用できるようになります。
インストールは以下の 2 つの方法があります。
Indy が提供しているインストール用のバッチファイルを使用する
パッケージファイルを開いて手動でコンパイルする
本ページではパッケージファイルを開いてコンパイルする方法を最初に説明しています。
[備考]
他のバージョンの Delphi へのインストールも、本ページで説明している方法とほとんど同じです。上の DEKO さんのサイトの記事を参考にしてください。
今回インストールした Indy 10.6.2 は Delphi 6 Personal 版にもインストールできます。今回のインストールのテストでは、同一 PC 上の Delphi 6(UP2) Pro, Delphi 2007-R2 Pro, Delphi XE(UP1) Pro および Delphi XE5(UP2) Pro で確認しています。
01_ インストール済み Indy コンポーネントと関係ファイルの削除
まず、既にインストールされている Indy のパッケージの削除と関係ファイルを削除します。この作業はバッチファイルを使用してインストールする場合も必要です。
元のバージョンに戻すためのファイルのバックアップ方法については、上の参考リンクの記事で確認してください。以下の説明は、旧バージョンの Indy を削除することを前提にした手順です。
[コンポーネント] [パッケージのインストール] のダイアログで、以下の Indy のパッケージを削除します。もし、他にも Indy の名前のあるパッケージがあれば、それも削除します。
Internet Direct (Indy) for D6 Propert and Component Editor
図1
パッケージの削除
Indy 10 をインストールしていると複数ある
関係ファイルの削除も必要
パッケージを削除しただけでは関係ファイルは削除されません。Delphi のインストール先のフォルダ内に下表に示すファイルがあればそれらを削除します。
Delphi はコンパイル時に下表に示すフォルダ内を検索します。したがって、旧いバージョンのファイルが存在すると、それらのファイルが原因で「未定義のエラー」や「異なるバージョンによりコンパイルされています」あるいは「... が見つかりません」等のエラーが発生し、コンパイルやインストールに失敗することがあります。
対象フォルダ
フォルダ内の削除すべきファイル
備考
bin
dclIndy*.*
Indy*.*
Indy の文字があるファイル全て
lib
dclIndy*.*
Id*.*
Indy*.*
Indy の文字があるファイル全て
先頭が Id のファイル全て
lib 階層下のフォルダにあればそれも削除
lib\Indy10
*.*
フォルダごと削除
source\Indy
source\Indy10
*.*
フォルダごと削除
Projects\Bpl
dclIndy*.*
Indy*.*
Indy の文字があるファイル全て
[備考]
先頭が Id のファイルがあるのは lib フォルダ、または lib フォルダの階層下のフォルダです。
Delphi のバージョンによっては、似たような名前があります。例えば InDAY... (d と y の間に a がある) というのがあります。これは削除しないでください。
Indy コンポーネントは以下のリポジトリから SVN を利用して入手できます。ブラウザで閲覧する時はユーザアカウントを Indy-Public-RO にして、パスワードは空白とします。
今回は、Indy 10.6.2 - Berlin RTM をダウンロードしてインストールしました。
図2
Indy のダウンロード
今回は Indy 10.6.2 - Berlin RTM をダウンロードした
[備考]
SVN (Subversion) の機能は最近の Delphi には実装されています。
例えば Delphi 10.1 Berlin Starter では [ファイル] [バージョン管理リポジトリから開く...] で、[Sebversion] を選択すると利用できます。
上の図は TortoiseSVN というソフトですが、少し古いバージョンです。
ダウンロードしたフォルダの階層下の Lib フォルダ内の、以下の 3 つのフォルダにライブラリのパスを通しておきます。設定は [ツール] [環境オプション] でダイアログを表示して、[ライブラリ] タブで行います。
後述のバッチファイルを使用するインストールの場合、ライブラリパスの設定は必要ありません。
D:\000_Delphi\Indy10_6_2\Lib\Core
D:\000_Delphi\Indy10_6_2\Lib\Protocols
D:\000_Delphi\Indy10_6_2\Lib\System
[備考]
ダウンロードした Indy を [Indy10_6_2] という名前のフォルダに置いていますが、これは説明のために付けています。バージョン番号の付いた名前ですと、バージョンアップした時に困ります。実際には別の名前にしてください。10.6.2 以降という意味であれば構わないでしょう。
図3
ライぶりパスの設定
Indy の Lib フォルダ階層下の以下のフォルダにパスを通す
Core
Protocols
System
Delphi の IDE を起動して、Lib フォルダ階層下の以下のパッケージファイルを開きます。
開くファイルの順番は関係ありませんが、コンパイルは下表のファイルの順番に実行する必要があります。これは、パッケージでコンパイルするファイルに依存関係があるからです。
Lib 内のフォルダ名
開くパッケージファイル名 (Delphi 6 の場合)
System
IndySystem60.dpk
Core
IndyCore60.dpk
Protocols
IndyProtocols60.dpk
Core
dclIndyCore60.dpk
Protocols
dclIndyProtocols60.dpk
パッケージファイル名をダブルクリックするか、ファイル名を選択して [アクティブ] ボタンをクリックしてダイアログを前面に表示します。そしてコンパイルします。上の表の順番に 5 つのパッケージを全てコンパイルします。
コンパイルしてもダイアログを閉じないでください。ダイアログを閉じてしまうと、パッケージファイルも閉じてしまいます。
図4
パッケージのコンパイル
ファイル名を選択して [アクティブ]
[コンパイル] したら Unit1 のウィンドウをクリック
[パッケージ] のダイアログは閉じない
太字になっている状態が操作対象のパッケージ名
[備考]
Delphi 2007, XE 等では 1 回の操作でまとめてコンパイルできます。
一番上のパッケージ名をダブルクリックして選択状態にした後、ポップアップメニュー [ここから下を] のサブメニューの [ここから下を全てコンパイル] をクリックします。
いくつかの Delphi のバージョン用に、拡張子が .groupproj のプロジェクトグループが用意されています。これを使用すると便利です。。
パッケージを全てコンパイルしたら、先頭が dcl の以下の 2 つのパッケージを、この順番でインストールします。
パッケージファイル名をダブルクリックするか、ファイル名を選択して [アクティブ] ボタンをクリックしてダイアログを前面に表示します。そしてインストールします。
dclIndyCore60.bpl
dclIndyProtocols60.bpl
図5
パッケージのインストール
以下の順番にインストール
dclIndyCore60.bpl dclIndyProtocols60.bpl
ファイル名を選択したら [アクティブ]
[インストール] して Unit1 のウィンドウをクリック
太字になっている状態のパッケージ名が操作対象
これでンストールは終了です。Delphi の IDE を閉じて再度起動します。
[コンポーネント] [パッケージのインストール] のダイアログを表示すると、2 つのパッケージがインストールされていることが確認できます。
コンパイル済みのユニットファイルは、Indy の Lib フォルダ階層下の、該当するパッケージがあるフォルダ内に保存されています。コンパイル済のパッケージファイルは、Delphi のインストール先の Bpl フォルダ内にあります。
図6
登録されたパッケージ
[備考]
以上の方法でインストールした場合、コンパイル済みのパッケージのファイルは Delphi 6 等は上の図のように%ProgramFiles% 階層下のフォルダに保存されます。Windows Vista 以降に対応したバージョンの Delphi では、%PUBLIC%\パブリックのドキュメント の階層下に保存されます。
具体的な場所は、上の図の [コンポーネント] [パッケージのインストール] のダイアログを表示して、パッケージ名を選択すれば確認できます。
06_ バッチファイル Fulld_6.bat を使用するインストール
Indy にはインストール用のバッチファイルが用意されています。そのバッチファイルを使用したインストール方法です。ただし、全ての Delphi のバージョンに用意されているわけではないようです。確認が必要です。
バッチファイルを実行する前に、インストール済みの Indy のパッケージを削除し、関係するファイルを削除しておきます。
コマンドプロンプトを管理者権限で起動したら、以下のコマンドを全て選択コピーして、コマンドプロンプトに貼り付けて実行します。
最初のコマンドはカレントディレクトリを Indy の Lib フォルダに移動します。次のコマンドが Indy に用意されているバッチファイル名です。Delphi 6 用は Fulld_6.bat です。
フォルダ名 (ディレトクリ名) 等は各自の環境に合わせて変更します。
copy code
cd C:\000 _Delphi\Indy10_6_2\Lib
Fulld_6.bat
図7
インストール実行
コマンドプロンプトを管理者権限で起動
上のコマンドを貼り付けて実行
図8
インストールしたファイルの場所
Indy のフォルダ内に D6 というフォルダが自動で作成される
その中に保存される
赤枠の 2 つをパッケージとして登録する
コンパイルされたユニットとパッケージファイルは、Indy のフォルダの階層下に D6 という名前のフォルダが自動で作成され、そこに保存されます。また、この D6 というフォルダにはライブラリのパスが自動で設定されます。
上記の操作でインストールしてもパッケージは登録されません。
[コンポーネント] [パッケージのインストール]
のダイアログで登録します。[追加] ボタンでファイルの選択ダイアログを表示したら、上の図の赤枠の、先頭の文字列が dcl の
2 つのパッケージファイルを選択します。下図のようにパッケージが登録されます。
[備考]
ソースコードにライブラリのパスが通ってなくてもコンポーネントは利用できますが、必要であれば上の方の記事を参考にして設定してください。
ソースコードを改変する必要がなければ、ライブラリのパスを設定するのではなく、[ブラウザ検索パス] を追加した方が無難です。[ブラウザ検索パス] は [ライブラリパス] の設定と同じダイアログを表示して設定できます。
ソースコードにライブラリのパスを設定すると、ソースコードがある場所にもコンパイル済みのファイルが保存されてしまいます。これはトラブル発生の原因となります。
図9
パッケージの登録
[追加] ボタンで登録する
この図は登録済みの状態
07_ Indy におけるコードページの設定とデコードとエンコード
コミュニティの場でも文字化けが話題になることがありますが、例えば TIdHTTP.Get メソッドではコードページの指定ができます。文字列の受信の際によく使用されている方法は、TMemoryStream 等で取得する方法です。TMemorsyStream には生のデータが格納さていますから、受信あるいは取得後にコードページを指定して文字列に変換できます。
基本的に画像等のバイナリデータは TStrema の派生クラスで送受信することになります。
コードページは以下のように、プログラム内でグローバルに設定しておくこともできます。
図10
Indy 10.6.2 で設定可能なコードページ
リスト1
Indy 10.6.2 でコードページをグローバルに設定する方法
copy code
implementation
uses
IdGlobal,
TypInfo;
{$R *.dfm}
// =============================================================================
// Indey 10.6.2 における文字コード(コードページ)の設定
//
// IdGlobalのメンバを使用するにはusesにIdGlobalを追加する
// =============================================================================
procedure TForm1.Button1Click(Sender: TObject);
begin
// 文字コード(コードページ)の自動変換のグローバル設定
// デフォルトはASCII
IdGlobal.GIdDefaultTextEncoding := encOSDefault; // 範囲外の文字は破棄される
IdGlobal.GIdDefaultTextEncoding := encASCII; // 範囲外の文字は破棄される
IdGlobal.GIdDefaultTextEncoding := encUTF8;
end ;
// =============================================================================
// 設定可能な文字コードの値のリスト
// IdTextEncodingType(列挙型)の値を列挙
//
// TyppeInfoの使用にはusesにTypInfoが必要
// =============================================================================
procedure TForm1.Button2Click(Sender: TObject);
var
LpInfo : PTypeInfo;
LpData : PTypeData;
i : Integer;
begin
Memo1.Clear;
LpInfo := TypeInfo(IdTextEncodingType);
// 列挙型であれば調査
if LpInfo^.Kind = tkEnumeration then begin
LpData := GetTypeData(LpInfo);
for i := LpData^.MinValue to LpData^.MaxValue do begin
Memo1.Lines.Add(GetEnumName(LpInfo, i));
end ;
end ;
end ;
デコード、エンコードの指定は Indy 10.5.7 では TEncoding が使用できましたが、Indy 10.6.2 では専用の定数名を使用する方式に変更になっています。
下のコードはその使用例です。
URLEncode 関数と ParamsEncode 関数は / , . ( %2F %2C %2E ) 等をエンコードしませせん。パラメータの区切り文字である & もエンコードしません。
[備考]
Delphi XE7 以降の System.NetEncoding ユニットには、エンコードとデコード関係のクラスがいくつか実装されています。それらのクラスメソッドを使用してデコードやエンコードができます。
図11
デコードの例
図12
エンコードの例
リスト2
Indy 10.6.2 におけるデコードとエンコードの指定方法
このコードの動作確認は Windows 7 U64(SP1) + Delphi 10.2.3 Tokyo Community + Indy 10.6.2
copy code
implementation
uses
IdURI,
IdGlobal;
{$R *.dfm}
// =============================================================================
// TIdURI.URLDecodeを使用したURL文字列のデコード
// usesにIdURI,IdGlobalが必要
// =============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
LSrcStr : string ;
LDstStr : string ;
begin
Memo1.Lines.Clear;
LSrcStr := '%E5%8D%B0%E5%88%B7%E3%80%80%E3%83%97%E3%83%AA%E3%83%B3%E3%82%BF' ;
LDstStr := TIdURI.URLDecode(LSrcStr, IndyTextEncoding_UTF8);
// 結果は'印刷 プリンタ'
Memo1.Lines.Add(LSrcStr);
Memo1.Lines.Add('' );
Memo1.Lines.Add(LDstStr);
end ;
// =============================================================================
// TIdURI.URLEncodeを使用したURL文字列のエンコード
// TIdURI.URLEncodeはプロトコルがある文字列をエンコードする
// プロトコルがないと変換に失敗する
// usesにIdURI,IdGlobalが必要
// =============================================================================
procedure TForm1.Button2Click(Sender: TObject);
var
LSrcStr : string ;
LDstStr : string ;
begin
Memo1.Lines.Clear;
LSrcStr := 'http://www.test.com/印刷 プリンタ' ;
LDstStr := TIdURI.URLEncode(LSrcStr, IndyTextEncoding_UTF8);
// 漢字部分の結果は'%E5%8D%B0%E5%88%B7%E3%80%80%E3%83%97%E3%83%AA%E3%83%B3%E3%82%BF'
Memo1.Lines.Add(LSrcStr);
Memo1.Lines.Add('' );
Memo1.Lines.Add(LDstStr);
end ;
// =============================================================================
// TIdURI.ParamsEncodeを使用した文字列のエンコード
// usesにIdURI,IdGlobalが必要
// =============================================================================
procedure TForm1.Button3Click(Sender: TObject);
var
LSrcStr : string ;
LDstStr : string ;
begin
Memo1.Lines.Clear;
LSrcStr := '印刷 プリンタ' ;
LDstStr := TIdURI.ParamsEncode(LSrcStr, IndyTextEncoding_UTF8);
// 結果は'%E5%8D%B0%E5%88%B7%E3%80%80%E3%83%97%E3%83%AA%E3%83%B3%E3%82%BF'
Memo1.Lines.Add(LSrcStr);
Memo1.Lines.Add('' );
Memo1.Lines.Add(LDstStr);
end ;
08_ Indy における User Agent ( ユーザエージェント ) の設定
ウェブページにアクセスする際、意味がある User Agent の設定情報がないとアクセスを拒否するサイトやウェブページがあります。
ウェブブラウザでアクセスする場合は、使用するブラウザが情報を持っています。実際にはウェブブラウザを使用しないので「偽装」ということになりますが、Indy を使用する場合は User Agent の値を明示的に設定する必要があります。User Agent の値は、以下のようにグローバルに設定することも、実際にアクセスする際に一時的に設定することもできます。
「偽装」ですから、どのウェブブラウザの設定を使用するかは任意です。
図13
実行時の User Agent 取得
IE 限定
この図は 64 ビット版の Windows 7 の IE 11
リスト3
Indy 10.6.2 における User Agent の設定
copy code
implementation
uses
IdHTTPHeaderInfo,
UrlMon;
{$R *.dfm}
// -----------------------------------------------------------------------------
// UrlMonの関数を使用したIE のUser Agentの値の取得(1)
// Ansi版,Unicode版のどちらのDelphiでも使用可能なようにAnsiCharを使用
//
// usesにUrlMonが必要
// -----------------------------------------------------------------------------
function Get_IE_UserAgent: string ;
var
LUserAgent : array [0 .. MAX_PATH - 1 ] of AnsiChar;
LdwSizeOut : DWord;
begin
try
LdwSizeOut := 0 ;
FillChar(LUserAgent, SizeOf(LUserAgent), #0 );
UrlMkGetSessionOption(URLMON_OPTION_USERAGENT,
@LUserAgent,
SizeOf(LUserAgent),
LdwSizeOut,
0 );
Result := string (LUserAgent);
except
// Urlxxxの例外はシステム例外なので実際にはexceptでは補足できない
on E: Exception do begin
// Result := E.Message;
Result := '' ;
end ;
end ;
end ;
// -----------------------------------------------------------------------------
// UrlMonの関数を使用したIE のUser Agentの値の取得(2)
// Ansi版,Unicode版のどちらのDelphiでも使用可能なようにAnsiCharを使用
//
// usesにUrlMonが必要
// -----------------------------------------------------------------------------
function Get_IE_ObtainUserAgent: string ;
var
LUserAgent : array [0 .. MAX_PATH - 1 ] of AnsiChar;
LdwSizeOut : DWord;
begin
Result := '' ;
LdwSizeOut := SizeOf(LUserAgent);
FillChar(LUserAgent, SizeOf(LUserAgent), #0 );
ObtainUserAgentString(0 , @LUserAgent, LdwSizeOut);
if LdwSizeOut > 0 then begin
Result := string (LUserAgent);
end ;
end ;
// =============================================================================
// Indey 10.6.2 におけるUser-Agent(ユーザエージェント)の設定
//
// GIdDefaultUserAgentの使用にはusesにIdHTTPHeaderInfoが必要
// =============================================================================
procedure TForm1.Button1Click(Sender: TObject);
const
UserAgent = 'Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko' ;
var
LText : string ;
begin
// グローバルに設定する場合
// グローバル変数GIdDefaultUserAgentに代入しておく
GIdDefaultUserAgent := UserAgent;
// 個別に設定する場合
IdHTTP1.Request.UserAgent := UserAgent;
// 実行時にUser Agentの値を取得する例(IE限定)
LText := Get_IE_UserAgent;
MessageBox(Handle, PChar(LText), 'IE User Agent' , MB_OK);
end ;
ブラウザの User Agennt は、JavaScript を使用して、例えば以下のような HTML コードをブラウザで表示することで確認することができます。Uset Agent の値は、ブラウザの種類、あるいはリリース等によって異なる値になります。
この HTML コードで取得した値と、上の UrlMon の関数 で取得した値が必ずしも同じ値になるとは限りません。
リスト4
ウェブブラウザの User Agent を調べるための HTML コード
拡張子を .html にして保存する。保存のコードページは Shift-jis でも UTF-8 でもよい
copy code
<!DOCTYPE html >
<html lang="ja" >
<head >
<meta charset ="UTF-8" >
<title >UserAgent Sample</title >
</head >
<body >
<span id="userAgent" ></span >
<script >
var userAgent = window.navigator.userAgent;
var element = document.getElementById("userAgent" );
element.innerText = userAgent;
</script >
</body >
</html >
Indy はバージョンによって仕様の一部が変更されることがあります。
仕様の変更に伴う修正がわずらわしいからと、バージョンアップを避けることもできすが、問題がある現象の修正や新しい機能の利用はできないことになります。バージョンアップによる仕様の変更に対応していくことも重要ではないかと考えます。
例えばイベントの引数に変更があった場合、エラーとなります。そのような場合は、新しいバージョンでイベントを作成し直します。メソッドや関数、あるいはプロパティ等は、似たような機能と思われる名前で推測したりすることになるでしょう。
10_ Delphi XE に Indy 10.6.2 インストール後に発生するエラー
Indy 10.6.2 は Delphi XE にもインストールできますが、避けた方が無難かも知れません。今回ダウンロードした Indy 10.6.2 - Berlin RTM にも、Delphi XE 用としてのインストール用パッケージグループもインストール用のバッチファイルも用意されていません。
インストール後に、Indy あるいは他のコンポーネントを配置したり、あるいは、既存のプロジェクトを開く時に以下のようなエラーが発生しました。このエラーが発生すると、フォームに配置したコンポーネントの一部が失われます。
これは、Delphi XE で実装された Windows Azure クラウド サービスを扱うためのコンポーネントのパッケージ dclWindowsAzureManagement150.bpl が原因で発生するようです。
筆者の場合、このパッケージの機能は使用しませんので、このパッケージを削除しました。[パッケージのインストール] で該当パッケージを削除しても削除できませんでした。そこで、レジストリのパッケージのリストからこのパッケージ名の項目を削除しました。
プロシージャ エントリ ポイント @Idheadercoderutf@initialization$qqrv がダイナミック リンク ライブラリ IndyProtocols150.bpl から見つかりませんでした。
パッケージ c:\program files (x86)\embarcadero\rad studio\8.0\bin\dclWindowsAzureManagement150.bpl を読み込めません。 指定されたプロシージャが見つかりません。
[備考]
Windows Azure 管理コンポーネントの登録名は、Delphi XE5 では「Embarcaderoクラウド管理コンポーネント」で、パッケージ名は dclCloudService190.bpl となってます。登録されているコンポーネントは TAmazonConnectionInfo, TAzureConnectionInfo の 2 つとなっています。
図14
Windows Azure 関係のエラー