基于C#开发PLC上位机(三) 您所在的位置:网站首页 三菱plc报错文件异常2401 基于C#开发PLC上位机(三)

基于C#开发PLC上位机(三)

2023-03-23 12:09| 来源: 网络整理| 查看: 265

       

目录

一.失败案例:

二.成功案例:

 结论

        使用控件有很多限制,总有些人不喜欢使用winform,习惯用别的工具开发界面。本文在探索一个通用的工程,添加.dll文件实现在任意C#工程中即可调用三菱提供的官方函数。

一.失败案例:

        示例工程中,在工程文件下bin目录查看引用的.dll文件,我们初步猜测项目必须引用的库为前两个。

         接下来开始实验,我们新建一个控制台应用程序,不同于示例中,控制台项目中没有任何界面或者控件。

在引用中添加上述两个库,即:

添加命名控件,随便写两行代码,验证一下相关函数是否可用,我这里使用的是Open函数。

 

       

        很遗憾,它在报错,这个报错的大概意思是指有个基类需要在程序集System.Windows.Forms中才能使用,现在缺少此程序集。

还是在刚才的引用中,找到这个程序集并选中,可以发现报错已经消失:

         

        接着运行此代码,很遗憾,还在报错,该报错的大概意思就是ActiveX控件只能在单线程使用,而控制台程序是在多线程下运行的:

         百度解决方案,当前线程不在单线程单元中,因此无法实例化 ActiveX 控件解决办法 - winzheng - 博客园 (cnblogs.com),按照此种方法尝试:

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using AxActProgTypeLib; using AxActUtlTypeLib; using ActUtlTypeLib; using System.Threading; namespace ConsoleApp1 { class Program { static void Main(string[] args) { Thread newThread = new Thread(new ThreadStart(ThreadMethod)); //ApartmentState Property is obsolete; // newThread.SetApartmentState(ApartmentState.MTA); // The following line is ignored since // ApartmentState can only be set once. newThread.SetApartmentState(ApartmentState.STA); Console.WriteLine("ThreadState: {0}, ApartmentState: {1}", newThread.ThreadState, newThread.ApartmentState); newThread.Start(); // Wait for newThread to start and go to sleep. Thread.Sleep(300); try { // This causes an exception since newThread is sleeping. newThread.SetApartmentState(ApartmentState.STA); } catch (ThreadStateException stateException) { Console.WriteLine("\n{0} caught:\n" + "Thread is not in the Unstarted or Running state.", stateException.GetType().Name); Console.WriteLine("ThreadState: {0}, ApartmentState: {1}", newThread.ThreadState, newThread.GetApartmentState()); } } static void ThreadMethod() { // Thread.Sleep(1000); AxActUtlType axActUtlType1 = new AxActUtlType(); axActUtlType1.ActLogicalStationNumber = 1; //Set the value of 'Password'. //The Open method is executed. int iReturnCode = axActUtlType1.Open(); Console.WriteLine(iReturnCode); } } }

        依然在报错:

         于是博主参照示例工程的引用项目,将没有的程序集都添加了进来:

        最终还在报和上述一样的错误,可以看出这个AxHost只能在winform下运行,此次尝试失败。

二.成功案例:

        接下来我们转变思路,经过我们上文中的做法,已经可以确定该控件必须在winform环境下运行,所以接下来可以尝试一下在控制台程序中内嵌一个窗体,类似Windows系统中内嵌一个Linux虚拟机。

        新建一个工程,在“解决方案-引用”中添加以下三个库:

        有些库的复制本地属性是False,意思就是直接添加不会被导入本地文件夹,在引用中添加后还需要手动将该文件复制进入工程文件中的bin文件,上述三个库并不需要,但是后续可能有的会需要,提前说明避免踩坑。           

        同样的,记得添加命名空间:

         下边粘贴代码:

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using AxActUtlTypeLib; using System.Threading; namespace ConsoleApp3 { class Program { static void Main(string[] args) { Thread newThread = new Thread(new ThreadStart(ThreadMethod)); //ApartmentState Property is obsolete; // newThread.SetApartmentState(ApartmentState.MTA); // The following line is ignored since // ApartmentState can only be set once. newThread.SetApartmentState(ApartmentState.STA); Console.WriteLine("ThreadState: {0}, ApartmentState: {1}", newThread.ThreadState, newThread.ApartmentState); newThread.Start(); // Wait for newThread to start and go to sleep. Thread.Sleep(300); try { // This causes an exception since newThread is sleeping. newThread.SetApartmentState(ApartmentState.STA); } catch (ThreadStateException stateException) { Console.WriteLine("\n{0} caught:\n" + "Thread is not in the Unstarted or Running state.", stateException.GetType().Name); Console.WriteLine("ThreadState: {0}, ApartmentState: {1}", newThread.ThreadState, newThread.GetApartmentState()); } void ThreadMethod() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); MainOperation formTest = new MainOperation(); int iReturnCode; iReturnCode = formTest.test(); Console.WriteLine(iReturnCode); Application.Run(formTest); } } } public partial class MainOperation : Form { public MainOperation() { } public int test() { AxActUtlTypeLib.AxActUtlType axActUtlType1 = new AxActUtlTypeLib.AxActUtlType(); this.Controls.Add(axActUtlType1); axActUtlType1.ActLogicalStationNumber = 1; int iReturnCode = axActUtlType1.Open(); return iReturnCode; } } }

        这个代码就是在单线程运行的基础上,建立一个Form,控件实际还是在form中运行,博主在尝试时曾提示过运行环境错误,故将管理器配置为X86,若无相关报错则无需理会:

运行结果如下:

        

        相同的问题,既然已经在form环境中运行控件了为什么还会报错?不知道大家记不记得前边文章中使用控件前需要勾选工具箱中组件,而这里我们是用的是控制台,根本没有选择组件这一说,就相当于我们使用的自定义组件没有注册:

         百度解决方案:引发类型为“System.Windows.Forms.AxHost+InvalidActiveXStateException”的异常 解决办法 - Marksion - 博客园 (cnblogs.com)

        再次尝试,我们事先已经配置并启动Communication Setup Utility,启动Simulator 3,再次启动:

        返回值为0,证明已经成功,下边粘贴修改后的Test函数代码:

public int test() { AxActUtlTypeLib.AxActUtlType axActUtlType1 = new AxActUtlTypeLib.AxActUtlType(); ((System.ComponentModel.ISupportInitialize)(axActUtlType1)).BeginInit(); this.Controls.Add(axActUtlType1); ((System.ComponentModel.ISupportInitialize)(axActUtlType1)).EndInit(); axActUtlType1.ActLogicalStationNumber = 1; int iReturnCode = axActUtlType1.Open(); return iReturnCode; } 结论

         本质上还是在Winform环境下调用的.dll,因为我们并没有看到三菱.dll库的底层,所以最终尝试的结果还是证明在winform控制台下调用库才能稳定运行。。

        

        



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有