fc2ブログ

2013年10月 の記事一覧

IEHost機能のセキュリティ警告を消去する

前回の記事(WEB上にDataGridViewを表示させる)の補足。(追記するとさらに長くなるので別記事にします)

IEHost機能を使用して、ユーザーコントロールからフォームを表示させようとすると、以下のようなセキュリティ警告が出てくる。

20131004_06image.jpg
(Button1押下時にフォームを出すようにしている)

http://type-y.com/2011/03/net-framework-20-microsoft-net.htmlと同じ現象だと思うが、セキュリティ警告を制御可能な「.NET Framework 2.0 Configuration」はVisualStudioのSDKをインストールしていないと使用できないらしい。

と思ったら、.netFrameworkが持ってるコードアクセスセキュリティポリシー(http://msdn.microsoft.com/ja-jp/library/vstudio/cb6t8dtz.aspx)を使用することでも制御できるようだ。

動作環境(クライアント)側で、以下をコマンドプロンプト(管理者権限で起動)で実行する。

>%windir%\Microsoft.NET\Framework\v2.0.50727\caspol.exe -q -force -machine -addgroup All_Code -zone Trusted FullTrust

表示してみるとセキュリティ警告が消える。(zoneがTrustedでないとだめっぽい)

20131004_07image.jpg

セキュリティポリシーを戻したい場合は、

>%windir%\Microsoft.NET\Framework\v2.0.50727\caspol.exe -q -all -reset


を実行。

一応参考までに…っていうかクライアント側の設定が多すぎ(-_-;)。

スポンサーサイト



WEB上にDataGridViewを表示させる

Web上にスプレッドシートを貼り付けてデータ編集できるアプリとか作れないかなと思い調べていたが、そのような開発には高額な「有料」という2文字が付きまとうようだ。(やはりスプレッドシート機能はお高い…)

…と、思ったら以下のサイト(以下『情報元サイト』と記述)を発見。
http://d.hatena.ne.jp/language_and_engineering/20100705/p1
http://q.hatena.ne.jp/1278844101
http://japan.internet.com/developer/20051220/25.html

どうやら.netのフォームコントロールをInternetExplorerにホストして表示することができるようだ。.netFrameworkに含まれるIEHost.dllがその機能を持ってるらしく、.net初期の頃からできる結構昔からの技らしい(-_-;)。しかもDataGridを表示させてる方もいらっしゃる!

調べたところ以下の手順で.netのDataGridViewをhtmlに貼り付けることができたが、そこそこ記事が長い・・。


■1.準備

準備段階として必要なソフト(全てフリー)・環境を以下に挙げてみた。
ちなみに自分の使用PCはWindows7Ulitimate(64bit) - (開発環境・動作環境(サーバー・クライアント)を全て兼用)

(1) Visual Studio Express 2012 for Windows Desktop - 開発環境用

.netでDataGridViewをユーザーコントロール画面に貼り付けたdllを作成する(この画面がブラウザに表示されることになる)為に用意する。情報元サイトによると.netFrameworkさえインストールしていれば、包括してるvbc.exeコマンドでビルド可能だが、開発ツールがある方が格段に開発し易いので用意。ちなみ言語は自分がなじみのあるVBを使用した。

使用バージョン:11.0.50727.42 (http://www.microsoft.com/visualstudio/jpn/downloads#d-2012-express)

(2) Visual Studio Express 2012 for Web - 開発環境用

グリッドに表示するデータのやりとりをWCFサービスで行いたい為(WEBサービスでも別に良いが、今はWCFサービスをマイクロソフトが推奨してるようなので)、WCFサービス機能を作成できるfor webもインストールする。

使用バージョン:11.0.50727.1 (http://www.microsoft.com/visualstudio/jpn/downloads#d-2012-express)

(3) IIS - 動作環境(サーバー)用

WEBサーバーからHTMLを取得しないと、HTMLに貼り付けたDataGridViewコントロールが表示されない。よってWEBサーバーを導入する。
単純にフォームコントロールの表示だけならAPACHEでも行けたが、今回はWCFサービス機能を使用するため、Windowsが標準で持ってるIISを使用する。

使用バージョン:IIS7.5

(4) データベース - 動作環境(サーバー)用

DataGridViewに表示するデータを保持するDBも用意しておく。オラクル好きなので、Oracle11gXEを用意。

使用DB:Oracle11gXE 11.2.0.3.0 (http://www.oracle.com/technetwork/jp/products/express-edition/downloads/index.html)

(5) ODAC - 動作環境(サーバー)用・開発環境用

データベース(オラクル)と接続するためのODAC(Oracle.DataAccess.dll)も用意する。と言ってもOracle11gXEがインストールされて入れば、Oracle.DataAccess.dllが既にDLされているので、それを拝借するだけ。ちなみにWindowsの場合、Oracle11gXEは32bit版しかないので、必然的Oracle.DataAccess.dllも32bit版になる。

使用バージョン:4.112.2.0(C:\oraclexe\app\oracle\product\11.2.0\server\odp.net\bin\4\Oracle.DataAccess.dll を使用)

(6) InternetExproler - 動作環境(クライアント)用

DataGridViewをブラウザで表示させるには.netFrameworkをサポートしてるIEが必要。IEのエンジンを使用していればSlepnirなどのブラウザでも表示可能。ちなみにIE5.01以降で表示可能。

使用IE:IE10.0.9200

(7) .netFramework - 動作環境用(クライアント)用

DataGridViewをブラウザで表示させるには.netFrameworkをインストールする必要がある。とは言え、現在のXP以降なら標準で.netFramework2.0以上がサポートされているので、特に何も用意する必要はない。

ちなみに動作環境(クライアント)用PCに.netFramework4.5以降がインストールされてる場合、何故かブラウザ側で(?)IEHost機能を無効にしてしまうので、少々レジストリによる小細工が必要。

一応使用バージョン:Microsoft .NET Framework 4.5 (http://www.microsoft.com/ja-jp/download/details.aspx?id=30653)
(というかVisualStudioインストールした時点で付いてきたバージョンを使用)


2.IISの設定 - 動作環境(サーバー)での作業

IISの設定確認を行う。ちなみにIISのインストールについてはこちらのページを参考:http://awoni.net/personal-site/iis/
(APACHEのポート番号(80)と被るのが嫌なので、自分はバインドでIISのポート番号を9090に変更している)

(1) C:\inetpub\wwwroot 直下に移動し、ここに適当に「sample」フォルダを作成する(以後ここに必要な実行ファイルを格納)。
(2) 「スタート」→「コントロールパネル」→「管理ツール」を開く。
(3) 「インターネットインフォメーションサービス(IIS)マネージャー」を開く。
(4) 左側の項目で「サイト」→「Default Web Site」を選択し、先ほど作成した「sample」フォルダをクリックする。
(5) 「IIS」項目の「ハンドラーマッピング」を開く。
(6) 右側「操作」項目の「機能のアクセス許可の編集」をクリック
(7) 「読み取り」と「スクリプト」にチェックが入っているか確認。

おそらく標準で「読み取り」と「スクリプト」にチェックが入っている(はず)ので確認程度。ちなみに「実行」にチェックを入れるとフォームコントロールが表示されないので外しておく。

また、ODAC(Oracle.DataAccess.dll)は32bit版を使用するので、以下の手順で32bitアプリを有効にしておく。(32bitPCなら関係ない作業のはず)

(8) 「インターネットインフォメーションサービス(IIS)マネージャー」を開いた状態で「アプリケーションプール」一覧を開く。
(9) 右側「操作」項目の「アプリケーションプールの既定値の設定」を開く。
(10) 「32ビットアプリケーションの有効化」項目を「True」にする。


■3.サンプルデータの作成 - 開発環境での作業

DataGridViewに表示するためのデータをDBで作成。以前の記事(VBAでRefCursorを用いたプロシージャを実行する(ADO版))で使用したsampleテーブル(スキーマ:admin)を使用。

SQL>create table sample (user_id number primary key, user_name varchar2(40), message varchar2(200));
SQL>insert into sample values (1, 'hoge-a', 'good morning.');
SQL>insert into sample values (2, 'hoge-b', 'good evening.');
SQL>commit;



■4.WCFサービスの作成 - 開発環境での作業

DataGridViewに表示するためのデータをやり取りするWCFサービスを作成しておく。今回はDBからデータを読み込んでクライアントに渡すメソッド(GetDataSet)と、グリッドで編集したデータをクライアントから受け取ってDBに保存するメソッド(SetDataSet)を作成。やり取りはDataSetを使用。

(1) 「Visual Studio Express 2012 for Web」を管理者権限で開く(管理者権限なのは後でデプロイするため)。
(2) 「ファイル」→「新しいプロジェクト」を選択。
(3) 「WCFサービスアプリケーション」を選択(サンプルなので名前はWcfService1のまま)してOKを押す。
(4) 「ソリューションエクスプローラー」→「MyProject」→「参照」を開く。
(5) 「追加」→「参照」から「Oracle.DataAccess.dll」を追加する。

次にコーディング。

(6) 「ソリューションエクスプローラー」からIService1.vbのコードを表示する。
(7) 以下をコピペしてGetDataSetとSetDataSetを宣言。(既存のGetDataメソッドは消去してる)

<ServiceContract()>
Public Interface IService1
    ' TODO: ここにサービス操作を追加します。
    <OperationContract()>
    Function GetDataSet() As DataSet

    <OperationContract()>
    Sub SetDataSet(ByVal ds As DataSet)
End Interface


(8) 「ソリューションエクスプローラー」からService1.svc.vbを開く。
(9) 以下をコピペ。

Imports Oracle.DataAccess.Client ' ①
Public Class Service1
    Implements IService1

    Private oraconn As OracleConnection

    Public Sub New()
        getDbConn(oraconn)
    End Sub

    Public Function GetDataSet() As DataSet Implements IService1.GetDataSet
        Dim ds As New DataSet

        Using cmd As New OracleCommand
            cmd.CommandType = CommandType.Text
            cmd.CommandText = "select * from sample order by user_id"
            cmd.Connection = oraconn
            Using da As New OracleDataAdapter
                da.SelectCommand = cmd
                da.Fill(ds, "sample")
            End Using
        End Using

        Return ds
    End Function

    Public Sub SetDataSet(ByVal ds As DataSet) Implements IService1.SetDataSet
        Dim str As String = String.Empty
        Dim dt As DataTable = ds.Tables("sample")
        Dim param(dt.Columns.Count) As OracleParameter

        Using txn As OracleTransaction = oraconn.BeginTransaction
            Try
                For Each row As DataRow In dt.Rows
                    If row.RowState <> DataRowState.Unchanged Then
                        Using cmd As New OracleCommand
                            cmd.CommandType = CommandType.Text
                            cmd.Connection = oraconn
                            cmd.BindByName = True
                            Select Case row.RowState
                                Case DataRowState.Added
                                    cmd.CommandText = "insert into sample values (:0, :1, :2)"
                                Case DataRowState.Deleted
                                    cmd.CommandText = "delete from sample where user_id = :3 "
                                Case DataRowState.Modified
                                    cmd.CommandText = "update sample set user_id = :0 " &
                                                      ", user_name = :1 " &
                                                      ", message = :2 " &
                                                      "where user_id = :3"
                                Case Else
                            End Select
                            For cnt As Integer = 0 To param.Length - 1
                                If cnt = param.Length - 1 Then
                                    If row.RowState <> DataRowState.Added Then
                                        cmd.Parameters.Add(cnt.ToString, OracleDbType.Decimal, row(0, DataRowVersion.Original), ParameterDirection.Input)
                                    End If
                                Else
                                    If row.RowState <> DataRowState.Deleted Then
                                        cmd.Parameters.Add(cnt.ToString, IIf(dt.Columns.Item(cnt).DataType = System.Type.GetType("System.Decimal"), OracleDbType.Decimal, OracleDbType.Varchar2), row(cnt, DataRowVersion.Current), ParameterDirection.Input)
                                    End If
                                End If
                            Next
                            cmd.ExecuteNonQuery()

                        End Using
                    End If
                Next
                txn.Commit()

            Catch ex As OracleException
                txn.Rollback()
                Throw ex

            End Try
        End Using
    End Sub

    Private Sub getDbConn(ByRef oraconn As OracleConnection)
        If oraconn Is Nothing Then
            oraconn = New OracleConnection
            oraconn.ConnectionString = "User Id=admin;Password=*****;Data Source=xe" ' ②
            oraconn.Open()
        End If
    End Sub

    Private Sub closeDbConn(ByRef oraconn As OracleConnection)
        If Not oraconn Is Nothing Then
            oraconn.Close()
            oraconn.Dispose()
        End If
    End Sub

    Public Sub Diposite()
        closeDbConn(oraconn)
    End Sub
End Class


備考:
・① Oracle.DataAccess.Clientをインポートする。
・② tnsnames.oraにXEのネットサービス名が無い場合は事前に追加しておく。*****は任意のパスワードを指定。ソースが汚いのは勘弁してね…。

最後にデプロイ。

(10) 「ソリューションエクスプローラー」を開き「WcfService1」の部分を右クリックし、「発行」を選択。
(11) 「プロファイル」画面で無記入のドロップダウンリストから「<新しいプロファイル>」を選択。
(12) 適当に「プロファイル名」を記入してOKを押す。(sampleにしてみた)
(13) 「接続」画面で以下を指定。

・発行方法:Web Deploy
・サーバー:localhost:9090
・サイト名:Default Web Site/sample


備考:
・サーバーは動作環境(サーバー)を指定。今回は開発環境と兼用してるのでlocalhostを指定。
・(自分は)ポート番号も変更しているので9090に設定。(変更してなければデフォルトの80にする)
・サイト名は2.で作成したsampleフォルダを指定。

(14) 「発行」を押下。

ビルドしたWCFサービスが動作環境(サーバー)のC:\inetpub\wwwroot\sample直下に構築されているのを確認。(Oracle.DataAccess.dllもBinに転送されている)


■5.クラスライブラリの作成 - 開発環境側での作業

DataGridViewをユーザーコントロールに貼り付けたクラスライブラリを作成する。

(1) 「Visual Studio Express 2012 for Windows Desktop」を開く(管理者権限でなくてよい)。
(2) 「ファイル」→「新しいプロジェクト」を選択。
(3) 「クラスライブラリ」を選択(サンプルなので名前はClassLibrary1のまま)してOKを押す。
(4) 「ソリューションエクスプローラー」→「MyProject」→「アプリケーション」を開いて以下を指定。

・ルート名前空間:ClassLibrary1 (デフォルトのまま)
・対象のフレームワーク:.NET Framework3.5


備考:
・対象フレームワークを変更するとプロジェクトを再度開くように促されるがそのまま「はい」を選ぶ。
・.NET Framework3.5にするのは、IEHostの機能が3.5までしか有効でないため。かつ、WCFサービスが3.0以上でないと機能しない為。

次にユーザーコントロールを作成。

(5) 「ソリューションエクスプローラー」を開き「ClassLibrary1」を右クリックする。
(6) 「追加」→「新しい項目の追加」を選択。
(7) 「ユーザーコントロール」(WPFじゃない方)を選択(名前はデフォルトのUserControl1.vbのまま)して、追加。
(8) 「デザインモード」になるので「ツールボックス」から「DataGridView」1つと「Button」2つをユーザーコントロールに貼り付ける。

20131004_01image.jpg

コーディングの前に、4.で配置したWCFサービスを参照する。

(9) 「ソリューションエクスプローラー」を開き「ClassLibrary1」を右クリックする。
(10) 「サービス参照の追加」をクリックして、以下の「アドレス」を指定する。

アドレス:http://*****:9090/sample/Service1.svc


備考:
*****は動作環境(サーバー)のIPアドレスかlocalhost。

(11) 「移動」をクリックして「1個のサービスが見つかりました」と表示されたらOKを押す。

最後にコーディング。Button1を押すとWCFサービスからDataSetを読み込み、Button2を押すとグリッドの変更データをWCFサービスに送る機能を実装。

(12) 「UserControl1.vb」のコードを表示して、以下をコピペ

Imports System.ServiceModel ' ①
Public Class UserControl1

    Private p_ds As New DataSet
    Private p_proxy As ServiceReference1.IService1

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Try
            p_proxy = getProxy()
            If Not p_ds Is Nothing Then
                p_ds.Dispose()
            End If
            p_ds = p_proxy.GetDataSet()

            DataGridView1.DataSource = p_ds
            DataGridView1.DataMember = "sample"
        Catch ex As Exception
            MsgBox(ex.Message)
        Finally
            killProxy(p_proxy)
        End Try
    End Sub

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        Try
            p_proxy = getProxy()
            Dim ds As New DataSet
            If p_ds.HasChanges = True Then
                ds = p_ds.GetChanges
                p_proxy.SetDataSet(p_ds)
                p_ds.AcceptChanges()
                MsgBox("データを更新しました")
            End If
        Catch ex As Exception
            MsgBox(ex.Message)
        Finally
            killProxy(p_proxy)
        End Try
    End Sub

    Private Function getProxy() As ServiceReference1.IService1
        Dim endPoint As New EndpointAddress("http://*****:9090/sample/Service1.svc") ' ②
        Dim httpBind As New System.ServiceModel.BasicHttpBinding()

        Return ChannelFactory(Of ServiceReference1.IService1).CreateChannel(httpBind, endPoint)
    End Function

    Private Sub killProxy(proxy As ServiceReference1.IService1)
        Dim clientChannel As IClientChannel = CType(proxy, IClientChannel)
        clientChannel.Close()
        clientChannel.Dispose()
    End Sub

End Class


備考:
・① System.ServiceModelをインポートする。
・② EndpointAddressはコード内で直接指定する(通常はapp.configで設定されるが、クラスライブラリの場合app.configが読み込めないので。*****はWCFサービスを発行する端末(動作環境(サーバー))のIPアドレスを指定(localhostでもいいが、ローカル内の他端末で使えなくなる)。

(12) 「ソリューションのビルド」を行い、作成されたClassLibrary1.dllを動作環境(サーバー)のC:\inetpub\wwwroot\sampleに配置する。

ちなみに既存のClass1.vbソースは消去しても構わない。


■6.HTMLの作成 - 動作環境(サーバー)での作業

5.で作成したユーザーコントロールをobjectタグでHTMLページに貼り付ける。

(1) 動作環境(サーバー)のC:\inetpub\wwwroot\sample直下にsample.htmlファイルを新規作成。
(2) sample.html内に以下のタグを追加して保存。

<html>
<body>
<object id="sample" classid="ClassLibrary1.dll#ClassLibrary1.UserControl1" width=800 height=500 VIEWASTEXT></object>
</body>
</html>


備考:
・#の後のClassLibrary1は5.の(4)で指定されてる「ルート名前空間」に等しい。


■7.ブラウザの設定 - 動作環境(クライアント)での作業

6.まで終われば後はクライアント側のブラウザで表示確認するだけだが、クライアント側でも少々設定が必要。

(1) IE(またはIEのエンジンを使用してるブラウザ)を開き、「インターネットオプション」を開く。
(2) 「セキュリティ」タブを開き、「信頼済みサイト」の「サイト」ボタンを押す。
(3) 「このWebサイトをゾーンに追加する」に、動作環境(サーバー)のアドレスを指定する。

・http://*****
*****は動作環境(サーバー)のIPアドレス(5.の(12)②でEndpointAddressをlocalhostにした場合はlocalhost)

情報元サイトによると、ActiveXが有効でないとIEHost機能を無効にしてしまう(らしい)。セキュリティレベルを変更したくないので、今回は信頼済みサイトに追加している。

また、クライアント側に.netFramework4.5以降がインストールされている場合、クライアントPCで以下のレジストリ操作が必要。

(4) コマンドプロンプトを開きregeditでレジストリエディターを開く。
(5) \HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework 直下に以下の値を追加する。

・属性:Dword値
・名前:EnableIEHosting
・値:1


詳細はhttp://connect.microsoft.com/VisualStudio/feedback/details/760918/net-framework-4-5-net-2-0-iehost-dllに記載されてます。(実際.netFramework4.0までインストールした環境で動作確認するとレジストリ操作なしで表示できる)


■8.動作確認 - 動作環境(クライアント)にて

最後に動作確認。IE(またはIEのエンジンを使用してるブラウザ)を開き、http://*****:9090/sample/sample.htmlにアクセスする(*****は動作環境(サーバー)のIPアドレス(5.の(12)②でEndpointAddressをlocalhostにした場合はlocalhost))

20131004_02image.jpg

5.で作成したユーザーコントロールがWeb上に表示される。
ここでButton1を押してみると、

20131004_03image.jpg

DBで作成したsampleテーブルデータが読み込まれる。
さらに以下の様に1行目を消去して、3行目に新しいデータを追加して、Button2を押してみる。

20131004_04image.jpg

上記の通り更新されたかsqldeveloperで確認してみる。

20131004_05image.jpg

更新されていることを確認。ちなみにクライアントの動作環境をローカル内の別端末にして実行しても問題はなかった。また外部で公開して別端末で実行しても問題なかった(外部公開の場合EndpointAddressを変える必要があるけど)。


以上で終わり。DataGridViewはExcelシートに近いので、セルのコピペもし易いし、Web上で使えるとかなり良い感じ。しかもコーディングとしてもWebアプリを作るというより、ほぼクライアントアプリを作ってる感じなのでやり易い(それは人それぞれか…)。

ただクライアント側で微妙に設定する必要があるので、個人の趣味程度の技術っぽい。(何よりIEHost機能は.netFramework4.0で終了になっているので、使用して欲しくない技術っぽい)。まぁ自分はそれで満足なので構わないケド…。

最後に、情報元サイト様に多大なる感謝です♪

Oracle11gXEでRMANを使ってデータベースの複製をする

簡易アプリ作成でデータベース(Oracle11gXE)を使ったりしているが、アプリ移植の為に、今あるDB環境の複製が欲しくなった。調べてみると、XEに付随してるリカバリーマネージャ(RMAN)を使うことで簡単にできるらしい。

ちなみに今の環境
OS:Windows7Ultimate(64bit)
DB:Oracle11gXE

流れとしては、XEと別に独自のインスタンスを作り、そのインスタンス用の専用フォルダを作っておき、XEで使用されるDBFやログファイル等をRMANで転送するだけ。
1.~4.あたりは以前の記事(Oracle11gXE)とやってることが被るので、少々説明を省き気味(汗)。詳細はOracle11gXEの方を覗いて頂けると幸いです。


■1.複製先インスタンスのwindowsサービスの作成

今回は複製先インスタンス名を「XE2」とする。Windowsではインスタンスのwindowsサービスを作成しないといけないのでoradim.exeを使って作成。コマンドプロンプト上で

>oradim.exe -NEW -SID XE2

を実行。


■2.フォルダの作成

複製先インスタンスが使用するフォルダを作成。フォルダ構成はXEと同じにしたいので以下の場所にフォルダを作成。(ちなみにOracle11gXEがC:\直下にインストールされてることを前提とした上での絶対path)

・C:\oraclexe\app\oracle\oradata\XE2
・C:\oraclexe\app\oracle\admin\XE2\adump
・C:\oraclexe\app\oracle\admin\XE2\dpdump
・C:\oraclexe\app\oracle\fast_recovery_area\XE2\ARCHIVELOG
・C:\oraclexe\app\oracle\fast_recovery_area\XE2\ONLINELOG



■3.initファイル(パラメータファイル)、PWD(パスワードファイル)の作成

複製先インスタンスのinitファイルを作成する(場所はC:\oraclexe\app\oracle\product\11.2.0\server\database)。XEインスタンスの静的initファイル(initXE.ora)が作られていない場合は、先にXEに接続してcreate pfile from spfileを実行してinitファイルを作成しておく。

initXE.oraをコピペして、ファイル名をinitXE2.oraにする。
initXE2.oraを以下のように追加修正

*.audit_file_dest='C:\oraclexe\app\oracle\admin\XE2\adump'
*.compatible='11.2.0.0.0'
*.control_files='C:\oraclexe\app\oracle\oradata\XE2\control.dbf'
*.db_name='XE2'
*.db_file_name_convert='C:\ORACLEXE\APP\ORACLE\ORADATA\XE\','C:\ORACLEXE\APP\ORACLE\ORADATA\XE2\'
*.log_file_name_convert='C:\oraclexe\app\oracle\fast_recovery_area\XE\ONLINELOG\','C:\oraclexe\app\oracle\fast_recovery_area\XE2\ONLINELOG\'

*.DB_RECOVERY_FILE_DEST_SIZE=10G
*.DB_RECOVERY_FILE_DEST='C:\oraclexe\app\oracle\fast_recovery_area'
*.diagnostic_dest='C:\oraclexe\app\oracle\.'
*.dispatchers='(PROTOCOL=TCP)(SERVICE=XE2)(DISPATCHERS=1)'
*.job_queue_processes=4
*.max_shared_servers=8
*.memory_target=1024M
*.open_cursors=300
*.processes=200
*.remote_login_passwordfile='EXCLUSIVE'
*.sessions=20
*.shared_servers=4
*.statistics_level='typical'
*.undo_management='AUTO'
*.undo_tablespace='UNDOTBS1'

オレンジ部分に記述されてるconvert句が重要。複製元のインスタンスのDBFとログファイルを指定して、複製先のフォルダを指定する。(複製元のinitXE.oraに記述する必要は無し)

また同じ場所にあるパスワードファイル(PWDXE.ora)もコピペしてファイル名を「PWDXE2.ora」にして置いておく(面倒なので複製元と同じ管理者パスワードにする為)。


■4.listener.ora、tnsnames.oraへの追加

複製先インスタンスで接続できるように、リスナーとネットサービス名を追加しておく。

・listener.ora
SID_LIST_LISTENER =
  (SID_LIST =
    (SID_DESC =
      (SID_NAME = XE)
      (ORACLE_HOME = C:\oraclexe\app\oracle\product\11.2.0\server) 
      (SERVICE_NAME = XE)
    )
    (SID_DESC =
      (SID_NAME = XE2)
      (ORACLE_HOME = C:\oraclexe\app\oracle\product\11.2.0\server) 
      (SERVICE_NAME = XE2)
    )

   
水色の部分を追加。

・tnsnames.ora
XE =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = ****)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = XE)
    )
  )
XE2 =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = ****)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = XE2)
    )
  )

 
水色の部分を追加。****は自分の環境かlocalhostで入力。(XEのネットサービス名を作っていない場合はそちらも追加)

listener.oraは変更後にlsnrctl reloadしておく。


■5.双方のインスタンスの起動

コマンドプロンプトでsqlplusを起動して、複製元のインスタンス(XE)と複製先インスタンス(XE2)を起動しておく。

・複製元インスタンス(XE)
>set oracle_sid=xe
>sqlplus / as sysdba
SQL>startup


・複製先インスタンス(XE2)
>set oracle_sid=xe2
>sqlplus / as sysdba
SQL>startup nomount


複製先はnomount状態で起動。(エラーが無いことを確認)
複製元はmountかopen状態であれば良い。(上記はopenで起動)


■6.リカバリーマネージャで複製

5.まで終われば後はDBを複製するだけの作業。

まずはコマンドプロンプトで、リカバリーマネージャ(RMAN)を起動。

>rman target sys/********@xe auxiliary sys/********@xe2

targetは複製元のログイン情報、auxiliaryは複製先のログイン情報。
********の部分はXEをインストールしたときに設定したSYSDBAのパスワードを入力。

最後に複製コマンドを実行。

RMAN>duplicate target database to XE2;

「Duplicate Db」と表示されれば複製完了(SPFILEなども自動的に作られている)。
完了後、複製先インスタンスはOPEN状態になっているので、念の為、複製先インスタンスのDBFとログファイルの入出力先を確認すると・・・

20131001_01image.jpg 20131001_02image.jpg

正常にXE2フォルダを指している。複製なので当然管理用GUIツールなども

20131001_03image.jpg 20131001_04image.jpg

このように使用できる。(パラメータがXE2を指しているのを確認。XEインスタンスと被るのでdbms_xdb.sethttpportでポートを変えておくと良いかも)
後は複製先インスタンスの起動・停止バッチをXEからコピペして作成しておくと良さそう。

ちなみにXEだけでなく、以前の記事(Oracle11gXE)で書いた独自で作ったインスタンスについても複製できる(というかそっちの方がやりたかった)。一つ気になったのはstandbyインスタンスにしても作成できたのでOracle11gXEでDataGuard機能が有効みたい(?)。

補足:
expdpなどで使うdirectoryの「DATA_PUMP_DIR」のパスだけXEと同じになっているので、以下をSYSで実行して切り替える。

SQL>create or replace directory DATA_PUMP_DIR as 'C:\oraclexe\app\oracle\admin\XE2\dpdump\';