如何寫入審計追蹤記錄
用腳本向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
