質問
WinCC(Siemens)(SCADA)のためのユーザー制御を書いた。今、私はコントロールへのポインタを渡したいです。これを行う唯一の方法は、プロパティへのポインタを書き込みます。
WinCCには、プロパティを設定する方法のみがあります。
- setpropbool
- setpropchar
- setpropdouble
- setpropword
コントロールからのプロパティにはUINTがデータ型としてUINTがあり、SetPropDoubleメソッドを使用してオブジェクトからアドレスを設定します。
WinCCグローバルスクリプト(ANSI-C)
//autoDB is an ADODB.Connection object
//object* autoDB = __object_create("ADODB.Connection");
extern __object* autoDB;
//SetPropDouble( "PictureName", "ControlName", "PropertyName", (DWORD)(&autoDB) );
SetPropDouble( "PictureName", "ControlName", "PropertyName", (DWORD)autoDB );
.
私は自分のコントロールをデバッグしました(WinCCプロセス上のフック)、プロパティセットがアドレス値を割り当てられるようになります。 0x03041080。
今質問:アドレスのC#(.NET)でオブジェクトを取得する方法は?
私の試してみる例外をスローする: executionEngineException
private ADODB.Connection _database;
private IntPtr _ptr = IntPtr.Zero;
public uint DataBase{
get{
return (uint)_ptr;
}
set{
if( value != 0 ){
_ptr = (IntPtr)value;
GCHandle gH = GCHandle.FromIntPtr(_ptr); // THIS LINE THROW THE EXCEPTION
_database = gH.Target;
}
}
}
.
OK:STRING
を使用するようにコードを変更しました
wincc
extern __object* autoDB;
DWORD addr = (DWORD)autoDB;
char sAddr[11];
sprintf( sAddr, "%d\0", addr );
SetPropChar( "PictureName", "ControlName", "DataBaseAddr", sAddr );
.
とC#が
private string _lpszDataBaseAddr = "";
public string DataBaseAddr{
get{
return _lpszDataBaseAddr;
}
set{
uint addr;
bool ret = uint.TryParse( value, out addr );
if( ! ret ){
return;
}
IntPtr ptr = (IntPtr)addr;
GCHandle gH = GCHandle.FromIntPtr( ptr ); // THE SAME ERROR!
}
}
.
その他の発見!
ADOオブジェクトからのアドレスは、コントロールを呼び出したプロセスメモリにはありません(OllyDBGとのデバッグ)。 WinCCには2つのプログラムがあります。視覚化のためのPDLRT.exe(これが私のコントロールを呼び出しています)およびscript.exeを実行して、グローバルスクリプト(ANSI-C)を実行しています。
PDLRTから、ADOオブジェクトからのポインタアドレスにアクセスしました。 ADOオブジェクトアドレスのC#のCall GChandleによって、例外がスローされます。 ( ExecutionEngineException )
解決 2
OK、
昔、Siemens
からサポートに尋ねます。
Siemens:ロードされたDLL、コントロールなどは、アプリケーション(メイン)メモリではなく、分離されたメモリにロードされます。DLL、コントロールの間のメモリアドレスシェアが機能していません。すべて分離されたメモリがあります。
スーパー。唯一の方法:パイプまたは他の通信実装(TCP / IP、...)。
他のヒント
C#がそのようなC ++へのポインタを通してアクセスできるかどうかはわかりません。
関係:(DWORD)(&autoDB)
は間違っています。これは、ポインタのアドレスを、無意味なプロパティの値として設定します。
ポインタの値、すなわち(DWORD) autoDB
。
また、SetPropDouble()
は、double
型の値、すなわち浮動小数点数を受け入れます。それはポインタを共有するための非常に良い方法ではありません。いくつかの異なる表現を試してください、文字列は十分な大きさの整数にアクセスできない場合は機能します。