WinCC的电子签名与审计追踪
如何写入审计追踪记录
用脚本向Audit中添加记录有两种方法,一种方法是用InserAuditEntryNew函数写入,另一种方法是生成属于“操作员输入消息”类型的报警消息,该报警消息会记录到Audit中。
Audit记录中的TargetName列是操作内容,Reason列是操作员的注释。使用InserAuditEntryNew函数生成的记录在TargetName列的内容默认为VBScripting Runtime或CScripting Runtime,而操作内容只能记录在Reason列处,这与其他记录的形式不一致,效果不好,因此在此不使用InserAuditEntryNew函数。
第二种方法,在报警记录的“系统,无确认”下的“操作员输入消息”中建立报警消息,当这条消息触发后,消息不仅会记录到报警数据库,也会记录到Audit数据库。触发报警消息可以用变量触发,也可以用脚本触发。使用脚本触发可以给消息传递参数,即向@1%s@等文本块中写入值。
WinCC中默认有一条编号为12508141的操作员输入消息,定义如下图,该消息用于记录新值旧值的更改。
12508141消息的内容不完全符合Audit消息记录的需要,新建一条编号为12508142消息。项目中可能会用WinCC控制多台设备,定义文本块@10%s@的作用是记录该操作针对哪台设备,文本块@7%s@记录执行了什么操作。有些项目中不使用Audit trail组件,而是用报警记录的数据库记录审计追踪,因此可在错误点列填上@10%s@,使用报警控件查看时便于筛选。该消息定义如下:
使用C脚本生成操作员消息
WinCC支持C和VB两种脚本,C脚本中提供了GCreateMyOperationMsg()函数生成操作员消息。
函数原型:
int GCreateMyOperationMsg( DWORD dwFlags, DWORD dwMsgNum, char* lpszPictureName, char* lpszObjectName, DWORD dwMyTextID, double doValueOld, double doValueNew, char* pszComment)
参数:
- dwFlags,该参数指定如何生成注释,可用以下常量值,值可以用或运算“|”输入:
常数 |
值 |
描述 |
FLAG_COMMENT_PARAMETER |
0x00000001 |
文本在运行时直接作为消息输入,没有自己的注释对话框。对注释的指针不能等于“NULL”。 |
FLAG_COMMENT_DIALOG |
0x00000003 |
出现一个注释对话框,输入的注释被转移到消息中 |
FLAG_TEXTID_PARAMETER |
0x00000100 |
提供文本库中的一个文本ID,将文本插入到消息的过程值中。 |
- dwMsgNum,该参数为消息编号,触发该编号的消息。消息必须属于“操作员输入消息”类型,不可使用其他类型的消息。
- lpszPictureName,该参数未在函数中使用,不起任何作用。
- lpszObjectName,该参数会写入到文本块@1%s@中和szInstance属性中,szInstance属性等同于文本块@10%s@。
- dwMyTextID,该参数是文本库ID,值会被写入到值@8%g@中。如果dwFlags参数为FLAG_TEXTID_PARAMETER,会将文本库中该ID的文本写入到文本块@8%s@中。
- doValueOld,该参数是变量旧值,值会被写入到值@2%g@中,在audit中会写入到OldValue列中。
- doValueNew,该参数是变量新值,值会被写入到值@3%g@中,在audit中会写入到NewValue列中。
- pszComment,该参数是注释字符串,如果dwFlags参数为FLAG_COMMENT_PARAMETER,该字符串会写入到报警的注释中,写入到Audit的Reason列。
返回值:
值 |
描述 |
0 |
函数执行完成没有任何错误 |
-101 |
消息不能被编辑 |
-201 |
当调用"MSRTGetComment()"特征引发一个错误 |
-301 |
当调用"MSRTCreateMsgInstanceWithComment()"特征引发一个错误 |
GCreateMyOperationMsg()函数生成的消息文本中未使用文本块@7%s@,我们参考GCreateMyOperationMsg函数进行修改,重新创建一个操作员消息函数GCreateMyOperationMsg2(),该函数值用lpszMsg参数代替lpszPictureName参数,lpszMsg参数的值被写入文本块@7%s@中。GCreateMyOperationMsg2()函数配合12508142消息使用。
函数原型:
int GCreateMyOperationMsg2( DWORD dwFlags, DWORD dwMsgNum, char* lpszMsg, char* lpszObjectName, DWORD dwMyTextID, double doValueOld, double doValueNew, char* pszComment)
参数:
- lpszMsg,该参数记录操作消息,会写入文本块@7%s@中。
- 其他参数与GCreateMyOperationMsg()函数一致。
函数代码:
- #pragma code ("kernel32.dll")
- void GetLocalTime( LPSYSTEMTIME lpSystemTime);
- BOOL GetComputerNameA(LPSTR Computername, LPDWORD size);
- VOID Sleep(DWORD dwMilliseconds); //RQ:1072746
- #pragma code()
- #define FLAG_COMMENT_PARAMETER 0x00000001
- #define FLAG_COMMENT_DIALOG 0x00000003
- #define FLAG_TEXTID_PARAMETER 0x00000100
- int GCreateMyOperationMsg2( DWORD dwFlags, DWORD dwMsgNum, char* lpszMsg, char* lpszObjectName, DWORD dwMyTextID, double doValueOld, double doValueNew, char* pszComment )
- {
- MSG_RTDATA_INSTANCECOMMENT_STRUCT MsgCreateEx;
- MSG_RTDATA_STRUCT MsgRTData; // for comment dialog
- CMN_ERROR scError;
- int iRet= FALSE;
- DWORD dwServiceID = 0;
- BOOL bOK;
- SYSTEMTIME time;
- DWORD dwBufSize = 256;
- char szComputerName[256] = "";
- char szSource[256] = "";
- char szMyText[MSG_MAX_TB_CONTENT + 1] = "";
- char szTmp[256] = ""; // for diagnosis output
- char* pszPrefix; // to define the type of WinCC project
- char* lpszCurrentUser;
- char* lpszParent;
- char * pszServerPrefix;
- //RQ:1072746 begin
- DWORD dwMaxCheckTime = 5000; // max time to wait 5000ms=5sec.
- DWORD dwStepCheckTime = 500; // start stepping waittime with 500ms
- DWORD dwReduceStepTime = 100; // reduce the steptime here by 100ms
- DWORD dwActWaitedTime = 0;
- DWORD dwInx = 0;
- //RQ:1072746 end
- printf("Start GCreateMyOperationMsg \r\n");
- //======================================
- // INIT_MESSAGE_STRUCT
- //======================================
- memset(&MsgCreateEx,0,sizeof(MsgCreateEx));
- memset(&MsgRTData,0,sizeof(MsgRTData));
- memset(&scError,0,sizeof(scError));
- GetLocalTime(&time);
- MsgCreateEx.stMsgTime = time;
- MsgRTData.stMsgTime = time;
- MsgCreateEx.dwMsgNr = dwMsgNum;
- MsgRTData.dwMsgNr = dwMsgNum;
- MsgCreateEx.wPValueUsed = (WORD)(0x0000 ); // no real process value used
- MsgRTData.wPValueUsed = (WORD)(0x0000 );
- MsgCreateEx.wTextValueUsed = 0x001F; // text values 1 .. 5 used for textblocks 1 .. 5
- MsgRTData.wTextValueUsed = 0x001F; // text values 1 .. 5 used for textblocks 1 .. 5
- MsgCreateEx.dwFlags = MSG_FLAG_TEXTVALUES;
- MsgRTData.dwFlags = MSG_FLAG_COMMENT | MSG_FLAG_TEXTVALUES;
- MsgCreateEx.dwMsgState = MSG_STATE_COME;
- MsgRTData.dwMsgState = MSG_STATE_COME;
- GetComputerNameA(szComputerName, &dwBufSize);
- sprintf(szTmp, "Computername = %s \r\n", szComputerName);
- printf(szTmp);
- strncpy(MsgCreateEx.szComputerName, szComputerName, sizeof(MsgCreateEx.szComputerName) -1);
- lpszCurrentUser = GetTagChar("@NOP::@CurrentUser");
- if (NULL != lpszCurrentUser )
- {
- strncpy( MsgCreateEx.szUser, lpszCurrentUser, sizeof (MsgCreateEx.szUser) - 1);
- }
- if ( dwFlags & FLAG_TEXTID_PARAMETER)
- {
- MsgCreateEx.dPValue[7] = dwMyTextID; // TextID
- MsgCreateEx.wPValueUsed = 0x0080; // for process value 8
- }
- MsgCreateEx.wPValueUsed = (WORD)(MsgCreateEx.wPValueUsed | 0x0006);
- MsgCreateEx.dPValue[1] = doValueOld; // old value
- MsgCreateEx.dPValue[2] = doValueNew; // new value
- //======================================
- // START_MESSAGE_SERVICE
- //======================================
- memset(&scError,0,sizeof(scError));
- // GetServerPrefix to determine MC or Server
- GetServerTagPrefix(&pszServerPrefix, NULL, NULL); //Return-Type: void
- if (NULL == pszServerPrefix)
- {
- printf("Serverapplication or Single Client\r\n");
- bOK = MSRTStartMsgService( &dwServiceID, NULL, NULL, 0, NULL, &scError ); // activate service
- }
- else
- {
- printf("MultiClient with Prefix : %s\r\n",pszServerPrefix); //Return - Type :char*
- bOK = MSRTStartMsgServiceMC( &dwServiceID, NULL, NULL, 0, NULL,pszServerPrefix, &scError ); // activate service
- }
- if (bOK == FALSE)
- {
- printf("GCreateMyOperationMsg() - Unable to start message service! \r\n");
- sprintf(szTmp, " Error1 = 0x%0x, Errortext = %s \r\n", scError.dwError1, scError.szErrorText);
- printf(szTmp);
- return (-101);
- }
- //======================================
- //======================================
- // PARSE PARAMETERS
- //======================================
- if ( ( dwFlags & FLAG_COMMENT_PARAMETER ) && ( NULL != pszComment ) )
- {
- strncpy(MsgCreateEx.szComment, pszComment, sizeof (MsgCreateEx.szComment) - 1);
- MsgCreateEx.dwFlags |= MSG_FLAG_COMMENT;
- }
- if ( dwFlags & FLAG_COMMENT_DIALOG )
- MsgCreateEx.dwFlags |= MSG_FLAG_COMMENT;
- if (lpszObjectName!= NULL) // = tagname
- {
- strncpy (szSource, lpszObjectName, sizeof (lpszObjectName) - 1);
- strncpy ( MsgCreateEx.szInstance, lpszObjectName, sizeof (MsgCreateEx.szInstance) - 1);
- strncpy ( MsgCreateEx.mtTextValue[0].szText, lpszObjectName, sizeof (MsgCreateEx.mtTextValue[1].szText) - 1);
- }
- if ( szMyText != NULL)
- {
- strncpy ( MsgCreateEx.mtTextValue[1].szText, szMyText , sizeof (MsgCreateEx.mtTextValue[1].szText) - 1);
- }
- if ( lpszMsg != NULL)
- {
- strncpy ( MsgCreateEx.mtTextValue[6].szText, lpszMsg , sizeof (MsgCreateEx.mtTextValue[6].szText) - 1);
- }
- //======================================
- //======================================
- // CREATE MESSAGE
- //======================================
- bOK = MSRTCreateMsgInstanceWithComment(dwServiceID, &MsgCreateEx, &scError) ;
- if ( TRUE == bOK)
- {
- if (FLAG_COMMENT_DIALOG == (dwFlags & FLAG_COMMENT_DIALOG) )
- {
- BOOL bOkay;
- HWND hWnd = FindWindow("PDLRTisAliveAndWaitsForYou", NULL);
- //RQ:1072746 begin
- MSG_COMMENT_STRUCT mComment;
- sprintf( mComment.szUser, MsgCreateEx.szUser, sizeof(mComment.szUser) - 1 );
- for (dwInx = 1;
- dwActWaitedTime < dwMaxCheckTime;
- dwInx++)
- {
- memset(&scError,0,sizeof(scError));
- mComment.dwMsgNr = dwMsgNum;
- mComment.stTime = time;
- bOkay = MSRTGetComment (dwServiceID, &mComment, &scError);
- if (TRUE == bOkay)
- {
- break;
- }
- else
- {
- Sleep(dwStepCheckTime);
- printf("#W401: GCreateMyOperationMsg(): pre MSRTGetComment() performance warning: waited=%ld / step=%ld/ round=%ld\r\n", dwActWaitedTime+dwStepCheckTime, dwStepCheckTime, dwInx);
- }
- dwActWaitedTime += dwStepCheckTime;
- if (100 < dwStepCheckTime)
- {
- dwStepCheckTime -=dwReduceStepTime;
- }
- }
- //RQ:1072746
- memset(&scError,0,sizeof(scError));
- bOkay= MSRTDialogComment (hWnd, &MsgRTData, &scError);
- if (TRUE == bOkay)
- {
- //MSG_COMMENT_STRUCT mComment; //RQ:1072746
- mComment.dwMsgNr = dwMsgNum;
- mComment.stTime = time;
- sprintf( mComment.szUser, MsgCreateEx.szUser, sizeof(mComment.szUser) - 1 );
- memset(&scError,0,sizeof(scError));
- bOkay = MSRTGetComment (dwServiceID, &mComment, &scError);
- if (TRUE == bOkay)
- {
- strncpy(MsgCreateEx.szComment, mComment.szText, sizeof (MsgCreateEx.szComment) - 1);
- }
- }
- else
- {
- printf("#E201: GCreateMyOperationMsg() - Error at MSRTGetComment() szErrorText=\"%s\" error2=%d\r\n", scError.szErrorText, scError.dwError2);
- iRet = -201;
- }
- }
- }
- if(bOK == FALSE)
- {
- printf ("#E301: GCreateMyOperationMsg() - Error at MSRTCreateMsgInstanceWithComment() szErrorText=\"%s\"\r\n", scError.szErrorText);
- iRet = -301;
- }
- //======================================
- //======================================
- // STOP_MESSAGE_SERVICE
- //======================================
- bOK= MSRTStopMsgService( dwServiceID, &scError);
- printf("End GCreateMyOperationMsg \r\n");
- return (iRet);
- }
C脚本操作员消息函数二次封装
在不要电子签名只需记录操作消息的地方,为了更方便使用,对函数进行二次封装为函数CreateMyOpMsg()。
函数原型:
int CreateMyOpMsg(char* lpszMsg, char* lpszdevice)
参数:
- lpszMsg,该参数记录操作消息,写入文本块@7%s@中。
- lpszdevice,该参数为设备名,写入到文本块@10%s@中。
返回值:
值 |
描述 |
0 |
函数执行完成没有任何错误 |
-101 |
消息不能被编辑 |
-201 |
当调用"MSRTGetComment()"特征引发一个错误 |
-301 |
当调用"MSRTCreateMsgInstanceWithComment()"特征引发一个错误 |
函数代码:
- #include "apdefap.h"
- int CreateMyOpMsg(char* lpszMsg, char* lpszdevice)
- {
- char userComm[1024]="";
- return GCreateMyOperationMsg2(0x00000001 ,12508142 , lpszMsg, lpszdevice, 0, 0 , 0 , userComm); //Return-Type: long int
- }
用VB脚本生成操作员消息
使用VB脚本创建操作员消息的脚本如下:
- '创建操作员消息
- dim myAlarm
- Set myAlarm = HMIRuntime.Alarms(12508142)
- MyAlarm.State = 5
- '--------------------------
- 'State Alarm Log Status
- '1 Came In
- '2 Went Out
- '5 Came in and comment
- '6 Gone and comment
- '--------------------------
- myAlarm.Comment = userComment
- myAlarm.UserName = userName
- myAlarm.ProcessValues(10) = Device
- myAlarm.ProcessValues(7) = Msg
- MyAlarm.Create
注意:使用VBS生成的操作员消息,在报警记录中没有计算机名。
VB脚本操作员消息函数二次封装
在不要电子签名只需记录操作消息的地方,为了更方便使用,对函数进行二次封装为函数CreateMyOpMsg()。
函数原型:
Function CreateMyOpMsg(inputMsg, device)
参数:
- inputMsg,该参数记录操作消息,写入文本块@7%s@中。
- device,该参数为设备名,写入到文本块@10%s@中。
返回值:
无
函数代码:
- Function CreateMyOpMsg(inputMsg, device)
- '创建操作员消息
- dim myAlarm
- Set myAlarm = HMIRuntime.Alarms(12508142)
- MyAlarm.State = 5
- '--------------------------
- 'State Alarm Log Status
- '1 Came In
- '2 Went Out
- '5 Came in and comment
- '6 Gone and comment
- '--------------------------
- myAlarm.Comment = userComment
- myAlarm.UserName = userName
- myAlarm.ProcessValues(10) = Device
- myAlarm.ProcessValues(7) = inputMsg
- MyAlarm.Create
- End Function
如何生成电子签名
C脚本执行电子签名
函数原型:
int EsigDialog(const char * inputMsg, const char * device)
参数:
- inputMsg,该参数为执行该操作的描述字符串,写入到文本块@7%s@中。
- device,该参数为设备名,写入到文本块@10%s@中。
返回值:
值 | 描述 |
-1 | 函数执行遇到错误 |
1 | 电子签名通过 |
2 | 用户取消了电子签名 |
3 | 三次电子签名未通过 |
注意:
该函数依赖函数GCreateMyOperationMsg2()
函数代码:
- #include "apdefap.h"
- int EsigDialog(const char * inputMsg, const char * device)
- {
- //获取用户名和计算机名
- char *userName = GetTagChar("@NOP::@CurrentUser"); //Return-Type: char*
- char *displayedUser = GetTagChar("@NOP::@CurrentUserName"); //Return-Type: char*
- char *computerName = GetTagChar("@NOP::@LocalMachineName"); //Return-Type: char*
- char *Domain = ""; //如果加入了域,在此填写域名
- int nRet = 0;
- char szBuf[1024]="";
- char myComm[1024]="";
- char userComm[1024]="";
- VARIANT vtComment;
- __object* EsigDlg;
- /*---判断用户是否登录---*/
- if (strlen(userName) == 0) {
- MessageBox(NULL,"用户未登录,请登录后再执行!","Error",MB_SYSTEMMODAL|MB_OK);
- return -1;
- }
- /*---电子签名---*/
- EsigDlg = __object_create("CCESigDlg.ESIG");
- if (!EsigDlg) {
- printf("Failed to create Picture Object\n");
- return -1;
- }
- EsigDlg->forcecomment = FALSE; //非强制注释
- nRet = EsigDlg->ShowDialog(userName,displayedUser,Domain,GetLanguage(),&vtComment);
- __object_delete(EsigDlg);
- /*---提取注释---*/
- sprintf(userComm,"%ls",vtComment.u.bstrVal);
- VariantClear(&vtComment);
- /*---合并注释---*/
- /*
- if (strlen(inputMsg)>0 && strlen(userComm)>0) {
- sprintf(myComm,"%s:%s", inputMsg, userComm);
- }
- else if (strlen(inputMsg)>0) {
- sprintf(myComm,"%s", inputMsg);
- }
- else if (strlen(userComm)>0) {
- sprintf(myComm,"%s", userComm);
- }
- */
- switch(nRet)
- {
- case 1:
- //InsertAuditEntryNew("","",myComm,0,szBuf);
- GCreateMyOperationMsg2(0x00000001, 12508142, inputMsg, device, 0, 0, 0, userComm); //Return-Type: long int
- break;
- case 2:
- break;
- case 3:
- break;
- }
- return nRet;
- }
C脚本执行电子签名并写入变量新值:
函数原型:
int TagNewValueES(const char *winccTagName,double newValue, const char *description, const char *device)
参数:
- winccTagName,该参数为WinCC变量名,与参数description拼接后写入到文本块@7%s@中。
- newValue,该参数为要写入的新值,只能为数值,不支持字符串,写入到数值块@3%g@中。
- description,该参数为变量描述,说明该变量的含义,与参数winccTagName拼接后写入到文本块@7%s@中。
- device,该参数为设备名,写入到文本块@10%s@中。
返回值:
值 | 描述 |
-1 | 函数执行遇到错误 |
1 | 电子签名通过 |
2 | 用户取消了电子签名 |
3 | 三次电子签名未通过 |
注意:
该函数依赖函数GCreateMyOperationMsg2()
函数代码:
- #include "apdefap.h"
- int TagNewValueES(const char *winccTagName,double newValue, const char *description, const char *device)
- {
- //获取用户名和计算机名
- char *userName = GetTagChar("@NOP::@CurrentUser"); //Return-Type: char*
- char *displayedUser = GetTagChar("@NOP::@CurrentUserName"); //Return-Type: char*
- char *computerName = GetTagChar("@NOP::@LocalMachineName"); //Return-Type: char*
- char *Domain = "" //如果加入了域,在此填写域名
- int nRet = 0;
- char szBuf[1024]="";
- char myComm[1024]="";
- char userComm[1024]="";
- char tagDescription[1024]="";
- double oldValue;
- VARIANT vtComment;
- __object* EsigDlg;
- /*---判断用户是否登录---*/
- if (strlen(userName) == 0) {
- MessageBox(NULL,"用户未登陆,请登陆后再执行!","Error",MB_SYSTEMMODAL|MB_OK);
- return -1;
- }
- /*---电子签名---*/
- EsigDlg = __object_create("CCESigDlg.ESIG");
- if (!EsigDlg) {
- printf("Failed to create Picture Object\n");
- return -1;
- }
- EsigDlg->forcecomment = FALSE; //非强制注释
- nRet = EsigDlg->ShowDialog(userName,displayedUser,Domain,GetLanguage(),&vtComment);
- __object_delete(EsigDlg);
- /*---提取注释---*/
- sprintf(userComm,"%ls",vtComment.u.bstrVal);
- VariantClear(&vtComment);
- /*---合并注释---*/
- /*
- if (strlen(description)>0 && strlen(userComm)>0) {
- sprintf(myComm,"%s:%s", description, userComm);
- }
- else if (strlen(description)>0) {
- sprintf(myComm,"%s", description);
- }
- else if (strlen(userComm)>0) {
- sprintf(myComm,"%s", userComm);
- }
- */
- switch(nRet)
- {
- case 1:
- //获取旧值
- //strcpy(oldValue,GetTagChar(winccTagName));
- oldValue = GetTagDouble(winccTagName); //Return-Type: double
- //写入新值
- //SetTagChar(winccTagName,newValue);
- SetTagDouble(winccTagName,newValue); //Return-Type: BOOL
- //创建操作员消息
- //InsertAuditEntryNew(oldValue,newValue,myComm,0,szBuf);
- sprintf(tagDescription,"%s %s", winccTagName, description);
- GCreateMyOperationMsg2(0x00000001 ,12508141 , tagDescription, device, 0, oldValue , newValue , userComm); //Return-Type: long int
- break;
- case 2:
- break;
- case 3:
- break;
- }
- return nRet;
- }
VB脚本执行电子签名
函数原型:
Function EsigDialog(inputMsg, device)
参数:
- inputMsg,该参数为执行该操作的描述字符串,写入到文本块@7%s@中。
- device,该参数为设备名,写入到文本块@10%s@中。
返回值:
值 | 描述 |
-1 | 函数执行遇到错误 |
1 | 电子签名通过 |
2 | 用户取消了电子签名 |
3 | 三次电子签名未通过 |
函数代码:
- Function EsigDialog(inputMsg, device)
- '获取用户名和计算机名
- Dim userName, displayedUser, Domain, computerName
- userName = HMIRuntime.Tags("@NOP::@CurrentUser").Read
- displayedUser = HMIRuntime.Tags("@NOP::@CurrentUserName").Read
- computerName = HMIRuntime.Tags("@NOP::@LocalMachineName").Read
- Domain = ""
- If userName = "" Then
- Msgbox "用户未登陆,请登陆后再执行"
- EsigDialog = -1
- Exit Function
- End If
- '电子签名
- Dim myEsig
- Dim myComment
- Dim userComment
- Dim ret
- Set myEsig = CreateObject("CCEsigDlg.ESIG")
- '不强制注释
- myEsig.forcecomment = False
- ret = myEsig.showDialog(userName,displayedUser,Domain, HMIRuntime.Language, userComment)
- ' If Trim(inputMsg)<>"" And Trim(userComment)<>"" Then
- ' myComment = inputMsg&":"&userComment
- ' Elseif Trim(inputMsg)<>"" Then
- ' myComment = inputMsg
- ' Elseif Trim(userComment)<>"" Then
- ' myComment = userComment
- ' Else
- ' myComment = ""
- ' End If
- Select Case ret
- Case 1 '用户成功获得验证
- 'Call InsertAuditEntryNew("", "", myComment, 0)
- '创建操作员消息
- dim myAlarm
- Set myAlarm = HMIRuntime.Alarms(12508142)
- MyAlarm.State = 5
- '--------------------------
- 'State Alarm Log Status
- '1 Came In
- '2 Went Out
- '5 Came in and comment
- '6 Gone and comment
- '--------------------------
- myAlarm.Comment = userComment
- myAlarm.UserName = userName
- myAlarm.ProcessValues(10) = device
- myAlarm.ProcessValues(7) = inputMsg
- MyAlarm.Create
- Case 2 '用户使用“取消”按钮关闭了对话框。
- Case 3 '用户 3 次验证均失败。
- End Select
- EsigDialog = ret
- End Function
VB脚本执行电子签名并写入新值
函数原型:
Function TagNewValueES(WinccTagName,NewValue,description,device)
参数:
- winccTagName,该参数为WinCC变量名,与参数description拼接后写入到文本块@7%s@中。
- newValue,该参数为要写入的新值,只能为数值,不支持字符串,写入到数值块@3%g@中。
- description,该参数为变量描述,说明该变量的含义,与参数winccTagName拼接后写入到文本块@7%s@中。
- device,该参数为设备名,写入到文本块@10%s@中。
返回值:
值 | 描述 |
-1 | 函数执行遇到错误 |
1 | 电子签名通过 |
2 | 用户取消了电子签名 |
3 | 三次电子签名未通过 |
函数代码:
- Function TagNewValueES(WinccTagName,NewValue,description,device)
- '获取用户名和计算机名
- Dim userName, displayedUser, Domain, computerName
- userName = HMIRuntime.Tags("@NOP::@CurrentUser").Read
- displayedUser = HMIRuntime.Tags("@NOP::@CurrentUserName").Read
- computerName = HMIRuntime.Tags("@NOP::@LocalMachineName").Read
- Domain = ""
- If userName = "" Then
- Msgbox "用户未登陆,请登陆后再执行"
- TagNewValueES = -1
- Exit function
- End If
- '电子签名
- Dim myEsig
- Dim myComment
- Dim userComment
- Dim ret
- Set myEsig = CreateObject("CCEsigDlg.ESIG")
- '不强制注释
- myEsig.forcecomment = False
- ret = myEsig.showDialog(userName,displayedUser, Domain, HMIRuntime.Language, userComment)
- ' If Trim(description)<>"" And Trim(userComment)<>"" Then
- ' myComment = description&":"&userComment
- ' Elseif Trim(description)<>"" Then
- ' myComment = description
- ' Elseif Trim(userComment)<>"" Then
- ' myComment = userComment
- ' Else
- ' myComment = ""
- ' End If
- Select Case ret
- Case 1 '用户成功获得验证
- '获取变量旧值
- dim OldValue, WinCCTag
- Set WinCCTag = HMIRuntime.Tags(WinccTagName)
- OldValue = WinCCTag.read
- '给变量写入新值
- WinCCTag.Write NewValue
- If WinCCTag.LastError <> 0 Then
- Msgbox WinCCTag.ErrorDescription
- TagNewValueES = -1
- Exit Function
- End If
- '创建操作员消息
- dim myAlarm
- set myAlarm = HMIRuntime.Alarms(12508141) '@10%s@: @7%s@ @102%s@ 新=@3%g@ @8%s@ 旧=@2%g@ @8%s@'
- MyAlarm.State = 5
- '--------------------------
- 'State Alarm Log Status
- '1 Came In
- '2 Went Out
- '5 Came in and comment
- '6 Gone and comment
- '--------------------------
- myAlarm.Comment = userComment
- myAlarm.UserName = userName
- myAlarm.ProcessValues(2) = OldValue'旧值
- myAlarm.ProcessValues(3) = NewValue'新值
- myAlarm.ProcessValues(7) = WinccTagName &" "&description '变量名+变量描述
- myAlarm.ProcessValues(10) = device'设备名
- MyAlarm.Create
- 'InsertAuditEntryNew(OldValue, NewValue, myComment, 0)
- Case 2 '用户使用“取消”按钮关闭了对话框。
- Case 3 '用户 3 次验证均失败。
- End Select
- TagNewValueES = ret
- End Function
WinCC的电子签名与审计追踪的更多相关文章
- Firebird 审计追踪
Firebird 打开审计追踪功能,即在服务器上打开日志记录功能,根据配置记录不同类型的服务器执行情况. 1.首先修改Firebird.conf文件,打开审计功能: AuditTraceConfigF ...
- ABP文档 - 审计日志
文档目录 本节内容: 简介 关于 IAuditingStore 配置 通过特性启用/禁用 注意 简介 维基百科:“一个审计追踪(也叫审计日志)是一个安全相关的时序记录.记录组.和/或记录源和目标,作为 ...
- ABP官方文档翻译 4.6 审计日志
审计日志 介绍 关于IAuditingStore 配置 通过特性启用/禁用 注意事项 介绍 维基百科:“审计追踪(也称为审计日志)是与安全相关的按时间先后的记录.记录集合.记录的目的地和源,提供一系列 ...
- 数据库开启对sys用户的审计
需求:客户想对数据库开启sys用户的审计功能,关闭其它用户的审计功能. 1)再一次巡检报告中,我们发现数据库版本11.2.0.4,开启审计功能,提供的建议如下,关闭审计alter system set ...
- Event Sourcing Pattern 事件源模式
Use an append-only store to record the full series of events that describe actions taken on data in ...
- Testing - 测试基础 - 阶段
估算 测试对软件工作量的估算的准确性 测试评估软件系统的状况的准确性 关注点: 不准确的估算 不适当的开发过程 不真实的状态报告 如何知道对工作量的估算是正确的 估算工作量的工具很容易出错 对软件工作 ...
- SharePoint Server 2010 中的基本任务
SharePoint Foundation 和 SharePoint Server 概述 SharePoint Foundation 2010 是一项用于 SharePoint 网站的基础技术,它可以 ...
- Threat Risk Modeling Learning
相关学习资料 http://msdn.microsoft.com/en-us/library/aa302419(d=printer).aspx http://msdn.microsoft.com/li ...
- 每个极客都应该知道的Linux技巧
每个极客都应该知道的Linux技巧 2014/03/07 | 分类: IT技术 | 0 条评论 | 标签: LINUX 分享到:18 本文由 伯乐在线 - 欣仔 翻译自 TuxRadar Linux. ...
随机推荐
- cookie、session、token的区别
一. cookie 1.什么是cookie? Cookie 技术产生源于 HTTP 协议在互联网上的急速发展.随着互联网时代的策马奔腾,带宽等限制不存在了,人们需要更复杂的互联网交互活动,就必须同服 ...
- synchronized被这么问,谁能受得了
synchronized是面试中经常会被问到的知识点,相关的问题点也很多,问题答案涉及的知识点也很多,有经验的面试官就会顺着你的答案不断追问一下,下面的对话场景就是相关面试题的连环炮. 面试官:说一下 ...
- Python-TCP客户端程序开发
TCP客户端,需要与服务端建立连接,连接建立成功后才可以进行数据的传输. # 1.导入模块 import socket if __name__ == '__main__': # 2.创建套接字对象 t ...
- UITableView 相关方法
最近闲来无事,总结一下 UITableViewDataSource和 UITableViewDelegate方法 UITableViewDataSource @required - (NSIntege ...
- UIView的作用
UIView [UIView的作用] 主要用来显示应用程序的内容,可以作为label.button等控件的容器.表示屏幕上的一块矩形区域,同时可以处理该区域的绘制和触屏事件. MVC,MVVM等设计架 ...
- Node升级——Node Binary管理模块"n"
Node.js的开发非常活跃,它的最新稳定版本也频繁变化,你不时会发现,一个模块不能在你当前的Node版本上使用,此时你需要升级Node 幸运的是,可以用一种非常简单的方法来管理你的Node版本,即使 ...
- 为什么每一个爬虫工程师都应该学习 Kafka
这篇文章不会涉及到Kafka 的具体操作,而是告诉你 Kafka 是什么,以及它能在爬虫开发中扮演什么重要角色. 一个简单的需求 假设我们需要写一个微博爬虫,老板给的需求如下: 开发爬虫对你来说非常简 ...
- [TimLinux] JavaScript table的td内容超过宽度缩为三个点
1. 思路 CSS控制td内容自动缩为三个点 JS控制鼠标悬浮显示td全部内容 2. 实现 HTML代码: <!DOCTYPE html> <html> <head> ...
- JavaScript 逻辑与(&&) 与 逻辑或(||) 运算规则
逻辑与(&&) 逻辑与(&&)操作可以应用于任何的操作类型,不仅仅是布尔值, 在有一个操作数不是布尔值的情况下,&&操作符就不一定返回布尔值:遵循下面规 ...
- JMeter之SteppingShape
1.背景 其实是这样的,最近包括以前都有同事问过宝路一个问题:JMeter测试计划中涉及到梯度压测时,整个测试计划执行完毕,聚合报告看的是整体的结果啊!并不能直观看到每个梯度下的吞吐量的值(虽然可以通 ...