以前、ブラザーのラベルプリンタを操作するb-PACについて、C#でいろいろと試してみました。
ブラザーのラベルプリンタまわりを操作する b-PAC SDK を使ってみた - メモ的な思考的な
そんな中、前回インストールしたpythonnet
を使うことで、.NET + b-PACを扱えるのではないかと考え、試してみることにしました。
環境
virtualenv環境は以下のとおりです。
D:\sandbox>mkdir bpac_python D:\sandbox>cd bpac_python D:\sandbox\bpac_python>virtualenv -p c:\python35-32\python.exe env D:\sandbox\bpac_python>env\Scripts\activate # pythonnetを入れるために、pipを8系にアップグレード (env) D:\sandbox\bpac_python>python -m pip install --upgrade pip (env) D:\sandbox\bpac_python>pip install pythonnet
COMオブジェクトの生成
COMオブジェクトを生成するには、Activator.CreateInstance(Type.GetTypeFromProgID('ProgID'))
を使うのが良さそうでした。
Instantiating a legacy COM object in C# dynamically (using its ID in a string) - Stack Overflow
以下のコードを動作させてみた結果、
import clr from System import Activator, Type doc = Activator.CreateInstance(Type.GetTypeFromProgID('bpac.Document')) print("doc: {}".format(doc.__class__)) #=> doc: <class 'System.__ComObject'>
b-PACのCOMオブジェクトが生成できたようです。
プリンタの列挙
列挙するために、GetInstalledPrintersを使ってみたところ、
printers = doc.Printer.GetInstalledPrinters
#=> AttributeError: '__ComObject' object has no attribute 'Printer'
エラーとなりました。
そこで、リフレクションを使ってPrinterを取得してみます。
printer = doc.GetType().InvokeMember("Printer", BindingFlags.GetProperty, None, doc, None ) print("Printer:{}".format(printer)) #=> Printer:System.__ComObject
取得できましたが、またComObjectっぽいようです。
属性を確認したところ、
print(dir(printer)) #=> ['CreateObjRef', 'Equals', 'Finalize', 'GetHashCode', 'GetLifetimeService', 'GetType', 'InitializeLifetimeService', 'MemberwiseClone', 'Overloads', 'ReferenceEquals', 'ToString', '__call__', '__class__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__overloads__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__']
GetInstalledPrinters
が見当たりませんでした。
そのため、再度リフレクションを使って取得してみます。
printers = doc.GetType().InvokeMember("GetInstalledPrinters", BindingFlags.GetProperty, None, printer, None ) print("InstalledPrinters:{}".format(printers)) #=> InstalledPrinters:System.Object[]
何かが取得できたようです。
中身を確認すると、
for p in printers: print("installed Printer:{}".format(p)) #=> installed Printer:Brother QL-720NW
プリンター情報が取得できました。
ここまでやったところで、
- プリンタ情報を取得するだけでもかなりの手間でつらい
- リフレクションを使ったイベントハンドラ設定方法がよく分からない
と感じたため、これ以上試すのはやめました。
b-PAC のFAQページにも
とあったことからも、やはりCOMを使うのが正しいのかなと感じました。
その他
なお、pythonnetでExcelを扱った場合は、
xlsx = Activator.CreateInstance(Type.GetTypeFromProgID('Excel.Application')) print("xlsx: {}".format(xlsx.__class__)) #=> xlsx: <class 'Microsoft.Office.Interop.Excel.ApplicationClass'>
のように良い感じになっていましたので、それ以降もうまいこと使える印象を受けました。
ソースコード
プリンタ情報の取得だけですが、GitHubに上げました。
thinkAmi-sandbox/bpac_python-sample
pythonnet_ver.py
が今回のファイルになります。