以下の記述は主に Xojo 2019 r3.1/3.2 のもの。 Xojo 2020 以降は Xojo フレームワークとしての Web2.0 に移行していてかなり相違があることに注意。
cgi/スタンドアロン/cloud(?) 共通
複数のWebアプリを同一ホストで動かす
Application Identifier の値を別個にする
サーバに設置する場合、アプリ名が異なっていたとしても標準では config.cfg ファイルが同じ名前のファイルとなるので、競合しないようにしないといけない。アプリごとに別ディレクトリに設置するなど。
cgi として動かすノウハウ
(2023/1/18追記)
cgi はこれより後の Xojo ではサポートされなくなり、また Xojo 2019 R3.2 の時代においても不安定。
安定稼働するには cgi 以外を選択する必要がある。
デプロイするには
Help - License Keys でライセンスを通しておく。
Deployボタンは Xojo Cloud 用。自前のサーバで動かす場合はBuildボタンを押す。
Buildボタンが押せない場合は左側の「Build Settings」でターゲットを選ぶ。
今回は、Ubuntu Linux 18.04で動かすのでLinuxを選択する。
Buildすると以下のようなファイルができるので、フォルダごと圧縮してサーバに転送。
Ubuntu 18.04 サーバで cgi として動かす設定
apache2 をあらかじめインストールしておく。
先の圧縮ファイルを例えば /var/www/html/test に展開して、そこで動かしたいとする。
apache の cgi モジュールをインストール
$ sudo a2enmod cgid
今回は、 /var/www 以下全てで CGI が動作するようにしました。
$ sudo vim /etc/apache2/apache2.conf
・・・
<Directory /var/www/>
Options Indexes FollowSymLinks
AllowOverride None
Require all granted
</Directory>
・・・
↓
・・・
<Directory /var/www/>
Options Indexes FollowSymLinks execCGI
AddHandler cgi-script .cgi .pl
AllowOverride None
Require all granted
</Directory>
・・・
今回は、サーバでcgiだけしか動かさないので /etc/apache2/apache2.conf に記述したが、そうでなければ /etc/apache2/conf-available/cgi-enabled.conf などでディレクトリ指定をするのが望ましい。
ブラウザで、http://(サーバIPアドレス)/test を開けたら index.cgi が動作するように設定します。Ubuntu 18.04では既に設定されていたので確認だけ。
$ sudo vim /etc/apache2/mods-enabled/dir.conf
以下のように設定されていました。
・・・
<IfModule mod_dir.c>
DirectoryIndex index.html index.cgi index.pl index.php index.xhtml index.htm
</IfModule>
・・・
変更の反映
$ sudo service apache2 reload
Ubuntu 18.04 サーバに設置する場合のアプリファイルの設定
/var/www/html/test に展開しました。
$ cd /var/www/html/test
アクセス権限を設定します。
$ sudo chown -R www-data:www-data *
$ sudo chmod 705 mysqlwebtest.cgi
$ sudo chmod 705 MySQLWebTest
http://(サーバIPアドレス)/test で動作するようにします。
$ sudo mv mysqlwebtest.cgi index.cgi
アプリ名の制限
アプリ名は標準ではプロジェクト名が引き継がれる。アプリ名を
Build settings の Linux App Name で指定した名前が cgi ファイル名になる。
ここで日本語を指定したがうまく動かないようだ。
IDEからの実行や、リモート実行時には問題ないが、cgi として動作できない。
また、Linux では Linux app Name が日本語の場合ビルドしても cgi ファイルが生成されない。
プロジェクト名が日本語、Linux app Name が英語の場合は cgi ファイルが生成されるが実行時にエラーとなる。
Raspberry Pi を サーバにして cgi で動かす場合
Raspberry Pi の設定
確認は以下の環境で行っています
- Raspbian GNU/Linux 10 (buster)
- Raspberry Pi 3 Model B
「Ubuntu 18.04 サーバで cgi として動かす設定」
アプリのビルド
Build Settings の Linux を選び、 Inspector で Architecture を ARM 32-bit を選びます。
アプリファイルの設定
「Ubuntu 18.04 サーバに設置する場合のアプリファイルの設定」
と同じ設定で動きました。
Raspberry Pi
デプロイをUSBメモリで
Windowsで作ったバイナリをRaspberryPiなどにデプロイする時、USBメモリを使うやり方。
USBメモリに作成したファイルをコピーしてRaspberryPiに刺して電源を入れる。
RaspberryPiではDocumentRootをUSBメモリにしておいて、そのままUSBメモリに入ったcgiが動作する。
している。
まず、USBメモリを起動時に /mnt にマウントする。
Raspberry Pi の /etc/rc.local の最後、
exit 0
の手前に
mount -o exec,uid=33,gid=33 /dev/sda1 /mnt
exit 0
と記述。vfat に入っているプログラムは通常実行できないが、実行権をつけてマウント、所有者のユーザ・グループをwww-data/www-data とすることで、cgi として動作するようになっている。当然、vfat なのでアクセス権に依存するプログラムは注意。
次に、apache2 の DocumentRootの設定。
/etc/apache2/apache2.confの
<Directory /var/www/>
Options Indexes FollowSymLinks execCGI
AddHandler cgi-script .cgi .pl
AllowOverride None
Require all granted
</Directory>
を以下のように書き換え
<Directory /mnt/>
Options Indexes FollowSymLinks execCGI
AddHandler cgi-script .cgi .pl
AllowOverride None
Require all granted
</Directory>
Raspberry Pi の GPIO操作
apache2 で cgi で動作させる場合は www-data となるので、通常では GPIO 操作に制限がある。
いろんなやりかたがあるが、セキュリティを特に気にしなくても良い場合は、sudoer に www-data を登録する。
$ sudo visudo
として、最後に
www-data ALL=(ALL) NOPASSWD: ALL
を追加する。
WebListBox
WebListBox の行全部削除
Desktop の ListBox だと RemoveAllRows ですが、WebだとDeleteAllRows
WebListBox のどの行をセレクトしたかを取得する
SelectionChanged イベントに書く
Var id As String
If Me.ListIndex < 0 Then
MessageBox("Please select a row.")
Else
id = Me.Cell(Me.ListIndex, 0)
End If
WebListBox の列数を取得する
Desktop アプリで使う
Listbox.ListCount
の代わりに
Listbox.RowCount
を使う
WebListBox の特定のセルの色を変える
テキストを赤にしたWebStyleを作り、
ListBox1.CellStyle(1,0) = WebStyleTextRed
となる。
WebStyleの作り方は別掲。
WebListBox に追加した行を取得
Desktop の ListBox だと LastAddedRowIndex ですが、Web だと該当のものが無いので LastIndex で代用
その他UI
Control を配列にする
同じ名前にすると配列にしてくれる
WebTextのフォント属性
フォントサイズやテキストカラーなどは、Desktopアプリのようには指定できない。代わりにスタイルを設定して適用する。
WebStyle の設定
Project Items から Style (カラーチップのアイコン)を選び、 Contentsペインにドラッグします
Add Property を押して必要な属性を設定します。
WebImageView
Desktopアプリだと
ImageWell1.Image = thumbnail
となるところが、Webアプリだと
WebImageView1.Picture = thumbnail
となる。
TextField で エンターを検出
WebTextField, WebTextArea and WebSearchField 共通。
Select Case details.KeyCode
Case details.KeyEnter
MessageBox("Enter!")
End Select
注:上記で KeyPressed イベントで動かしていたが、 Xojo 2020 R2.1 では KeyPressed は使えなくなった。代わりに TextChanged を使うが details が使えないのでこの方法は使えない。エンター検出には JavaScript が必要かな。
ブラウザの縦スクロールができない
WebPage1のSizeのMinHeightを増やしておく
プロパティetc
WebSession.ClientTime
返ってくるのはWebサーバの時刻
Command.Execute
LinuxでCommand.Executeするときの改行コード
Dim Command As New Shell
Command.Execute("echo "+id+" >> log")
MsgBox(Command.Result)
としたところ、log の改行コードはlfでした。
実行パス
何と、 "/"
トラブルシューティング
RaspberryPiで実行したら、以下のようなエラーが出た
[Sat Apr 25 17:18:16.790080 2020] [cgid:error] [pid 450:tid 1858057248] [client 192.168.162.19:56411] End of script output before headers: mysqlwebcardwrite.cgi, referer: http://192.168.162.77/
Can't use an undefined value as a symbol reference at /mnt/MySQLWebCardWrite/mysqlwebcardwrite.cgi line 118.
はてなーと思っていたら何もしてないのにそのまま動くようになった。
起動に時間がかかっていたようだ。
(2021/05/18追記)
Webアプリをcgiで動かす時に、結構これが発生する。
別インスタンスで XOJO Web アプリが動いている場合にこれが発生しやすいようだ。
スタンドアローン Web アプリだとこのような問題は発生しない。
cf., 「Xojo で スタンドアローン Web アプリを RaspberryPi で動かす」
https://qiita.com/nanbuwks/items/615a929babca8986e634