CookieGetterの修正
和魂に入れているCookieGetterの修正を、本来のCookieGetter側に入れようとしている。
それだけではつまらないので、CookieGetterの最大の問題である「firefoxを使うときSQLiteのC#ラッパDLLのバージョンがビルド時と違うモノを使うと落ちる」を修正してみる。
この間書いたエントリの通り、動的にDLLを読み込めばOK。
まだ、十分見直していないのだが、classFirefoxCookieGetter.cs ファイルを以下の様に書き換える。
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.Reflection;
namespace CookieGetter
{
class classFirefoxCookieGetter
{
static public ICookieGetter getInstance(classCookieGetter.BROWSER_TYPE browser)
{
ICookieGetter obj = null;
switch (browser)
{
case classCookieGetter.BROWSER_TYPE.FIREFOX3:
obj = new classFirefox3CookieGetter();
break;
}
return obj;
}
private class classFirefox3CookieGetter : classCookieGetter
{
string assemblyName_ = "System.Data.SQLite.dll";
object hConnection_;
Type typeSQLiteConnection_;
Type typeSQLiteCommand_;
Type typeSQLiteDataReader_;
public classFirefox3CookieGetter()
{
// アセンブリ内のモジュールを取得
Assembly assembly = Assembly.LoadFrom(assemblyName_);
// アセンブリ内のクラスを取得
Module module = assembly.GetModule(assemblyName_);
typeSQLiteConnection_ = module.GetType("System.Data.SQLite.SQLiteConnection");
// クラスを動的に作成する
if (typeSQLiteConnection_ != null)
{
string file = searchFile(base.getAppdataPath() + "\\Mozilla\\Firefox\\Profiles\\", "cookies.sqlite", true);
hConnection_ = Activator.CreateInstance(typeSQLiteConnection_, new Object[] { "Data Source=" + file });
}
typeSQLiteCommand_ = module.GetType("System.Data.SQLite.SQLiteCommand");
typeSQLiteDataReader_ = module.GetType("System.Data.SQLite.SQLiteDataReader");
}
override public string getCookieValue(string url, string key)
{
string result = "";
string query = "SELECT value FROM moz_cookies where host==\'" + url + "\' AND name==\'" + key + "\'";
string[][] values = select_table(query);
if (values != null && values.Length > 0)
{
result = values[0][0];
}
else
{
result = "";
}
return result;
}
override public string[][] getCookies(string url)
{
string query = "SELECT name, value FROM moz_cookies where host==\'" + url + "\'";
return select_table(query);
}
private string[][] select_table(string query)
{
ArrayList values = new ArrayList();
//SQLiteConnection hConnection = new SQLiteConnection("Data Source=" + file);
//SQLiteCommand myCommand = new SQLiteCommand(query, hConnection);
Object myCommand = Activator.CreateInstance(typeSQLiteCommand_, new Object[] { query, hConnection_ });
// データベース接続を開く
//hConnection_.Open();
// ※:SQLiteConnection::Open()は、引数ありのメソッドが無いので、GetMethod()の第二引数を指定しなくてもOK
MethodInfo connectionOpen = typeSQLiteConnection_.GetMethod("Open");
connectionOpen.Invoke(hConnection_, null);
//SQLiteDataReader myReader;
//myReader = myCommand.ExecuteReader();
// ※:SQLiteCommand::ExecuteReader()はoverloadなメソッドが他にあるため、GetMethod()の第二引数に明示的に"引数なし"を指定する
MethodInfo connectionExecuteReader = typeSQLiteCommand_.GetMethod("ExecuteReader", new Type[0]);
object myReader = connectionExecuteReader.Invoke(myCommand, null);
//int fieldCount = myReader.FieldCount;
PropertyInfo readerfieldCount = typeSQLiteDataReader_.GetProperty("FieldCount");
int fieldCount = (int)readerfieldCount.GetValue(myReader, null);
string[] col;
MethodInfo readerRead = typeSQLiteDataReader_.GetMethod("Read");
MethodInfo readerGetString = typeSQLiteDataReader_.GetMethod("GetString", new Type[] { typeof(int) });
//while (myReader.Read())
// ※:SQLiteDataReader::Read()はoverloadなメソッドが他にあるため、GetMethod()の第二引数に明示的に"引数なし"を指定する
while ((bool)readerRead.Invoke(myReader, new Type[0]))
{
col = new string[fieldCount];
for (int i = 0; fieldCount > i; i++)
{
//col[i] = myReader.GetString(i);
col[i] = (string)readerGetString.Invoke(myReader, new object[] { (object)i });
}
values.Add(col);
}
//myReader.Close();
// ※:SQLiteDataReader::Close()は、引数ありのメソッドが無いので、GetMethod()の第二引数を指定しなくてもOK
MethodInfo readerClose = typeSQLiteDataReader_.GetMethod("Close");
readerClose.Invoke(myReader, null);
//hConnection.Close();
// ※:SQLiteConnection::Close()は、引数ありのメソッドが無いので、GetMethod()の第二引数を指定しなくてもOK
MethodInfo connectionClose = typeSQLiteConnection_.GetMethod("Close");
connectionClose.Invoke(hConnection_, null);
//hConnection.Dispose();
// ※:SQLiteConnection::Dispose()は、引数ありのメソッドが無いので、GetMethod()の第二引数を指定しなくてもOK
MethodInfo connectionDispose = typeSQLiteConnection_.GetMethod("Dispose");
connectionDispose.Invoke(hConnection_, null);
if (values.Count == 0)
{
return null;
}
else
{
return (string[][])values.ToArray(typeof(string[]));
}
}
}
}
}
問題はすでにfirefoxが実行されている状態でCookieを読もうとすると SQLiteConnection::Open() で例外「The database file is locked\r\ndatabase is locked」が発生してしまう。 これは、frefoxが起動中はクッキーファイルを LOCK したままにする仕様(?)の所為らしい。しょうがないので、例外をキャッチしなければならない・・・。
●ついで
SQLiteを使用するには、SQLite.dll と C#ラッパDLLが必要である。
- SQLite.dllは、本家HPから(上の方にある)メニューDOWNLOAD→Precompiled Binaries For Windowsにあるどれかで sqlite3.dll を取得する。例えば2009/11/22現在最新であるsqlite3_analyzer-3.6.1.zipとか。sqlite3.dllは、パスが通っているところに入れる。別にCookieGetterを動かすAPと同じディレクトリにあってもよい。
- C#ラッパDLLは、sourceFORGEから拾ってくる。System.Data.SQLite.DLLが必要。SQLite-1.0.65.0-source.zip を落として、binディレクトリにある System.Data.SQLite.DLL をアプリのexeがあるところに置けば良い。
もう眠い・・・、実際に修正したものをアップするのは明日ソースを確認してからにしよう。
« 読了:屍肉の聖餐 | トップページ | 今日届いた本 »
« 読了:屍肉の聖餐 | トップページ | 今日届いた本 »
コメント