private void Btn_DisConn_Click(object sender, EventArgs e) { try { if (IOPCSyncIO20Obj != null) { Marshal.ReleaseComObject(IOPCSyncIO20Obj); IOPCSyncIO20Obj = null; } ServerObj.RemoveGroup(pSvrGroupHandle, 0); if (IOPCGroupStateMgtObj != null) { Marshal.ReleaseComObject(IOPCGroupStateMgtObj); IOPCGroupStateMgtObj = null; } if (MyobjGroup1 != null) { Marshal.ReleaseComObject(MyobjGroup1); MyobjGroup1 = null; } if (ServerObj != null) { Marshal.ReleaseComObject(ServerObj); ServerObj = null; } } catch (System.Exception error) { MessageBox.Show(error.Message, "Result-Stop Server", MessageBoxButtons.OK, MessageBoxIcon.Error); } }
int pSvrGroupHandle = 0; //OPCGroup句柄 //连接OPCServer,建立相应OPCGroup组,并添加需要读写的Item private void Btn_Conn_Click(object sender, EventArgs e) { //定义变量 Type svrComponenttype; Int32 dwRequestedUpdateRate = 1000; //订阅读取速度 Int32 hClientGroup = 1; Int32 pRevUpdateRate; OpcRcw.Da.OPCITEMDEF[] ItemArray; float deadband = 0; int TimeBias = 0; //使用C#托管代码时,内存地址和GC回收不需要关心,CLR已经给我们暗箱操作 //如果在C#中调用了非托管代码,比如VC的DLL,而且它有一个回调函数,需要引用C#中的某个对象并操作,这时候需要小心 //要是非托管代码中用到的托管代码那个对象被GC给回收了,这时候就会报内存错误 //所以就要把那个对象钉住"Pin",让它的内存地址固定,而不被垃圾回收掉,然后我们自己管理,自己释放内存,这时候就需要GCHandle GCHandle hTimeBias, hDeadband; hTimeBias = GCHandle.Alloc(TimeBias, GCHandleType.Pinned); hDeadband = GCHandle.Alloc(deadband, GCHandleType.Pinned); Guid iidRequiredInterface = typeof(IOPCItemMgt).GUID; try { svrComponenttype = Type.GetTypeFromProgID("OPC.SimaticNet", "192.168.0.102"); //OPCServer ServerObj = (OpcRcw.Da.IOPCServer)Activator.CreateInstance(svrComponenttype); //注册 try { ServerObj.AddGroup("MyOPCGroup1", //增加组 0, dwRequestedUpdateRate, hClientGroup, hTimeBias.AddrOfPinnedObject(), hDeadband.AddrOfPinnedObject(), LOCALE_ID, out pSvrGroupHandle, out pRevUpdateRate, ref iidRequiredInterface, out MyobjGroup1); IOPCSyncIO20Obj = (IOPCSyncIO)MyobjGroup1; //Query interface for sync calls on group object IOPCGroupStateMgtObj = (IOPCGroupStateMgt)MyobjGroup1; ItemArray = new OPCITEMDEF[2]; //定义读写的item,共2个变量 ItemArray[0].szAccessPath = ""; ItemArray[0].szItemID = "S7:[S7 conncetion_1]DB10,INT0"; //地址,不同数据类型表示方法不同 ItemArray[0].bActive = 1; //是否激活 ItemArray[0].hClient = 1; //表示ID ItemArray[0].dwBlobSize = 0; ItemArray[0].vtRequestedDataType = 2; ItemArray[1].szAccessPath = ""; ItemArray[1].szItemID = "S7:[S7 connection_1]DB10,STRING14.10"; ItemArray[1].bActive = 1; ItemArray[1].hClient = 2; ItemArray[1].dwBlobSize = 0; ItemArray[1].pBlob = IntPtr.Zero; ItemArray[1].vtRequestedDataType = 8; IntPtr pResults = IntPtr.Zero; IntPtr pErrors = IntPtr.Zero; try { ((OpcRcw.Da.IOPCItemMgt)MyobjGroup1).AddItems(2, ItemArray, out pResults, out pErrors); int[] errors = new int[2]; IntPtr pos = pResults; ItemServerHandle = new int[2]; Marshal.Copy(pErrors, errors, 0, 2); if (errors[0] == 0) { OPCITEMRESULT result = (OPCITEMRESULT)Marshal.PtrToStructure(pos, typeof(OPCITEMRESULT)); ItemServerHandle[0] = result.hServer; } if (errors[1] == 0) { pos = new IntPtr(pos.ToInt32() + Marshal.SizeOf(typeof(OPCITEMRESULT))); OPCITEMRESULT result = (OPCITEMRESULT)Marshal.PtrToStructure(pos, typeof(OPCITEMRESULT)); ItemServerHandle[1] = result.hServer; } } catch (System.Exception error) { MessageBox.Show(error.Message, "Result-Adding Items", MessageBoxButtons.OK, MessageBoxIcon.Error); } finally { //free the memory if (pResults != IntPtr.Zero) { Marshal.FreeCoTaskMem(pResults); pResults = IntPtr.Zero; } if (pErrors != IntPtr.Zero) { Marshal.FreeCoTaskMem(pErrors); pErrors = IntPtr.Zero; } } } catch (System.Exception error) { MessageBox.Show(String.Format("Error while creating group object:-{0}", error.Message), "Result-Add group", MessageBoxButtons.AbortRetryIgnore, MessageBoxIcon.Error); } finally { if (hDeadband.IsAllocated) { hDeadband.Free(); } if (hTimeBias.IsAllocated) { hTimeBias.Free(); } } } catch (System.Exception error) { MessageBox.Show(String.Format("Error while creating server object:-{0}", error.Message), "Result-Create Server", MessageBoxButtons.AbortRetryIgnore, MessageBoxIcon.Error); } }
/// <summary> /// 添加组和标签异步读取 /// </summary> /// <param name="name"></param> public static void OPCServerADDgroup(string name, string itemname) { Int32 dwRequestedUpdateRate = 1000; Int32 hClientGroup = 1; Int32 pRevUpdateRate; float deadband = 0; int TimeBias = 0; GCHandle hTimeBias, hDeadband; hTimeBias = GCHandle.Alloc(TimeBias, GCHandleType.Pinned); hDeadband = GCHandle.Alloc(deadband, GCHandleType.Pinned); Guid iidRequiredInterface = typeof(IOPCItemMgt).GUID; if (connectedOK == false) { MessageBox.Show("OPC服务器没有连接,读取数据失败"); return; } IntPtr pResults = IntPtr.Zero; /* 保存AddItems函数的执行结果 */ IntPtr pErrors = IntPtr.Zero; /* 保存AddItems函数的执行错误 */ /* 执行结果信息 */ try { Serverobj.AddGroup(name, 0, dwRequestedUpdateRate, hClientGroup, hTimeBias.AddrOfPinnedObject(), hDeadband.AddrOfPinnedObject(), LOCALE_ID, out pSvrGroupHandle, out pRevUpdateRate, ref iidRequiredInterface, out MyobjGroup1); //增加相应的组 IOPCAsyncIO2Obj = (IOPCAsyncIO2)MyobjGroup1; //为组同步读写定义句柄 IOPCGroupStateMgtObj = (IOPCGroupStateMgt)MyobjGroup1; //组管理对象 pIConnectionPointContainer = (IConnectionPointContainer)MyobjGroup1; //增加特定组的异步调用连接 Guid iid = typeof(IOPCDataCallback).GUID; //为所有的异步调用创建回调 pIConnectionPointContainer.FindConnectionPoint(ref iid, out pIConnectionPoint); //为OPC server 的连接点与客户端接收点之间建立连接 // pIConnectionPoint.Advise(this, out dwCookie); tItemSvrHandleArray = new int[1]; OPCITEMDEF[] itemarray = new OPCITEMDEF[4]; itemarray[0].szAccessPath = ""; /* 访问路径"" */ itemarray[0].szItemID = itemname; /* OPC标签名称 */ itemarray[0].hClient = 1; tItemSvrHandleArray[0] = 1; /* 客户机的标签索引 */ itemarray[0].dwBlobSize = 0; itemarray[0].pBlob = IntPtr.Zero; itemarray[0].vtRequestedDataType = 2; ItemSvrHandleArray = new int[1, 1]; ((IOPCItemMgt)MyobjGroup1).AddItems(1, itemarray, out pResults, out pErrors); //将标签加入到组中 int[] errors = new int[1]; /* 每个标签的错误信息 */ IntPtr pos = pResults; Marshal.Copy(pErrors, errors, 0, 1); /* pErrors->errors */ for (int i = 0; i < 1; i++) /* 检查每个标签的error */ { if (errors[i] == 0) /* 如果无错误=0 */ { if (i != 0) /* 如果不是第一个标签则指针移动一个OPCITEMRESULT */ { pos = new IntPtr(pos.ToInt32() + Marshal.SizeOf(typeof(OPCITEMRESULT))); } OPCITEMRESULT result = (OPCITEMRESULT)Marshal.PtrToStructure(pos, typeof(OPCITEMRESULT)); /* IntPtr->OPCITEMRESULT */ ItemSvrHandleArray[0, 0] = result.hServer; /* 保存该标签在服务器中的句柄,以后读写标签数值时要用到 */ } else { /* 如果有错误(向服务器添加标签失败) */ connectedOK = false; /* 连接失败 */ // String strError; // Serverobj.GetErrorString(errors[i], LOCALE_ID, out strError); /* 获取错误信息 */ // OutputExceptionToDatabase(.......) /* 将异常信息输出到数据库 */ throw new Exception("添加标签:" + itemarray[i].szItemID + " 错误!" //+ strError ); /* 抛出异常 */ } } } catch (System.Exception error) { MessageBox.Show("group组添加失败失败\n" + error.Message); } finally { if (pResults != IntPtr.Zero) { Marshal.FreeCoTaskMem(pResults); pErrors = IntPtr.Zero; } if (pErrors != IntPtr.Zero) { Marshal.FreeCoTaskMem(pErrors); pErrors = IntPtr.Zero; } } }