Свій CSharp код в ZennoPoster

Коли я починав писати свої проєкти в ZennoPoster для мене дуже страшним виглядали рекомендації написати щось на C# чи використати для рішення якийсь сніппет. Більше того, коли я зустрічав якийсь фрагмент C# коду, я все таки старався переробити його так, щоб цей самий фукнціонал працював використовуючи блоки з стрілочками.

І все це я думаю тому, що я не знав зовсім C#, не розумів як це працює, і взагалі що очікувати від виконання тих чи інших інструкцій. Крім того, чомусь коли скопіював фрагмент коду на форумі виявлялось що програма видає помилку, не працює. Не не знаючи C# не зрозуміло як саме зробити так, щоб цей код запрацював. Саме тому було найкращим рішенням користуватись тільки блоками, які виходили по помилці в цілком конкретних випадках.

Але, через деякий час, я все таки знайшов в собі сили і бажання почати використовувати фрагменти CSharp коду в своїх проєктах. І хоча тоді все ще я зовсім не розумів чому інколи появляються якісь не зрозумілі помилки – це не мішало мені використовувати готові фрагменти.

І вже зараз, через декілька років активного створення всяких різних проєктів я все більше використовую C# для вирішення своїх задач, а сам ZennoPoster виконує в основному завдання оболонки, менеджера, який керує процесом виконання моїх інструкцій. Думаю, що якби я сьогоднішній дав декілька порад собі в минулому – то мабуть це дуже сильно вплинуло б взагалі на процес освоєння CSharp коду в рамках програми ZennoPoster. Тому приведу деякі з них тут – думаю початківцям будуть корисними.

Локальні змінні в ZennoPoster – це текстові рядки

Звичайні змінні, які створюються в проєктах і потім використовуються у вигляді макросів, наприклад так:

{-Variable.temp-}

– це звичайні текстові рядки. І коли приходиться використовувати їх у своїх фрагментах C# коду, з ними приходиться працювати саме як з текстовими рядками. Однак, звертатись до них потрібно по-іншому:

string temp1 = project.Variables["temp"].Value;
var temp2 = project.Variables["temp"].Value;
var temp3 = project.ExecuteMacro("{-Variable.temp-}");

Тобто, перш за все, потрібно змінну прочитати, і записати в нову змінну в самому блоці коду.
Звичайно, можна використовувати ці конструкції і в інших рядках, але коли приходиться змінити одну локальну змінну на іншу – то приходиться дуже уважно шукати її і всюди проводити заміну. Набагато простіше, коли в кожному блоці коду всі локальні змінні прочинаті на початку, і тоді заміну потрібно проводити тільки в одному місці.

Також, з блока свій C# код можна повертати значення в локальну змінну.
Тобто, виконались якісь інструкції, і результат можна передати в локальну змінну, щоб у якомусь іншому блокці продовжити обробку цих даних.

return temp1;
return 1;
return "текст";

В будь-якому із випадків, значення, яке повертається з блоку Свій C# код буде перетворено в текстовий рядок.
Тобто, є у наприклад змінна, яка має в собі значення True чи False. А в локальну змінну буде встановлено саме текстову версію:

bool check = true;
return check; // буде виконано приблизно як рядком нижче
return check.ToString(); // буде виконано приблизно так

Точно так, в текстовий рядок буде переведений любий об’єкт.
Але інколи, коли потрібно з одного блоку вернути декілька значеннь, приходиться встановлювати значення локальних змінних в самому коді:

string temp1 = project.Variables["temp"].Value;
temp1 += "- HI";
project.Variables["temp"].Value = temp1; // присвоїти значення

А коли потрібно працювати не з текстовими рядками, то при встановленні значеннь в локальні змінні приходиться приводити тип даних до текстових рядків самостійно. Ось приклад:

bool check = true;
project.Variables["temp"].Value = check; // помилка !!!
project.Variables["temp"].Value = check.ToString(); // Ось так потрібно привести до рядка

Так от, багато хто не розуміє цього. І в результаті получається щось приблизно таке, коли в одній локальній змінні збережено значення 1, в іншій – значення 2. І коли хочеться наприклад виконати операцію 1+2 – не виходить це зробити. Виникає помилка.
А помилка в тому, що в ZennoPoster всі локальні змінні – це текстові рядки. Тому, коли ми беремо їх в C# код і є необхідність працювати з ними як з числами, то потрібно перш за все привести тип даних до чисел, а уже тоді виконувати операції. Ось приклад:

int x = int.Parse(project.Variables["x"].Value);
int y = int.Parse(project.Variables["y"].Value);
project.Variables["z"].Value = string.Format("{0}", x+y ); // присвоїти значення

В цьому фрагменті я взяв локальну змінну x, перетворив її в число, те саме зробив зі змінною y. Після чого, виконав операцію x+y, і знаючи що змінні в ZennoPoster мають текстовий тип даних – зразу перетворив результат у текст, використовуючи string.Format. Власне я в своїх фрагментах коду дуже часто користуюсь string.Format.

Свій C# код в ZennoPoster це як метод Main

На фрагменти коду, в ZennoPoster потрібно дивитись як на окремі програми. І кожна програма на C# має свою точку входу – метод Main, з якого визиваються будь-які інші методи. Точно так і тут, тільки в нашому випадку сам блок Свій C# код це і є простір, в якому вказані інструкції як у методі Main. А вже звідси слідує, що всередині не можна створювати свої класи, простори імен.

Крім того, блок Свій C# також, як і будь-який інший блок може завершити свою роботу успішно, а може закінчити роботу не успішно. Після чого управління буде передано по стрілочці до наступного блоку. Так от, коли з успішним завершенням все зрозуміло, то з не успішним – все чуть-чуть складніше.

З однієї сторони, коли всередині коду будуть не корректні інструкції, наприклад коли project.Variables[“x”].Value = true – то проєкт не зможе виконуватись, тому що очікується що в локальну змінну можна записати тільки текстовий рядок, а тип даних bool повинен бути приведений до текстового рядка. З іншої сторони, в процесі виконання інструкцій може статись помилка, наприклад коли ми захочемо виконати щось на кшталт return 1/0; – блок також завершить виконання з помилкою.

Так от, інформація про ці помилки появляться в лозі ZennoPoster, якщо по червоному виходу з блока не під’єднаний інший блок. І саме цікаве, що після того, як я бачив подібні помилки в лозі в мене ніколи чомусь не появлялось бажання прочитати що саме сталось. Мабуть тому, що опис помилки був на англійській мові, і було простіше скопіювати текст помилки і шукати на форумі що саме відбулось.

Наприклад, якщо в локальних змінних немає змінної з іменем x, а є фрагмент коду, який використовуює її:

return project.Variables["x"].Value;

В цей момент буде помилка, що такої змінної немає. Але чомусь завжди на форумі люди запускають код, бачуть цю помилку, роблять скришот і просять допомогти з вирішенням проблеми. Тобто, якщо б просто взяти текст опису помилки, і перекласти його використовуючи Google Translate – то фактично зразу було б зрозуміло в чому проблема. Тому, рекомендую читати текст помилки в лозі!

В C# кожна інструкція повинна завершуватись символом ; – і також часто на форумі зустрічаються скриншоти, коли люди не можуть зрозуміти що відбулось, а потрібно було просто прочитати інструкції і добавити в потрібному рядку цей симол.

Console.WriteLine не працює – використовуємо project.SendInfoToLog

Часто зустрічається, і зустрічалась у мене проблема, коли візьмеш код, наприклад на Stack Overflow чи наприклад його згенерує ChatGTP, і код не працює в ZennoPoster. Люди, в цьому випадку зразу приходять на форум, і просять адаптувати код для ZennoPoster (звичайно, пораду вище вони не читали, тобто повідомлення про помилки не читали, які були виведені в лог ZennoPoster).

З однієї сторони приклади коду на Stack Overflow чи штучний інтелект ChatGTP оформляють у вигляді методів – а в нашому випадку у ZennoPoster в блоці Свій C# код потрібно використовувати тільки тіло методу, тобто об’являти методи всередині блоку неможна.
З іншої сторони для демонстрації результатів у тестових прикладах використовується звичайна інструкція Console.WriteLine(“text”);, але вона не працює в ZennoPoster, що може також приводити до помилки.

В ZennoPoster для перегляду повідомлення використовуюється інструкція:

project.SendInfoToLog("текст",true);

Тут також потрібно розуміти, що якщо в Console.WriteLine ми можемо подавати будь-який об’єкт і він автоматично приводиться до текстового рядка, то у випадку з ZennoPoster – в інструкцію, яка вказана в фрагменті потрібно самостійно подавати повідомлення уже в текстовому вигляді. Якщо передати туди число чи будь-який інший об’єкт, то звичайно одержимо помилку.

Я думаю, що уже цих рекомендацій достатньо для того, щоб адаптувати більшість фрагментів C# коду для роботи в ZennoPoster.
Звичайно, що більш складні фрагменти коду, які використовують інші незалежні бібліотеки адаптувати буде складніше, і не завжди можливо.
Проте, для вирішення більшості завданнь в ZennoPoster достатньо звичайних блоків чи адаптованих фрагментів C# коду, яких дуже багато можна знайти в розділі для початківців на форумі.

Залишити відповідь

Ваша e-mail адреса не оприлюднюватиметься. Обов’язкові поля позначені *