【发布时间】:2014-06-04 09:37:38
【问题描述】:
我为 WinCC (Siemens) (SCADA) 编写了一个用户控件。现在我想将一个指针传递给控件。这样做的唯一方法是:将指针写入属性。
WinCC只有这个方法来设置属性
- SetPropBOOL
- SetPropChar
- SetPropDouble
- SetPropWord
控件的属性具有 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;
}
}
}
好的:我已将代码更改为使用 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-Object 的地址不在调用我的控件的进程内存中(使用 ollydbg 进行调试)。 WinCC 有两个程序:用于可视化的 PDLRT.exe(这是调用我的控件)和用于运行 GLOBAL-SCRIPT (Ansi-C) 的 SCRIPT.exe。
从 PDLRT,我可以访问来自 ADO-Object 的指针地址。通过在 ADO-object-address 的 C# 中调用 GCHandle,将引发异常。 (ExecutionEngineException)
【问题讨论】: