Работа с переменными проекта в ZennoPoster
⚠️ Переменные должны быть созданы заранее
- Все переменные должны быть созданы в ProjectMaker до выполнения кода
- Попытка доступа к несуществующей переменной вызовет исключение
- API
IZennoPosterProjectModelпозволяет только читать и изменять существующие локальные переменные, но НЕ создавать новые
⚠️ Тип данных переменных
- Все переменные в ZennoPoster имеют тип
string - При работе с числами, булевыми значениями и другими типами необходимо выполнять конвертацию
📋 ОСНОВЫ РАБОТЫ С ЛОКАЛЬНЫМИ ПЕРЕМЕННЫМИ
Получение значения переменной
// Базовое получение значения (переменная должна существовать!)
string userName = project.Variables["UserName"].Value;
string email = project.Variables["Email"].Value;
// Проверка на пустое значение (если переменная существует)
if (string.IsNullOrEmpty(email)) {
project.SendWarningToLog("Переменная Email пуста", false);
}Установка значения переменной
// Установка строкового значения
project.Variables["UserName"].Value = "ivan_petrov";
// Установка числа - конвертация в string
int age = 25;
project.Variables["Age"].Value = age.ToString();
// Установка булевого значения - конвертация в string
bool isLoggedIn = true;
project.Variables["IsLoggedIn"].Value = isLoggedIn.ToString();
// Установка текущей даты и времени
project.Variables["CurrentDateTime"].Value = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
// Универсальный код
var someObject = object;
project.Variables["object"].Value = $"{someObject}";
🔢 РАБОТА С ЧИСЛОВЫМИ ДАННЫМИ
Конвертация из string в числовые типы
// Получение числового значения из переменной
string countStr = project.Variables["Count"].Value;
int count = int.Parse(countStr);
count++;
project.Variables["Count"].Value = count.ToString();
// Работа с double
string priceStr = project.Variables["Price"].Value;
double price = double.Parse(priceStr);
price *= 1.2; // Увеличиваем цену на 20%
project.Variables["Price"].Value = price.ToString("F2"); // Форматируем до 2 знаков после запятойАрифметические операции
// Инкремент счетчика
string attemptStr = project.Variables["Attempts"].Value;
int attempts = int.Parse(attemptStr);
attempts++;
project.Variables["Attempts"].Value = attempts.ToString();
// Вычисление суммы
string sum1Str = project.Variables["Sum1"].Value;
string sum2Str = project.Variables["Sum2"].Value;
int sum1 = int.Parse(sum1Str);
int sum2 = int.Parse(sum2Str);
int total = sum1 + sum2;
project.Variables["TotalSum"].Value = total.ToString();🔤 РАБОТА СО СТРОКОВЫМИ ДАННЫМИ
Конкатенация строк
// Простая конкатенация
string firstName = project.Variables["FirstName"].Value;
string lastName = project.Variables["LastName"].Value;
project.Variables["FullName"].Value = firstName + " " + lastName;
// Форматирование строки
string template = project.Variables["MessageTemplate"].Value;
string userName = project.Variables["UserName"].Value;
project.Variables["PersonalMessage"].Value = template.Replace("{username}", userName);Обработка текста
// Удаление лишних пробелов
string rawText = project.Variables["RawInput"].Value;
project.Variables["CleanInput"].Value = rawText.Trim();
// Изменение регистра
string email = project.Variables["Email"].Value;
project.Variables["EmailLower"].Value = email.ToLower();
// Проверка на содержание подстроки
string url = project.Variables["CurrentUrl"].Value;
if (url.Contains("success")) {
project.Variables["IsSuccess"].Value = "True";
} else {
project.Variables["IsSuccess"].Value = "False";
}🔀 РАБОТА С БУЛЕВЫМИ ЗНАЧЕНИЯМИ
Установка и проверка булевых переменных
// Установка булевого значения
project.Variables["IsProcessed"].Value = "True";
project.Variables["HasErrors"].Value = "False";
// Проверка булевого значения
string isLoggedInStr = project.Variables["IsLoggedIn"].Value;
bool isLoggedIn = isLoggedInStr == "True";
if (isLoggedIn) {
// Пользователь авторизован
project.Variables["LastLoginTime"].Value = DateTime.Now.ToString();
} else {
// Необходима авторизация
project.Variables["LoginRequired"].Value = "True";
}
// Переключение булевого значения
string currentState = project.Variables["FeatureEnabled"].Value;
bool isEnabled = currentState == "True";
project.Variables["FeatureEnabled"].Value = (!isEnabled).ToString();📅 РАБОТА С ДАТОЙ И ВРЕМЕНЕМ
Установка даты и времени
// Текущая дата и время
project.Variables["CurrentDateTime"].Value = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
// Только дата
project.Variables["CurrentDate"].Value = DateTime.Now.ToString("yyyy-MM-dd");
// Только время
project.Variables["CurrentTime"].Value = DateTime.Now.ToString("HH:mm:ss");
// Дата в различных форматах
project.Variables["DateRus"].Value = DateTime.Now.ToString("dd.MM.yyyy");
project.Variables["DateUS"].Value = DateTime.Now.ToString("MM/dd/yyyy");
// Unix timestamp
project.Variables["Timestamp"].Value = ((DateTimeOffset)DateTime.Now).ToUnixTimeSeconds().ToString();Операции с датами
// Добавление дней к дате
string currentDateStr = project.Variables["StartDate"].Value;
DateTime startDate = DateTime.Parse(currentDateStr);
DateTime endDate = startDate.AddDays(30);
project.Variables["EndDate"].Value = endDate.ToString("yyyy-MM-dd");
// Вычисление разности между датами
string date1Str = project.Variables["Date1"].Value;
string date2Str = project.Variables["Date2"].Value;
DateTime date1 = DateTime.Parse(date1Str);
DateTime date2 = DateTime.Parse(date2Str);
TimeSpan difference = date2 - date1;
project.Variables["DaysDifference"].Value = difference.Days.ToString();🌐 РАБОТА С URL И ПУТЯМИ
Формирование URL
// Базовый URL с параметрами
string baseUrl = project.Variables["BaseUrl"].Value;
string userId = project.Variables["UserId"].Value;
string apiKey = project.Variables["ApiKey"].Value;
project.Variables["FullUrl"].Value = $"{baseUrl}/user/{userId}?key={apiKey}";
// URL-кодирование параметров
string searchQuery = project.Variables["SearchQuery"].Value;
string encodedQuery = Macros.TextProcessing.UrlEncode(searchQuery, "utf-8");
project.Variables["EncodedQuery"].Value = encodedQuery;Извлечение частей URL
// Извлечение домена из URL
string fullUrl = project.Variables["FullUrl"].Value;
Uri uri = new Uri(fullUrl);
project.Variables["Domain"].Value = uri.Host;
project.Variables["Path"].Value = uri.AbsolutePath;
project.Variables["Query"].Value = uri.Query;🔍 УСЛОВНАЯ ЛОГИКА С ПЕРЕМЕННЫМИ
If-else конструкции
// Простое условие
string status = project.Variables["Status"].Value;
if (status == "success") {
project.Variables["Message"].Value = "Операция выполнена успешно";
} else if (status == "error") {
project.Variables["Message"].Value = "Произошла ошибка";
} else {
project.Variables["Message"].Value = "Неизвестный статус";
}
// Множественные условия
string userType = project.Variables["UserType"].Value;
string isVip = project.Variables["IsVip"].Value;
string discount = "0";
if (userType == "premium") {
discount = "15";
} else if (userType == "regular" && isVip == "True") {
discount = "10";
} else if (userType == "regular") {
discount = "5";
}
project.Variables["Discount"].Value = discount;Switch-подобная логика
// Эмуляция switch через if-else
string action = project.Variables["Action"].Value;
string result = "";
if (action == "login") {
result = "Выполняется авторизация...";
} else if (action == "logout") {
result = "Выполняется выход...";
} else if (action == "register") {
result = "Выполняется регистрация...";
} else {
result = "Неизвестное действие";
}
project.Variables["ActionResult"].Value = result;🔧 ПРАКТИЧЕСКИЕ ПРИМЕРЫ
Счетчик попыток с ограничением
// Получаем текущее количество попыток
string attemptsStr = project.Variables["LoginAttempts"].Value;
int attempts = int.Parse(attemptsStr);
// Увеличиваем счетчик
attempts++;
project.Variables["LoginAttempts"].Value = attempts.ToString();
// Проверяем лимит
int maxAttempts = 3;
if (attempts >= maxAttempts) {
project.Variables["MaxAttemptsReached"].Value = "True";
project.SendWarningToLog($"Достигнуто максимальное количество попыток: {attempts}", false);
// Прерываем выполнение
ZennoPoster.SetTries(new Guid(project.TaskId), 0);
}Генерация уникальных идентификаторов
// GUID
project.Variables["UniqueId"].Value = Guid.NewGuid().ToString();
// Timestamp + случайное число
string timestamp = DateTimeOffset.Now.ToUnixTimeSeconds().ToString();
string random = Global.Classes.rnd.Next(1000, 9999).ToString();
project.Variables["SessionId"].Value = timestamp + "_" + random;Работа с массивами данных в одной переменной
// Сохранение массива как строки с разделителем
string[] emails = {"test1@mail.com", "test2@mail.com", "test3@mail.com"};
project.Variables["EmailList"].Value = string.Join("|", emails);
// Извлечение массива из строки
string emailListStr = project.Variables["EmailList"].Value;
if (!string.IsNullOrEmpty(emailListStr)) {
string[] emailArray = emailListStr.Split('|');
if (emailArray.Length > 0) {
project.Variables["FirstEmail"].Value = emailArray[0];
project.Variables["EmailCount"].Value = emailArray.Length.ToString();
}
}Валидация данных
// Проверка email
string email = project.Variables["Email"].Value;
bool isValidEmail = !string.IsNullOrEmpty(email) && email.Contains("@") && email.Contains(".");
project.Variables["IsValidEmail"].Value = isValidEmail.ToString();
// Проверка телефона (простая)
string phone = project.Variables["Phone"].Value;
bool isValidPhone = !string.IsNullOrEmpty(phone) && phone.Length >= 10;
project.Variables["IsValidPhone"].Value = isValidPhone.ToString();
// Комплексная валидация
bool allValid = isValidEmail && isValidPhone;
project.Variables["AllFieldsValid"].Value = allValid.ToString();⚡ ОПТИМИЗАЦИЯ И ЛУЧШИЕ ПРАКТИКИ
Избегание повторных обращений
// ❌ Плохо - множественные обращения к одной переменной
if (project.Variables["Status"].Value == "processing") {
project.SendInfoToLog($"Статус: {project.Variables["Status"].Value}", false);
}
// ✅ Хорошо - одно обращение
string status = project.Variables["Status"].Value;
if (status == "processing") {
project.SendInfoToLog($"Статус: {status}", false);
}Инициализация переменных по умолчанию
// Проверка и установка значений по умолчанию
string counter = project.Variables["Counter"].Value;
if (string.IsNullOrEmpty(counter)) {
project.Variables["Counter"].Value = "0";
}
string status = project.Variables["Status"].Value;
if (string.IsNullOrEmpty(status)) {
project.Variables["Status"].Value = "idle";
}🚨 ОБРАБОТКА ОШИБОК
Безопасная работа с переменными (EAFP подход)
// EAFP - Easier to Ask for Forgiveness than Permission
try {
// Пытаемся получить и обработать переменную
string valueStr = project.Variables["Count"].Value;
int value = int.Parse(valueStr);
value++;
project.Variables["Count"].Value = value.ToString();
} catch (Exception ex) {
// Если что-то пошло не так - обрабатываем ошибку
project.SendErrorToLog($"Ошибка при работе с переменной Count: {ex.Message}", false);
// Устанавливаем безопасное значение по умолчанию
project.Variables["Count"].Value = "1";
}Проверка существования переменной
// Функция для проверки существования переменной
bool VariableExists(string variableName) {
try {
string value = project.Variables[variableName].Value;
return true;
} catch {
return false;
}
}
// Использование
if (VariableExists("OptionalSetting")) {
string setting = project.Variables["OptionalSetting"].Value;
// Работаем с переменной
} else {
project.SendInfoToLog("Переменная OptionalSetting не найдена", false);
}🌐 ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ
Что такое глобальные переменные?
Глобальные переменные в ZennoPoster - это переменные, которые:
- Доступны всем потокам и проектам в рамках одного экземпляра ZennoPoster
- Организованы по пространствам имен (namespaces) для лучшей структуризации
- Могут быть созданы программно во время выполнения
- Сохраняют свои значения между запусками разных потоков
Получение глобальной переменной
// Получение глобальной переменной по namespace и имени
IGlobalVariable gv = project.GlobalVariables["MyNamespace", "VariableName"];
// Получение значения
string value = gv.Value.ToString();
// Безопасное получение с проверкой на null
IGlobalVariable gv = project.GlobalVariables["Settings", "ApiKey"];
if (gv != null && gv.Value != null) {
string apiKey = gv.Value.ToString();
project.SendInfoToLog($"API ключ получен: {apiKey}", false);
} else {
project.SendWarningToLog("Глобальная переменная ApiKey не найдена", false);
}Создание и установка глобальных переменных
// Создание новой глобальной переменной с установкой значения
project.GlobalVariables.SetVariable("MyNamespace", "NewVariableName", "NewValue");
// Создание переменных для разных целей
project.GlobalVariables.SetVariable("Counters", "TotalProcessed", "0");
project.GlobalVariables.SetVariable("Settings", "MaxRetries", "5");
project.GlobalVariables.SetVariable("Auth", "AccessToken", "your_token_here");
project.GlobalVariables.SetVariable("Timing", "LastUpdate", DateTime.Now.ToString());Изменение значения существующей глобальной переменной
// Получаем переменную и изменяем её значение
IGlobalVariable counter = project.GlobalVariables["Counters", "TotalProcessed"];
if (counter != null) {
int currentValue = int.Parse(counter.Value.ToString());
currentValue++;
counter.Value = currentValue.ToString();
}
// Более короткий способ через SetVariable (перезапишет существующую)
string currentCountStr = project.GlobalVariables["Counters", "TotalProcessed"]?.Value?.ToString() ?? "0";
int currentCount = int.Parse(currentCountStr);
currentCount++;
project.GlobalVariables.SetVariable("Counters", "TotalProcessed", currentCount.ToString());Работа с метаданными глобальной переменной
// Получение информации о переменной
IGlobalVariable gv = project.GlobalVariables["Settings", "DatabaseUrl"];
if (gv != null) {
string name = gv.Name; // Имя переменной
string ns = gv.Namespace; // Пространство имен
string comment = gv.Comment; // Комментарий
object value = gv.Value; // Значение
// Установка комментария
if (string.IsNullOrWhiteSpace(comment)) {
gv.Comment = "URL для подключения к базе данных";
}
project.SendInfoToLog($"Переменная {ns}.{name}: {value} ({comment})", false);
}🔄 ПРАКТИЧЕСКИЕ СЦЕНАРИИ ИСПОЛЬЗОВАНИЯ ГЛОБАЛЬНЫХ ПЕРЕМЕННЫХ
Глобальный счетчик для всех потоков
// Инициализация счетчика (выполнять только один раз)
project.GlobalVariables.SetVariable("Statistics", "ProcessedItems", "0");
// Увеличение счетчика в каждом потоке (потокобезопасно)
IGlobalVariable counter = project.GlobalVariables["Statistics", "ProcessedItems"];
if (counter != null) {
lock (counter) {
int current = int.Parse(counter.Value.ToString());
current++;
counter.Value = current.ToString();
project.SendInfoToLog($"Обработано элементов: {current}", false);
// Проверка лимита
if (current >= 1000) {
project.GlobalVariables.SetVariable("Control", "StopProcessing", "True");
}
}
}Общие настройки для всех потоков
// Инициализация настроек (в главном потоке или один раз)
project.GlobalVariables.SetVariable("Config", "ApiUrl", "https://api.example.com");
project.GlobalVariables.SetVariable("Config", "Timeout", "30");
project.GlobalVariables.SetVariable("Config", "UserAgent", "MyBot/1.0");
// Использование настроек в любом потоке
string apiUrl = project.GlobalVariables["Config", "ApiUrl"]?.Value?.ToString() ?? "";
string timeoutStr = project.GlobalVariables["Config", "Timeout"]?.Value?.ToString() ?? "30";
string userAgent = project.GlobalVariables["Config", "UserAgent"]?.Value?.ToString() ?? "DefaultUA";
int timeout = int.Parse(timeoutStr) * 1000;
// Использование в HTTP запросе
string response = ZennoPoster.HTTP.Request(
method: ZennoLab.InterfacesLibrary.Enums.Http.HttpMethod.GET,
url: apiUrl + "/data",
proxy: project.GetProxy(),
UserAgent: userAgent,
Timeout: timeout,
respType: ZennoLab.InterfacesLibrary.Enums.Http.ResponceType.BodyOnly
);Система глобальных флагов управления
// Инициализация флагов управления
project.GlobalVariables.SetVariable("Control", "PauseAllThreads", "False");
project.GlobalVariables.SetVariable("Control", "StopOnError", "False");
project.GlobalVariables.SetVariable("Control", "MaintenanceMode", "False");
// Проверка флагов в каждом потоке
string pauseFlag = project.GlobalVariables["Control", "PauseAllThreads"]?.Value?.ToString() ?? "False";
if (pauseFlag == "True") {
project.SendInfoToLog("Поток приостановлен по глобальному флагу", false);
// Ожидание снятия флага
while (pauseFlag == "True") {
Thread.Sleep(5000);
pauseFlag = project.GlobalVariables["Control", "PauseAllThreads"]?.Value?.ToString() ?? "False";
}
}
// Установка флага при критической ошибке
try {
// Критически важная операция
} catch (Exception ex) {
project.SendErrorToLog($"Критическая ошибка: {ex.Message}", true);
project.GlobalVariables.SetVariable("Control", "StopOnError", "True");
// Прерывание выполнения
ZennoPoster.SetTries(new Guid(project.TaskId), 0);
}Кеширование данных между потоками
// Кеширование токена авторизации
string cachedToken = project.GlobalVariables["Cache", "AuthToken"]?.Value?.ToString() ?? "";
string tokenExpiry = project.GlobalVariables["Cache", "TokenExpiry"]?.Value?.ToString() ?? "";
bool needNewToken = string.IsNullOrEmpty(cachedToken);
if (!string.IsNullOrEmpty(tokenExpiry)) {
DateTime expiry = DateTime.Parse(tokenExpiry);
needNewToken = DateTime.Now >= expiry;
}
if (needNewToken) {
// Получение нового токена (только один поток должен это делать)
IGlobalVariable tokenVar = project.GlobalVariables["Cache", "AuthToken"];
if (tokenVar != null) {
lock (tokenVar) {
// Повторная проверка после получения блокировки
cachedToken = tokenVar.Value?.ToString() ?? "";
if (string.IsNullOrEmpty(cachedToken)) {
// Получаем новый токен
string newToken = GetAuthToken(); // Ваша функция получения токена
DateTime newExpiry = DateTime.Now.AddHours(1);
project.GlobalVariables.SetVariable("Cache", "AuthToken", newToken);
project.GlobalVariables.SetVariable("Cache", "TokenExpiry", newExpiry.ToString());
cachedToken = newToken;
}
}
}
}
// Использование кешированного токена
string headers = $"Authorization: Bearer {cachedToken}";Глобальная статистика и мониторинг
// Инициализация статистики
project.GlobalVariables.SetVariable("Stats", "TotalRequests", "0");
project.GlobalVariables.SetVariable("Stats", "SuccessfulRequests", "0");
project.GlobalVariables.SetVariable("Stats", "FailedRequests", "0");
project.GlobalVariables.SetVariable("Stats", "StartTime", DateTime.Now.ToString());
// Обновление статистики в потоке
void UpdateStats(bool isSuccess) {
// Общее количество запросов
IGlobalVariable totalVar = project.GlobalVariables["Stats", "TotalRequests"];
if (totalVar != null) {
lock (totalVar) {
int total = int.Parse(totalVar.Value.ToString());
total++;
totalVar.Value = total.ToString();
}
}
// Успешные или неуспешные
string statType = isSuccess ? "SuccessfulRequests" : "FailedRequests";
IGlobalVariable statVar = project.GlobalVariables["Stats", statType];
if (statVar != null) {
lock (statVar) {
int count = int.Parse(statVar.Value.ToString());
count++;
statVar.Value = count.ToString();
}
}
}
// Использование
try {
// Выполнение запроса
string response = ZennoPoster.HTTP.Request(/* параметры */);
UpdateStats(true);
} catch {
UpdateStats(false);
}
// Вывод статистики
string total = project.GlobalVariables["Stats", "TotalRequests"]?.Value?.ToString() ?? "0";
string success = project.GlobalVariables["Stats", "SuccessfulRequests"]?.Value?.ToString() ?? "0";
string failed = project.GlobalVariables["Stats", "FailedRequests"]?.Value?.ToString() ?? "0";
project.SendInfoToLog($"Статистика: Всего={total}, Успешно={success}, Ошибок={failed}", false);🔒 ПОТОКОБЕЗОПАСНОСТЬ ГЛОБАЛЬНЫХ ПЕРЕМЕННЫХ
Правильное использование lock
// Правильный способ - блокировка на объекте переменной
IGlobalVariable sharedCounter = project.GlobalVariables["Shared", "Counter"];
if (sharedCounter != null) {
lock (sharedCounter) {
int current = int.Parse(sharedCounter.Value.ToString());
current++;
sharedCounter.Value = current.ToString();
// Любые другие операции с этой переменной
project.SendInfoToLog($"Счетчик: {current}", false);
}
}
// Комплексная операция с несколькими переменными
IGlobalVariable var1 = project.GlobalVariables["Data", "Variable1"];
IGlobalVariable var2 = project.GlobalVariables["Data", "Variable2"];
if (var1 != null && var2 != null) {
// Блокируем по одной переменной для избежания deadlock
lock (var1) {
lock (var2) {
// Атомарная операция с двумя переменными
int val1 = int.Parse(var1.Value.ToString());
int val2 = int.Parse(var2.Value.ToString());
val1++;
val2 += val1;
var1.Value = val1.ToString();
var2.Value = val2.ToString();
}
}
}⚖️ СРАВНЕНИЕ: ЛОКАЛЬНЫЕ vs ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ
| Характеристика | Локальные переменные | Глобальные переменные |
|---|---|---|
| Область видимости | Только текущий поток | Все потоки |
| API доступа | project.Variables["name"] | project.GlobalVariables["namespace", "name"] |
| Создание | Только в ProjectMaker | В коде или ProjectMaker |
| Пространства имен | Нет | Да |
| Потокобезопасность | Не требуется | Требуется lock |
| Производительность | Высокая | Ниже (из-за синхронизации) |
| Использование | Данные потока | Общие настройки, счетчики |
Когда использовать глобальные переменные:
- Общие настройки для всех потоков
- Счетчики и статистика
- Флаги управления выполнением
- Кеширование данных между потоками
- Координация между потоками
Когда использовать локальные переменные:
- Данные специфичные для потока
- Промежуточные результаты
- Состояние выполнения конкретного потока
- Временные значения