public OpcConnector(string progId, string plcName, string opcAddressFmt)
        {
            m_The_srv = new OpcServer();
            m_The_srv.Connect(progId);
            Thread.Sleep(500); // we are faster then some servers!

            // add our only working group
            m_The_grp = m_The_srv.AddGroup(plcName + "-strings", false, 900);

            // add two items and save server handles
            for (int i = 0; i < StrCount; i++)
                m_Item_defs[i] = new OPCItemDef(string.Format(opcAddressFmt, plcName, 272 + i*6), true, i + 1,
                                                VarEnum.VT_EMPTY);
            OPCItemResult[] rItm;
            m_The_grp.AddItems(m_Item_defs, out rItm);
            if (rItm == null) return;
            if (HRESULTS.Failed(rItm[0].Error) || HRESULTS.Failed(rItm[1].Error)) {
                InstantLogger.msg("OPCDirectWriter: {0} -- AddItems - some failed", plcName);
                m_The_grp.Remove(true);
                m_The_srv.Disconnect();
                return;
            }
            for (int i = 0; i < StrCount; i++)
                m_Handles_srv[i] = rItm[i].HandleServer;
            m_The_grp.WriteCompleted += TheGrpWriteComplete;
        }
Exemplo n.º 2
0
        protected void OnConnect()
        {
            List<OPCItemDef> items = new List<OPCItemDef>();
            string[] codes =
            {
                "VW134,WORD",
                "VD114,REAL",
                "VW159,WORD",
                "VD34,REAL",
                "VD54,REAL",
                "VD74,REAL",
                "VB485,BYTE",
                "VW313,WORD",
                "VW890,WORD",
                "A0.1,BOOL",
                "A0.2,BOOL",
                "A1.0,BOOL",
                "VB490,BYTE",
                "E0.3,BOOL",
                "AEW4,WORD",
                "AEW6,WORD",
                "A0.6,BOOL"
            };
            int i = 0;
            foreach (var code in codes)
            {
                i++;
                OPCItemDef item = new OPCItemDef(this.Code(code), true, i, VarEnum.VT_EMPTY);
                items.Add(item);
            }

            if (this.group.AddItems(items.ToArray(), out this.results))
            {
                RecordManager.DoSystemEventRecord(this, string.Format("AddItems OK"), RecordType.Event, true);
                int[] data = this.results.Select((r) => r.HandleServer).ToArray();

                RecordManager.DoSystemEventRecord(this, string.Join(", ", data), RecordType.Event, true);

            }
            else
            {
                RecordManager.DoSystemEventRecord(this, string.Format("AddItems Failed"), RecordType.Error, true);

            }
        }
        private void buttProbeSincRead_Click(object sender,EventArgs e)
        {
            OpcGroup theSinchroGrp;    // ���������� ��� ���, ���� ������
             OPCItemDef[] aD;           // ��(���������)�����, ���� ������
             OPCItemResult[] arrRes;    // ����������� ����������
             OPCItemState[] sts;        // �������(���������)�� ������ ��������� �����
             int[] serverhandles;       // ��� ������ ����� �.�.���� ����������
             string sPLC_Adr = "S7:[PLC01]DB2,int102";
             string[] sPLC_AdrLi = { "S7:[PLC01]DB2,int102"  // ACT_WATCHDOG01_PLC
                               ,"S7:[PLC11]DB2,int48"    // ACT_C1_WATCHDOG1_PLC
                               ,"S7:[PLC21]DB2,int48"    // ACT_C2_WATCHDOG1_PLC
                               ,"S7:[PLC31]DB2,int48"    // ACT_C3_WATCHDOG1_PLC
                               };
             string sErgValue = "";
             bool bErg = true;
             clsPointInfo[] probePointLi = new clsPointInfo[sPLC_AdrLi.GetLength(0)];

             try {
            theSinchroGrp = theSrv.AddGroup("OPCdotNET-Sinchro",true,60000);
            aD = new OPCItemDef[1];

            aD[0] = new OPCItemDef(sPLC_Adr,true,itmHandleClient,VarEnum.VT_EMPTY);
            theGrp.AddItems(aD,out arrRes);
            if (arrRes == null) {
               MessageBox.Show(this,"AddItems" + i,"arrRes == null",MessageBoxButtons.OK,MessageBoxIcon.Warning);
               }
            else {
               if (arrRes[0].Error != HRESULTS.S_OK) {
                  MessageBox.Show(this,"AddItems" + i,"arrRes[0].Error != HRESULTS.S_OK",MessageBoxButtons.OK,MessageBoxIcon.Warning);
                  }
               }

            //// add event handler for data changes
            //theSinchroGrp.DataChanged += new DataChangeEventHandler(this.theGrp_DataChange);
            //theSinchroGrp.WriteCompleted += new WriteCompleteEventHandler(this.theGrp_WriteComplete);
            sts = new OPCItemState[1];       // �� ����, ����� �� �������������
            itmHandleServer = 0;             // ��� �� 0. ������� � "sPLC_AdrLi"
            serverhandles = new int[1] { itmHandleServer };
            theSinchroGrp.Read(OPCDATASOURCE.OPC_DS_DEVICE,serverhandles,out sts);  // ������ ��������� ����� ��������� �����
            foreach (OPCItemState s in sts) {
               try {
                  if (HRESULTS.Succeeded(s.Error)) {
                     if (s.HandleClient < sPLC_AdrLi.GetLength(0)) {
                        if (s.DataValue != null) {
                           setTextInTxbViaDelegate(ref txtItemQual,OpcGroup.QualityToString(s.Quality));
                           setTextInTxbViaDelegate(ref txtItemTimeSt,DateTime.FromFileTime(s.TimeStamp).ToString());
                           probePointLi[s.HandleClient].opcItem = s;
                           if (s.DataValue.GetType() == typeof(SByte[])) {
                              probePointLi[s.HandleClient].sDataValue = ConvertToRus((SByte[])s.DataValue,probePointLi[s.HandleClient].iDataLength);
                              setTextInTxbViaDelegate(ref txtItemValue,probePointLi[s.HandleClient].sDataValue);
                              sErgValue = probePointLi[s.HandleClient].sDataValue;
                              }
                           else {
                              if (s.DataValue.GetType() == typeof(DateTime)) {
                                 probePointLi[s.HandleClient].dtDataValue = Convert.ToDateTime(s.DataValue);
                                 setTextInTxbViaDelegate(ref txtItemValue,LoggDateToString(probePointLi[s.HandleClient].dtDataValue));
                                 sErgValue = LoggDateToString(probePointLi[s.HandleClient].dtDataValue);
                                 }
                              else {
                                 probePointLi[s.HandleClient].iDataValue = Convert.ToInt32(s.DataValue);
                                 setTextInTxbViaDelegate(ref txtItemValue,probePointLi[s.HandleClient].iDataValue.ToString());
                                 sErgValue = probePointLi[s.HandleClient].iDataValue.ToString();
                                 }
                              }
                           AddLogg("Pkt" + s.HandleClient + "," + s.DataValue.GetType() + " ��������: '" + sErgValue + "'");
                           }
                        else {
                           AddLogg("s.HandleClient{" + s.HandleClient + "}>=probePointLi.Count{" + sPLC_AdrLi.GetLength(0) + "}");
                           }
                        }
                     }
                  else {
                     setTextInTxbViaDelegate(ref txtItemTimeSt,DateTime.FromFileTime(s.TimeStamp).ToString());
                     setTextInTxbViaDelegate(ref txtItemQual,"error");
                     setTextInTxbViaDelegate(ref txtItemValue,"ERROR 0x" + s.Error.ToString("X"));
                     AddLogg("s.HandleClient{" + s.HandleClient + "} ERROR 0x" + s.Error.ToString("X"));
                     }
                  }
               catch (Exception exc) {
                  AddLogg("Pkt" + s.HandleClient + ","
                     + ((s.DataValue == null) ? " DataValue==null" : s.DataValue.GetType().ToString())
                     + " " + exc.Message);
                  }
               }
            GC.Collect(); // just for fun
            }
             catch (Exception eXc) {
            MessageBox.Show(this,"OPC Exception!",eXc.Message,MessageBoxButtons.OK,MessageBoxIcon.Warning);
            return;
            }
        }
        //------------------------ ��� ������ ���� 1 ����� � ������ !!!
        // opcid    "S7:[PLC31]db2,int12"
        public bool ViewItem(string opcid)
        {
            try {
            RemoveItem();		// first remove previous item if any

            itmHandleClient = 1234;
            OPCItemDef[] aD = new OPCItemDef[1];
            aD[0] = new OPCItemDef(opcid,true,itmHandleClient,VarEnum.VT_EMPTY);
            OPCItemResult[] arrRes;
            theGrp.AddItems(aD,out arrRes);
            if (arrRes == null)
               return false;
            if (arrRes[0].Error != HRESULTS.S_OK)
               return false;

            itmHandleServer = arrRes[0].HandleServer;
            itmAccessRights = arrRes[0].AccessRights;
            itmTypeCode = VT2TypeCode(arrRes[0].CanonicalDataType);
            txtItemDataType.Text = DUMMY_VARIANT.VarEnumToString(arrRes[0].CanonicalDataType);

            if ((itmAccessRights & OPCACCESSRIGHTS.OPC_READABLE) != 0) {
               int cancelID;
               theGrp.Refresh2(OPCDATASOURCE.OPC_DS_DEVICE,7788,out cancelID);
               }
            else
               txtItemValue.Text = "no read access";

            if (itmTypeCode != TypeCode.Object)				// Object=failed!
                {
               // check if write is premitted
               //if ((itmAccessRights & OPCACCESSRIGHTS.OPC_WRITEABLE) != 0)
               //btnItemWrite.Enabled = true;
               }
            }
             catch (COMException) {
            MessageBox.Show(this,"AddItem " + opcid + " OPC error!","ViewItem",MessageBoxButtons.OK,MessageBoxIcon.Warning);
            return false;
            }
             return true;
        }
        public bool DoInit()
        {
            string[] itemstrings = new string[5];
             string sPLC_Adr = "*UnDef*",sAlias = "*UnDef*",sGroup = "",sDesc = "";
             int iPLCDataLength;

             sAliasToControl = "ACT_C1_STAHLMARKE0";
             itemstrings[2] = itemstrings[3] = itemstrings[4] = "-";
             try {
            selectedOpcSrv = "OPC.SimaticNET.1";   // ����� ���� ��������
            AddLogg("������� �� " + sCompName);
            AddLogg("LoadDefinitions()-Start");
            LoadDefinitions();
            AddLogg("LoadDefinitions()-End");

            theSrv = new OpcServer();
            if (!DoConnect(selectedOpcSrv)) {
               AddLogg("DoConnect(" + selectedOpcSrv + ")=false");
               //////////return false;
               }
            // add event handler for server shutdown
            theSrv.ShutdownRequested += new ShutdownRequestEventHandler(this.theSrv_ServerShutDown);
            // precreate the only OPC group in this example
            if (!CreateGroup()) {
               AddLogg("CreateGroup()=false");
               //////////return false;
               }
            AddLogg("DoInit: Start");
            RemoveItem();		// first remove previous item if any
            cbCtrlAliases.Items.Clear();
            groupLi = new List<clsGroupInfo>();
            pointLi = new List<clsPointInfo>();
            j = 0;
            for (i = 0; i < strItems_Alias.Count; i++) {
               try {
                  itemclsPointInfo = new clsPointInfo();
                  itmHandleClient = j;
                  sPLC_Adr = strItems_adrPLC[i];   // "LOCATION0   PLC13:DB2,STRING66,8" // S7:[PLC13]DB2,STRING66,8
                  sAlias = strItems_Alias[i];
                  sGroup = strItems_Groups[i];
                  sDesc = strItems_Desc[i];
                  //k = sPLC_Adr.IndexOf("STRING");
                  k = sPLC_Adr.IndexOf("CHAR");
                  if (k < 0) {
                     itemclsPointInfo.iDataLength = 0;
                     }
                  else {
                     string[] sSplitted = sPLC_Adr.Trim().Split(',');
                     itemclsPointInfo.iDataLength = Convert.ToInt32(sSplitted[sSplitted.GetLength(0) - 1].Trim());
                     }
                  OPCItemDef[] aD = new OPCItemDef[1];
                  aD[0] = new OPCItemDef(sPLC_Adr,true,itmHandleClient,VarEnum.VT_EMPTY);
                  OPCItemResult[] arrRes;
                  theGrp.AddItems(aD,out arrRes);
                  if (arrRes == null) {
                     AddLogg("DoInit:AddItem" + i + " " + sPLC_Adr + " arrRes == null");
                     //continue;
                     }
                  else {
                     if (arrRes[0].Error != HRESULTS.S_OK) {
                        AddLogg("DoInit:AddItem" + i + " " + sPLC_Adr + " arrRes[0].Error != HRESULTS.S_OK");
                        //continue;
                        }
                     else {
                        itmHandleServer = arrRes[0].HandleServer;
                        itmAccessRights = arrRes[0].AccessRights;
                        itmTypeCode = VT2TypeCode(arrRes[0].CanonicalDataType);

                        txbActPoint.Text = sPLC_Adr;
                        txtItemDataType.Text = DUMMY_VARIANT.VarEnumToString(arrRes[0].CanonicalDataType);

                        //if ((itmAccessRights & OPCACCESSRIGHTS.OPC_READABLE) != 0) {
                        //   int cancelID;
                        //   theGrp.Refresh2(OPCDATASOURCE.OPC_DS_DEVICE,7788,out cancelID);
                        //   }
                        //else {
                        //   txtItemValue.Text = "no read access";
                        //   AddLogg("DoInit:AddItem" + i + " " + sPLC_Adr + " no read access");
                        //   }
                        if (itmTypeCode != TypeCode.Object) {
                           // Object=failed!
                           ////AddLogg("DoInit:AddItem" + i + " " + sPLC_Adr + " Object=failed");
                           // check if write is permitted
                           if ((itmAccessRights & OPCACCESSRIGHTS.OPC_WRITEABLE) != 0) {
                              //btnItemWrite.Enabled = true;
                              ////AddLogg("DoInit:AddItem" + i + " " + sPLC_Adr + " write is permitted");
                              }
                           }
                        itemstrings[0] = sAlias;
                        itemstrings[1] = sPLC_Adr;
                        //listOpcView.Items.Add(new ListViewItem(itemstrings,0));
                        itemclsPointInfo.sAlias = sAlias;
                        string[] sEvtNameSplitted = sAlias.Split('_');
                        //for (k = 0; k < sEvtNameSplitted.GetLength(0); k++){
                        //   AddLogg("DEBUG sEvtNameSplitted[" + k + "] = '" + sEvtNameSplitted[k]+"'");
                        //}
                        if (sEvtNameSplitted[0] == "ACT" || sEvtNameSplitted[0] == "SP") {   // Fool-Proof
                           if (sEvtNameSplitted[1] == "C1" || sEvtNameSplitted[1] == "C2" || sEvtNameSplitted[1] == "C3") {
                              itemclsPointInfo.iCnvNr = Convert.ToInt32(sEvtNameSplitted[1].Substring(1,1));
                              if (sEvtNameSplitted[0] == "SP"){
                                 itemclsPointInfo.sAliasInfoTeil = itemclsPointInfo.sAlias.Substring(6,itemclsPointInfo.sAlias.Length -6);
                              }
                              else{
                                 itemclsPointInfo.sAliasInfoTeil = itemclsPointInfo.sAlias.Substring(7,itemclsPointInfo.sAlias.Length - 7);
                                 }
                           }
                           else {
                              itemclsPointInfo.iCnvNr = 0;
                              if (sEvtNameSplitted[0] == "SP"){
                                 itemclsPointInfo.sAliasInfoTeil = itemclsPointInfo.sAlias.Substring(3,itemclsPointInfo.sAlias.Length -3);
                              }
                              else{
                                 itemclsPointInfo.sAliasInfoTeil = itemclsPointInfo.sAlias.Substring(4,itemclsPointInfo.sAlias.Length - 4);
                                 }
                           }
                           if (sEvtNameSplitted[0] == "SP"){
                              itemclsPointInfo.bIsSetPoint = true;
                           }
                        }
                        else {
                           AddLogg("DoInit:AddItem" + i + " " + sAlias + " �� ���������� � 'ACT_'/'SP_'");
                           }
                        itemclsPointInfo.sPLC_Adr = sPLC_Adr;
                        itemclsPointInfo.sDesc = sDesc;
                        itemclsPointInfo.CanonicalDataType = arrRes[0].CanonicalDataType;
                        itemclsPointInfo.sCanonicalDataType = DUMMY_VARIANT.VarEnumToString(arrRes[0].CanonicalDataType);
                        itemclsPointInfo.AccessRights = arrRes[0].AccessRights;
                        itemclsPointInfo.itmTypeCode = itmTypeCode;

                        pointLi.Add(itemclsPointInfo);
                        cbCtrlAliases.Items.Add(sAlias + " " + sPLC_Adr);
                        // ���� � ������ ����
                        //k = groupLi.FindIndex(delegate(clsGroupInfo lfdGroupInfo) {  // ** ��� ���������
                        //                         return lfdGroupInfo.sName == sGroup;
                        //                         }
                        //                     );
                        string @group = sGroup;                                        // ** ����� !!!
                        k = groupLi.FindIndex(lfdGroupInfo => lfdGroupInfo.sName == group);
                        if (k < 0) {                                           // ��� ������ ����� ������, ��������������, ��� TAKE_OVER !!
                           itemclsGroupInfo = new clsGroupInfo();
                           itemclsGroupInfo.sName = sGroup;
                           groupLi.Add(itemclsGroupInfo);
                           pointLi[pointLi.Count - 1].bIsTakeOver = true;  // rueckwerts in PointLi schreiben
                           }
                        k = pointLi.Count - 1;                             // wegen DEBUG
                        pointLi[k].iIdxInGroupLi = groupLi.Count - 1;      // gehoert zu dieser Gruppe;rueckwerts in PointLi schreiben
                        k = groupLi.Count - 1;                             // wegen DEBUG
                        groupLi[k].iItemsCnt++;                            // so viele Punkte in der Gruppe
                        groupLi[k].iIdxInPointLi.Add(pointLi.Count - 1);   // eigentlisch Punkte(als pointLi[Index])
                        DoStoreToOracle(j);                                // AnfangsZustand in Oracle generieren
                        AddLogg("�������� Pkt" + j + " group '" + groupLi[k].sName + "',Alias'" + sAlias + "' " + sPLC_Adr);
                        j++;
                        }
                     }
                  }
               catch (/*COMException*/ Exception comExc)
               {
                  //MessageBox.Show(this,"AddItem " + sPLC_Adr + " OPC error!","DoInit",MessageBoxButtons.OK,MessageBoxIcon.Warning);
                  AddLogg("DoInit:AddItem" + i + " '" + sPLC_Adr + "' OPC exception:" + comExc.Message);
                  //return false;
                  continue;
                  }
               }
            int cancelID;
            theGrp.Refresh2(OPCDATASOURCE.OPC_DS_DEVICE,7788,out cancelID);
            }
             catch (Exception e) {		// exceptions MUST be handled
            //MessageBox.Show(this,"init error! " + e.ToString(),"Exception",MessageBoxButtons.OK,MessageBoxIcon.Warning);
            AddLogg("DoInit:AddItem" + i + " '" + sPLC_Adr + "' init error! " + e.Message);
            AddLogg("DoInit: Ende - false");
            return false;
            }
             AddLogg("DoInit: Ende-true,� pointLi " + pointLi.Count + " � groupLi " + groupLi.Count);
             mainGate = new MainGateClient(new InstanceContext(new DummyListener()));

             return true;
        }
        // -----------------------------------------------------------------------------------
        public bool ValidateItems(	OPCItemDef[] arrDef, bool blobUpd,
            out OPCItemResult[] arrRes)
        {
            arrRes			= null;
            bool hasblobs	= false;
            int	count		= arrDef.Length;

            IntPtr	ptrDef = Marshal.AllocCoTaskMem( count * sizeOPCITEMDEF );
            int	runDef = (int) ptrDef;
            OPCITEMDEFintern	idf = new OPCITEMDEFintern();
            idf.wReserved = 0;
            foreach( OPCItemDef d in arrDef )
            {
            idf.szAccessPath		= d.AccessPath;
            idf.szItemID			= d.ItemID;
            idf.bActive				= d.Active;
            idf.hClient				= d.HandleClient;
            idf.vtRequestedDataType	= (short) d.RequestedDataType;
            idf.dwBlobSize = 0;	idf.pBlob = IntPtr.Zero;
            if( d.Blob != null )
                {
                idf.dwBlobSize = d.Blob.Length;
                if( idf.dwBlobSize > 0 )
                    {
                    hasblobs = true;
                    idf.pBlob = Marshal.AllocCoTaskMem( idf.dwBlobSize );
                    Marshal.Copy( d.Blob, 0, idf.pBlob, idf.dwBlobSize );
                    }
                }

            Marshal.StructureToPtr( idf, (IntPtr) runDef, false );
            runDef += sizeOPCITEMDEF;
            }

            IntPtr	ptrRes;
            IntPtr	ptrErr;
            int	hresult = ifItems.ValidateItems( count, ptrDef, blobUpd, out ptrRes, out ptrErr );

            runDef = (int) ptrDef;
            if( hasblobs )
            {
            for( int i = 0; i < count; i++ )
                {
                IntPtr blob = (IntPtr) Marshal.ReadInt32( (IntPtr)(runDef + 20) );
                if( blob != IntPtr.Zero )
                    Marshal.FreeCoTaskMem( blob );
                Marshal.DestroyStructure( (IntPtr) runDef, typeOPCITEMDEF );
                runDef += sizeOPCITEMDEF;
                }
            }
            else
            {
            for( int i = 0; i < count; i++ )
                {
                Marshal.DestroyStructure( (IntPtr) runDef, typeOPCITEMDEF );
                runDef += sizeOPCITEMDEF;
                }
            }
            Marshal.FreeCoTaskMem( ptrDef );

            if( HRESULTS.Failed( hresult ) )
            Marshal.ThrowExceptionForHR( hresult );

            int	runRes = (int) ptrRes;
            int	runErr = (int) ptrErr;
            if( (runRes == 0) || (runErr == 0) )
            Marshal.ThrowExceptionForHR( HRESULTS.E_ABORT );

            arrRes		= new OPCItemResult[ count ];
            for( int i = 0; i < count; i++ )
            {
            arrRes[i] = new OPCItemResult();
            arrRes[i].Error = Marshal.ReadInt32( (IntPtr) runErr );
            if( HRESULTS.Failed( arrRes[i].Error ) )
                continue;

            arrRes[i].HandleServer		= Marshal.ReadInt32( (IntPtr) runRes );
            arrRes[i].CanonicalDataType	= (VarEnum)(int) Marshal.ReadInt16( (IntPtr)(runRes + 4) );
            arrRes[i].AccessRights		= (OPCACCESSRIGHTS) Marshal.ReadInt32( (IntPtr)(runRes + 8) );

            int ptrblob	= Marshal.ReadInt32( (IntPtr)(runRes + 16) );
            if( (ptrblob != 0) )
                {
                int blobsize	= Marshal.ReadInt32( (IntPtr)(runRes + 12) );
                if( blobsize > 0 )
                    {
                    arrRes[i].Blob = new byte[ blobsize ];
                    Marshal.Copy( (IntPtr) ptrblob, arrRes[i].Blob, 0, blobsize );
                    }
                Marshal.FreeCoTaskMem( (IntPtr) ptrblob );
                }

            runRes += sizeOPCITEMRESULT;
            runErr += 4;
            }

            Marshal.FreeCoTaskMem( ptrRes );
            Marshal.FreeCoTaskMem( ptrErr );
            return hresult == HRESULTS.S_OK;
        }
Exemplo n.º 7
0
        // ------------------------ IOPCItemMgt ---------------

        internal void AddItems(OPCItem[] items)
        {
            OPCItemDef[] arrDef = new OPCItemDef[items.Length];

            for (int i = 0; i < items.Length; i++)
            {
                arrDef[i] = new OPCItemDef(items[i].ID, items[i].HandleClient);
            }


            bool hasblobs = false;
            int  count    = arrDef.Length;

            IntPtr           ptrDef = Marshal.AllocCoTaskMem(count * sizeOPCITEMDEF);
            int              runDef = (int)ptrDef;
            OPCITEMDEFintern idf    = new OPCITEMDEFintern();

            idf.wReserved = 0;
            foreach (OPCItemDef d in arrDef)
            {
                idf.szAccessPath        = d.AccessPath;
                idf.szItemID            = d.ItemID;
                idf.bActive             = d.Active;
                idf.hClient             = d.HandleClient;
                idf.vtRequestedDataType = (short)d.RequestedDataType;
                idf.dwBlobSize          = 0; idf.pBlob = IntPtr.Zero;
                if (d.Blob != null)
                {
                    idf.dwBlobSize = d.Blob.Length;
                    if (idf.dwBlobSize > 0)
                    {
                        hasblobs  = true;
                        idf.pBlob = Marshal.AllocCoTaskMem(idf.dwBlobSize);
                        Marshal.Copy(d.Blob, 0, idf.pBlob, idf.dwBlobSize);
                    }
                }

                Marshal.StructureToPtr(idf, (IntPtr)runDef, false);
                runDef += sizeOPCITEMDEF;
            }

            IntPtr ptrRes;
            IntPtr ptrErr;
            int    hresult = ifItems.AddItems(count, ptrDef, out ptrRes, out ptrErr);

            runDef = (int)ptrDef;
            if (hasblobs)
            {
                for (int i = 0; i < count; i++)
                {
                    IntPtr blob = (IntPtr)Marshal.ReadInt32((IntPtr)(runDef + 20));
                    if (blob != IntPtr.Zero)
                    {
                        Marshal.FreeCoTaskMem(blob);
                    }
                    Marshal.DestroyStructure((IntPtr)runDef, typeOPCITEMDEF);
                    runDef += sizeOPCITEMDEF;
                }
            }
            else
            {
                for (int i = 0; i < count; i++)
                {
                    Marshal.DestroyStructure((IntPtr)runDef, typeOPCITEMDEF);
                    runDef += sizeOPCITEMDEF;
                }
            }
            Marshal.FreeCoTaskMem(ptrDef);

            if (HRESULTS.Failed(hresult))
            {
                Marshal.ThrowExceptionForHR(hresult);
            }

            int runRes = (int)ptrRes;
            int runErr = (int)ptrErr;

            if ((runRes == 0) || (runErr == 0))
            {
                Marshal.ThrowExceptionForHR(HRESULTS.E_ABORT);
            }


            for (int i = 0; i < count; i++)
            {
                OPCItem item = items[i];
                item.Group = this;
                item.Error = Marshal.ReadInt32((IntPtr)runErr);
                if (HRESULTS.Failed(item.Error))
                {
                    continue;
                }

                item.HandleServer = Marshal.ReadInt32((IntPtr)runRes);
                item.DataType     = Helper.VT2TypeCode((VarEnum)(int)Marshal.ReadInt16((IntPtr)(runRes + 4)));
                item.AccessRights = (OPCACCESSRIGHTS)Marshal.ReadInt32((IntPtr)(runRes + 8));

                int ptrblob = Marshal.ReadInt32((IntPtr)(runRes + 16));
                if ((ptrblob != 0))
                {
                    int blobsize = Marshal.ReadInt32((IntPtr)(runRes + 12));
                    if (blobsize > 0)
                    {
                        item.Blob = new byte[blobsize];
                        Marshal.Copy((IntPtr)ptrblob, item.Blob, 0, blobsize);
                    }
                    Marshal.FreeCoTaskMem((IntPtr)ptrblob);
                }

                runRes += sizeOPCITEMRESULT;
                runErr += 4;
            }

            Marshal.FreeCoTaskMem(ptrRes);
            Marshal.FreeCoTaskMem(ptrErr);
            if (hresult == HRESULTS.S_OK)
            {
                return;
            }
            else
            {
                string itemstring = "";
                foreach (OPCItem item in items)
                {
                    itemstring += item.ID + ",";
                }

                try
                {
                    Exception excep = Marshal.GetExceptionForHR(hresult);

                    throw (new Exception(excep.Message + " 添加OPCItem时出错" + itemstring));
                }
                catch
                {
                    throw (new Exception("HRESULTS:" + hresult + " 添加OPCItem时出错" + itemstring));
                }
            }
        }