2

i have written a user control for WinCC (Siemens) (SCADA). Now I want to pass a pointer to the control. The only way to do this is: write the pointer to a property.

WinCC has only this methods to set properties

  • SetPropBOOL
  • SetPropChar
  • SetPropDouble
  • SetPropWord

The property from control has UInt as datatype and i use the SetPropDouble method to set the address from an object.

WinCC Global Script (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 );

I've debug my control (hook on WinCC-process) and i see the property-set becomes assigned an address-value e.g. 0x03041080.

Now the question: How can i get the object in c# (.Net) on the address?

My try throws an exception: 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: i've changed my code to use STRING

WinCC

extern __object* autoDB;
DWORD addr = (DWORD)autoDB;
char sAddr[11];
sprintf( sAddr, "%d\0", addr );
SetPropChar( "PictureName", "ControlName", "DataBaseAddr", sAddr );

And c# is now

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!
    }
}

Other findings!

The address from the ADO-Object is not in the process-memory who called my control (debug with ollydbg). WinCC has two programs: PDLRT.exe for visualisation (this is calling my control) and SCRIPT.exe for running GLOBAL-SCRIPT (Ansi-C).

From PDLRT, i've access to the pointer-address from ADO-Object. By call GCHandle in C# of the ADO-object-address, the exception is thrown. (ExecutionEngineException)

4

2 回答 2

3

我不知道 C# 是否可以像这样通过指向 C++ 的指针进行访问。

无论如何, this:(DWORD)(&autoDB)是错误的,它将指针的地址作为属性的值,这是没有意义的。

您需要指针的值,即(DWORD) autoDB.

此外,SetPropDouble()接受类型的值double,即浮点数。这不是共享指针的好方法,指针是(大)整数。尝试一些不同的表示,如果您无法访问足够大的整数,字符串可能会起作用。

于 2014-06-04T09:39:09.883 回答
0

好的,

很久以前,我已经请求支持Siemens

西门子:加载的 Dll、控件等加载在单独的内存中,而不是在应用程序(主)内存中。Dlls,控件之间的内存地址共享....不起作用。都有单独的记忆。

极好的。唯一方法:管道或其他通信实现(TCP/IP,...)。

于 2018-07-27T11:27:13.823 回答