< October 2003 | November 2003 | December 2003 >

November 30, 2003

外部シンボル "_main" は未解決です

ATL COM AppWizard でActiveX DLLを作成して、DebugでビルドしてVBで作ったチョンプロからコールしてOK、よし、Releaseビルドだ!と、アクティブな構成の設定で「Win32 Release MinDependency」を選択してビルドするとこんなエラーがでました。

LIBCMT.lib(crt0.obj) : error LNK2001: 外部シンボル "_main" は未解決です
ReleaseMinDependency/PrivateProfiles.dll : fatal error LNK1120: 外部参照 1 が未解決です。
link.exe の実行エラー

PrivateProfiles.dll - エラー 2、警告 0

Debugビルドでは通っていたので、なにかビルドの設定だろうとは思うのですが、よく分かりません。こういうときは、同じようなエラーの情報がないか、検索してみるに限ります。basp21のBabaさんのサイトにそのものズバリの情報がありました。以下はCOM プログラミング2[Baba Centerfolds]からの引用。

このエラーは、Cランタイム関数がリンクされていないときに発生します。
Cのランタイム関数をプロジェクト内で使っていると発生します。
ReleaseビルドのデフォルトではATL COM AppWizardは、Cランタイムをリンクしません。
これは、_ATL_MIN_CRTプリプロセッサ文字が指定されているためです。
対策としては:
●[プロジェクトの設定] -[C/C++]-[プリプロセッサの定義]で_ATL_MIN_CRTを削除
こうするとCのランタイムがリンクされてエラーが消えます。

ふむふむ。確かに、LocalFree関数を使っていました。早速プリプロセッサの定義を直し、解決しました。

November 27, 2003

ADOでOracleのバインド変数つきPL/SQLを実行する

プロバイダがOraOLEDB.Oracle.1なら可能みたい。
MSDAORA.1ではできなかった。

November 26, 2003

ADOでストアドを使う

ASPで書くのが面倒な処理はDB側でプロシージャにしておくと便利な場合がある。

MSDEでプロシージャを作ってASPから呼び出してみた。

'ASP
Dim adoCmd
Set adoCmd    = Server.CreateObject("ADODB.Command")
With adoCmd
    .CommandText                    = "pCheckValid"
    .CommandType                    = adCmdStoredProc
    Set .ActiveConnection           = adoConGRDB
    .Parameters("@emp_cd")          = strEmpCd
    .Parameters("@require_admin")   = "1"
    Call .Execute()
End With
If Not IsNull(adoCmd.Parameters("@ret_msg")) Then
    Call Response.Write(adoCmd.Parameters("@ret_msg"))
    Set adoCmd    = Nothing
    Exit Sub
End If

ポイントは、CommandText, CommandTypeを設定後にActiveConnectionを設定すること。そうしないと、パラメータがうまくバインドしない。(なんで?)

ちなみに、パラメータにEmptyを渡すとそのパラメータは「省略された」物として扱われる。ASPのCOOKIEやRequest.Formなどの初期値もEmptyなので、その値をパラメータとして渡す場合は、プロシージャ側で初期値を設定しておくのがお勧めである。

※ プロシージャ側でデフォルト値が指定されていないパラメータを省略すると実行時エラーになってしまう。

プロシージャの中身は、こんな感じ(実際に使ったものをいろいろ省略したため変なプロシージャだが)

続きを読む...

November 25, 2003

Refreshヘッダ

一定秒後に指定したページにジャンプさせるためのメタタグはこのように書く。

<meta http-equiv="Refresh" content="0; url=http://frog.raindrop.jp" />
同じように、HTTPヘッダでREFRESHを吐き出すと、同じ動作をさせることができる。
<%
Call Response.AddHeader("REFRESH", "0; url=http://frog.raindrop.jp")
%>
ただし、若干UAによって動作が違うらしい。
また、ヘッダとして出力する場合は、当然、コンテンツの出力の前に出力する必要がある。
(メタタグはbody要素の後ろにまたhead要素を作って、その中に書いてもちゃんと効くみたい。私はASPで「実行中...」などと画面に出しておき、処理完了後にメタタグで画面遷移、なんてことをしている。)
あと、REFRESHヘッダはRFCにはない。

November 21, 2003

ブラウザのキャッシュを無効にする

お決まりのヘッダです。わたしは、これをたとえば"nocache.asp"などとして保存しておき、

Call Server.Execute("./nocache.asp")

などとしています。

<%@ Language=VBScript %><%
	'@@ キャッシュを無効にする
	With Response
		Call .AddHeader("Pragma", "no-cache")
		Call .AddHeader("Cache-control", "no-cache")
		.Expires = 0
		.CacheControl = "Private"
	End With
%>

テーブルを返すFUNCTION

ログイン者が登録されたIPからログインしたときのみレコードを返すFUNCTIONを作ったのですが、結局IPのチェックが仕様から外れたため使わなくなったので、ここに挙げておくことにします。

使用する表はこんな感じ。端末表は、IPとネットマスクを持っていて、マスク後の値と比較します。

社員表 EMP_TBL
COLUMN      TYPE         PRIMARY
----------- ------------ -------
emp_cd      CHAR(6)      TRUE
password    CHAR(12)     
valid_from  CHAR(8)      TRUE
valid_to    CHAR(8)
section_cd  CHAR(7)
admin_flg   CHAR(1)
emp_name    VARCHAR(24)

端末表 EMP_TERM_TBL
COLUMN      TYPE         PRIMARY
----------- ------------ -------
emp_cd      CHAR(6)      TRUE
valid_from  CHAR(8)      TRUE
term_ip     CHAR(15)     TRUE
term_mask   CHAR(15)     TRUE
続きを読む...

November 19, 2003

ASPからコールするCOMコンポーネント

VBでASPからコールするActiveX DLLやActiveX EXEを作成する場合のポイントらしきものです。

  1. データ型

    ASPで使用するスクリプト言語は型がありません。したがって

    • 引数はByValで
    • ByRefで渡す引数はVariantに
    と言う感じにします。
  2. プロジェクトのプロパティ
    • 「対話型インターフェースの抑制」にチェック
    • 「メモリに保持」にチェック
    • スレッドモデル
      • スコープがApplication---シングル スレッド
      • スコープがSession-------アパートメントスレッド
      で作成します。このあたり、VC++で作成すると「Both」が選択できた気がしますが、VBでそれに当たるのはないのかな?
  3. ASP組み込みオブジェクトへのアクセス

    以下の2つに参照設定を行って、ASPからと同じように、Response.Writeでクライアントへの出力を行ったり、Request.ServerVariablesで環境変数を取得したりすることができます。

    • COM+ Services Type Library(Win2K以降の場合。9xやNTは)
    • Microsoft Active Server Pages Object Library

    ASP組み込みオブジェクトにアクセスするには、GetObjectContextメソッドを使います。Responseオブジェクトを例に取ると

    Dim aspResponse         As ASPTypeLibrary.Response
    
        Set aspResponse = GetObjectContext("Response")
        Call aspResponse.Write("Hello ASP!")
    		

    と言うような感じです。このとき、クラスのMTSTransactionModeプロパティが、"NotAnMTSObject"ではうまくいきませんでした。"Uses Transaction"にするとうまくいきましたが、どういう値であるべきかまでは調べていません。

    また、この処理を、Class_Initiarizeプロシージャに記述したオブジェクトを、Global.asa内で生成したり、アプリケーションスコープのobjectタグで宣言すると、うまく動作しないようです。

(04/01/24 追記)

Applicationスコープにするには、スレッドモデルがBothまたはNeutralのコンポーネントを作成する必要があります。つまり、VBで作成することはできません。

November 18, 2003

分散トランザクションを開始できないエラー

Oracleのビューを使用するのように、Oracleのリンクサーバーを作成して、それを使用して更新処理を行う場合に、こんなエラーをよく目にします。

-2147217900(0x80040E14)
Microsoft OLE DB Provider for SQL Server
OLE DB プロバイダ 'MSDAORA.1' は分散トランザクションを開始できなかったので、要求した操作は実行されませんでした。

このエラーが出る要因は、調べた限り、以下のものがありそうです。

  1. MSDTCが起動していない
  2. MtxOCI.dllが読み込めない
  3. トランザクションをネストしている(?)

1は、コントロールパネル>管理ツール>サービスを開き、Distributed Transaction Coordinatorという項目を探して、サービスが開始されているか確認します。

2は、レジストリの設定が正しいかどうか確認します。ちなみにクライアントがOracle9i Enterprise Edition Release 9.2.0.1.0の場合は以下の値で動作しました。

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSDTC\MTxOCI]
"OracleXaLib"="oraclient9.dll"
"OracleSqlLib"="orasql9.dll"
"OracleOciLib"="oci.dll"

MSDE等には9iに関しての情報がないのですが、インストールされているのはoraclient9.dllなので、まあそれでいいんでしょう。(DLLの名前なんてバージョンごとに変えないでほしいのですが・・・)

Oracleのビューを使用する

OracleのDBサーバとローカルのMSDEを連携しやすくするために、リンクサーバーを使用してビューを作りました。

USE TESTDB
GO
/* リンクサーバーを追加 */
EXEC sp_addlinkedserver
   @server		= 'ORASRV',	/* リンクサーバの参照名。好きにつける。 */
   @srvproduct	= 'Oracle',	/* 固定 */
   @provider	= 'MSDAORA.1',	/* 使用するプロバイダ */
   @datasrc		= 'OraSrv'	/* Netサービス名 */

/* リンクサーバーにログオンできるようにする */
EXEC sp_addlinkedsrvlogin
    @rmtsrvname		= 'ORASRV',	/* さっきつけた参照名 */
    @useself		= 'FALSE',	/* TRUEならSQLServerの認証情報を使用する */
    @locallogin		= 'sa',	/* どのログインで使用するか。NULLなら全ログイン */
    @rmtuser		= 'SCOTT',	/* お約束 */ 
    @rmtpassword	= 'TIGER'	/* これもお約束 */
GO
/* ビューを追加する */
CREATE VIEW EMP AS
SELECT * FROM SPSVR1..SCOTT.EMP
GO

上のように、MSDEからOracleのオブジェクトを指定する場合は、リンクサーバー名..スキーマ.オブジェクト、となります。(要はカタログ部がないのね)

参考

続きを読む...

November 17, 2003

Server.Execute()

「006~ASP 0231~Server.Execute エラー~無効な形式の URL または完全認証されている絶対 URL が使用されました。相対 URL を使用してください。」に悩まされること半日、Server.Executeメソッドで、パスパラメータにクエリ文字列が使えるってのはウソ!ってな情報 [Microsoft Windows 2000 Serverドキュメント]を得ました。
正確にはこうらしいです

Server.Execute を呼び出す .asp ファイルで利用できる QueryString は実行 .asp ファイルで利用できるので、Server.Execute のパス パラメータに含まれる QueryString を渡す必要はありません。ただし、Path パラメータに含まれる別のクエリー文字列を渡すことはできません。

迷惑な・・・。

November 14, 2003

XSLTを使用してXHTMLを出力する

HTMLを出力するサンプルは巷にあふれているんだけど、XHTMLとして出力する方法がなかなかわからなかったので、サンプルを作ってみました。ついでなんで、XHTMLにネームスペースのプリフィックスをつける例としてみました。
(もちろん、stylesheetのところで宣言しているXHTMLのプリフィックス":xhtml"を省略し、namespase-alias指定を削除すると、通常のXHTMLのようにかけます)

ポイント(というほどのことでもないけど)は、outputでmethod="xml"にすることでしょうか。

ただし、これを使用してMSXMLで変換をかけると、xml宣言がencoding="UTF-16"固定になってしまいます。形だけでも"Shift_JIS"で出てほしいものです。

(多分、COMコンポーネントなので、出力はユニコードだから、ってことなんだろう、と解釈)

お題のxml サンプルxsl

続きを読む...

November 4, 2003

日付を整形する

MSDE/SQL Serverで、VBAのFormat関数、あるいはOracleのTO_CHAR関数のような関数は実装されていませんが、日付を整形するにはCONVERT関数が使用できます。
1> SELECT CONVERT(CHAR(8),GETDATE(),112)
2> go

--------
20031104

(1 件処理されました)