用脚本向Audit中添加记录有两种方法,一种方法是用InserAuditEntryNew函数写入,另一种方法是生成属于“操作员输入消息”类型的报警消息,该报警消息会记录到Audit中。
Audit记录中的TargetName列是操作内容,Reason列是操作员的注释。使用InserAuditEntryNew函数生成的记录在TargetName列的内容默认为VBScriptingRuntime或CScriptingRuntime,而操作内容只能记录在Reason列处,这与其他记录的形式不一致,效果不好,因此在此不使用InserAuditEntryNew函数。

第二种方法,在报警记录的“系统,无确认”下的“操作员输入消息”中建立报警消息,当这条消息触发后,消息不仅会记录到报警数据库,也会记录到Audit数据库。触发报警消息可以用变量触发,也可以用脚本触发。使用脚本触发可以给消息传递参数,即向@1%s@等文本块中写入值。

WinCC中默认有一条编号为12508141的操作员输入消息,定义如下图,该消息用于记录新值旧值的更改。

12508141消息的内容不完全符合Audit消息记录的需要,新建一条编号为12508142消息。项目中可能会用WinCC控制多台设备,定义文本块@10%s@的作用是记录该操作针对哪台设备,文本块@7%s@记录执行了什么操作。有些项目中不使用Audittrail组件,而是用报警记录的数据库记录审计追踪,因此可在错误点列填上@10%s@,使用报警控件查看时便于筛选。该消息定义如下:

WinCC支持C和VB两种脚本,C脚本中提供了GCreateMyOperationMsg()函数生成操作员消息。
函数原型:
intGCreateMyOperationMsg(DWORDdwFlags,DWORDdwMsgNum,char*lpszPictureName,char*lpszObjectName,DWORDdwMyTextID,doubledoValueOld,doubledoValueNew,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消息使用。
函数原型:
intGCreateMyOperationMsg2(DWORDdwFlags,DWORDdwMsgNum,char*lpszMsg,char*lpszObjectName,DWORDdwMyTextID,doubledoValueOld,doubledoValueNew,char*pszComment)
参数:
lpszMsg,该参数记录操作消息,会写入文本块@7%s@中。
其他参数与GCreateMyOperationMsg()函数一致。
函数代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
pragmacode()
defineFLAG_COMMENT_DIALOG0x00000003
W401:GCreateMyOperationMsg():preMSRTGetComment()performancewarning:waited=%ld/step=%ld/round=%ld\r\n",dwActWaitedTime+dwStepCheckTime,dwStepCheckTime,dwInx);
}
dwActWaitedTime+=dwStepCheckTime;
if(100dwStepCheckTime)
{
dwStepCheckTime-=dwReduceStepTime;
}
}
//RQ:1072746
memset(scError,0,sizeof(scError));
bOkay=MSRTDialogComment(hWnd,MsgRTData,scError);
if(TRUE==bOkay)
{
//MSG_COMMENT_STRUCTmComment;//RQ:1072746
=dwMsgNum;
=time;
sprintf(,,sizeof()-1);
memset(scError,0,sizeof(scError));
bOkay=MSRTGetComment(dwServiceID,mComment,scError);
if(TRUE==bOkay)
{
strncpy(,,sizeof()-1);
}
}
else
{
printf("E301:GCreateMyOperationMsg()-ErroratMSRTCreateMsgInstanceWithComment()szErrorText=\"%s\"\r\n",);
iRet=-301;
}
//======================================
//======================================
//STOP_MESSAGE_SERVICE
//======================================
bOK=MSRTStopMsgService(dwServiceID,scError);
printf("GCreateMyOperationMsg\r\n");
return(iRet);
}
C脚本操作员消息函数二次封装在不要电子签名只需记录操作消息的地方,为了更方便使用,对函数进行二次封装为函数CreateMyOpMsg()。
函数原型:
intCreateMyOpMsg(char*lpszMsg,char*lpszdevice)
参数:
lpszMsg,该参数记录操作消息,写入文本块@7%s@中。
lpszdevice,该参数为设备名,写入到文本块@10%s@中。
返回值:
值
描述
0
函数执行完成没有任何错误
-101
消息不能被编辑
-201
当调用"MSRTGetComment()"特征引发一个错误
-301
当调用"MSRTCreateMsgInstanceWithComment()"特征引发一个错误
函数代码:
1
2
3
4
5
6
7
include""
intEsigDialog(constchar*inputMsg,constchar*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="";//如果加入了域,在此填写域名
intnRet=0;
charszBuf[1024]="";
charmyComm[1024]="";
charuserComm[1024]="";
VARIANTvtComment;
__object*EsigDlg;
/*---判断用户是否登录---*/
if(strlen(userName)==0){
MessageBox(NULL,"用户未登录,请登录后再执行!","Error",MB_SYSTEMMODAL|MB_OK);
return-1;
}
/*---电子签名---*/
EsigDlg=__object_create("");
if(!EsigDlg){
printf("FailedtocreatePictureObject\n");
return-1;
}
EsigDlg-forcecomment=FALSE;//非强制注释
nRet=EsigDlg-ShowDialog(userName,displayedUser,Domain,GetLanguage(),vtComment);
__object_delete(EsigDlg);
/*---提取注释---*/
sprintf(userComm,"%ls",);
VariantClear(vtComment);
/*---合并注释---*/
/*
if(strlen(inputMsg)0strlen(userComm)0){
sprintf(myComm,"%s:%s",inputMsg,userComm);
}
elseif(strlen(inputMsg)0){
sprintf(myComm,"%s",inputMsg);
}
elseif(strlen(userComm)0){
sprintf(myComm,"%s",userComm);
}
*/
switch(nRet)
{
case1:
//InsertAuditEntryNew("","",myComm,0,szBuf);
GCreateMyOperationMsg2(0x00000001,12508142,inputMsg,device,0,0,0,userComm);//Return-Type:longint
break;
case2:
break;
case3:
break;
}
returnnRet;
}
C脚本执行电子签名并写入变量新值:函数原型:
intTagNewValueES(constchar*winccTagName,doublenewValue,constchar*description,constchar*device)
参数:
winccTagName,该参数为WinCC变量名,与参数description拼接后写入到文本块@7%s@中。
newValue,该参数为要写入的新值,只能为数值,不支持字符串,写入到数值块@3%g@中。
description,该参数为变量描述,说明该变量的含义,与参数winccTagName拼接后写入到文本块@7%s@中。
device,该参数为设备名,写入到文本块@10%s@中。
返回值:
值
描述
-1
函数执行遇到错误
1
电子签名通过
2
用户取消了电子签名
3
三次电子签名未通过
注意:
该函数依赖函数GCreateMyOperationMsg2()
函数代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include""
intTagNewValueES(constchar*winccTagName,doublenewValue,constchar*description,constchar*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=""//如果加入了域,在此填写域名
intnRet=0;
charszBuf[1024]="";
charmyComm[1024]="";
charuserComm[1024]="";
chartagDescription[1024]="";
doubleoldValue;
VARIANTvtComment;
__object*EsigDlg;
/*---判断用户是否登录---*/
if(strlen(userName)==0){
MessageBox(NULL,"用户未登陆,请登陆后再执行!","Error",MB_SYSTEMMODAL|MB_OK);
return-1;
}
/*---电子签名---*/
EsigDlg=__object_create("");
if(!EsigDlg){
printf("FailedtocreatePictureObject\n");
return-1;
}
EsigDlg-forcecomment=FALSE;//非强制注释
nRet=EsigDlg-ShowDialog(userName,displayedUser,Domain,GetLanguage(),vtComment);
__object_delete(EsigDlg);
/*---提取注释---*/
sprintf(userComm,"%ls",);
VariantClear(vtComment);
/*---合并注释---*/
/*
if(strlen(description)0strlen(userComm)0){
sprintf(myComm,"%s:%s",description,userComm);
}
elseif(strlen(description)0){
sprintf(myComm,"%s",description);
}
elseif(strlen(userComm)0){
sprintf(myComm,"%s",userComm);
}
*/
switch(nRet)
{
case1:
//获取旧值
//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:longint
break;
case2:
break;
case3:
break;
}
returnnRet;
}
VB脚本执行电子签名函数原型:
FunctionEsigDialog(inputMsg,device)
参数:
inputMsg,该参数为执行该操作的描述字符串,写入到文本块@7%s@中。
device,该参数为设备名,写入到文本块@10%s@中。
返回值:
值
描述
-1
函数执行遇到错误
1
电子签名通过
2
用户取消了电子签名
3
三次电子签名未通过
函数代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
FunctionEsigDialog(inputMsg,device)
'获取用户名和计算机名
DimuserName,displayedUser,Domain,computerName
userName=("@NOP::@CurrentUser").Read
displayedUser=("@NOP::@CurrentUserName").Read
computerName=("@NOP::@LocalMachineName").Read
Domain=""
IfuserName=""Then
Msgbox"用户未登陆,请登陆后再执行"
EsigDialog=-1
ExitFunction
If
'电子签名
DimmyEsig
DimmyComment
DimuserComment
Dimret
SetmyEsig=CreateObject("")
'不强制注释
=False
ret=(userName,displayedUser,Domain,,userComment)
'IfTrim(inputMsg)""AndTrim(userComment)""Then
'myComment=inputMsg":"userComment
'ElseifTrim(inputMsg)""Then
'myComment=inputMsg
'ElseifTrim(userComment)""Then
'myComment=userComment
'Else
'myComment=""
'If
SelectCaseret
Case1'用户成功获得验证
'CallInsertAuditEntryNew("","",myComment,0)
'创建操作员消息
dimmyAlarm
SetmyAlarm=(12508142)
=5
'--------------------------
'StateAlarmLogStatus
'1CameIn
'2WentOut
'5Cameinandcomment
'6Goneandcomment
'--------------------------
=userComment
=userName
(10)=device
(7)=inputMsg
Case2'用户使用“取消”按钮关闭了对话框。
Case3'用户3次验证均失败。
Select
EsigDialog=ret
Function
VB脚本执行电子签名并写入新值函数原型:
FunctionTagNewValueES(WinccTagName,NewValue,description,device)
参数:
winccTagName,该参数为WinCC变量名,与参数description拼接后写入到文本块@7%s@中。
newValue,该参数为要写入的新值,只能为数值,不支持字符串,写入到数值块@3%g@中。
description,该参数为变量描述,说明该变量的含义,与参数winccTagName拼接后写入到文本块@7%s@中。
device,该参数为设备名,写入到文本块@10%s@中。
返回值:
值
描述
-1
函数执行遇到错误
1
电子签名通过
2
用户取消了电子签名
3
三次电子签名未通过
函数代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
FunctionTagNewValueES(WinccTagName,NewValue,description,device)
'获取用户名和计算机名
DimuserName,displayedUser,Domain,computerName
userName=("@NOP::@CurrentUser").Read
displayedUser=("@NOP::@CurrentUserName").Read
computerName=("@NOP::@LocalMachineName").Read
Domain=""
IfuserName=""Then
Msgbox"用户未登陆,请登陆后再执行"
TagNewValueES=-1
Exitfunction
If
'电子签名
DimmyEsig
DimmyComment
DimuserComment
Dimret
SetmyEsig=CreateObject("")
'不强制注释
=False
ret=(userName,displayedUser,Domain,,userComment)
'IfTrim(description)""AndTrim(userComment)""Then
'myComment=description":"userComment
'ElseifTrim(description)""Then
'myComment=description
'ElseifTrim(userComment)""Then
'myComment=userComment
'Else
'myComment=""
'If
SelectCaseret
Case1'用户成功获得验证
'获取变量旧值
dimOldValue,WinCCTag
SetWinCCTag=(WinccTagName)
OldValue=
'给变量写入新值
TagNewValueES=-1
ExitFunction
If
'创建操作员消息
dimmyAlarm
setmyAlarm=(12508141)'@10%s@:@7%s@@102%s@新=@3%g@@8%s@旧=@2%g@@8%s@'
=5
'--------------------------
'StateAlarmLogStatus
'1CameIn
'2WentOut
'5Cameinandcomment
'6Goneandcomment
'--------------------------
=userComment
=userName
(2)=OldValue'旧值
(3)=NewValue'新值
(7)=WinccTagName""description'变量名+变量描述
(10)=device'设备名
'InsertAuditEntryNew(OldValue,NewValue,myComment,0)
Case2'用户使用“取消”按钮关闭了对话框。
Case3'用户3次验证均失败。
Select
TagNewValueES=ret
Function
版权声明:本文原创发表于博客园,作者为星墨本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则视为侵权。
原文地址






















