Коли я починав писати свої проєкти в 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# коду, яких дуже багато можна знайти в розділі для початківців на форумі.