RMapsを使う為に、Windows7(x64)環境で Mobile Atlas Creator を使う
Androidタブレットを買ったんですが、Wi-Fi環境なので、基本外に持ち出す事が出来ないんですね。
(Wi-Fiルーターを持ち歩く必要がある)
Google Mapsは便利なので、これを外で電子地図代わりに使いたい。
けど、Wi-Fiルーターで接続しないと、地図表示できない。…うーん。という訳で、悩んでいたんですが、どうやらローカル地図ソフトなるものがある事を知った次第。
- 人々柱の備忘録| RMaps Android ローカルMAP
http://hitobitobashira.blog64.fc2.com/blog-entry-132.html - 人々柱の備忘録| Maps (-) Android オフライン地図をいつでも簡単キャッシュ
http://hitobitobashira.blog64.fc2.com/blog-entry-162.html - 人々柱の備忘録| Androidのオフライン地図アプリまとめ iPhoneとの比較
http://hitobitobashira.blog64.fc2.com/blog-entry-157.html
という訳で、RMapsというソフトを入れてみる事に。
動かしてみた感じ、良さげだったので、パソコンからオフライン地図データを取得して、RMapsに入れ込む事にしました。
オフラインな地図データ作成ソフトの存在
RMapsをWi-Fiが届かない環境でも使えるようにする為には、オフライン地図データが必要な訳ですね。
描画速度の速さで、↓このページからダウンロードできる Mobile Atlas Creator か TrekBuddy Atlas Creatorが良いように感じました。
- android-map - Solutions to Offline Google Maps for Android-powered phones. - Google Project Hosting
http://code.google.com/p/android-map/ - 作者と思われるページ:Dr. TYT 的 Android 地圖
http://android-map.blogspot.com/
本家?か良く判らないんですが、Mobile Atlas Creatorからダウンロードできる配布物は、SQLiteのバージョン不一致か良く判りませんが、少なくとも、Windows7(x64)な環境では正しく地図データを作成してくれません。
(当初、しょうがないので、VirtualPCで動かしていた)
ソフトの経歴としては、TrekBuddy Atlas CreatorからMobile Atlas Creatorにメンテナンスが移っているようなので、現在だと Mobile Atlas Creator(の、このサイトバージョン)を使った方が良いでしょう。
自分は、Mobile_Atlas_Creator_1.8_SQLite.zipをダウンロードして動かしてみたんですが、何の設定変更も無しに、地図データを作成してくれました。
多分、正しく動く SQLiteライブラリが同梱されているお陰だと思われます。
皆さんが紹介されている、TrekBuddy Atlas Creatorも使えます。(というか、タブレットでの動作確認は、こちらばかり試していた)
この場合、Windows7(x64)環境では、そのままでは使えません。x64に対応したSQLiteのライブラリに更新する必要があるので注意して下さい。
x64なSQLiteは、↓ここで紹介されている通り、やはり同サイトの、Mobile_Atlas_Creator_1.7_SQLite.zip内の「Win x64(64bit)」フォルダにある、「sqlite_jni.dll」に上書きする必要があります。
- Updating problems [myProject]'. no sqlite_jni in java.library.path | The Log of "__ ____"
http://thelogofthewook.blogspot.com/2011/12/updating-problems-myproject-no.html#!/2011/12/updating-problems-myproject-no.html
使い方
使い方は、基本皆さんの説明ページを読んで下さい。
そちらの方が、詳細で判りやすいです。
- 人々柱の備忘録| RMaps Android ローカルMAP
http://hitobitobashira.blog64.fc2.com/blog-entry-132.html - TrekBuddy Atlas Creator & RMaps
http://wp.07ch.com/?page_id=57 - RMapsを使ってトレイルランに(XperiaにオフラインでGPS): くろすけの、まったりと過ごす日々
http://kuro277.cocolog-nifty.com/blog/2010/08/rmapsxperiagps-.html
まぁ、それだと芸が無いので、同じ説明で申し訳ありませんが、順を追って説明をば。
1.アプリを起動すると、地図がどーんと表示されます。
ここで、注意ば必要なのは、左ドラッグは領域選択。右ドラッグが地図の移動です。最初、アレ?と思って固まりました。
1 posted by (C)wacky
2.地図データを作成したい大体の場所まで移動したら、おもむろに地図データを作成したい部分を左ドラッグで選択します。
選択した後、左ペインの「Zoom Levels」の数値を選択して下さい。これは地図の詳細度を指定します。
あまり大きい値を入れると、データサイズが莫大になるので、選択した際に表示される「xxx tiles」の値を睨みながら選んで下さい。
2 posted by (C)wacky
3.次に左ペインの「Add selection」をクリックします。
領域設定した情報は、下側の「Saved profiles」の下の「Save」で保存できるようなので、テケトーに保存しましょう。
3 posted by (C)wacky
4.次に左ペインの「Create atlas」で、地図データの情報取得と作成を行います。
全ての作業が完了したら、「Open Atlas Folder」ボタンが有効になります。
4 posted by (C)wacky
ちなみに、「Atlas settings」の「Format」で作成する地図データの形式を選ぶ事ができるようです。
6 posted by (C)wacky
5.「Open Atlas Folder」ボタンをクリックすると、作成された地図データファイル(.sqlitedb)のフォルダがオープンされます。
これを、タブレット端末の、SDカードの「//rmaps/maps」フォルダにコピーします。
5 posted by (C)wacky
6.タブレット端末を起動して、RMapsを起動し、Menuを選び、「その他」→「Settings」→「User defined maps」で、作成した地図データファイルを選択→「Enable map」にチェックを入れます。
一旦画面に戻って、Menuを選び、「Maps」で選択した地図データファイル名を選択すると、オフラインな地図データを表示するようになります。
感想
人々柱の備忘録さんのページで、オフライン地図アプリのまとめが載っていて、非常に参考になります。
- 人々柱の備忘録| Androidのオフライン地図アプリまとめ iPhoneとの比較
http://hitobitobashira.blog64.fc2.com/blog-entry-157.html
つーか、iPhone版もあるんですね。知らなかった。
こうなると、手持ちのiPod touchにGPSが欲しくなるなぁ。次期バージョンで搭載してくれないかなぁ?
Windows7でIrvineを使用する際の気づき
ダウンローダ Irvineは、大きめのファイルや複数のリンクに分けられている細かいファイル(ネット小説系は、やけにリンク細切れが多くて、後でゆっくり見たい時大変)をダウンロードするのに便利なんですね。
今だったら、DCさくらの方がWindows7も正式サポートしているんで、こっちの方が良いと思うんですが、何故か こっちを使い続けています。
Windows7の動作報告関係のページだと、Irvine使えるよ!って報告例が多いのですが、一部の方は使えないよ。と報告している方も居るようですね。
- Irvineフリー版|Windows 7 アプリケーション動作報告リスト
http://w7.vector.jp/softrev/detail.php?s_no=20263 - Windows 7 @ ウィキ - 対応ソフト(x64)
http://www15.atwiki.jp/win7/pages/30.html
自分のマシンは、Windows7(x64)でIE9の環境(正確にはメインブラウザはSleipnir)なんですが、Irvineは ちゃんと使えています。(Irvine 1.3.0)
ただ、ちゃんと使えるようにする為には、ちょっとしたテクニックがあるようです。現時点で、判っている事を、メモしておきます。
Tips1.Program Files フォルダ以外にインストールする
これは結構有名なようです。
- Program Filesの読み取り専用を解除できません。 - Microsoft Answers
http://answers.microsoft.com/ja-jp/windows/forum/windows_7-files/program/7333d51a-f8db-4164-b87e-ed5a2b01245f - Windows Vista & 7のUAC対策について
http://www.trycut.com/uac.htm - Windows Vista/7 のファイルの仮想化(Virtualization)について
http://pasofaq.jp/windows/vista/virtualstore.htm
自分の場合、適当なフォルダを掘って、その中にIrvineを入れて動かしています。
Tips2.実行ファイルに管理者権限を与えずに動かす
先のwikiでは、管理者権限与えて動かせば。とありますが、どうも管理者権限を与えてしまうと、IEの右クリックメニューによる Irvine連携が機能しなくなるようです。
(もしかしたら、最初の起動だけは管理者権限必要かも知れません)
これ、何で気づいたかと言うと、オレオレなスクリプトで、Irvineにダウンロードアイテムを登録しようとした際に気づいたんですね。
JavaScriptで、IrvineにアクセスするActiveXオブジェクトを起動しようと思って、簡単なJavaScriptを書いたんですよ。
o = new ActiveXObject('Irvine.Api'); WScript.Echo(o);
これを実行したら、以下のエラーが出てきたんですね。
$ cscript test.js Microsoft (R) Windows Script Host Version 5.8 Copyright (C) Microsoft Corporation 1996-2001. All rights reserved. test.js(1, 1) (null): 要求された操作には管理者特権が必要です。
これを見て、「はっ」と気づいたんですよ。IEの右クリックメニューでも、「オブジェクトが生成できない」とか言ってたな。と。
で、Irvineの実行ファイルに与えていた管理者権限を外したら、ちゃんとIEの右クリックメニューからの「Irvineへ登録」が機能し始めた次第です。
テケトーな予想ですが、以下の動きじゃないかな?と思ってます。
- 管理者権限で起動した際、自分のアカウントとは別の専用アカウントで起動。
- スクリプトからアプリのActiveXオブジェクトを得ようとする(new ActiveXObject(...))。
- スクリプトのアカウントはxxさん、アプリのアカウントは管理者権限さん。
アカウントが違うので、アプリへのアクセスを蹴られる。 - 結果、ActiveXオブジェクトの生成に失敗する。
要するにクライアントのアカウントと、Irvineのアカウントを同じにしろや。って事です。
だから、Irvineに管理者権限を与えてしまうと、クライアント 例えばスクリプトやIEやSleipnirも管理者権限で起動しないと、連携出来ないって寸法な訳ですね。
最後に
という訳で、ちょっとした気づきでした。
後、おまけですが、Irvineにダウンロードアイテムを登録するには、ぶっちゃけ以下のコードで大体OKのようです。
var Irvine = new ActiveXObject('Irvine.Api'); var IrvineItem = new ActiveXObject('Irvine.Item'); IrvineItem.Url = ダウンロードしたいURL; IrvineItem.FileName = ダウンロード時のファイル名; Irvine.Current.AddItem(IrvineItem);
APIリファレンスは、 http://hp.vector.co.jp/authors/VA024591/doc/api.txt にあります。
Google Documents List APIを使って、Google ドキュメントにファイルを自動アップロードする
自分は、個人的な気づきをテキストファイルにメモしたりしているんですね。
メールやはてブも使っていますが、ネット経由とローカルファイルでは、どうしても応答速度に違いが出てしまいますからね。
そうやって、書き留めたテキストファイルですが、何時までもローカルに置いておくのも嫌なんですね。
プライベートなネットストレージに突っ込んでおけば、ローカルマシンが壊れた際の復旧や、タブレットなどの別のマシンからも参照できるので、便利になる訳です。
ネットストレージに突っ込んだデータの検索性で、非常に便利なのは、今の所、Google ドキュメントかEvernote辺りかな?と感じています。
特に、Google ドキュメントは、検索がバカ早なので、結構お気に入りです。
(MicrosoftさんのSkyDriveは容量はピカイチなのですが、検索を自分のアップしたものに絞れないのがネック<何か方法があるのかなぁ?)
(ちなみに、Yahooはサービス規約をポンポン変えるので、不安で使えない)
という訳で
という訳で、テキストファイルをGoogle ドキュメントに自動アップロードしようと思いました。
要するに、タスクスケジューラ等で、ローカルに置いたテキストファイルを定期的にアップロード&更新しちゃおうって訳です。
当初は、適当なソフトを使おうか?と思っていたんですが、ぐぐると結構楽に実装できる事が判ったので、勉強がてら自作する事にしました。
- Client Libraries and Sample Code - Google Documents List API - Google Code
http://code.google.com/intl/ja/apis/documents/code.html - Python Language Guide (v1.0) - Google Documents List Data API v1.0 - Google Code
http://code.google.com/intl/ja/apis/documents/docs/1.0/developers_guide_python.html - Google Document にファイルをアップロードするバッチを作ってみた - Limitの日記
http://d.hatena.ne.jp/limitusus/20090929/1254232748 - imageryblog: Google ドキュメントにファイルをアップロード,ダウンロードする方法 #googledocs
http://blog.firefly-vj.net/2011/08/google-googledocs.html - Google Documents List Data API v3.0 を python から利用してみた。 (tonextone.com/type/)
http://tonextone.com/type/2010/06/20-0028.html
クライアントのライブラリは、Client Libraries and Sample Code - Google Documents List API - Google CodeのDownloadから取得します。
自分が取得したのは、gdata-2.0.14.zip でした。
ダウンロードして、setup.pyでinstallすればインストールされます。
I:\Wacky\src\test\google\gdata-2.0.14>python setup.py install ... byte-compiling C:\tool2\Python27\Lib\site-packages\gdata\youtube\__init__.py to __init__.pyc byte-compiling C:\tool2\Python27\Lib\site-packages\gdata\__init__.py to __init__ .pyc running install_egg_info Writing C:\tool2\Python27\Lib\site-packages\gdata-2.0.14-py2.7.egg-info
後は、上のリンクで紹介されているサンプルコードを元にAPIを叩けばOKです。
では、早速今回作ったコードを示します。
#!/bin/env python # -*- encoding: cp932 -*- """ Google Documentにテキストファイルをアップロードする なお、テキストファイルは、utf-8形式がデフォルトである。(Google Documentの場合) """ import sys import os import os.path import pdb import gdata.docs import gdata.docs.service def get_exe_dir_name(): """実行スクリプトのフォルダを取得""" return os.path.abspath(os.path.dirname(__file__)) def copy_to_utf8(src_fpath, dst_dir=None): """src_fpath(コピー元のファイルパス)からdst_dir(コピー先ディレクトリ)に、utf-8変換コピーする""" fname = os.path.split(src_fpath)[1] if dst_dir == None: dst_dir = get_exe_dir_name() dst_fpath = os.path.join(dst_dir, fname) s = "nkf32 -w8 \"%s\" > \"%s\"" % (src_fpath, dst_fpath) print "call: ", s os.system(s) return dst_fpath def list_file(cli): """Google Documentのファイル一覧を得る""" i = 0 for e in cli.GetDocumentListFeed().entry: i = i + 1 print "%02d : file [%s][%s]" % (i, e.title.text.decode('utf-8'), e.GetDocumentType()) def list_dir(cli): """Google Documentのフォルダ一覧(コレクション)を得る""" i = 0 q = gdata.docs.service.DocumentQuery(categories=['folder'], params={'showfolders': 'true'}) for e in cli.Query(q.ToUri()).entry: i = i + 1 print "%02d : dir [%s]" % (i, e.title.text.decode('utf-8').encode('cp932')) def find_file(cli, name): """Google Documentに指定した名前のファイルがあるか調べる。あればオブジェクトを、無ければNoneを返す""" for e in cli.GetDocumentListFeed().entry: if e.title.text.decode('utf-8') == unicode(name, 'cp932'): return e return None def upload_text(cli, fpath, name=None): """Google Documentに、ファイルをアップロードする。既にファイルがあれば置き換える \arg fpath アップロード元のファイルパス \arg name アップロード時の名前 """ if name == None: name = os.path.split(fpath)[1] print "アップロード中(%s, %s)..." % (name, fpath) ms = gdata.MediaSource(file_path=fpath, content_type=gdata.docs.service.SUPPORTED_FILETYPES['TXT']) exist_file = find_file(cli, name) e = None if exist_file == None: print " new upload file!!" e = cli.Upload(ms, unicode(name, 'cp932')) else: print " replace file!!" e = cli.Put(ms, exist_file.GetEditMediaLink().href) print " OK!!" print " href=%s" % (e.GetAlternateLink().href) def main(argv): print "[%s]のファイルを作業フォルダにコピー中" % argv[1] up_file = copy_to_utf8(argv[1]) print "upload file:[%s]" % up_file print "Google Documentにアクセス中...", cli = gdata.docs.service.DocsService() cli.ClientLogin("<アカウント>", "<パスワード>") print "アクセス完了!!" print "\n--- Google Document List ---" list_dir(cli) list_file(cli) print "" upload_text(cli, up_file, None) print "アップロード完了!!" if __name__ == "__main__": argv = sys.argv print "argc=%d" % len(argv) for i in range(len(argv)): print "%d-[%s]" % (i, argv[i]) main(argv)
使い方は、アップロードしたいテキストファイルのパスを第1引数に与えるだけです。
スクリプトのフォルダに、nkf32でUTF-8変換したテキストファイルを一旦配置し、それからGoogle ドキュメントにアップロードする仕掛けです。
今度は、いきなり安くなった NEC Life Touch NOTEを買ってみた
ネットアレルギーな親に慣れてもらうように、プレゼント用に安いネット端末を探していたんですね。
ちなみに購入基準としては、以下の感じ。
- 安い事
興味を持ってもらえるか心配だったので。 - パソコンはなるべく避けたい
フリーダム過ぎて、ウィルス感染が怖い。XP EmbeddedでEWF掛けてあれば少し安心なんですけど、パソコンで そういうのは、見当たらないです。 - 素早く立ち上がる事
数秒で起動できればベター。 - 自分の知っているメーカ製である事
あまりに挑戦者なメーカのものは、自分も判んないので。
そうしたら、NEC Life Touch NOTEが、2万を切っているじゃ、あ〜りませんか?
日本電気 LifeTouch NOTE NA70W/1A ピアノブラック LT-NA70W1A
- 出版社/メーカー: NEC
- 発売日: 2011/03/10
- メディア: Personal Computers
- クリック: 403回
- この商品を含むブログ (4件) を見る
ネット検索すると、目の付け所がシャープな人たちが、購入している方が結構多かったんですね。
正直、AndroidよりiPadとかの方が、動きがシャープ&安定しているので欲しかったんですが、まぁ安いし。
ついでにキーボード付きなのが、(普通とは違って自分的には)ポイント高かった。…キーボードでポチポチする方が年配には物理的な反応があって良いかな?と。
で、早速購入しました。
初期設定は自分が行って、親に渡して反応見てます。
身の周りのキーワードをポツポツ入力して、ほぅ。と感心して見てくれているので、結論として買って良かったかな。と。
ACアダプタが付いているので、一々充電する必要も無し、ちゃぶ台の片隅に置いて、思いついた時に引っ張り出して眺められるので、非常に便利ですね。
評価で、開くと液晶パネルの重みで倒れる。とあったのですが、バッテリを付けてない場合の事なのかな?そういう事は、今の所無いです。
キーボードの大きさは、ブラインドタッチには少々難ですが、結構大きいので2本指打法には問題無いレベル。
カメラの質は10万画素?というぐらいの感じでしたが、解像度に対して画面が大きすぎるんでしょうね。
ちなみに、一番引っかかったのは実は無線LANの設定でして、親機にアクセス掛かったMACアドレスを、Life Touchのものと暫く勘違いしていました。
設定の所のMACアドレスを見て、「ありゃ?間違っている」と気づいて、ようやく解決した次第。
ブラウジングの速度や起動速度も、気になるほど遅い訳でもなし。
(多分)Javascriptてんこ盛りのEvernote for Webが、開くのが異常に遅いぐらいで、まぁ親は使わないしね。
とにかく、満足のいく買い物でした。
与太話
このLife Touch NOTEって、今年の2月の製品なんですよね。
半年程度で、ここまで下がるってのは、開発者の方は涙だろうなぁ。
ただ、初期設定の4〜5万だと、ネットブックと完全に競合しちゃうんですよね。
そういう点で、本当申し訳無いですが、この価格帯で他の競合と争える製品だったのかな?と、感じています。
東芝REGZAの外部録画装置として、WD Elementsを買った
自宅のテレビで、東芝REGZAを買っているんですが、時折見るだけ。と、HDDも繋がずに放置していました。
というのも、正直テレビを見ると言ったら、朝起きた時のニュースと、帰った時のBGV替わりでしかなく、時折BSで科学番組や旅行番組をやるので、ぼけっと見るぐらい。
地上波は天気予報を見る為に切り替えるぐらいしか使わないという、体たらくでした。
(ところで、最近のニュースは、N○Kでさえアナウンサーが独り語りを始めたりするので、正直どうよ?と思ったり。<オマエノ意見なんぞ聞きたくないわ。事実だけ正確にイエーみたいな)
とはいえ、時折流れる科学番組を見損ねるのは、ちょっと勿体無いと思ってたりしてたんですね。
そうしたら、先日コンピュータショップに行ったら、WD ElementsというUSB HDDが8,000円くらいで2TBという安さ。
WD Elements Desktop 2.0TB (USB2.0, 静音/省電力, PC&Mac, レグザ/アクオス/ブラビアTV録画対応) WDBAAU0020HBK-JESN
- 出版社/メーカー: WESTERNDIGITAL
- 発売日: 2010/08/23
- メディア: Personal Computers
- 購入: 13人 クリック: 177回
- この商品を含むブログ (9件) を見る
他のメーカのより妙に重いなぁ。けど、独自の3年保証とかしているし、まぁ良いか。と、思わず衝動買いしてしまいました。
(同じ価格帯だと、他のメーカのは1TBしかなかった)
早速繋いでみたんですが、えらい静か。耳をHDDに付けて聞いてみたんですが、時折「コツッ」とか言っているような気がする程度。
裏面に白いLEDがあって、動いている時はこれが点滅しているようなんですが、表に何も無いので、動いているかどうかさえ、良く判らない。
ちなみに、USBへのアクセスが入って初めて、HDDの電源が入る仕掛けのようで、使用しているREGZAだといきなり「録画ボタン」を押すと、「HDDが見つからねーよ」と、言われました。
一旦、番組表から「予約リスト」を表示した後、一旦閉じて「録画リスト」に入り直したら、ちゃんとリスト表示されました。
ちょっと操作が面倒だけど、まぁ、良いか。
RPGツクール2000/2003関連ツール開発用SDK(rpg2kdevSDK)を弄る遊び
昨日は、蚊に噛まれて その痒みで目が醒めてしまいました。
かゆいよー。
不純なゲームの遊び方
先日、フリーで えっちなゲームを見つけて、暇つぶしに遊んでました。
まぁ、背徳の旋律とか、VHゲームとかですね。
ゲームをしながら、よく作りこんでいるなぁ。と感心していたのですが、ちょっと困った問題が。
遊んでいたゲームが、どうも色んなサブシナリオを用意しているようで、作者さんが、どんな話を作りこんだのか知りたくなってきたんですね。
でも、自分にはゲームセンスも無いし、某掲示板の専用板で出てくる話題は、ある程度知った事を前提に書かれていて、どう進めれば良いのか分からない。
(攻略本があったりして非常に助かっているのですが、最新となると…)
下手にフラグを立てると、バグってハニーな状態になる場合や、別のイベントが見られなくなる場合もあるようで、行き当たりばったりも望ましいとは言えない。
中身を知る方法は無いかしらん?と、ぐぐってると、RPGツクール2000だと、体験版で中身を見る事ができる事がわかりました。
やったー。と、眺めて楽しんでいたんですが、ウィンドウを開いては閉じる作業を行うのが、段々億劫になってきた。
もっと簡単に閲覧できるようなビューワか何か無いかしらん?と、更にぐぐっていると、構造を解析している方を見つけました。
- TopPage - RPGツクール2000/2003/XP 解析データまとめページ
http://rpg2kdev.sue445.net/?TopPage
ありがたや、ありがたや。
しかも、SDKまで公開して下さっている。
- DownLoad - RPGツクール2000/2003/XP 解析データまとめページ
http://rpg2kdev.sue445.net/?DownLoad
ありがたや、ありがたや。
___ ,;f ヽ i: i | | ありがたやありがたや | | ///;ト, | ^ ^ ) ////゙l゙l; (. >ノ(、_, )ヽ、} l .i .! | ,,∧ヽ !-=ニ=- | │ | .| /\..\\`ニニ´ !, { .ノ.ノ / \ \ ̄ ̄ ̄../ / .|
気づき
という訳で、SDKを弄繰り回しながら、遊んでます。
それはともかく、ちょっくら見つけたバグっぽい動きと修正方法をば。
CDimensionクラスのコンストラクタに渡す引数値ですが、256以上を与えると、charにキャストされちゃうみたいです。
例えば↓のように。
CDim2 v(256, 257); printf("%d %d\n", v.GetX(), v.GetY());
と記述すると、
0 1
が出力されてしまいます。
これをFixするには、CDimensionクラス(CDimension.h)のコンストラクタを、以下のように修正します。
/// コンストラクタ CDimension(DimType x, ...) { memcpy(m_Dimension, &x, sizeof(m_Dimension)); }
修正すると、以下のように意図された値が出力されます。
256 257
ちなみに
資料とツクールの表示データと比較しながら、どうやったらテキストで取り出せるか試行中…。
という訳で、不純なゲームの遊び方を、研究中です。なはは。
.NETから統合アーカイバ仕様DLLを呼び出すなら、x86でビルドしよう
今回は、ちょっとした気づきです。
- 動的PInvokeによる統合アーカイバ仕様DLLを使用した書庫の展開と作成(1/4):CodeZine
http://codezine.jp/article/detail/444
で提供されている.NET向けのライブラリを使って、オレオレアプリを作っていたんですね。
この都度、Win7(64bit)環境で動くかな?と思って動かしたら、動かない。
エラーログを見たら、「DLLが無ぇよ」とおっしゃる。
そんなまさか!?と思いつつ、システムフォルダを検索すると、unlha32.dllなどの統合アーカイバ仕様DLLは、どうやら「C:\Windows\SysWow64」フォルダに在る模様。
ちゃんとDLLは存在するのに、ライブラリは見つけられない。
コードを追いかけていくと、DLLの存在チェックは、CommonArchiver.csのExistDLL関数内の SearchPath というWin32 APIを呼び出して実現している模様。
/// <summary> /// DLLが存在するか調べる /// </summary> /// <returns></returns> public bool ExistsDll() { IntPtr pathPtr; return Win32.NativeMethods.SearchPath( null, this.DllFileName, null, 0, null, out pathPtr) != 0; }
ここまで来て、ふと以前読んだ、↓の記事を思い出しました。
- EXE を作るプロジェクトのデフォルトが Any CPU から x86 に変わった理由 - または Any CPU の本当の意味 - 当面C#と.NETな記録
http://d.hatena.ne.jp/siokoshou/20091102/p1
Win64(64ビットバージョンの Windows)によって PE ファイル(EXE と DLL)は32ビット「または」64ビットとマークできるようになりました。32ビット EXE は Win64 上では、プロセスに32ビットオペレーティングシステムの幻想を見せる「WOW(Windows32 on Windows64)」の中で走ります。通常、32ビット DLL は32ビットプロセスだけにロードでき、64ビット DLL は64ビットプロセスだけにロードできます。
ここまで来て、プロジェクトの設定を確かめてみると、プラットフォームターゲットが「Any CPU」になっています。
これを「x86」に変えた所、思ったとおり、DLLを参照できるようになりました。
よかった、よかった。
解説
という程のものでも無いですが。
要するに、自分のアプリが「Any CPU」だった為、以下の動きになっていたと思われます。
- hoge.exeを動かす。
「Any CPU」なので、EXEは64ビットだよ〜と、マークされる。 - ExistDLLのSearchPath APIを呼び出す。
検索パスはnull指定なので、API仕様に書かれている通り、実行パスのフォルダ→カレントフォルダ→Windowsのシステムフォルダ→Windowsディレクトリ→環境変数PATHの設定 の順番に検索をかけていく。 - ↑で、Windowsのシステムフォルダを検索する時、64ビットモードで動いているので、検索フォルダは「C:\Windows\System32」となる。
- 「C:\Windows\System32」フォルダは、純粋に64ビットなDLLしか存在しないので、unlha32.dllなどの32ビットDLLは存在しない。存在しないので、ExistDLLはFALSEになって変える。
対して、「x86」でEXEをビルドしておく事で、3.番目の挙動が変わります。
3.↑で、Windowsのシステムフォルダを検索する時、32ビットモードで動いているので、検索フォルダは「C:\Windows\SysWow64」となる。
多分、すべてを.NETで記述するか、64ビット対応のDLLを用意していれば、問題なく動作するんでしょうけど、この場合はしょうがないですね。