Automation Anywhere v11.xのBotファイル「.atmx」の正体

Automation Anywhere v11.xのBotファイルは、ローカルPC上で.atmxという拡張子のファイルになっています。v11.xのBotファイルは構築中も完成後パブリッシュした後も同じひとつの.atmxとなることから、ポータブル性に優れています[^1]。

[^1]: A2019では基本Control Room側にBotファイルが保存されるようになったので大きな方針転換がなされました。

この.atmxファイルですが、特にフォーマットの仕様が公開されているわけではないので、調べてみることにしました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/0983f127-665a-99f2-1a17-a832a67aec9b.png)


# 利用するsample.atmxファイル
前に[RPA Challengeを解いたときのBot](https://qiita.com/RPAbot/items/961e75fcd6fe0b63bfdb)を使います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/ab7285c5-89e5-9c52-369c-41f6d48cf382.png)

ファイルサイズは2,947KBあります。Automation Anywhere Enterprise Clientがインストールされている環境では、.atmxファイルは「Automation Anywhere Task File」として関連付けがされています。

# 実はzip形式、Office Open XML形式/nugetパッケージ形式と酷似
さて、いよいよ.atmxファイルを解析してみましょう。まず、バイナリエディタで.atmxファイルを覗いてみると、最初に「PK...」という文字があることがわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/b64da89e-9c6e-025a-9d19-c57633e7f0a0.png)

これは、実はZIPファイルのファイルヘッダーのシグニチャになっています[^2]。これはつまり、拡張子を.zipに変更してファイルを開くと、中の構造を見られる可能性があります。さっそくファイル名末尾に.zipを追加して、Windowsエクスプローラで展開してみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/5f8722d1-d426-19b9-c69d-3c45ef029277.png)

[^2]: 『[ZIPの仕様を日本語でまとめる](https://gist.github.com/ysakasin/2edf8d3bf55c6ebf63f82851e302b030)』等を参照してください。

すると、案の定、展開された.zipファイルの中身のフォルダーを見ると、以下のファイルが入っていることがわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/1f687347-930b-8aa7-a366-02d035827d3e.png)

この中で特徴的なのは`[Content_Types].xml`というファイルです。これは、Office Open XML形式やnugetパッケージの中に含まれています。今回の場合、ファイルの中身は以下のようになっていました。この中に、含まれているすべてのファイルのファイル形式が記載されています。

```XML:[Content_Types].xml
<?xml version="1.0" encoding="utf-8"?>
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
  <Override PartName="/properties" ContentType="text/xml" />
  <Override PartName="/dependencies" ContentType="text/xml" />
  <Override PartName="/commands" ContentType="text/xml" />
  <Override PartName="/46842abc-843b-40ec-acf6-63473944cc91" ContentType="image/jpeg" />
  <Override PartName="/ca9f9414-dcb4-4809-9a47-17a1b0f8298a" ContentType="image/jpeg" />
  <Override PartName="/42ab84a6-b0fa-4a68-b8ef-8dc812c23709" ContentType="image/jpeg" />
  <Override PartName="/51eda008-f04d-4237-ae30-dd932e1f0621" ContentType="image/jpeg" />
  <Override PartName="/3b2218b7-4622-4d1f-bf41-047574d3a9a5" ContentType="image/jpeg" />
  <Override PartName="/dd278e08-7f50-47e2-a376-08bb25eccf32" ContentType="image/jpeg" />
  <Override PartName="/6ea9ad55-b298-438c-b2f6-81a8d7a2baba" ContentType="image/jpeg" />
  <Override PartName="/12731ae5-7f57-474a-800d-f4e6538cdea9" ContentType="image/jpeg" />
  <Override PartName="/8e0a4c12-eec9-43d2-b9fe-531e1cb65ff2" ContentType="image/jpeg" />
  <Override PartName="/7190a550-58ab-4333-aac8-45bcf86817de" ContentType="image/jpeg" />
  <Override PartName="/2ae7dc04-156e-40f3-9ea5-fae8ffa5ad03" ContentType="image/jpeg" />
  <Override PartName="/Document" ContentType="Automation/Resource" />
</Types>
```
### properties
`[Content_Types].xml`に記載の通り、中身はXMLファイルです。ファイルの属性情報/プロジェクト設定情報が含まれています。

```XML:properties
<Properties>
  <Version>2.0</Version>
  <Description />
  <Created>12/14/2019 23:41:27</Created>
  <RunDuration />
  <TotalCommands>17</TotalCommands>
  <TotalClicks>0</TotalClicks>
  <TotalMouseClicks>0</TotalMouseClicks>
  <TotalKeystrokes>0</TotalKeystrokes>
  <TotalObjectUsed>10</TotalObjectUsed>
  <FileSize>0</FileSize>
  <ReplaySpeedType>0</ReplaySpeedType>
  <HotKey />
  <Schedule />
  <RepeatType>0</RepeatType>
  <RepeatTimes />
  <RepeatInterval />
  <IsRepeatOnError>False</IsRepeatOnError>
  <Status />
  <LastRunTime />
  <LastModified>05/24/2020 14:52:34</LastModified>
  <PlayModeType>3</PlayModeType>
  <IsRunWithSimilerWindows>False</IsRunWithSimilerWindows>
  <IsNotifyEMail>False</IsNotifyEMail>
  <Email />
  <PriorityType>0</PriorityType>
  <IsBlockKeystroke>False</IsBlockKeystroke>
  <IsStealthMode>False</IsStealthMode>
  <IsCapsLockOn>False</IsCapsLockOn>
  <IsNumLockOn>False</IsNumLockOn>
  <TaskTimeout>0</TaskTimeout>
  <IsContentAnalyticsEnabled>False</IsContentAnalyticsEnabled>
  <Identity>a0923292-4756-4c67-bfde-e00f8c60bbf2</Identity>
  <WorkOrderQueueName>
  </WorkOrderQueueName>
  <QueueWorkItemID>
  </QueueWorkItemID>
  <IsProtected>False</IsProtected>
</Properties>
```
### dependencies
`[Content_Types].xml`に記載の通り、中身はXMLファイルです。依存関係がある場合はこちらに記載されるようです。

```XML:dependencies
<?xml version="1.0"?>
<Dependencies xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
```
### commands
`[Content_Types].xml`に記載の通り、中身はXMLファイルです。アクションリストの本体が保存されているようですが、中身は難読化されており、容易には解析できないようになっています。Automation Anywhereのバージョンだけかろうじて理解できます。

```XML:commands
<QaNHn3mu8famQ74EEqOqg Version="11.3.3">
  <LitLWLWHlMIDo>4LzavUx5FJAtP+keyxwnR+7qbJxykLd3sVlVGsVWGfhCDMC2RNDVwg3I1TOiqn9ZxSMudIuRYJco8nA1NQ5Iqudy1rsYkZz6+a8qjaJqm9fKCSPXntaAnyXUUVVIWCV3ntQrb9Y4767HQw/mIo+i3/mywdcius7tM5cfsiG/fNW5iVIThMaUpEEqk5vNKlNbKIQPpNmZ3YymzAXg6B2dzXJS49mciYA4zuOzlAC+HvaSbiUesU+Iv6LBuW/8LjMUH6otQ0HqQjZ2FmB0SWTMZcp8xiKr8FmHCHEKdzf7GbDfcK24/QU9x01dGAdILCVMFXVnYe+IduY1kJJjO/YR7TAWS9QoShfFlaG84jPXH84=</LitLWLWHlMIDo>
...

```
### Document
`[Content_Types].xml`に記載の通り、中身はXMLファイルです。作成されたAutomation Anywhereのバージョン情報などが格納されているのでしょうか。(先ほどのcommandsファイル内のバージョン情報と矛盾しますが...)

```XML:Document
<AvatarFile>
  <MetaInfo>
    <FileVersion>1.0</FileVersion>
    <ProductName>Automation Anywhere</ProductName>
    <ProductType>AAES</ProductType>
    <ProductVersion>11.3.2</ProductVersion>
    <ProductBuild>11.3.2</ProductBuild>
  </MetaInfo>
  <Avatars />
</AvatarFile>
```
### GUIDのファイル名
`[Content_Types].xml`の記載によると、これはJPEGファイルです。ファイルサイズもこの種類のファイルが一番大きい傾向があります。ただ、バイナリエディタで中を見てみると必ずしもJPEG形式ではなく、BMP等他の画像フォーマットの場合もあります。ただ、.jpg拡張子を付けてペイントで開けば、ペイントもファイル形式を賢く判断して正しいフォーマットで開いてくれるので問題ありません。Object Cloning、Web Recorder等で画面キャプチャーを行った場合はこの種類のファイルが格納されているようです。


# A2019の「Botの移行」アクションで変換してみると...
A2019では「Botの移行」アクションを使って、v11.xの.atmxをA2019 Control Roomで使える形式にして取り込むことができます。以下の通り、Botを作成してv11.xの.atmxファイルを指定します。変換後のファイルはControl Roomに取り込まれるため、自分のマイBotフォルダーを後で参照することになります。「出力フォルダーパス (オプション)」に指定するのはログファイルの出力先の場所です。
使用したA2019は.12 (ビルド4111)商用版です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/3a8ab8f8-d27f-b94e-875e-61ce88ed4ffd.png)

このBotを作成すると、マイBotに「sample」というBotが正常に作成されました。
A2019変換後のアクションリストは以下の通りとなりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/48fb4c9b-534d-b821-6c5b-10e5ac42d20d.png)
このままの形で実行も問題なくできました。
v11.xでは7秒くらいで終わっていたタスクですが、A2019では17-18秒くらいかかるようです。

# A2019変換後のBotファイルをエクスポートして中身を見てみた
エクスポート権限を持っているユーザーでBotファイルをエクスポートしてみます。
A2019の場合、拡張子は最初から.ZIPです。ファイルサイズは...なんと75MBあります！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/655846fd-c9de-b648-80d8-2c460d838ece.png)

中身を見てみると、v11.xの時と大きく違うのは使われているパッケージファイルがすべて.ZIPファイルの中に含まれているところで、これらだけで約80MBあります。本体のサイズはv11.xの時とそれほどかわっていないことがわかります。A2019では「ファット」Botファイルをわざわざ作ることで、アクションパッケージのバージョン相違による互換性を保つところを重視しているようです。

```:Export.20200524_155947.zip
Export.20200524_155947\.
│ 2020/05/24  16:04            25,280 bot-command-comment-2.0.0-20200418-005342.jar
│ 2020/05/24  16:04        22,090,921 bot-command-legacyautomation-1.0.0-20200422-075546.jar
│ 2020/05/24  16:04         3,330,380 bot-command-legacysupport-1.0.0-20200422-075549.jar
│ 2020/05/24  16:04            41,447 bot-command-loop-2.0.0-20200418-005424.jar
│ 2020/05/24  16:04        10,144,929 bot-command-msexcel-2.0.0-20200422-000103.jar
│ 2020/05/24  16:04         3,354,068 bot-command-number-2.0.0-20200418-005433.jar
│ 2020/05/24  16:04        44,113,083 bot-command-recorder-2.0.4-20200422-175245.jar
│ 2020/05/24  16:04           648,885 bot-command-string-2.0.0-20200302-140306.jar
│ 2020/05/24  16:04             3,491 manifest.json
│
└─Automation Anywhere
    └─Bots
        │  2020/05/24  16:04           106,197 sample
        │
        └─sampleMetadata
                2020/05/24  16:04           127,274 12731ae5-7f57-474a-800d-f4e6538cdea9.png
                2020/05/24  16:04           128,785 2ae7dc04-156e-40f3-9ea5-fae8ffa5ad03.png
                2020/05/24  16:04           127,117 3b2218b7-4622-4d1f-bf41-047574d3a9a5.png
                2020/05/24  16:04         1,002,294 42ab84a6-b0fa-4a68-b8ef-8dc812c23709.png
                2020/05/24  16:04         1,002,294 46842abc-843b-40ec-acf6-63473944cc91.png
                2020/05/24  16:04            10,930 51eda008-f04d-4237-ae30-dd932e1f0621.png
                2020/05/24  16:04           128,006 6ea9ad55-b298-438c-b2f6-81a8d7a2baba.png
                2020/05/24  16:04           127,996 7190a550-58ab-4333-aac8-45bcf86817de.png
                2020/05/24  16:04           127,913 8e0a4c12-eec9-43d2-b9fe-531e1cb65ff2.png
                2020/05/24  16:04             7,182 ca9f9414-dcb4-4809-9a47-17a1b0f8298a.png
                2020/05/24  16:04           127,541 dd278e08-7f50-47e2-a376-08bb25eccf32.png
```

Botファイル全体のカタログに当たるものは`manifest.json`です。JSON形式で記載されています。

```Javascript:manifest.json
{
  "files":
  [{
    "path":"Automation Anywhere\\Bots\\sample",
    "contentType":"application/vnd.aa.taskbot",
    "metadataForFile":null,
    "manualDependencies":[],
    "scannedDependencies":[]
   },
   {
    "path":"Automation Anywhere\\Bots\\sample\\2ae7dc04-156e-40f3-9ea5-fae8ffa5ad03.png",
    "contentType":"image/png",
    "metadataForFile":"Automation Anywhere\\Bots\\sample",
    "manualDependencies":null,
    "scannedDependencies":null
   },
   {
    "path":"Automation Anywhere\\Bots\\sample\\8e0a4c12-eec9-43d2-b9fe-531e1cb65ff2.png",
    "contentType":"image/png",
    "metadataForFile":"Automation Anywhere\\Bots\\sample",
    "manualDependencies":null,
    "scannedDependencies":null
   },
   {
    "path":"Automation Anywhere\\Bots\\sample\\42ab84a6-b0fa-4a68-b8ef-8dc812c23709.png",
    "contentType":"image/png",
    "metadataForFile":"Automation Anywhere\\Bots\\sample",
    "manualDependencies":null,
    "scannedDependencies":null
   },
   {
    "path":"Automation Anywhere\\Bots\\sample\\51eda008-f04d-4237-ae30-dd932e1f0621.png",
    "contentType":"image/png",
    "metadataForFile":"Automation Anywhere\\Bots\\sample",
    "manualDependencies":null,
    "scannedDependencies":null
   },
   {
    "path":"Automation Anywhere\\Bots\\sample\\dd278e08-7f50-47e2-a376-08bb25eccf32.png",
    "contentType":"image/png",
    "metadataForFile":"Automation Anywhere\\Bots\\sample",
    "manualDependencies":null,
    "scannedDependencies":null
   },
   {
    "path":"Automation Anywhere\\Bots\\sample\\3b2218b7-4622-4d1f-bf41-047574d3a9a5.png",
    "contentType":"image/png",
    "metadataForFile":"Automation Anywhere\\Bots\\sample",
    "manualDependencies":null,
    "scannedDependencies":null
   },
   {
    "path":"Automation Anywhere\\Bots\\sample\\ca9f9414-dcb4-4809-9a47-17a1b0f8298a.png",
    "contentType":"image/png",
    "metadataForFile":"Automation Anywhere\\Bots\\sample",
    "manualDependencies":null,
    "scannedDependencies":null
   },
   {
    "path":"Automation Anywhere\\Bots\\sample\\46842abc-843b-40ec-acf6-63473944cc91.png",
    "contentType":"image/png",
    "metadataForFile":"Automation Anywhere\\Bots\\sample",
    "manualDependencies":null,
    "scannedDependencies":null
   },
   {
    "path":"Automation Anywhere\\Bots\\sample\\12731ae5-7f57-474a-800d-f4e6538cdea9.png",
    "contentType":"image/png",
    "metadataForFile":"Automation Anywhere\\Bots\\sample",
    "manualDependencies":null,
    "scannedDependencies":null
   },
   {
    "path":"Automation Anywhere\\Bots\\sample\\6ea9ad55-b298-438c-b2f6-81a8d7a2baba.png",
    "contentType":"image/png",
    "metadataForFile":"Automation Anywhere\\Bots\\sample",
    "manualDependencies":null,
    "scannedDependencies":null
   },
   {
    "path":"Automation Anywhere\\Bots\\sample\\7190a550-58ab-4333-aac8-45bcf86817de.png",
    "contentType":"image/png",
    "metadataForFile":"Automation Anywhere\\Bots\\sample",
    "manualDependencies":null,
    "scannedDependencies":null
   }
  ],
  "packages":
  [
   {
    "name":"LegacyAutomation",
    "version":"1.0.0-20200422-075546",
    "path":"bot-command-legacyautomation-1.0.0-20200422-075546.jar"
   },
   {
    "name":"Excel_MS",
    "version":"2.0.0-20200422-000103","path":"bot-command-msexcel-2.0.0-20200422-000103.jar"
   },
   {
    "name":"String","version":"2.0.0-20200302-140306",
    "path":"bot-command-string-2.0.0-20200302-140306.jar"
   },
   {
    "name":"Loop","version":"2.0.0-20200418-005424",
    "path":"bot-command-loop-2.0.0-20200418-005424.jar"
   },
   {
    "name":"Recorder","version":"2.0.4-20200422-175245",
    "path":"bot-command-recorder-2.0.4-20200422-175245.jar"
   },
   {
    "name":"Comment","version":"2.0.0-20200418-005342",
    "path":"bot-command-comment-2.0.0-20200418-005342.jar"
   },
   {
    "name":"Number","version":"2.0.0-20200418-005433",
    "path":"bot-command-number-2.0.0-20200418-005433.jar"
   },
   {
    "name":"LegacySupport",
    "version":"1.0.0-20200422-075549",
    "path":"bot-command-legacysupport-1.0.0-20200422-075549.jar"
   }
  ]
}
```

sampleはコマンドの本体 (commands) にあたるもので、v11.xでは難読化されていましたが、A2019ではJSON形式で可読形式で記載されています。

```Javascript:sample
{
"nodes":
[
 {
  "uid":"4389d686-86bd-4099-a7a3-122a81517b85",
  "commandName":"configuration",
  "packageName":"LegacyAutomation",
  "attributes":
  [
   {
    "name":"hideBrowser",
    "value":
    {
      "type":"BOOLEAN",
      "boolean":false
    }
   },
   {
     "name":"ieAsProcess",
     "value":
      {
        "type":"BOOLEAN",
        "boolean":false
      }
   },
   {
     "name":"ieTimeout",
     "value":
      {
        "type":"NUMBER",
        "number":"240"
      }
   }
  ]
 },
...
```

ちなみに、余談ですが、Javaのパッケージである.jarファイルもZIP形式です。これも拡張子を.zipにすると中身が見れます。

# 注意点
扱うにあたっていくつか気づいた注意点を挙げます。

* Email Automationコマンドで電子メール本文に画像を挿入する場合、ローカルPCの絶対パスで指定され、画像ファイルが.atmxファイルに取り込まれるわけではないようです。したがって、指定した画像ファイルを消したり、PCを替えたりすると、リンクが切れてしまいます。.atmxファイルの中でもdependencies等に記載があるわけではないので注意が必要です。
* v11.xの場合、コマンドセットは固定ですが、MetaBotにより拡張が可能です。しかし、ここに依存関係が生じます。A2019 「Botの移行」アクションでもMetaBotはサポートされていません。