PDA

Просмотр полной версии : C# в МастерСКАДА



Кулаков Андрей
10.01.2017, 07:09
С каждым ответом SCADAMaster у меня возникает всё больше вопросов, поэтому я создаю отдельную тему, в которой надеюсь докопаться до истины. На данный момент задача разобраться как внутри одного скрипта создавать объекты класса объявленного в другом скрипте или использовать методы другого скрипта. Как я уже говорил - я начинающий и в МастерСКАДА, и в C#, поэтому прошу отвечать последовательно и подробно, не пропуская мои вопросы.

В качестве примера мне был предложен следующий проект:
Скрипт вызова скрипта из другого скрипта.zip (http://www.owen.ru/forum/attachment.php?attachmentid=28628&d=1483956123)

Я правильно понимаю, что RT это RunTime, (скрипт, который должен выполняться в режиме исполнения)? С DT вообще неясно.
RT скрипты вроде работают, но DT - нет.

DT/Test

using System;
using MasterSCADA.Script.FB;
using MasterSCADA.Hlp;
using FB;
using System.Linq;
using MasterSCADALib;
using MasterSCADA.Common;
using System.Windows.Forms;

public partial class ФБ : ScriptBase
{
public override void DoAction()
{
MessageBox.Show("Метод выполнен");
}
}

DT/Проверка вызова скрипта

using System;
using MasterSCADA.Script.FB;
using MasterSCADA.Hlp;
using FB;
using System.Linq;
using MasterSCADALib;
using MasterSCADA.Common;


public partial class ФБ : ScriptBase
{
public override void DoAction()
{
var Скрипт = (ScriptFB)HostFB.TreeItemHlp.Project.Item("Объект.DT.Test").FBObject; //получаем ссылку на первый скрипт

using (dynamic obj = Скрипт.CompileAndGetScriptObject(true))
{
obj.DoAction();
}
}
}
Насколько я понимаю задумку - в первом скрипте в методе DoAction() мы вызываем метод MessageBox.Show(), который становится доступным после подключения using System.Windows.Forms;
Второй скрипт сначала получает ссылку на первый скрипт, потом должен обратиться к методу DoAction() первого скрипта. Синтаксис мне не понятен. Почему мы используем "using" в середине кода?
На строчке "using (dynamic obj = Скрипт.CompileAndGetScriptObject(true))" компиляция выдаёт ошибку:

DT.Проверка вызова скрипта" : (CS1061) 'MasterSCADA.Script.FB.ScriptFB' does not contain a definition for 'CompileAndGetScriptObject' and no extension method 'CompileAndGetScriptObject' accepting a first argument of type 'MasterSCADA.Script.FB.ScriptFB' could be found (are you missing a using directive or an assembly reference?)

RT/Скрипт

using System;
using MasterSCADA.Script.FB;
using MasterSCADA.Hlp;
using FB;
using FB.FBAttributes;
using System.Linq;

public partial class ФБ : ScriptBase
{
bool? M = false;

public override void Execute()
{
HostFB.TreeItemHlp.Project.ErrorTracer.ReportError ("Ваша строка");
if (Параметр1==true && M==false)
{
var Скрипт = (ScriptFB)HostFB.TreeItemHlp.Project.Item("Объект.RT.Test").FBObject; //получаем ссылку на первый скрипт
dynamic obj = Скрипт.ScriptObject;
obj.DoAction();
}
M = Параметр1;
}
}
RT/Test

using System;
using MasterSCADA.Script.FB;
using MasterSCADA.Hlp;
using FB;
using System.Linq;
using MasterSCADALib;
using MasterSCADA.Common;


public partial class ФБ : ScriptBase
{
public override void DoAction()
{
Параметр1="Метод выполнен";
}
}

Здесь по переднему фронту "Параметр1" скрипта "RT/Скрипт" происходит вызов метода DoAction() скрипта "RT/Test" и "Параметр1" скрипта "RT/Test" навсегда принимает значение "Метод выполнен".

bool? M = false; - гугл говорит, что "bool?" это тип, который может принимать значение NULL. Почему мы не используем тип "bool"?

Для обращения к скрипту мы используем иной синтаксис (dynamic obj = Скрипт.ScriptObject; ), не как в DT, хотелось бы увидеть пояснения по этому поводу.

Я вообще могу создавать классы вне библиотечных скриптов? Компилятор постоянно ругается. Если да, то в какой части скрипта происходит объявление пользовательских классов?

Что касается


1. Напишите на в Visual Studio библиотеку с нужными вам классами, скомпилируйте, положите в папку скады, пропишите в скрипте на вкладке Настройки и обращайтесь к ней.

постараюсь проверить завтра, когда установлю Visual Studio. Но это не тот путь, которым я хотел бы идти.


Зачем нужно назначать несколько библиотечных скриптов одному скрипту? Пропишите в библиотечном скрипте все нужные классы и работайте. - чтобы не лепить все классы в одну кучу, а иерархически их разнести по объектам структуры самой МастерСкада.

Дополнительный вопрос был про отладку, на данный момент вижу три способа:
1) HostFB.TreeItemHlp.Project.ErrorTracer.ReportError ("Ваша строка");
Сообщения будут выводится в лог скады. Для открытия окна лога нажмите красную кнопку в правом нижнем углу скады.
Работает только в режиме исполнения, не работает в режиме отладки.
2) using System.Windows.Forms;
MessageBox.Show("Ваша строка");
Работает только в режиме исполнения, не работает в режиме отладки.
3)
Но есть вариант лучше, посмотрите эту статью:
http://blog.insat.ru/2016/10/script-csharp8.html
опять же постараюсь проверить завтра.

Я прекрасно понимаю, что никто мне ничем не обязан, поэтому заранее благодарю за любую помощь.

SCADAMaster
10.01.2017, 09:30
Почему мы используем "using" в середине кода?

https://msdn.microsoft.com/ru-ru/library/yh598w02.aspx



На строчке "using (dynamic obj = Скрипт.CompileAndGetScriptObject(true))" компиляция выдаёт ошибку:

Установите текущую версию 3.8. Код измените на:
var Скрипт = (ScriptFB)HostFB.TreeItemHlp.Project.Item("Объект.DT.Test").FBObject; //получаем ссылку на первый скрипт
System.Reflection.Assembly tt;
using (dynamic obj = Скрипт.CompileAndGetScriptObject(out tt,true))
{
obj.DoAction();
}



bool? M = false; - гугл говорит, что "bool?" это тип, который может принимать значение NULL. Почему мы не используем тип "bool"?

Потому что входы могут иметь неопределенный тип - если значения на них нет.



1) HostFB.TreeItemHlp.Project.ErrorTracer.ReportError ("Ваша строка");
Сообщения будут выводится в лог скады. Для открытия окна лога нажмите красную кнопку в правом нижнем углу скады.
Работает только в режиме исполнения, не работает в режиме отладки.

У нас все работает.



2) using System.Windows.Forms;
MessageBox.Show("Ваша строка");
Работает только в режиме исполнения, не работает в режиме отладки.

Это вообще в режиме исполнения использовать нельзя. Только в режиме разработки.

Кулаков Андрей
10.01.2017, 11:54
прошу отвечать последовательно и подробно, не пропуская мои вопросы.

Я вообще могу создавать классы вне библиотечных скриптов? Компилятор постоянно ругается. Если да, то в какой части скрипта происходит объявление пользовательских классов?


Ваше сообщение слишком короткое.

SCADAMaster
10.01.2017, 12:42
Я вообще могу создавать классы вне библиотечных скриптов? Компилятор постоянно ругается. Если да, то в какой части скрипта происходит объявление пользовательских классов?

Можете. Создавать нужно вне класса ФБ


public class MyClass
{
bool k=false;
MyClass()
{
k=true;
}
}

public partial class ФБ : ScriptBase
{
public override void DoAction()
{

}
}

Кулаков Андрей
11.01.2017, 07:25
Остаётся открытым вопрос - можно ли определить класс в одном скрипте, а создавать и использовать объект этого класса в другом? Определить класс именно в скрипте, а не в библиотечном скрипте и не в подключаемой сборке. Если это принципиально возможно - хотелось бы увидеть пример. Спасибо.

SCADAMaster
11.01.2017, 09:06
Нет, так сделать нельзя.

Кулаков Андрей
19.01.2017, 06:33
Таки добрался до visual studio и пишу свою библиотеку. Сейчас такой вопрос - я не могу в ней использовать HostFB.TreeItemHlp.Project.ErrorTracer.ReportError ("Ваша строка"), компилятор ругается "Имя "HostFB" не существует в текущем контексте". Я добавил в ссылки (references) проекта те же библиотеки, что указаны в "настройки/ссылки на сборки" у скриптов в мастерскада, а так же добавил те же пространства имён

using MasterSCADA.Script.FB;
using MasterSCADA.Hlp;
using FB;
using FB.FBAttributes;
using MasterSCADALib;
using MasterSCADA.Common;
но это не дало результата. Я что-то делаю не так? Это вообще реализуемо? Или мне смотреть в сторону событий C#?

SCADAMaster
19.01.2017, 08:45
Попробуйте this вместо HostFB

Кулаков Андрей
20.01.2017, 02:09
Нет, все равно не видит.

SCADAMaster
20.01.2017, 12:06
Должно работать. Вот пример кода:
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using FB;
using FB.VisualFB;
using InSAT.Library.Interop;
.......
this.TreeItemHlp.Project.ErrorTracer.ReportError("Пишу всякое и это ошибка по умолчанию");
this.TreeItemHlp.Project.ErrorTracer.ReportError("Пишу всякое и это ошибка",true);
this.TreeItemHlp.Project.ErrorTracer.ReportError("Пишу всякое Не ошибка", false);

Вот видео работы:
https://www.screencast.com/t/2MB4ze4dl6

Кулаков Андрей
23.01.2017, 02:04
И так тоже не видит. Может там какие нюансы о которых я не в курсе? Можете посмотреть мой проект? Visual Studio 2015.

Если не можете, то можете привести пример элементарного класса (public class) в методе (public void) которого вызывается сообщение? Интересует полный исходный код со всеми директивами using + ссылки проекта.
И вообще, может я что-то неправильно понимаю? Я создаю новый проект в visual studio, подключаю ссылки, прописываю директивы, после этого он должен видеть классы МастерСкады и нормально компилироваться, правильно?

SCADAMaster
23.01.2017, 08:42
Приведенная строка предназначена для вывода сообщений из ФБ или скрипта. У вас же собственный класс. Поэтому вам нужно или делать собственный вывод в лог, или при возникновении ошибок в классе выводить ошибки уже в самом скрипте.

Кулаков Андрей
23.01.2017, 13:00
Но я же сразу написал про это =_=
То есть так сделать нельзя? Я хотел создать объект этого класса в скрипте, тогда сообщения и будут вызываться из скрипта. Но я не могу этот класс скомпилировать.

SCADAMaster
23.01.2017, 13:08
То есть так сделать нельзя?
Выводить сообщения из вашей библиотеки - нет.
Подключить библиотеку к скрипту - да.

Кулаков Андрей
24.01.2017, 04:45
В принципе смог реализовать вызов ErrorReport из подключаемой dll через события, но наблюдаю совершенно непонятное поведение скриптов. Я несколько раз получил заданные мной сообщения, но после этого они перестали выдаваться. И по ощущениям скрипт в принципе перестал запускаться. Попробовал создать абсолютно новый скрипт, ничего к нему не подключать и просто в методе Execute присваивать значение выходному параметру - ничего не происходит. При этом Ваш скрипт из выложенного проекта с названием RT работает. В чем может быть причина?
ЗЫ: при экспорте проекта не экспортируются добавленные dll, считаю это неправильным.

SCADAMaster
24.01.2017, 08:44
Скрипты из объекта RT у нас работают корректно. Остальные у вас не назначены компьютерам