VBを用いてCGIを作るために最低限必要なのは「標準出力」である。逆に言えば、VB自体にこの機能が付いていないから苦労するのであって、ここさえクリアすれば後はどうって事はない。標準出力と標準入力はペアなので、ここでは双方を説明しておく。重要なのはまず標準出力だろう。これがなければプログラム処理結果を表示させることができない。文字列をテキストエリアに入れたり、アップロードファイルを指定させて、POSTさせるとなると「標準入力」も必要になってくるが、まあ、最初は別に使うことはないだろう。
標準入出力を行うためには、API関数を使わなければならない。ステップとしては、とても簡単で、まずAPIを使い標準入出力用のファイルハンドラを取得し、その後、ファイルハンドラを使い入出力を実行するだけだ。入出力においては、バッファ用の文字列変数を用いて、一気に読み書きしてしまえば良い。実際に、宣言部と実行部のプログラム例を示しておこう。
Private Declare Function GetStdHandle Lib "kernel32" (ByVal nStdHandle As Long) As Long
Private Declare Function ReadFile Lib "kernel32" _
(ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, _
lpNumberOfBytesRead As Long, lpOverlapped As Any) As Long
Private Declare Function WriteFile Lib "kernel32" _
(ByVal hFile As Long, ByVal lpBuffer As String, ByVal nNumberOfBytesToWrite As Long, _
lpNumberOfBytesWritten As Long, lpOverlapped As Any) As Long
Const STDIN_HANDLE = -10&
Const STDOUT_HANDLE = -11&
APIの宣言は3つあり、標準入出力ハンドラを取得する「GetStdHandle」と、読み取りを行う「ReadFile」と、書き込みを行う「WriteFile」である。定数は2つだが、これらは標準入出力ハンドラを取得するAPIに渡すためのものである。
宣言が出来ているとして、標準出力の実行部プログラムを例示する。ここでは、Bufferという文字変数に格納されている文字列を送り出すものとしている。この例示では、Bufferの中身は空なので、動くはずはない。実際のプログラミングにおいては、送り出す文字列を引数にしたファンクションかサブルーチンにすれば良いであろう。
Dim Std_Hdl As Long
Dim Written_Bytes As Long
Dim API_Result as Long
Dim StdOut_Length As Long
Dim Buffer As String
StdOut_Length = LenB(StrConv(Buffer, vbFromUnicode)) + 2
Std_Hdl = GetStdHandle(STDOUT_HANDLE)
API_Result = WriteFile(Std_Hdl, Buffer, StdOut_Length, Written_Bytes, ByVal 0&)
変数名は変更しても構わない。処理終了後、APIの戻り値と、書き込み済のバイト数が確認できる。大抵は問題無く動くし、ここでエラーが生じたとして、恐らくはWWWサーバ側がエラー値を戻すことになるので、エラートラップは設置しなくても構わないと考えている。えらく簡単にできてしまうもんだ。
さて、ついでと言っては何だが、標準入力の実行部も例示しよう。環境変数から「Content-Length」の値を持ってきて、これが0でなければ標準入力がある、と認識して動くようにすれば良い。出力と同様、Bufferという文字変数に標準入力値を入れるようにする。例によって、プログラムの例示。
Dim Std_Hdl As Long
Dim Read_Bytes As Long
Dim API_Result as Long
Dim StdIn_Length As Long
Dim Buffer As String
StdIn_Length = Environ("CONTENT_LENGTH")
If StdIn_Length > 0 Then
Buffer = Space(StdIn_Length)
Std_Hdl = GetStdHandle(STDIN_HANDLE)
API_Result = ReadFile(Std_Hdl, Buffer, StdIn_Length, Read_Bytes, ByVal 0&)
Else
Buffer = ""
End If
とまあ、こんな感じになる。大雑把に言って、標準出力とほとんど同じ様なものである。
なお、ファイルのアップロードなどを行う場合は、バイナリ変数の配列を指定することも必要な場合がある。この場合は、上記の「Dim Buffer As String」の代りに「Dim Buffer() As Byte」と「Redim Buffer(StdIn_Length)」を用いてやり、「ReadFile」中の「Buffer」を「Buffer(0)」としてちょっと改造してやれば動く。もしくは、上記で取得した標準入力文字列をバイト変数の配列領域にコピーする方法もあるだろう(確かAPIで出来たはずだが..忘れた)。
標準出力する文字列の作り方(?)は別項目としてあるので参照して頂きたい。標準入力で得たデータの意味や、扱い方についても、別項目とする。