参考文献链接:http://www.cnblogs.com/zjjking/archive/2009/01/23/1380218.html
客户端的实现:安装了KepServer的驱动,引用了Interop.OPCAutomation.dll
客户端程序:
1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Windows.Forms; 9 using OPCAutomation; 10 using System.Threading; 11 12 namespace OPCClient 13 { 14 public partial class Form1 : Form 15 { 16 //public enum MyOPCType : ushort 17 //{ 18 // _byte = 0, 19 // _short = 1, 20 // _bool = 2, 21 // _string = 3, 22 // _string2 = 4, 23 //}; 24 //OPCType mytype; 25 public struct aItem 26 { 27 public string NameForOPC; 28 //public MyOPCType opc_type; 29 public object Value; 30 public bool Writeable; 31 public string Descrip; 32 public string Timestamps; 33 public string Quality; 34 35 public int itmHandleClient; 36 public int itmHandleServer; 37 } 38 aItem[] Data_Array; 39 aItem[] Data_Array2; 40 public Form1() 41 { 42 InitializeComponent(); 43 } 44 #region 私有变量 45 OPCServer MyServer; 46 OPCGroups MyGroups; 47 48 OPCGroup MyGroup; 49 OPCGroup MyGroup2; 50 51 OPCItems MyItems; 52 OPCItems MyItems2; 53 54 OPCItem[] MyItem; 55 OPCItem[] MyItem2; 56 #endregion 57 string strHostIP = ""; 58 string strHostName = ""; 59 60 private void Form1_Load(object sender, EventArgs e) 61 { 62 GetLocalServer(); 63 Data_Array = new aItem[5]; 64 65 Data_Array[0].NameForOPC = "A0000"; 66 Data_Array[0].Value = 0; 67 //Data_Array[0].opc_type = MyOPCType._byte; 68 Data_Array[0].itmHandleClient = 0; 69 Data_Array[0].Writeable = false; 70 71 72 Data_Array[1].NameForOPC = "A0001"; 73 Data_Array[1].Value = 0; 74 //Data_Array[1].opc_type = MyOPCType._short; 75 Data_Array[1].itmHandleClient = 1; 76 Data_Array[1].Writeable = false; 77 78 Data_Array[2].NameForOPC = "A0002"; 79 Data_Array[2].Value = false; 80 //Data_Array[2].opc_type = MyOPCType._bool; 81 Data_Array[2].itmHandleClient = 2; 82 Data_Array[2].Writeable = false; 83 84 Data_Array[3].NameForOPC = "B001"; 85 Data_Array[3].Value = ""; 86 //Data_Array[3].opc_type = MyOPCType._string; 87 Data_Array[3].itmHandleClient = 3; 88 Data_Array[3].Writeable = false; 89 90 Data_Array[4].NameForOPC = "B002"; 91 Data_Array[4].Value = ""; 92 //Data_Array[4].opc_type = MyOPCType._string2; 93 Data_Array[4].itmHandleClient = 4; 94 Data_Array[4].Writeable = false; 95 96 Data_Array2 = new aItem[4]; 97 98 Data_Array2[0].NameForOPC = "B001"; 99 Data_Array2[0].Value = ""; 100 //Data_Array2[0].opc_type = MyOPCType._string; 101 Data_Array2[0].itmHandleClient = 3; 102 Data_Array2[0].Writeable = false; 103 104 Data_Array2[1].NameForOPC = "B002"; 105 Data_Array2[1].Value = ""; 106 //Data_Array2[1].opc_type = MyOPCType._string; 107 Data_Array2[1].itmHandleClient = 0; 108 Data_Array2[1].Writeable = false; 109 110 Data_Array2[2].NameForOPC = "W01"; 111 Data_Array2[2].Value = ""; 112 //Data_Array2[2].opc_type = MyOPCType._string; 113 Data_Array2[2].itmHandleClient = 1; 114 Data_Array2[2].Writeable = true; 115 116 Data_Array2[3].NameForOPC = "W02"; 117 Data_Array2[3].Value = ""; 118 //Data_Array2[3].opc_type = MyOPCType._string; 119 Data_Array2[3].itmHandleClient = 2; 120 Data_Array2[3].Writeable = true; 121 } 122 private void GetLocalServer() 123 { 124 strHostName = System.Net.Dns.GetHostName(); 125 System.Net.IPHostEntry ipEntry = System.Net.Dns.GetHostEntry(strHostName); 126 for (int i = 0; i < ipEntry.AddressList.Length; i++) 127 { 128 if (ipEntry.AddressList[i].AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork) 129 { 130 strHostIP = ipEntry.AddressList[i].ToString(); 131 break; 132 } 133 } 134 135 try 136 { 137 MyServer = new OPCServer(); 138 object serverList = MyServer.GetOPCServers(strHostName); 139 140 foreach (string alist in (Array)serverList) 141 { 142 comboBox_ServerNames.Items.Add(alist); 143 } 144 if (comboBox_ServerNames.Items.Count >= 1) 145 { 146 comboBox_ServerNames.SelectedIndex = 0; 147 } 148 textBox_IP.Text = strHostIP; 149 } 150 catch(Exception err) 151 { 152 throw new Exception("GetLoaclServer :" + err.Message); 153 } 154 } 155 156 private void buttonConnect_Click(object sender, EventArgs e) 157 { 158 try 159 { 160 161 //MyServer.Connect(comboBox_ServerNames.SelectedItem.ToString(), strHostIP); 162 MyServer.Connect(comboBox_ServerNames.SelectedItem.ToString(), ""); //连接本机,后面的IP就不需要了 163 164 if (MyServer.ServerState == (int)OPCServerState.OPCRunning) //判断是否连接上了 165 { 166 CreateGroup(); 167 } 168 else 169 { 170 throw new Exception("ServerState: " + MyServer.ServerState); 171 } 172 173 MyServer.ServerShutDown += ServerShutDown;//服务器断开事件,没有发现他在哪里用的。 174 175 } 176 catch (Exception err) 177 { 178 MessageBox.Show("ConnectServer:" + err.Message); 179 } 180 } 181 private bool CreateGroup() 182 { 183 try 184 { 185 MyGroups = MyServer.OPCGroups; 186 MyGroup = MyServer.OPCGroups.Add("Group1"); 187 MyGroup2 = MyServer.OPCGroups.Add("Group2"); 188 OPCGroup Mygroup3 = MyGroups.Add("Test3"); //待删除的组 189 //以下设置属性 190 { 191 MyGroups.DefaultGroupIsActive = true; //激活组 192 MyGroups.DefaultGroupDeadband = 0; //死区值,设为0时,服务器端该组内任何数据变化都通知组 193 MyGroups.DefaultGroupUpdateRate = 200; //默认组群的刷新频率为200ms 194 195 MyGroup.UpdateRate = 100; //刷新频率为1秒 196 MyGroup.IsSubscribed = true; //使用订阅功能,即可以异步,默认为false。 197 //如果没有订阅,则该组的DataChange回调事件不会发生 198 MyGroup2.UpdateRate = 100; 199 MyGroup2.IsSubscribed = true; 200 } 201 MyGroup.DataChange += new DIOPCGroupEvent_DataChangeEventHandler(GroupDataChange); 202 203 MyGroup2.DataChange += new DIOPCGroupEvent_DataChangeEventHandler(GroupDataChange2); 204 MyGroup2.AsyncWriteComplete += new DIOPCGroupEvent_AsyncWriteCompleteEventHandler(GroupAsyncWriteComplete); 205 MyGroup2.AsyncReadComplete += new DIOPCGroupEvent_AsyncReadCompleteEventHandler(GroupAsyncReadComplete); 206 207 MyServer.OPCGroups.Remove("Test3");//移除组 208 //添加Item 209 AddGroupItems(); //设置组内的Items 210 } 211 catch (Exception err) 212 { 213 throw new Exception("CreateGroup:" + err.Message); 214 } 215 return true; 216 } 217 private void AddGroupItems() 218 { 219 #region Important clue 220 //没有搞懂以下的意义。经测试,感觉不是这样的,如果有好几个string,clienthandle都是3的话,那订阅的 221 //DataChange事件在触发的时候clienthandle都是一样的,这样不知道如何分辨是哪一个Item的值了。所以我用的 222 //都是比3要大的值。 223 224 //MyItem2[0] = MyItems2.AddItem("BPJ.Db1.dbb96", 0);//byte 225 //MyItem2[1] = MyItems2.AddItem("BPJ.Db1.dbw10", 1);//short 226 //MyItem2[2] = MyItems2.AddItem("BPJ.Db16.dbx0", 2);//bool 227 //MyItem2[3] = MyItems2.AddItem("BPJ.Db11.S0", 3);//string 228 #endregion 229 230 MyItems = MyGroup.OPCItems; 231 MyItems2 = MyGroup2.OPCItems; 232 233 MyItem = new OPCItem[Data_Array.Length]; 234 MyItem2 = new OPCItem[Data_Array2.Length]; 235 236 for (int i = 0; i < Data_Array.Length; i++) 237 { 238 //MyItem[i] = MyItems.AddItem(Data_Array[i].NameForOPC, (int)(Data_Array[i].opc_type)); 239 MyItem[i] = MyItems.AddItem(Data_Array[i].NameForOPC, Data_Array[i].itmHandleClient); 240 } 241 242 for (int i = 0; i < Data_Array2.Length; i++) 243 { 244 //MyItem2[i] = MyItems2.AddItem(Data_Array2[i].NameForOPC, (int)(Data_Array2[i].opc_type)); 245 MyItem2[i] = MyItems2.AddItem(Data_Array2[i].NameForOPC, Data_Array2[i].itmHandleClient); 246 } 247 //移除组内Item的方法 248 //Array Errors; 249 //int[] temp = new int[] { 0, MyItem[3].ServerHandle }; 250 //Array serverHandle = (Array)temp; 251 //MyItems.Remove(1, ref serverHandle, out Errors); 252 //MyItem[3] = MyItems.AddItem("BPJ.Db11.S0", 3);//string 253 254 } 255 256 public void ServerShutDown(string Reason)//服务器先行断开 257 { 258 MyServer.OPCGroups.RemoveAll(); 259 MyServer.Disconnect(); 260 } 261 void GroupDataChange(int TransactionID, int NumItems, ref Array ClientHandles, ref Array ItemValues, ref Array Qualities, ref Array TimeStamps) 262 { 263 bool UpdateFlg = false; 264 int UpdateNum = -1; 265 for (int i = 1; i <= NumItems; i++) 266 { 267 for (int j = 0; j < Data_Array.Length; j++) 268 { 269 //if (Data_Array[j].itmHandleClient == Convert.ToInt32(ClientHandles.GetValue(i))) 270 if (Data_Array[j].itmHandleClient == Convert.ToInt32(ClientHandles.GetValue(i))) 271 { 272 Data_Array[j].Value = ItemValues.GetValue(i).ToString(); 273 Data_Array[j].Quality = Qualities.GetValue(i).ToString(); 274 Data_Array[j].Timestamps = TimeStamps.GetValue(i).ToString(); 275 276 UpdateFlg = true; 277 UpdateNum = j; 278 break; 279 } 280 } 281 if (UpdateFlg == true) 282 { 283 switch (UpdateNum) 284 { 285 case 0: 286 this.textBoxA0.Text = Data_Array[0].Value.ToString(); 287 break; 288 case 1: 289 this.textBoxA1.Text = Data_Array[1].Value.ToString(); 290 break; 291 case 2: 292 this.textBoxA2.Text = Data_Array[2].Value.ToString(); 293 break; 294 case 3: 295 this.textBoxB1.Text = Data_Array[3].Value.ToString(); 296 break; 297 case 4: 298 this.textBoxB2.Text = Data_Array[4].Value.ToString(); 299 break; 300 } 301 UpdateFlg = false; 302 } 303 304 } 305 } 306 void GroupDataChange2(int TransactionID, int NumItems, ref Array ClientHandles, ref Array ItemValues, ref Array Qualities, ref Array TimeStamps) 307 { 308 309 for (int i = 1; i <= NumItems; i++) 310 { 311 for (int j = 0; j < Data_Array2.Length; j++) 312 { 313 if (Data_Array2[j].itmHandleClient == Convert.ToInt32(ClientHandles.GetValue(i))) 314 { 315 Data_Array2[j].Value = ItemValues.GetValue(i).ToString(); 316 Data_Array2[j].Quality = Qualities.GetValue(i).ToString(); 317 Data_Array2[j].Timestamps = TimeStamps.GetValue(i).ToString(); 318 319 break; 320 } 321 } 322 323 } 324 } 325 void GroupAsyncWriteComplete(int TransactionID, int NumItems, ref Array ClientHandles, ref Array Errors) 326 { 327 labelSysWrite.Text = "异步写完成。NumItems:" + NumItems.ToString() + "\r\n时间:" + DateTime.Now.ToString(); 328 } 329 void GroupAsyncReadComplete(int TransactionID, int NumItems, ref System.Array ClientHandles, ref System.Array ItemValues, ref System.Array Qualities, ref System.Array TimeStamps, ref System.Array Errors) 330 { 331 bool UpdateFlg = false; 332 int UpdateNum = -1; 333 for (int i = 1; i <= NumItems; i++) 334 { 335 for (int j = 0; j < Data_Array2.Length; j++) 336 { 337 if (Data_Array2[j].itmHandleClient == Convert.ToInt32(ClientHandles.GetValue(i))) 338 { 339 Data_Array2[j].Value = ItemValues.GetValue(i).ToString(); 340 Data_Array2[j].Quality = Qualities.GetValue(i).ToString(); 341 Data_Array2[j].Timestamps = TimeStamps.GetValue(i).ToString(); 342 UpdateFlg = true; 343 UpdateNum = j; 344 break; 345 } 346 } 347 if (UpdateFlg) 348 { 349 switch (UpdateNum) 350 { 351 case 0: 352 this.textBoxB1_2.Text = ItemValues.GetValue(i).ToString(); 353 break; 354 case 1: 355 this.textBoxB2_2.Text = ItemValues.GetValue(i).ToString(); 356 break; 357 default: 358 break; 359 } 360 UpdateFlg = false; 361 } 362 } 363 labelSysRead.Text = "异步读完成。NumItems:" + NumItems.ToString() + "\r\n时间:" + DateTime.Now.ToString(); 364 } 365 366 private void buttonSysRead_Click(object sender, EventArgs e) 367 { 368 //同步读 369 object ItemValues, Qualities, TimeStamps; 370 371 MyItem2[0].Read(1, out ItemValues, out Qualities, out TimeStamps); 372 this.textBoxB1_2.Text = Convert.ToString(ItemValues); 373 374 MyItem2[1].Read(1, out ItemValues, out Qualities, out TimeStamps); 375 this.textBoxB2_2.Text = Convert.ToString(ItemValues); 376 } 377 private void buttonASysRead_Click(object sender, EventArgs e) 378 { 379 //异步读,会在事件中给出读的值 380 int[] tmp = new int[] { 0, MyItem2[0].ServerHandle, MyItem2[1].ServerHandle }; 381 Array serverHandles = (Array)tmp; 382 Array Errors; 383 int cancelID; 384 MyGroup2.AsyncRead(2, ref serverHandles, out Errors, 1, out cancelID); 385 386 //经测试,也可以读出数据。有的时候会有些延迟 387 //this.textBoxB1_2.Text = MyItem2[0].Value; 388 //this.textBoxB2_2.Text = MyItem2[1].Value; 389 } 390 private void buttonSysWrite_Click(object sender, EventArgs e) 391 { 392 //同步写 393 MyItem2[2].Write(textBoxW1_2.Text); 394 MyItem2[3].Write(textBoxW2_2.Text); 395 396 this.textBoxW1_2.Text = ""; 397 this.textBoxW2_2.Text = ""; 398 } 399 400 private void buttonASysWrite_Click(object sender, EventArgs e) 401 { 402 //异步写 403 //异步写时,Array数组从下标1开始而非0! 404 int[] tmp = new int[] { 0, MyItem2[2].ServerHandle, MyItem2[3].ServerHandle }; 405 Array serverHandles = (Array)tmp; 406 object[] valueTemp = new object[3] { "", textBoxW1_2.Text, textBoxW2_2.Text }; 407 Array values = (Array)valueTemp; 408 Array Errors; 409 int cancelID; 410 MyGroup2.AsyncWrite(2, ref serverHandles, ref values, out Errors, 1, out cancelID); 411 412 this.textBoxW1_2.Text = ""; 413 this.textBoxW2_2.Text = ""; 414 } 415 416 private void buttonSysRead2_Click(object sender, EventArgs e) 417 { 418 //同步读 419 object ItemValues, Qualities, TimeStamps; 420 421 MyItem2[2].Read(1, out ItemValues, out Qualities, out TimeStamps); 422 this.textBoxW1_2.Text = Convert.ToString(ItemValues); 423 424 MyItem2[3].Read(1, out ItemValues, out Qualities, out TimeStamps); 425 this.textBoxW2_2.Text = Convert.ToString(ItemValues); 426 } 427 428 private void Form1_FormClosing(object sender, FormClosingEventArgs e) 429 { 430 //善后,关闭之前的工作。 431 if (MyGroup != null) 432 { 433 MyGroup.DataChange += new DIOPCGroupEvent_DataChangeEventHandler(GroupDataChange); 434 } 435 436 if (MyGroup2 != null) 437 { 438 MyGroup2.DataChange += new DIOPCGroupEvent_DataChangeEventHandler(GroupDataChange2); 439 MyGroup2.AsyncWriteComplete += new DIOPCGroupEvent_AsyncWriteCompleteEventHandler(GroupAsyncWriteComplete); 440 MyGroup2.AsyncReadComplete += new DIOPCGroupEvent_AsyncReadCompleteEventHandler(GroupAsyncReadComplete); 441 } 442 if (MyServer != null) 443 { 444 //MyServer.OPCGroups.RemoveAll(); 445 MyServer.Disconnect(); 446 } 447 } 448 449 450 } 451 }
服务器的实现:OPCDAAuto.dll(regsvr32注册)、引用WtOPCsvr_Library.dll、WtOPCSvr.dll(破解)
服务器端程序:
1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Windows.Forms; 9 using System.Runtime.InteropServices; 10 using System.Threading; 11 namespace OPCServer_1 12 { 13 14 15 public partial class Form1 : Form 16 { 17 const string CLSID_Value = "{7A078FB8-5286-417C-B94F-E948D2D9DFF0}"; 18 WtOPCsvr_Library.WtOPCsvr_DLL.WriteNotificationDelegate WriteCallBack; 19 public delegate void UpdateTextBox(string Content1, string Content2, string Content3, string Content4, string Content5); 20 public enum MyOPCType : ushort 21 { 22 _byte = 0, 23 _short = 1, 24 _bool = 2, 25 _string = 3, 26 }; 27 public struct aItem 28 { 29 public string NameForOPC; 30 public MyOPCType opc_type; 31 public object Value; 32 public bool Writeable; 33 public string Descrip; 34 35 public uint TagHandle; 36 } 37 aItem[] Data_Array; 38 39 System.Timers.Timer UpdateTimer; 40 public Form1() 41 { 42 InitializeComponent(); 43 44 WriteCallBack = new WtOPCsvr_Library.WtOPCsvr_DLL.WriteNotificationDelegate(MyWriteCallBack); 45 } 46 public void MyWriteCallBack(UInt32 hItem, ref Object Value, ref UInt32 ResultCode) 47 { 48 if (hItem == Data_Array[5].TagHandle) 49 { 50 Data_Array[5].Value = Convert.ToString(Value); 51 52 textBoxW1.Text = Data_Array[5].Value.ToString(); 53 54 } 55 else if (hItem == Data_Array[6].TagHandle) 56 { 57 Data_Array[6].Value = Convert.ToString(Value); 58 textBoxW2.Text = Data_Array[6].Value.ToString(); 59 60 } 61 62 63 } 64 private void buttonSend_Click(object sender, EventArgs e) 65 { 66 CreateTag(); 67 UpdateTimer.Enabled = true; 68 69 this.buttonSend.Enabled = false; 70 } 71 private void Init_Timer() 72 { 73 UpdateTimer = new System.Timers.Timer(5000); 74 UpdateTimer.Elapsed += new System.Timers.ElapsedEventHandler(UpdateTimer_Elapsed); 75 UpdateTimer.AutoReset = false; 76 UpdateTimer.Enabled = false; 77 } 78 private void UpdateTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) 79 { 80 Random rad = new Random(); 81 82 Data_Array[0].Value = rad.Next(0, 255); 83 Data_Array[1].Value = rad.Next(-255, 1000); 84 Data_Array[2].Value = !Convert.ToBoolean(Data_Array[2].Value); 85 Data_Array[3].Value = (((double)rad.Next(0, 100) - 50.0) / 100).ToString(); 86 Data_Array[4].Value = (((double)rad.Next(0, 100) - 50.0) / 100).ToString(); 87 88 for (int i = 0; i < 5; i++)//仅仅对前5个进行更新 89 { 90 WtOPCsvr_Library.WtOPCsvr_DLL.UpdateTagByName(Data_Array[i].NameForOPC, Data_Array[i].Value, 192); 91 } 92 UpdateTextBox updatetextbox = new UpdateTextBox(UpdateUI); 93 94 this.BeginInvoke(updatetextbox, Data_Array[0].Value.ToString(), Data_Array[1].Value.ToString(), 95 Data_Array[2].Value.ToString(), Data_Array[3].Value.ToString(), Data_Array[4].Value.ToString()); 96 97 98 UpdateTimer.Enabled = true; 99 } 100 private void UpdateUI(string Content1, string Content2, string Content3, string Content4, string Content5) 101 { 102 textBoxA0.Text = Content1; 103 textBoxA1.Text = Content2; 104 textBoxA2.Text = Content3; 105 106 textBoxB1.Text = Content4; 107 textBoxB2.Text = Content5; 108 } 109 private void Form1_Load(object sender, EventArgs e) 110 { 111 Check_Register(); 112 Init_OPCSvr(); 113 //CreateTag(); 114 115 Init_Timer(); 116 } 117 # region OPC 118 private void Check_Register() 119 { 120 Microsoft.Win32.RegistryKey Key_Clsid = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey("OPC服务器_1", false); 121 if (Key_Clsid == null) 122 { 123 //注册 124 string exePath = Application.StartupPath + "\\OPCServer_1.exe"; 125 bool Flg = WtOPCsvr_Library.WtOPCsvr_DLL.UpdateRegistry(CLSID_Value, "OPC服务器_1", "_1OPC服务器", exePath); 126 127 } 128 //WtOPCsvr_Library.WtOPCsvr_DLL.UnregisterServer(CLSID_Value, "临时OPC服务器"); 129 } 130 [DllImport("WtOPCSvr.dll")] 131 public static extern UInt32 Deactivate30MinTimer([MarshalAs(UnmanagedType.LPStr)] String SerailNum); 132 private void Init_OPCSvr() 133 { 134 UInt32 tt = 22; 135 string key = "JVRPS53R5V64226N62H4"; 136 tt = Deactivate30MinTimer(key); 137 WtOPCsvr_Library.WtOPCsvr_DLL.SetVendorInfo("University"); 138 WtOPCsvr_Library.WtOPCsvr_DLL.InitWTOPCsvr(CLSID_Value, 5000); 139 //开启回写 140 WtOPCsvr_Library.WtOPCsvr_DLL.EnableWriteNotification(WriteCallBack, true); 141 } 142 private void CreateTag() 143 { 144 Data_Array = new aItem[7]; 145 Data_Array[0].NameForOPC="A0000"; 146 Data_Array[0].Value = 0; 147 Data_Array[0].opc_type = MyOPCType._byte; 148 Data_Array[0].Writeable = false; 149 150 Data_Array[1].NameForOPC = "A0001"; 151 Data_Array[1].Value = 0; 152 Data_Array[1].opc_type = MyOPCType._short; 153 Data_Array[1].Writeable = false; 154 155 Data_Array[2].NameForOPC = "A0002"; 156 Data_Array[2].Value = false; 157 Data_Array[2].opc_type = MyOPCType._bool; 158 Data_Array[2].Writeable = false; 159 160 Data_Array[3].NameForOPC = "B001"; 161 Data_Array[3].Value = ""; 162 Data_Array[3].opc_type = MyOPCType._string; 163 Data_Array[3].Writeable = false; 164 165 Data_Array[4].NameForOPC = "B002"; 166 Data_Array[4].Value = ""; 167 Data_Array[4].opc_type = MyOPCType._string; 168 Data_Array[4].Writeable = true; 169 170 Data_Array[5].NameForOPC = "W01"; //回写 171 Data_Array[5].Value = ""; 172 Data_Array[5].opc_type = MyOPCType._string; 173 Data_Array[5].Writeable = true; 174 175 Data_Array[6].NameForOPC = "W02"; //回写 176 Data_Array[6].Value = ""; 177 Data_Array[6].opc_type = MyOPCType._string; 178 Data_Array[6].Writeable = true; 179 180 for (int i = 0; i < Data_Array.Length; i++) 181 { 182 Data_Array[i].TagHandle = WtOPCsvr_Library.WtOPCsvr_DLL.CreateTag(Data_Array[i].NameForOPC, Data_Array[i].Value, (ushort)Data_Array[i].opc_type, Data_Array[i].Writeable); 183 } 184 } 185 #endregion 186 } 187 }