用脚本向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@,使用报警控件查看时便于筛选。该消息定义如下:


使用C脚本生成操作员消息

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

版权声明:本文原创发表于博客园,作者为星墨本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则视为侵权。

原文地址