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関数を使っていました。早速プリプロセッサの定義を直し、解決しました。
プロバイダがOraOLEDB.Oracle.1なら可能みたい。
MSDAORA.1ではできなかった。
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なので、その値をパラメータとして渡す場合は、プロシージャ側で初期値を設定しておくのがお勧めである。
※ プロシージャ側でデフォルト値が指定されていないパラメータを省略すると実行時エラーになってしまう。
プロシージャの中身は、こんな感じ(実際に使ったものをいろいろ省略したため変なプロシージャだが)
一定秒後に指定したページにジャンプさせるためのメタタグはこのように書く。
<meta http-equiv="Refresh" content="0; url=http://frog.raindrop.jp" />同じように、HTTPヘッダでREFRESHを吐き出すと、同じ動作をさせることができる。
<%ただし、若干UAによって動作が違うらしい。
Call Response.AddHeader("REFRESH", "0; url=http://frog.raindrop.jp")
%>
お決まりのヘッダです。わたしは、これをたとえば"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 %>
ログイン者が登録された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
VBでASPからコールするActiveX DLLやActiveX EXEを作成する場合のポイントらしきものです。
ASPで使用するスクリプト言語は型がありません。したがって
以下の2つに参照設定を行って、ASPからと同じように、Response.Writeでクライアントへの出力を行ったり、Request.ServerVariablesで環境変数を取得したりすることができます。
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で作成することはできません。
Oracleのビューを使用するのように、Oracleのリンクサーバーを作成して、それを使用して更新処理を行う場合に、こんなエラーをよく目にします。
-2147217900(0x80040E14)このエラーが出る要因は、調べた限り、以下のものがありそうです。
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の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のオブジェクトを指定する場合は、リンクサーバー名..スキーマ.オブジェクト、となります。(要はカタログ部がないのね)
「006~ASP 0231~Server.Execute エラー~無効な形式の URL または完全認証されている絶対 URL が使用されました。相対 URL を使用してください。」に悩まされること半日、Server.Executeメソッドで、パスパラメータにクエリ文字列が使えるってのはウソ!ってな情報 [Microsoft Windows 2000 Serverドキュメント]を得ました。
正確にはこうらしいです
Server.Execute を呼び出す .asp ファイルで利用できる QueryString は実行 .asp ファイルで利用できるので、Server.Execute のパス パラメータに含まれる QueryString を渡す必要はありません。ただし、Path パラメータに含まれる別のクエリー文字列を渡すことはできません。
HTMLを出力するサンプルは巷にあふれているんだけど、XHTMLとして出力する方法がなかなかわからなかったので、サンプルを作ってみました。ついでなんで、XHTMLにネームスペースのプリフィックスをつける例としてみました。
(もちろん、stylesheetのところで宣言しているXHTMLのプリフィックス":xhtml"を省略し、namespase-alias指定を削除すると、通常のXHTMLのようにかけます)
ポイント(というほどのことでもないけど)は、outputでmethod="xml"にすることでしょうか。
ただし、これを使用してMSXMLで変換をかけると、xml宣言がencoding="UTF-16"固定になってしまいます。形だけでも"Shift_JIS"で出てほしいものです。
(多分、COMコンポーネントなので、出力はユニコードだから、ってことなんだろう、と解釈)
1> SELECT CONVERT(CHAR(8),GETDATE(),112)
2> go
--------
20031104
(1 件処理されました)