如何写入审计追踪记录

用脚本向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的电子签名与审计追踪的更多相关文章

  1. Firebird 审计追踪

    Firebird 打开审计追踪功能,即在服务器上打开日志记录功能,根据配置记录不同类型的服务器执行情况. 1.首先修改Firebird.conf文件,打开审计功能: AuditTraceConfigF ...

  2. ABP文档 - 审计日志

    文档目录 本节内容: 简介 关于 IAuditingStore 配置 通过特性启用/禁用 注意 简介 维基百科:“一个审计追踪(也叫审计日志)是一个安全相关的时序记录.记录组.和/或记录源和目标,作为 ...

  3. ABP官方文档翻译 4.6 审计日志

    审计日志 介绍 关于IAuditingStore 配置 通过特性启用/禁用 注意事项 介绍 维基百科:“审计追踪(也称为审计日志)是与安全相关的按时间先后的记录.记录集合.记录的目的地和源,提供一系列 ...

  4. 数据库开启对sys用户的审计

    需求:客户想对数据库开启sys用户的审计功能,关闭其它用户的审计功能. 1)再一次巡检报告中,我们发现数据库版本11.2.0.4,开启审计功能,提供的建议如下,关闭审计alter system set ...

  5. Event Sourcing Pattern 事件源模式

    Use an append-only store to record the full series of events that describe actions taken on data in ...

  6. Testing - 测试基础 - 阶段

    估算 测试对软件工作量的估算的准确性 测试评估软件系统的状况的准确性 关注点: 不准确的估算 不适当的开发过程 不真实的状态报告 如何知道对工作量的估算是正确的 估算工作量的工具很容易出错 对软件工作 ...

  7. SharePoint Server 2010 中的基本任务

    SharePoint Foundation 和 SharePoint Server 概述 SharePoint Foundation 2010 是一项用于 SharePoint 网站的基础技术,它可以 ...

  8. Threat Risk Modeling Learning

    相关学习资料 http://msdn.microsoft.com/en-us/library/aa302419(d=printer).aspx http://msdn.microsoft.com/li ...

  9. 每个极客都应该知道的Linux技巧

    每个极客都应该知道的Linux技巧 2014/03/07 | 分类: IT技术 | 0 条评论 | 标签: LINUX 分享到:18 本文由 伯乐在线 - 欣仔 翻译自 TuxRadar Linux. ...

随机推荐

  1. day20191120笔记

    1.spring的优势 U盘拷.总结.微信公众号:.2.笔试,课前默写,默完之后要回答问题.3.微服务,带着,知识点,卷子.ssm整个东西讲一下.面试是综合能力.背面试题. 通过基础很重要.学精烂熟于 ...

  2. 【Android - 进阶】之Drawable简介

    Drawable是什么?Android给我们的解释是:“A general abstraction for 'something that can be drawn'.”,翻译过来就是:对于可以绘制的 ...

  3. jenkins 如何让job对应一个节点

    1.配置job:如图,在label expression 里面填写[节点标签名]或者是[节点名称]. 2.配置节点: 3.构建:第一个红线,表明使用哪个节点进行构建.  第二个红线,表明工作目录.

  4. 2019-2020-1 20199304《Linux内核原理与分析》第二周作业

    计算机工作原理 存储程序计算机模型 冯·诺依曼体系结构 冯·诺依曼体系结构如图所示: 冯·诺依曼体系结构包含五大部分 运算器:在控制器的统一控制下,负责对数据进行加工.完成各种运算,如算术运算.逻辑运 ...

  5. ELK的简单搭建

    Environment  (都需要Java环境,jdk){ elasticsearch kibana 安装nginx用以测试 logstash } 1.首先拉取软件包,给予Java语言开发首选配置Ja ...

  6. 宝塔面板的数据库连接本地Navicat Premium

    把宝塔面板的数据库连接本地Navicat Premium,这样就方便操作了.下面我教大家如何实现. 第一步:在阿里云的安全组添加安全规则,配置安全组放开3306端口 第二步:打开宝塔设置数据库的权限, ...

  7. java多线程与线程池

    1. 场景描述 以前多线程也常用,这次因需再页面上用到多线程,如下图,总结下,有需要的朋友可以参考下. 2. 解决方案 2.1 线程池概念 线程池官方定义不说了,通俗说下:池子的概念,事先(预定义)创 ...

  8. 【nodejs原理&源码赏析(7)】【译】Node.js中的事件循环,定时器和process.nextTick

    [摘要] 官网博文翻译,nodejs中的定时器 示例代码托管在:http://www.github.com/dashnowords/blogs 原文地址:https://nodejs.org/en/d ...

  9. 深度研究:回归模型评价指标R2_score

    回归模型的性能的评价指标主要有:RMSE(平方根误差).MAE(平均绝对误差).MSE(平均平方误差).R2_score.但是当量纲不同时,RMSE.MAE.MSE难以衡量模型效果好坏.这就需要用到R ...

  10. 小白学 Python 爬虫(16):urllib 实战之爬取妹子图

    人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Li ...