Скрипты на С, VBS и VBA в помощь разработчикам

Обсуждение SCADA-систем и HMI SIEMENS: WinCC OA, WinCC, WinCC Flexible, ProTool
Аватара пользователя
alex
Администратор
Сообщений в теме: 21
Сообщения: 1714
Зарегистрирован: 05 апр 2010, 21:58
Откуда: Москва
Благодарил (а): 43 раза
Поблагодарили: 95 раз
Контактная информация:

Скрипты на С, VBS и VBA в помощь разработчикам

#1

Сообщение alex » 02 апр 2014, 21:25

В этой теме находятся примеры кода на стандартных для WinCC скриптовых языках программирования, позволяющие решать различные задачи при разработке проектов, обеспечивая тем самым гибкий подход к реализации требуемого функционала.

Внимание! Тема развивается модераторами и администраторами форума.



Аватара пользователя
alex
Администратор
Сообщений в теме: 21
Сообщения: 1714
Зарегистрирован: 05 апр 2010, 21:58
Откуда: Москва
Благодарил (а): 43 раза
Поблагодарили: 95 раз
Контактная информация:

C: void LogMsg (DWORD dwErrorCode, char* szErrorText, char* pszNameFunc)

#2

Сообщение alex » 02 апр 2014, 21:36

Функция ведения пользовательского журнала работы проекта. Пишет в файл журнала, который обычно находится в директории проекта и дублирует вывод в окно диагностики GSC Diagnostic.

/*
    (с) 2014 www.proasutp.com

    Функция выводит сообщение в окно диагностики и в файл, если имя файла определено во внешней переменной szLogFileName.

    Вход:
        dwErrorCode - код ошибки;
        szErrorText - описание ошибки;
        pszNameFunc - название функции где возникла ошибка.
    Выход:
        Нет.

*/


#include "apdefap.h"

void LogMsg (DWORD dwErrorCode, char* szErrorText, char* pszNameFunc)
{
   
    #define BUFFER_MAX_SIZE 1000            // размер буфера вывода в файл, значение выбрано "с запасом", т.к. размер строки вывода в файл редко будет превышать указанный
   
    extern char szLogFileName[];            // внешняя глобальная переменная с именем файла, которая должна сформироваться при инициализации проекта как <ProjectName>.err
    char szTime [20] = "";                  // дата и время записи сообщения
    char szMsgBuff[BUFFER_MAX_SIZE]= "";    // строковый буфер для сообщения

    FILE *file = NULL;

    if (dwErrorCode)
       
printf
Чтобы увидеть ссылку зарегистрируйтесь или войдите под своим логином.
("Код ошибки - %d(%x);  Сообщение - %s; Функция - %s\r\n", dwErrorCode, dwErrorCode,((szErrorText!=NULL)&&(szErrorText[0]!=0)) ? szErrorText : "", ((pszNameFunc!=NULL)&&(pszNameFunc[0]!=0)) ? pszNameFunc : "");
    else
       
printf
Чтобы увидеть ссылку зарегистрируйтесь или войдите под своим логином.
("%s; Функция - %s\r\n",((szErrorText!=NULL)&&(szErrorText[0]!=0)) ? szErrorText : "", ((pszNameFunc!=NULL)&&(pszNameFunc[0]!=0)) ? pszNameFunc : "");


    if (szLogFileName==NULL && szLogFileName[0]==0)
    {
       
printf
Чтобы увидеть ссылку зарегистрируйтесь или войдите под своим логином.
("Сообщение не записано в лог-файл, его имя еще не определено!\r\n");
        return;
    }

    file =
fopen
Чтобы увидеть ссылку зарегистрируйтесь или войдите под своим логином.
(szLogFileName, "a+");

    if (file)
    {
        GetTime (szTime, sizeof (szTime));

        // устанавливаем заданный размер буфера выводы, т.к. по умолчанию он часто имеет меньший размер,
        // что приводит к его переполнению и ошибке типа "access violation"

       
setbuf
Чтобы увидеть ссылку зарегистрируйтесь или войдите под своим логином.
(file,szMsgBuff);

       
fprintf
Чтобы увидеть ссылку зарегистрируйтесь или войдите под своим логином.
(file,"%sКод ошибки: %d(%x); Сообщение: %s; Функция: %s\n", szTime, dwErrorCode, dwErrorCode, ((szErrorText!=NULL)&&(szErrorText[0]!=0)) ? szErrorText : "", ((pszNameFunc!=NULL)&&(pszNameFunc[0]!=0)) ? pszNameFunc : "");
       
fclose
Чтобы увидеть ссылку зарегистрируйтесь или войдите под своим логином.
(file);
    }
    else
printf
Чтобы увидеть ссылку зарегистрируйтесь или войдите под своим логином.
("Не могу открыть файл \"%s\" для записи сообщения!\r\n", szLogFileName);
}



Аватара пользователя
alex
Администратор
Сообщений в теме: 21
Сообщения: 1714
Зарегистрирован: 05 апр 2010, 21:58
Откуда: Москва
Благодарил (а): 43 раза
Поблагодарили: 95 раз
Контактная информация:

C: BOOL GetCurDir (char* pszCurDir, DWORD dwSizeBuf)

#3

Сообщение alex » 02 апр 2014, 21:52

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

/*
        (с) 2014 www.proasutp.com

        Функция возвращает в буфер строки полный путь к директории проекта WinCC.

        Вход:
                pszCurDir - ссылка на буфер;
                dwSizeBuf - размер буфера;
        Выход:
                Если функция выполнилась успешно, тогда возвращается TRUE, иначе FALSE.

*/


#include "apdefap.h"

BOOL GetCurDir (char* pszCurDir, DWORD dwSizeBuf)
{
    char szProjectFile [MAX_PATH+1] = "";
    CMN_ERROR dmErr;
    DM_DIRECTORY_INFO dmDirInfo;
    BOOL ret = FALSE;
    int i = 0;

    // Получаем проект, который запущен в режим RunTime
    ret = DMGetRuntimeProject(szProjectFile, sizeof (szProjectFile), &dmErr);
    if (!ret)
    {
        LogMsg (dmErr.dwError1, "Не могу получить Runtime проект", "GetCurDir");
        return FALSE;
    }

    // Получаем директорию запущенного проекта
    ret = DMGetProjectDirectory ("MyApp",szProjectFile, &dmDirInfo, &dmErr);
    if (!ret)
    {
        LogMsg (dmErr.dwError1, "Не могу получить проектную директорию", "GetCurDir");
        return FALSE;
    }

    for (i=0; i < dwSizeBuf; i++)  pszCurDir[i] = dmDirInfo.szProjectDir[i];
    pszCurDir[i] = '\0';

    return TRUE;
}



Аватара пользователя
alex
Администратор
Сообщений в теме: 21
Сообщения: 1714
Зарегистрирован: 05 апр 2010, 21:58
Откуда: Москва
Благодарил (а): 43 раза
Поблагодарили: 95 раз
Контактная информация:

C: BOOL GetEnvVarValue (char* pszEnvVarName, char* pszValue, long nSize)

#4

Сообщение alex » 02 апр 2014, 22:04

Иногда встает задача прочитать текущее значение переменной окружения операционной системы Windows...

/*
        (с) 2014 www.proasutp.com

        Функция возвращает в строковый буфер значение переменной окружения.

        Вход:
                pszEnvVarName - указатель на имя переменной окружения;
                pszValue - указатель на строковый буфер куда будет записано значение переменной окружения;
        nSize - размер строкового буфера.
        Выход:
                Если функция выполнилась успешно, тогда возвращается TRUE, иначе FALSE.

*/


#include "apdefap.h"
BOOL GetEnvVarValue (char* pszEnvVarName, char* pszValue, long nSize)
{

    #pragma code ("kernel32.dll")
        DWORD GetEnvironmentVariableA (LPCTSTR lpName,  // address of environment variable name
                                    LPTSTR lpBuffer,    // address of buffer for variable value
                                    DWORD nSize         // size of buffer, in characters
                                   );
    #pragma code ()

    DWORD ret=0;
    char szErrText[256] = "";

    if (pszEnvVarName == NULL) {
        LogMsg ((DWORD)-1, "Передан нулевой указатель на имя переменной окружения (pszEnvVarName=NULL)", "GetEnvVarValue");
        return FALSE;
        }

    if (pszEnvVarName[0] == 0) {
        LogMsg ((DWORD) -1, "Передана пустая строка в переменной имени переменной окружения (pszEnvVarName is Empty)", "GetEnvVarValue");
        return FALSE;
        }

    if (pszValue == NULL) {
        LogMsg ((DWORD)-1, "Передан нулевой указатель на строковый буфер под значение переменной окружения (pszValue =NULL)", "GetEnvVarValue");
        return FALSE;
        }

    if (nSize <= 0) {
        LogMsg ((DWORD)-1, "Передано неправильное значение длины строкового буфера (nSize<=0)", "GetEnvVarValue");
        return FALSE;
        }

    ret = GetEnvironmentVariableA (pszEnvVarName, pszValue, nSize);

    if (ret == 0) {
       
sprintf
Чтобы увидеть ссылку зарегистрируйтесь или войдите под своим логином.
(szErrText,"Переменная окружения с именем <%s> не найдена!", pszEnvVarName);
        LogMsg ((DWORD)-1, szErrText, "GetEnvVarValue");
        return FALSE;
        }

    if (ret > (nSize - 1)) {
       
sprintf
Чтобы увидеть ссылку зарегистрируйтесь или войдите под своим логином.
(szErrText,"Размер буфера pszValue недостаточен для значения переменной окружения (текущий = %d), необходим буфер размером не менее %d!",nSize,ret);
        LogMsg ((DWORD)-1, szErrText, "GetEnvVarValue");
        return FALSE;
        }

    return TRUE;
}



Аватара пользователя
alex
Администратор
Сообщений в теме: 21
Сообщения: 1714
Зарегистрирован: 05 апр 2010, 21:58
Откуда: Москва
Благодарил (а): 43 раза
Поблагодарили: 95 раз
Контактная информация:

C: BOOL GetProjectName (char* pszPrjName, DWORD dwSizeBuf)

#5

Сообщение alex » 02 апр 2014, 22:11

Как получить динамически имя запущенного проекта WinCC, ниже ответ...

/*
        (с) 2014 www.proasutp.com

        Функция возвращает имя текущего проекта.

        Вход:
                pszPrjName - указатель на строковый буфер;
                dwSizeBuf - размер строкового буфера.
        Выход:
                Если функция выполнилась успешно, тогда возвращается TRUE, иначе FALSE.

*/


#include "apdefap.h"

BOOL GetProjectName (char* pszPrjName, DWORD dwSizeBuf)
{
    CMN_ERROR dmErr;
    BOOL ret = FALSE;
    long l1 = 0, l2 = 0, i=0, j=0, c=0;
    char s[_MAX_PATH+1] = "";

    // Получаем проект который запущен в режим RunTime

    ret = DMGetRuntimeProject(s, sizeof(s), &dmErr);

    if (!ret) {
        LogMsg (dmErr.dwError1, "Не могу получить имя проекта","GetProjectName");
        return FALSE;
        }

    // Т.к. мы получаем имя проекта вида  "\\PCNAME\WinCC60_Project_ProjectName\ProjectName.mcp",
    // то необходимо выделить только имя "ProjectName"

    c =
strlen
Чтобы увидеть ссылку зарегистрируйтесь или войдите под своим логином.
(s);

    for (i = c-1,l1 = 0,l2 = 0; i >= 0; i--)    {
        if (s[i] == '.') l2 = i;
        if (s[i] == '\\') { l1 = i; break;}
        }

    if ( (l1 == 0) || (l2 == 0) ) {
        LogMsg (dmErr.dwError1, "Ошибка выделения границ имени проекта","GetProjectName");
        return FALSE;
        }

    l1++;
 
    if ((l1-l2+1) > dwSizeBuf ) {
        LogMsg (dmErr.dwError1, "Длина имени проекта превышает размер  буфера строки szPrjName","GetProjectName");
        return FALSE;
        }

    for (i = l1, j = 0; i < l2; i++, j++) szPrjName[j] = s[i];
    szPrjName[j] = 0;
   
    return TRUE;
}



Аватара пользователя
alex
Администратор
Сообщений в теме: 21
Сообщения: 1714
Зарегистрирован: 05 апр 2010, 21:58
Откуда: Москва
Благодарил (а): 43 раза
Поблагодарили: 95 раз
Контактная информация:

C: void GetTime (char* pszTime, DWORD dwSize)

#6

Сообщение alex » 02 апр 2014, 22:18

Получаем текущую дату в виде строки...

/*
        (с) 2014 www.proasutp.com

        Функция возвращает в строковый буфер текущее время в формате: dd.mm.yyyy hh:mm:ss

        Вход:
                pszTime - указатель на буфер;
                dwSize - размер буфера.
        Выход:
                Если функция выполнилась успешно, тогда возвращается TRUE, иначе FALSE.

*/


void GetTime (char* pszTime, DWORD dwSize)
{
    time_t t = 0;
    char *pDateTime = NULL;
    char Day [4] = "";
    char Date [3] = "";
    char Month [4] = "";
    char Year [5] = "";
    char Time [9] = "";
    char tm [20] = "";
    int i = 0;

   
time
Чтобы увидеть ссылку зарегистрируйтесь или войдите под своим логином.
(&t);
    pDateTime =
ctime
Чтобы увидеть ссылку зарегистрируйтесь или войдите под своим логином.
(&t);

   
sscanf
Чтобы увидеть ссылку зарегистрируйтесь или войдите под своим логином.
(pDateTime, "%s %s %s %s %s", Day, Month, Date, Time, Year);

    if (
strcmp
Чтобы увидеть ссылку зарегистрируйтесь или войдите под своим логином.
(Month,"Jan") == 0)
strcpy
Чтобы увидеть ссылку зарегистрируйтесь или войдите под своим логином.
(Month, "01");
    if (
strcmp
Чтобы увидеть ссылку зарегистрируйтесь или войдите под своим логином.
(Month,"Feb") == 0)
strcpy
Чтобы увидеть ссылку зарегистрируйтесь или войдите под своим логином.
(Month, "02");
    if (
strcmp
Чтобы увидеть ссылку зарегистрируйтесь или войдите под своим логином.
(Month,"Mar") == 0)
strcpy
Чтобы увидеть ссылку зарегистрируйтесь или войдите под своим логином.
(Month, "03");
    if (
strcmp
Чтобы увидеть ссылку зарегистрируйтесь или войдите под своим логином.
(Month,"Apr") == 0)
strcpy
Чтобы увидеть ссылку зарегистрируйтесь или войдите под своим логином.
(Month, "04");
    if (
strcmp
Чтобы увидеть ссылку зарегистрируйтесь или войдите под своим логином.
(Month,"May") == 0)
strcpy
Чтобы увидеть ссылку зарегистрируйтесь или войдите под своим логином.
(Month, "05");
    if (
strcmp
Чтобы увидеть ссылку зарегистрируйтесь или войдите под своим логином.
(Month,"Jun") == 0)
strcpy
Чтобы увидеть ссылку зарегистрируйтесь или войдите под своим логином.
(Month, "06");
    if (
strcmp
Чтобы увидеть ссылку зарегистрируйтесь или войдите под своим логином.
(Month,"Jul") == 0)
strcpy
Чтобы увидеть ссылку зарегистрируйтесь или войдите под своим логином.
(Month, "07");
    if (
strcmp
Чтобы увидеть ссылку зарегистрируйтесь или войдите под своим логином.
(Month,"Aug") == 0)
strcpy
Чтобы увидеть ссылку зарегистрируйтесь или войдите под своим логином.
(Month, "08");
    if (
strcmp
Чтобы увидеть ссылку зарегистрируйтесь или войдите под своим логином.
(Month,"Sep") == 0)
strcpy
Чтобы увидеть ссылку зарегистрируйтесь или войдите под своим логином.
(Month, "09");
    if (
strcmp
Чтобы увидеть ссылку зарегистрируйтесь или войдите под своим логином.
(Month,"Oct") == 0)
strcpy
Чтобы увидеть ссылку зарегистрируйтесь или войдите под своим логином.
(Month, "10");
    if (
strcmp
Чтобы увидеть ссылку зарегистрируйтесь или войдите под своим логином.
(Month,"Nov") == 0)
strcpy
Чтобы увидеть ссылку зарегистрируйтесь или войдите под своим логином.
(Month, "11");
    if (
strcmp
Чтобы увидеть ссылку зарегистрируйтесь или войдите под своим логином.
(Month,"Dec") == 0)
strcpy
Чтобы увидеть ссылку зарегистрируйтесь или войдите под своим логином.
(Month, "12");

   
sprintf
Чтобы увидеть ссылку зарегистрируйтесь или войдите под своим логином.
(tm, "%s.%s.%s %s ", Date, Month, Year, Time);

    for (i=0; i<dwSize; i++) pszTime[i] = tm[i];
    pszTime[i] = '\0';
}



Аватара пользователя
alex
Администратор
Сообщений в теме: 21
Сообщения: 1714
Зарегистрирован: 05 апр 2010, 21:58
Откуда: Москва
Благодарил (а): 43 раза
Поблагодарили: 95 раз
Контактная информация:

C: BOOL IsServer ()

#7

Сообщение alex » 02 апр 2014, 22:26

Иногда необходимо знать какую функцию выполняет ПК на котором работает проект, т.е. он является сервером или клиентом?

/*
        (с) 2014 www.proasutp.com

        Функция определяет является ли ПК сервером WinCC.

        Вход:
        Нет

        Выход:
                TRUE - ПК выполняет фунцию сервера WinCC, FALSE - нет, это клиентский ПК.

*/


BOOL IsServer ()
{
    BOOL bIsServer = FALSE;

    bIsServer = (0 ==
strcmp
Чтобы увидеть ссылку зарегистрируйтесь или войдите под своим логином.
(GetTagChar("@local::@LocalMachineName"),GetTagChar("@@local::@ServerName")));
    return bIsServer;
}



Аватара пользователя
alex
Администратор
Сообщений в теме: 21
Сообщения: 1714
Зарегистрирован: 05 апр 2010, 21:58
Откуда: Москва
Благодарил (а): 43 раза
Поблагодарили: 95 раз
Контактная информация:

C: int MsgBox (char* pszCaption, char* pszMessage, DWORD dwFlags)

#8

Сообщение alex » 02 апр 2014, 22:37

Обвязка стандартной функции WinAPI
MessageBox
Чтобы увидеть ссылку зарегистрируйтесь или войдите под своим логином.
для вывода модальных сообщений в проекте WinCC.

/*
        (с) 2014 www.proasutp.com

        Функция выводит стандартное модальный диалоговое окно с сообщением

        Вход:
        pszCaption - указатель на строку заголовка окна;
        pszMessage - указатель на строку сообщения;
        dwFlags - стандартные флаги, см. MSDN, функцию WinAPI MessageBox

        Выход:
                Результат возвращаемый функцией MessageBox.

*/


int MsgBox (char* pszCaption, char* pszMessage, DWORD dwFlags)
{
    HANDLE h = NULL;

    // Получаем хендл главного окна проекта WinCC
    h = FindWindow("PDLRTisAliveAndWaitsForYou","WinCC-Runtime - ");

    // Вызываем модальное диалоговое окно с сообщением
    return MessageBox (h, pszMessage, pszCaption, dwFlags);
}



Аватара пользователя
alex
Администратор
Сообщений в теме: 21
Сообщения: 1714
Зарегистрирован: 05 апр 2010, 21:58
Откуда: Москва
Благодарил (а): 43 раза
Поблагодарили: 95 раз
Контактная информация:

C: void PlaySoundOn (char* pszWaveFile)

#9

Сообщение alex » 02 апр 2014, 22:46

Функция проигрывания wav-файла через стандартную функцию WinAPI
PlaySound
Чтобы увидеть ссылку зарегистрируйтесь или войдите под своим логином.
.

/*
        (с) 2014 www.proasutp.com

        Функция проигрывает wav-файл.

        Вход:
                pszWaveFile - ссылка на строковый буфер содержащий полный путь к звуковому файлу;
        Выход:
                Нет

*/


void PlaySoundOn (char* pszWaveFile)
{
    #pragma code ("Winmm.dll")
    long WINAPI PlaySoundA (char* pszSound , void* hmode, DWORD dwFlag);  
    #pragma code()

    #define SND_ASYNC               0x0001      /* play asynchronously */
    #define SND_NODEFAULT           0x0002      /* silence (!default) if sound not found */
    #define SND_LOOP                0x0008      /* loop the sound until next sndPlaySound */
    #define SND_NOSTOP              0x0010      /* don't stop any currently playing sound */
    #define SND_NOWAIT          0x00002000      /* don't wait if the driver is busy */
    #define SND_FILENAME        0x00020000      /* name is file name */

   
    if ( (pszWaveFile != NULL) && (pszWaveFile[0]!= 0)) {
        int i = SND_ASYNC | SND_NOSTOP | SND_LOOP;
        PlaySoundA (pszWaveFile, NULL, i);
        }
    else {
       
printf
Чтобы увидеть ссылку зарегистрируйтесь или войдите под своим логином.
("Failed: Wrong argument <pszWaveFile> in function PlaySoundOn!\r\n");
        }
}



Аватара пользователя
alex
Администратор
Сообщений в теме: 21
Сообщения: 1714
Зарегистрирован: 05 апр 2010, 21:58
Откуда: Москва
Благодарил (а): 43 раза
Поблагодарили: 95 раз
Контактная информация:

C: void PlaySoundStop ()

#10

Сообщение alex » 02 апр 2014, 22:50

Функция прекращает проигрывание wav-файла. Например, это удобно если было запущено циклическое проигрывание файла.

/*
        (с) 2014 www.proasutp.com

        Функция прекращает проигрывание wav-файл.

        Вход:
                Нет
        Выход:
                Нет

*/


void PlaySoundStop ()
{
    #pragma code ("Winmm.dll")
    long WINAPI PlaySoundA (const char * pszSound , void * hmode, DWORD dwFlag );  
    #pragma code()

    PlaySoundA(NULL,NULL,0);
}




Если эта тема может быть полезна другим, поделитесь ссылкой:

Вернуться в «SIMATIC: WinCC OA, WinCC, WinCC Flexible, ProTool»