FAQ - 技術的質問: Object Script

FAQのトップページに戻る


IDQuestion
019CachéからWindows上の外部DLLを呼び出したい
020プログラムからルーチンの日付やサイズをリストする方法
021プログラムからLock情報を取得したい
022設定されているネームスペース一覧をプログラムで取得する方法はありますか?
023ユーザが作成したクラス一覧をプログラムで取得する方法はありますか?
024CachéサーバのIPやマシン名を取得するにはどうすればいいですか?
025CachéクライアントのIPやマシン名を取得するにはどうすればいいですか?
026半角スペース及び全角スペースをトリムする方法を教えてください。
027$ETRAP使用時にエラーが複数回報告されるのはなぜですか?
028アプリケーションから明示的にエラー詳細情報をログ出力する方法を教えてください。
079グローバルの特定ノードのエクスポート
080DSM では Break コマンドを ZBREAK ON, ZBREAK OFF で有効,無効にできましたが Cachéで同様の機能はありますか?
081Caché ObjectScriptを使ってネットワークプリンタに出力できますか?
082クラス内で定義(記述)されたプロパティの情報、例えば名称、タイプ、パラメータ等を取得する方法はありますか?
084^ERRORSにエラーをログするために^%ETNを使いたいのですが、^%ETNは必ずHALTしてしまいます。HALTしないようにするにはどうすればいいですか?
085$ZF関数を使用して外部コマンドを実行する場合、コマンド文字列に日本語が含まれていると エラーが発生してコマンドが実行できません。
142全角/半角混在文字列から指定された幅の文字列を取得する方法を教えてください。
153プログラムからグローバルのインポート/エクスポート処理を呼び出すことはできますか?(V5.0用)
154プログラムからグローバルのインポート/エクスポート処理を呼び出すことはできますか?(V5.1以降)
155プログラムからルーチンをインポート/エクスポートすることはできますか?
165for文のスペースに関するよくある間違い
176ファイルを読み込んだ際にファイルの終端を判断する方法を教えて下さい。
179Cachéの変数等に命名規約のようなものは、ありますか?
185関数、メソッドを呼び出す際に可変数引数を渡すことはできますか?
186ターミナルでプログラム実行を行なってエラーが発生したあと、プロンプトを元に戻す方法は?
187Killコマンドの実行に関して、確認のメッセージを出す仕組みはありますか?
209Cachéで文字列を置換するにはどうすれば良いですか?

それぞれの項目についてのお問い合わせは、各項目内のをクリックしてください。

 

Question : 019

CachéからWindows上の外部DLLを呼び出したい

Windows外部DLLをCachéから呼び出すためにはCachéから引数や戻り値を正しく引き渡すためにラッパーDLLを作成する必要があります。

また、手元にプログラムソースがあるDLLの場合は、Caché対応用にプログラムを変更してビルドすることもできます。

サンプルはCaché対応のDLLを作り、Cachéターミナルから呼び出す簡単なサンプルです。

| Back to Top

Question : 020

プログラムからルーチンの日付やサイズをリストする方法

クラス %Routine を使用します。

ルーチンについて以下のような query で取得できます。
例では *.OBJ について実施しています。

set rs=##class(%ResultSet).%New("%Routine:RoutineList")
do rs.Execute("*.OBJ",,1)
while (rs.Next()) {
	set name=rs.Get("Name")
	set size=rs.Get("Size")
	set date=rs.Get("Date")
	if name["%" continue
	w name,",",size,",",date,!
}
d rs.Close()
q

また、コンパイルされたクラスについても同様に以下の query で取得できます。

set rs=##class(%ResultSet).%New("%ClassDefinition:ClassInfo")
do rs.Execute("")
while (rs.Next()) {
	set name=rs.Get("Name")
	set date=$ZDATETIME(rs.Get("TimeChanged"))
	if name["%" continue
	w name," ",date,!
}
d rs.Close()
q

| Back to Top

Question : 021

プログラムからLock情報を取得したい

2つの方法を紹介します、%SYS.LockQuery クラスの使用 と SSVN 構造化システム変数の使用です。

1. %SYS.LockQuery クラスの使用。

   Set Rset=##class(%ResultSet).%New("%SYS.LockQuery:List")
   //Collect all locks in lock table.
   Do Rset.Execute("")
	 
   Set Rset=##class(%ResultSet).%New("%SYS.LockQuery:List")
   //Collect all locks in lock table.
   Do Rset.Execute()

   While (Rset.Next()) {
      Write !,Rset.FullReference
      Write !,Rset.Owner
      Write !,Rset.DelKey,!
   }

   Do Rset.Close()

より詳細なLock情報を取得する場合には、List クエリーではなく、Detail クエリーを使用します。

上記の、%New("%SYS.LockQuery:List") を、%New("%SYS.LockQuery:Detail") として下さい。

その他 条件を指定してLock情報を取得する事が出来ます。
詳細については以下をご覧下さい。

http://docs.intersystems.com/cache20082j/csp/documatic/%25CSP.Documatic.cls?PAGE=CLASS&LIBRARY=DOCBOOK&CLASSNAME=%25SYS.LockQuery

2. SSVN 構造化システム変数の使用。

以下のサンプルは現在のネームスペースにあるロックを検索し、表示します。
またLOCKET というローカル配列にあるロック名を格納します。

SET lname=""
FOR I=1:1 {
    SET lname=$ORDER(^$LOCK(lname))
    QUIT:lname=""
    SET LOCKET(I)=lname
    WRITE !,"the lock name is: ",lname
}
WRITE !,"All lock names listed"
QUIT

詳細については以下をご覧下さい。

http://docs.intersystems.com/cache20082j/csp/docbook/DocBook.UI.Page.cls?KEY=RCOS_slock

| Back to Top

Question : 022

設定されているネームスペース一覧をプログラムで取得する方法はありますか?

%SYS.Namespace クラスの List クエリで取得することができます。クエリの実行方法の詳細はサンプルをご覧ください

| Back to Top

Question : 023

ユーザが作成したクラス一覧をプログラムで取得する方法はありますか?

%ClassDefinition クラスの ClassInfo クエリで取得することができます。クエリの実行方法の詳細はサンプルをご覧ください。

| Back to Top

Question : 024

CachéサーバのIPやマシン名を取得するにはどうすればいいですか?

以下の関数で取得できます。

set hostname=$SYSTEM.Server.HostName()
set ip=$SYSTEM.Server.IPAddresses()

| Back to Top

Question : 025

CachéクライアントのIPやマシン名を取得するにはどうすればいいですか?

以下の関数で取得できます。

set client=$P($ZIO,"/")

CachéサーバがWindowsの場合、上記にクライアントマシン名が格納されます。

そこで

set ip=$SYSTEM.Server.IPAddresses(client)

とすれば、IPアドレスが取得できます。

Cachéサーバが、Linux等の場合、clientにはクライアントマシンのIPアドレスが格納されます。

| Back to Top

Question : 026

半角スペース及び全角スペースをトリムする方法を教えてください。

トリム関数($ZSTRIP)には、任意の1文字をトリム対象として追加指定することが出来ます。

Set a="  全角・半角スペースを含む文字列  "
Set b=$ZSTRIP(a,"<>W",$C($ZHEX("3000")))

なお、$ZHEX("3000")は16進数の3000のことで、Unicodeでの全角スペースの文字コードです。

| Back to Top

Question : 027

$ETRAP使用時にエラーが複数回報告されるのはなぜですか?

$ETRAPを使用してエラートラップを行っている場合、あるコールレベルでエラーが発生すると明示的に$ECODEをクリアしない限り、同エラーは全てのコールレベルで報告され続けます。

意図的に、このようなエラーハンドリングを行うのでなければ、エラー処理関数内で、Set $ECODE="" を実行してください。

サンプルをご覧下さい。

| Back to Top

Question : 028

アプリケーションから明示的にエラー詳細情報をログ出力する方法を教えてください。

アプリケーションでエラーを検出した際に、エラー・トラップ・ユーティリティ(%ETN)を使用することにより、エラー詳細情報を明示的に ログ出力させることが出来ます。

%ETNの使用方法については、サンプルをご参照ください。

記録されたログは、下記の方法でご確認頂けます。

・Caché5.1以降
 システム管理ポータルの
 [ホーム] > [システムログ] > [アプリケーションエラーログの表示] で、
 該当ネームスペースと日付を選択して表示。

・Caché5.0.x
 コントロールパネルの
 [ログ] > [アプリケーションエラー] で表示。
また、ログの確認は、エラー・レポート・ユーティリティ(%ERN)でも参照することが可能です。

%ETN、および、%ERNの詳細については、下記ドキュメントページをご参照ください。

http://docs.intersystems.com/cache20091j/csp/docbook/DocBook.UI.Page.cls?KEY=GCOS_debug#GCOS_debug_errortraputils

| Back to Top

Question : 079

グローバルの特定ノードのエクスポート

Q:次のようなグローバルにて特定のノード
^ADATA("A"),^ADATA("B"),^ADATA("C")
だけをエクスポートしたいとき、エクスポート可能でしょうか?

^ADATA("A")="Aノード"
^ADATA("A",100,1)=""
^ADATA("A",101,2)=""
^ADATA("A",103,3)=""
   :
^ADATA("B")="Bノード"
^ADATA("B",200,1)=""
^ADATA("B",201,2)=""
^ADATA("B",203,3)=""
   :
^ADATA("C")="Cノード"
^ADATA("C",300,1)=""
^ADATA("C",301,2)=""
^ADATA("C",303,3)=""

A:ルーチン^%GOGEN でグローバルの特定のノードのみをエクスポートすることが可能です。

以下オペレーションの例になります。

USER>d ^%GOGEN
 
Device: c:\temp\temp.gsa   Parameters: "WNS"=>
Warning:  Use a "V" format to avoid problems with control characters.
Global ^ADATA("A")  --->^ADATA("A")のみ 
Global ^ADATA("B")
Global ^ADATA("C")
Global ^ADATA("D",  --->^ADATA("D", 以下のノードすべて

%GOGENで出力されたファイルは%GIGEN にてインポートを行います。

| Back to Top

Question : 080

DSM では Break コマンドを ZBREAK ON, ZBREAK OFF で有効,無効にできましたが Cachéで同様の機能はありますか?

以下の $ZUTIL関数にて同様のことが行えます。

$ZUTIL(68,5,n)

現在のプロセスに引数のない BREAK コマンド処理を有効あるいは無効にします。

  $ZUTIL(68,5,0) BREAKコマンドを無効
  $ZUTIL(68,5,1) BREAKコマンドを有効

http://docs.intersystems.com/cache20091j/csp/docbook/DocBook.UI.Page.cls?KEY=RCOS_fzutil68-5

またシステム全体でBREAKコマンドを有効,無効にするには以下の$ZUTIL関数で行えます。

$ZUTIL(69,5,n)

http://docs.intersystems.com/cache20091j/csp/docbook/DocBook.UI.Page.cls?KEY=RCOS_fzutil69-5

構成マネージャ(システム管理ポータル)の設定でも可能です。

V5.0.x

構成マネージャ -> 詳細タブ -> ObjectScript -> 引数のないBREAKを無視=はい

V5.1 ~ V2008.2

システム管理ポータル -> 構成 -> 詳細設定 -> ObjectScript -> 引数のないBREAKを無視

V2009.1以降

システム管理ポータル -> 構成 -> 追加の設定 -> 互換性設定 -> BreakMode

値を真(チェックをつける)と引数なしBREAKを無視しない

| Back to Top

Question : 081

Caché ObjectScriptを使ってネットワークプリンタに出力できますか?

Cachéサーバから、別端末のプリンタに出力するには、以下の3つのステップを実行します。 (Windows用)

1. ユーザ設定

・Cachéサーバ端末
・プリンタが接続されている端末

の両方に、同じユーザ名・パスワードのユーザがあることが前提条件となりますので、2つの端末上で、そのようなユーザを設定します。

例)ユーザ名:Printer パスワード:Printerを2つの端末で同様に登録する。

ユーザ登録が完了したら、Cachéシステム上で、そのユーザをAdministratorsグループに登録します。

※一番簡便な方法は、Administratorユーザのパスワードを、2つの端末上で同じにすることです。
(これで上記の条件を満たします。)

2. Caché起動ユーザの変更

以下の手順で、Caché起動ユーザを変更します。

Windowsコントロールパネル→管理ツール→サービス→Cacheコントローラ for XXXX (構成名)→ログオンタブ

アカウント: 1のユーザ名
パスワード:1のパスワード
を登録し、Cachéを再起動します。

3.  プログラミング例

次のCaché ObjectScriptを実行します。
printernameはプリンタ名です(環境によって変更してください)

USER> set prn="|PRN|\\xxx.xxx.xxx.xxx\printername" ; (xxx.. はIP)
USER> open prn use prn write "OK" close prn

| Back to Top

Question : 082

クラス内で定義(記述)されたプロパティの情報、例えば名称、タイプ、パラメータ等を取得する方法はありますか?

クラスに定義されたプロパティの情報については %Dictionary.ClassDefinetion と %Dictionary.PropertyDefinition を用いて取得できます。

以下サンプルになります。

ClassInfo

 // プロパティ情報取得
getPropInfo(classname)
  set cls=##class(%Dictionary.ClassDefinition).%OpenId(classname)
  set x=cls.Properties
  for i=1:1:x.Count() {
    // プロパティ情報を取得(%Dictionary.PropertyDefinition)
    set prop=x.GetAt(i)
    if prop="" continue

      set propname=prop.Name // プロパティ名
        set proptype=prop.Type // プロパティタイプ
        if propname="" continue
      w propname," ",proptype,!

}
quit

実行例

USER>d getPropInfo^ClassInfo("User.Person")
Age %Integer
Name %String 

| Back to Top

Question : 084

^ERRORSにエラーをログするために^%ETNを使いたいのですが、^%ETNは必ずHALTしてしまいます。HALTしないようにするにはどうすればいいですか?

^%ETNのBACKエントリ(BACK^%ETN)を呼び出してください。

| Back to Top

Question : 085

$ZF関数を使用して外部コマンドを実行する場合、コマンド文字列に日本語が含まれていると エラーが発生してコマンドが実行できません。

$ZFで使用する文字列は、Caché内部のUnicodeから文字列変換されずに渡されます。

このため、文字列に日本語(漢字)を含んでいる場合はご覧になったエラーが発生いたします。

これを回避するには、お使いいただいているOSにあわせて文字コードを明示的に変換していただく必要がございます。文字コード変換には$ZConvert($ZCVT)関数を使用します。例えば、Windowsの場合、変数 cmd にコマンドが格納されているのであれば次のようにシフトJIS(SJIS)に変換します。

Set ret=$ZF(-1,$ZCVT(cmd,"O","SJIS"))

| Back to Top

Question : 142

全角/半角混在文字列から指定された幅の文字列を取得する方法を教えてください。

$ExtractはCaché上では文字単位で処理を行うため、そのままでは全角/半角文字を区別した区切り位置指定を行うことができません。

全角/半角文字の文字幅を取得する関数 $ZPosition がございますので、$zposition関数と$extractを組み合わせることでご希望のことを行うことができます。

例:

全角=2、半角=1 の幅として全角5文字分(半角10文字)だけ出力

USER>s str="あい1234うえお"
 
USER>w $extract(str,1,$zposition(str,10,2))

あい1234う

| Back to Top

Caché5.0.xQuestion : 153

プログラムからグローバルのインポート/エクスポート処理を呼び出すことはできますか?(V5.0用)

以下の方法は、V5.0.xバージョンにのみ適用されます。
V5.1以降では、使用できません。

V5.0.xでは、以下の様な方法でグローバルのインポート/エクスポート処理をプログラムの中に組み込むことができます。

(表記上、コマンド/行の途中で改行が含まれている可能性があります)

1. グローバルエクスポート方法

一般的に、“WNS”オプションは制御文字などのバイナリデータを含まないグローバルをエクスポートまたはインポートする場合に使用し、それ以外のフォーマット (ブロックモード, “WNV”) をバイナリデータの保存に使用します。

処理は、出力グローバルの指定の部分(1.1)とエクスポート処理の部分(1.2)の2つで構成されます。

1.1 出力グローバルの指定

1.1.1 基本形(個別にグローバル名を指定する)

Kill ^%utility($j)
s ^%utility($j,1)="^Global1”
s ^%utility($j,2)="^Global2”

1.1.2 全てのグローバルをエクスポートする場合
(新しいデータベースにモード7 (%GOF 形式)で出力する場合を除いて推奨されません)

Kill ^%utility($j)
S glocount=$$Fetch^%GD("*",1,0)
; 不要なグローバルのエントリを削除
If $I=2 Kill ^%utility("SPOOL") ; $IO 特殊変数が2の場合^SPOOLをエクスポートしない
Set GLO="" s GC=0 For G=1:1 Set GLO=$O(^%utility($J,GLO)) Quit:GLO="" i $d(@GLO) s GC=GC+1,glist(GC)=GLO
Kill ^%utility($j)
M ^%utility($j)=glist

1.1.3 制御文字やルーチンソース、オブジェクトが格納されているグローバルを除くほぼ全てのグローバルをエクスポートする場合(新しいデータベースに全体をコピーするのでない限り、推奨されません)

Kill ^%utility($j)
; 制御文字コードをデータに持つ%qCache 、 rOBJ を除外する
; ルーチンとオブジェクトの定義ソースグローバルを除外
S glocount=$$Fetch^%GD("*;'%qCache*;'rOBJ;'ROUTINE;'r*;'odd*",1,0)
; 不要なグローバルのエントリを削除
If $I=2 Kill ^%utility("SPOOL") ; $IO 特殊変数が2の場合^SPOOLを出力しない
Set GLO="" s GC=0 For G=1:1 Set GLO=$O(^%utility($J,GLO)) Quit:GLO="" i $d(@GLO) s GC=GC+1,glist(GC)=GLO
Kill ^%utility($j)
M ^%utility($j)=glist

1.1.4 ^A から ^EZZZZZZ... までのすべてのグローバルをエクスポート (既存のデータベースに対して特定のグローバルをエクスポートする場合に推奨される方法):

Kill ^%utility($j)
S glocount=$$Fetch^%GD("A*;B*;C*;D*;E*",1,0)
; 不要なグローバルのエントリを削除
If $I=2 Kill ^%utility("SPOOL") ; $IO 特殊変数が2の場合^SPOOLを出力しない
Set GLO="" s GC=0 For G=1:1 Set GLO=$O(^%utility($J,GLO)) Quit:GLO="" i $d(@GLO) s GC=GC+1,glist(GC)=GLO
Kill ^%utility($j)
M ^%utility($j)=glist

1.2 エクスポート処理

1.2.1 ブロック形式のエクスポート (%GOF 相当):

Set flag=$$main^%Wgs("FILE.GOF:(""WNU"")",7,"Header Comment",0,0)

1.2.2 レコード形式のエクスポート, Caché ストリーム形式ファイルフォーマット (%GO 相当):

S RM=80
Set flag=$$main^%Wgs("FILE.GSA:(""WNS"")",5,"Header Comment",0,0)

1.2.3 レコード形式のエクスポート, Caché 可変長レコード形式ファイルフォーマット (%GO 相当):

S RM=80
Set flag=$$main^%Wgs("FILE.GSA:(""WNV"")",5,"Header Comment",0,0)

2. グローバルインポート方法

2.1 ブロック形式のグローバルインポート (%GIF 相当) 全グローバル

s file="FILE.GOF"
k ^%utility($j)
s IO=0
s header=$$header^%Wgr(file_":(""RU"")",7,0)
f i=2:1 s glo=$p($p(header,$c(1),i),$c(19)) q:glo="" s ^%utility($j,glo)=""
s flag=$$main^%Wgr(file_":(""RU"")",7,"*",0,0,0)
k ^%utility($j)

2.2 ブロック形式のグローバルインポート (%GIF 相当) 選択グローバル

k ^%utility($J)
s ^%utility($J,"Global1")="" ; ノード部にグローバル名( ^ は不要)を設定します
s ^%utility($J,"Global2")=""
s IO=0
s header=$$header^%Wgr("FILE.GOF:(""RU"")",7,0) ; (A)
s flag=$$main^%Wgr("FILE.GOF:(""RU"")",7,"*",0,0,0)

(ここで FILE.GOF がファイル名です。ファイル名は絶対パスで指定してください)

k ^%utility($J)

選択グローバルをインポートするには、以下の内容で "*"となっている部分をインポートする
グローバルのリスト($c(13,10)デリミタ)に置き換えてください。

例:

"^A*"_$c(13,10)_"^Dictionary"を指定すると、A から Dictionary までのすべてのグローバルがインポートされます。これにさらに制限をかけることができます。リストア対象グローバルは、^%utility($j グローバルでも指定する必要があります。

また、(A)の部分で取得したheaderにグローバルリストが格納されているので、そこから選択を行うことも可能です。

2.3 レコード形式ファイルのグローバルインポート, Cachéストリームファイル形式 (%GI 相当) 全グローバル

s IO=0
s flag=$$main^%Wgr("FILE.GSA:(""RS"")",5,"*",0,0,0)

補足: エラーが発生する場合は、 ("RS") パラメータを省略してください。

2.4 レコード形式ファイルのグローバルインポート, Caché 可変長ファイル形式 (%GI 相当) 全グローバル:

s IO=0
s flag=$$main^%Wgr("FILE.GSA:(""RV"")”,5,"*",0,0,0)

| Back to Top

Caché5.1.x~Question : 154

プログラムからグローバルのインポート/エクスポート処理を呼び出すことはできますか?(V5.1以降)

V5.1以降では、以下の様な方法で、グローバルのインポート/エクスポート処理をプログラムに組み込むことができます。

1. グローバルエクスポート方法

1.1 XML形式でのエクスポート

グローバルをXML形式のファイルにエクスポートする場合、$system.OBJ.Export() を使用します。

1.1.1. 指定したグローバルをエクスポートする場合

エクスポート対象グローバルを グローバル名.gbl で指定します(先頭の ^ は不要)。

例:

do $system.OBJ.Export("a.gbl,b,gbl","c:\temp\globals.xml",,.errors)

結果については、errors に格納されます。$system.OBJ.Export() の詳細はクラスリファレンス %SYSTEM.OBJ を参照してください。

1.1.2. ネームスペース内の全グローバルをエクスポートする場合

%SYS.GlobalQueryクラスでグローバル一覧を取得し、それを $system.OBJ.Export() に渡してエクスポートを実行します

例:

Set rs=##class(%ResultSet).%New("%SYS.GlobalQuery:NameSpaceList")
Do rs.Execute()
kill globals
While rs.Next() {
    set globals(rs.Get("Name")_".gbl")=""
}
Do $system.OBJ.Export(.globals,"c:\temp\allglobal.xml",,.errors)

(ここでは簡略化のためエラーチェックは省略しています)

1.2. ブロック形式でのエクスポート(%GOFユーティリティと同等)

ブロック形式でグローバルをエクスポートするには、クラス %Library.Global のメソッドExport() を使用します。エクスポート対象グローバルは、1.1.1と同じ形式で指定します。

各引数の詳細はクラスリファレンスを参照してください。

例:

USER>set status=##class(%Library.Global).Export(,"a.gbl,b.gbl","c:\test.gof",7)

GO/GOF形式でエクスポートの開始 07/23/2008 17:01:03
グローバルをエクスポート中: ^a
グローバルをエクスポート中: ^b
エクスポートが正常に完了しました。

USER>

2. グローバルインポート方法

2.1 XML形式ファイルのインポート

2.1.1 ファイルに含まれる全グローバルをインポートする

XMLファイルに含まれる全グローバルをインポートするには $system.OBJ.Load() を使用します。

例:

do $system.OBJ.Load("c:\temp\globals.xml",,.errors)

2.1.2 ファイルに含まれるグローバルのうち一部のみをインポートする

XMLファイルに含まれる一部のグローバルのみ選択してインポートする場合、一旦$system.OBJ.Load() で 第5引数の listonly を 1 に設定してXMLファイルを読み込み、第4引数(出力引数)で得られたリストからインポート対象を選択して第6引数で指定します。

例:

Set file="c:\temp\globals.xml"
// まずXMLに含まれるアイテム一覧を取得
Do $system.OBJ.Load(file,,.errors,.list,1 /* listonly */)
Set item=$Order(list(""))
kill loaditem
While item'="" {
    If item["Sample" {          // Sample を含むもののみインポート
        Set loaditem(item)=""	
        Set item=$Order(list(item))
    }
}
// 作成されたリストでインポート処理実行
Do $system.OBJ.Load(file,,.errors,,,.loaditem)

2.2 ブロック形式でのインポート(%GIFユーティリティと同等)

ブロック形式でエクスポートされたグローバルをインポートするには、$system.OBJ.Load() またはクラス %Library.Global の Import() メソッドを使用します。

ファイル中の特定のグローバルのみインポートする場合は、2.1.2と同じ方法が使用できます。

例1:

USER>d $system.OBJ.Load("c:\test.gof")

ロード開始 07/23/2008 17:01:49
ファイル c:\test.gof を gbl としてロード中
インポートしたグローバル: ^a
インポートしたグローバル: ^b
ロードが正常に完了しました。

USER>

例2:

USER>set status=##class(%Library.Global).Import(,"*","c:\test.gof",7)  

| Back to Top

Question : 155

プログラムからルーチンをインポート/エクスポートすることはできますか?

ルーチンエクスポート/インポート方法

1. エクスポート方法

a. ルーチンを個別に指定してエクスポートする場合は、$system.OBJ.Export() を使用します。

例:

do $system.OBJ.Export("TEST1.mac,TEST2.mac","c:\temp\routines.xml",,.errors)

指定する形式は ルーチン名.拡張子 で、拡張子は mac,bas,int,inc,obj を指定します。

エクスポート中のエラーは errors に格納されます。$system.OBJ.Export() の詳細はクラスリファレンス %SYSTEM.OBJ を参照してください。

b. ワイルドカードを使用してエクスポートする場合は、$system.OBJ.ExportPattern() を使用します。

例:

do $system.OBJ.ExportPattern("*.mac",c:\temp\allmacroutines.xml")

(Cache2008.1より、$system.OBJ.Export() でもワイルドカードが使用できるようになりました)

2. インポート方法

a. ファイルに含まれる全ルーチンをインポートする

ファイルに含まれる全ルーチンをインポートするには $system.OBJ.Load() を使用します。

例:

do $system.OBJ.Load("c:\temp\routines.xml",,.errors)

b. ファイルに含まれるルーチンのうち一部のみをインポートする

XMLファイルに含まれる一部のルーチンのみ選択してインポートする場合、一旦 $system.OBJ.Load() で、第5引数の listonly を 1 に設定してXMLファイルを読み込み、第4引数(出力引数)で得られたリストからインポート対象を選択して第6引数で指定します。

例:

Set file="c:\temp\routines.xml"
// まずXMLに含まれるアイテム一覧を取得   	
Do $system.OBJ.Load(file,,.errors,.list,1 /* listonly */)
Set item=$Order(list(""))
kill loaditem
While item'="" {
    If item["Sample" Set loaditem(item)="" {    // Sample を含むもののみインポート
                  Set item=$Order(list(item)
    }
}
// 作成されたリストでインポート処理実行
Do $system.OBJ.Load(file,,.errors,,,.loaditem)

| Back to Top

Question : 165

for文のスペースに関するよくある間違い

Cachéの場合、for文の条件式と波カッコの間は、スペースが必要です。

main()[a] PUBLIC
{
//for i=1:1:10{  ←誤:10と{の間にスペースが必要 
for i=1:1:10 { 
set a(i)="data"_i
write a(i),!
}
quit
}

| Back to Top

Question : 176

ファイルを読み込んだ際にファイルの終端を判断する方法を教えて下さい。

以下の2つの方法があります。

1) $ZTRAP を使用して、 <ENDOFFILE> をトラップします (既定の動作)

2) 終端に $ZEOF を設定し、$ZEOF が現れるまでファイルを読み続けます。

既定では、<ENDOFFILE> エラーは有効に設定されており、1)によりファイルの終端を判断することになります。

1) のサンプルをご紹介します。

  kill file,i,x
  set $ZT="EOF"		;; jump to EOF when the error happened
  set file="C:\temp\a.txt"
  open file:"R"		;; Read mode
  use file
  for i=1:1 {
     read x(i)		;; Read each line
  }
EOF
  close file		;; jump here
  write "END!!",!
  zw x

| Back to Top

Question : 179

Cachéの変数等に命名規約のようなものは、ありますか?

守らなければならない規則の様なものはありません。

しかし、チームで開発を行なう際には、何らかの命名規約を作ることをお勧めします。

一般的には、変数名から使用目的が容易に想像できる様な名前付けが好ましいです。

名前の長短で実行性能には、有意な差はないと考えて結構ですので、一目見て内容が理解しやすく、他の名前と明確な区別ができるよう、ある程度の長さを持った命名を心がけることをお勧めします。

また、先頭のアルファベットを大文字にする、単語の先頭は大文字にするというのが一般的です。

しかし、昨今は、Javaで良く使われる、先頭は小文字で初めて、途中の単語の始まりを大文字にするという命名規約を使う開発者も増えてきました。

さらに変数のタイプ(一時変数、パラメータなど)がわかるように、先頭の文字で表現する方法もよく使われます。

(例: tSC,pLengthなど)

| Back to Top

Caché2007.1.x~Question : 185

関数、メソッドを呼び出す際に可変数引数を渡すことはできますか?

引数名の後ろに...をつけることで可変数の引数を実装可能です。

Cachéでは、配列を使って任意の数の引数を渡すことができます。

以下にサンプルのクラス実装を示します。

Class TEST.ARGTEST1 Extends %RegisteredObject {
ClassMethod NewMethod1(Arg... As %String) As %Boolean { kill ^a merge ^a = Arg }
}

このクラスをコンパイルして、Cachéターミナルで確認してみます。

TEST>DO ##class(TEST.ARGTEST1).NewMethod1(1,2,3,4,5)
TEST>ZWRITE ^a
^a=5
^a(1)=1
^a(2)=2
^a(3)=3
^a(4)=4
^a(5)=5

| Back to Top

Question : 186

ターミナルでプログラム実行を行なってエラーが発生したあと、プロンプトを元に戻す方法は?

ターミナルでルーチンを実行し、プログラム上でエラーが発生した場合に、エラートラップを適切に設定していない場合、以下のようなデバッグモードになります。

USER>d ^error1
 w A
 ^
<UNDEFINED>a+2^error1 *A
USER 2d0>

この状態から、ルーチン起動の前の状態に戻るには、Quitコマンドを入力します。

USER 2d0>Quit

また、エラーが発生したルーチン内でトランザクション処理を行なっている場合には、以下のような表示のプロンプトになります。

USER>d ^error1
 w A
 ^
<UNDEFINED>a+3^error1 *A
TL1:USER 2d0>q
TL1:USER>

このようにプロンプトの先頭にTL+数字が表示されている場合には、完了していないトランザクションがあることを示しています。

この状態では、Quitコマンドを入力しても元のプロンプトには戻りません。

最初にTrollbackコマンドを入力し、その後でQuitコマンドを実行することで元のプロンプトに戻ります。

TL1:USER>Trollback

| Back to Top

Question : 187

Killコマンドの実行に関して、確認のメッセージを出す仕組みはありますか?

Killコマンドに対して確認のメッセージを出す仕組みは用意されていません。

確かにKillコマンドの誤用(あるいは悪意による意図的操作など)は、お使いのシステムに致命的な影響を与える可能性がありますので、その様な危険性を排除するためには、セキュリティ設定の強化により、その様な操作を手作業で実施できる人間を制限するなどの措置を取られることをお勧めします。

| Back to Top

Caché2008.2.x~Question : 209

Cachéで文字列を置換するにはどうすれば良いですか?

Caché Basicでは、Replace関数を使って、文字列の置換が実現できます。

Caché ObjectsScriptでは、2008.2以降、$Replace関数というBasicと同等機能が実装されました。

| Back to Top