Xojo で Web アプリ Tips ( Web1.0 )


以下の記述は主に Xojo 2019 r3.1/3.2 のもの。 Xojo 2020 以降は Xojo フレームワークとしての Web2.0 に移行していてかなり相違があることに注意。

# cgi/スタンドアロン/cloud(?) 共通

## 複数のWebアプリを同一ホストで動かす

Application Identifier の値を別個にする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/03b20381-8ddc-5e01-2951-3067e4fc9ff0.png)

サーバに設置する場合、アプリ名が異なっていたとしても標準では config.cfg ファイルが同じ名前のファイルとなるので、競合しないようにしないといけない。アプリごとに別ディレクトリに設置するなど。

# cgi として動かすノウハウ


（2023/1/18追記）
cgi はこれより後の Xojo ではサポートされなくなり、また Xojo 2019 R3.2 の時代においても不安定。
安定稼働するには cgi 以外を選択する必要がある。



## デプロイするには

Help - License Keys でライセンスを通しておく。

Deployボタンは Xojo Cloud 用。自前のサーバで動かす場合はBuildボタンを押す。
Buildボタンが押せない場合は左側の「Build Settings」でターゲットを選ぶ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/42b5c072-30e7-0d9d-8bee-ae251beda62c.png)

今回は、Ubuntu Linux 18.04で動かすのでLinuxを選択する。

Buildすると以下のようなファイルができるので、フォルダごと圧縮してサーバに転送。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/8451af18-8adb-d8dd-0df6-220b1f31321c.png)



## 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 ファイル名になる。
ここで日本語を指定したがうまく動かないようだ。

Windowsでビルド、Linuxに転送した場合。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/410335e0-5532-fe97-8af7-2e0219f50493.png)

IDEからの実行や、リモート実行時には問題ないが、cgi として動作できない。

また、Linux では Linux app Name が日本語の場合ビルドしても cgi ファイルが生成されない。

プロジェクト名が日本語、Linux app Name が英語の場合は cgi ファイルが生成されるが実行時にエラーとなる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/2fbb8132-129e-0b69-3964-6a499e4a74f3.png)



## Raspberry Pi を サーバにして cgi で動かす場合

### Raspberry Pi の設定

確認は以下の環境で行っています

- Raspbian GNU/Linux 10 (buster)
- Raspberry Pi 3 Model B

「Ubuntu 18.04 サーバで cgi として動かす設定」


### アプリのビルド

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/e6f6af35-1019-7c0d-25d3-d3d396af5fcc.png)

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
```
とすると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/7ae2bb7b-f1eb-67fb-f33c-12c450f527a2.png)

となる。
WebStyleの作り方は別掲。

## WebListBox に追加した行を取得

Desktop の ListBox だと LastAddedRowIndex ですが、Web だと該当のものが無いので LastIndex で代用
# その他UI


## Control を配列にする

同じ名前にすると配列にしてくれる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/f92c404b-56e9-85eb-20bb-624fdd3a18dc.png)

## WebTextのフォント属性

フォントサイズやテキストカラーなどは、Desktopアプリのようには指定できない。代わりにスタイルを設定して適用する。

## WebStyle の設定

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/cdd3e705-3eb8-09bc-ddc5-b1a7d2cf31b1.png)

Project Items から Style (カラーチップのアイコン)を選び、 Contentsペインにドラッグします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/e12aaf83-0bd2-85a8-b513-d64d1936312a.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/31f49ce6-49d5-5597-2ce6-04c154919671.png)
Add Property を押して必要な属性を設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/2ebc647b-8560-ce9a-dc7a-052958f70a6d.png)


## 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でした。

## 実行パス

何と、 "/"

# トラブルシューティング

## End of script output before headers

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

## DB 出力の浮動小数点の誤差

Mysql/mariadb で double/float などの値を受け取ると以下のようになる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/e242ae8f-25d2-41ea-ba4d-4c80237290c8.png)

コードは以下のようにしている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/5a425d37-943f-4039-b151-379ef334aec7.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/970a6c7a-69cf-4891-bf10-744f9b9e48f6.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/830483ce-91f2-4db8-ace3-f32102952cd7.png)


これを解決するには、SQL文を変更。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/e46f9588-2969-44b0-b30a-7bf1e1193ff4.png)
うまくいきました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/88578413-c434-4e23-90a1-57e699fc1a78.png)