82. NotesclientPrint相同的信息,以状态栏的问题
这可能是一个小问题。但其他人也应该得到满足。在Notesclient使用LotusScript的Print当该语句是输出到状态栏,假设实际参数传递多次调用相同,状态栏将显示只有一次的信息。
例如:
Print "a"
Print "a"
Print "a"
不会输出三行a,而仅仅有一行。
假设作为參数的变量内容同样,多次调用也仅仅会输出一次。
比如:
Print view.Toplevelentrycount
Print view.Toplevelentrycount
Print view.Toplevelentrycount
你也许会问,即使这有些不正常,也没什么妨碍,反复输出有什么意义呢?原因例如以下。在client应用程序中。这些对Print的调用都是为了在程序执行时给用户(不论是普通用户还是开发人员人员)信息和反馈。Print反复的静态信息的用例会出如今报告事件和处理进度时,比如在批量审批流程、处理附件、查找特定记录等等时,能够在发生或处理完一个事件后,调用这样的语句:Print"A purchase workflow is reviewed.",Print "A XXX record is found."。以上情况还能够通过在输出的信息中加入序列号来解决。
而受这样的输出丢失影响更大的则是Print的參数为变量的情况。尤其是在调试程序时。往往会在代码的不同处Print同一变量,以理解某些语句的效果或弄清错误的原因。
这时应该的多行输出变为一行,令人困扰。
当然能够人为加入一些凝视使得每次输出都有区别。但非常麻烦。
Print仅仅在client执行的代码中,也就是输出到client状态栏时,有这样的行为。包括它的代码执行在server端时,按触发方式或者输出到server控制台,或者返回给浏览器。都没有这个问题。所以这是Print语句的特性。抑或是Notes客户机状态栏的问题。似乎更有可能是后者。
这样的行为是不是bug?或者是出于某些限制或考量有意设计如此?非计算机科班出身的我,想不出来。在网上也没有查到。
只是我印象中Firefox的Firebug插件的控制台也曾有同样行为,用console.log()方法输出反复信息时。仅仅会显示一条。后来有了改进,在输出信息的左边会在括号中标注反复输出的次数,比如(5)Show me again.
剩下的就是怎样应对,即workaround。
首先easy想到的就是写一个函数包装Print。在实际要输出的信息前附上当前时间。
除却我们的目的。显示输出信息的时间本身也是故意的。
遗憾的是LotusScript里的日期时间类型Variant仅仅精确到秒,假设反复信息的输出是在同一秒内。问题依然。LotusScript可获得的最精确的当前时间是Timer函数的返回值。精确到百分之中的一个秒。于是我们能够写出例如以下函数:
Public Function PrintMsg(msg As Variant)
Dim strTime As String
strTime=Format(Now, "hh:mm:ss")
Dim hs As Long
hs=Timer Mod 100
strTime=strTime & ":" & hs
Print(strTime & " - " & msg)
End Function
但在应用时会发现,百分之中的一个秒对于计算机和LotusScript仍然是非常漫长的(这是件好事),所以在相似以下的代码中,输出的信息对于Print语句仍然是同样的,也就会发生丢失。
call PrintMsg(view.Toplevelentrycount)
Call CreateDoc(db)
call PrintMsg(view.Toplevelentrycount)
LotusScript里的时间仅仅精确到百分之中的一个秒,是由于Notes和Domino是跨平台的,不同操作系统支持的时间精度不等,但最少都在十毫秒数量级。
利用GetThreadInfo函数凭藉操作系统的clocktick概念实际能获得时间段的更高精度。
以下是网上曾有人对不同系统的測试结果 (http://searchdomino.techtarget.com/tip/Accurate-LotusScript-timing-technique):
Ticks per second:
Win2000 Domino 6.0 (ticks per second1000)
Win2000 Domino 5.0.9a (ticks per second1000)
AIX 4.3.3 ML 9 with Domino 5.0.11 (ticks per second = 1,000,000)
Solaris 8 with Domino 5.0.11 (ticks per second = 1,000,000)
SuSE Linux 8.1 with Domino 6.0.1 (ticks per second 1000)
SunOS 5.8 Generic_108528-18 with Domino Release 6.0.1; (ticks per second 1000)
因此以下的代码演示了怎样获得一段时间小于一秒的部分,并将它转化到毫秒单位。
dim tick1 as Long, tick2 as Long, tps as Long
tps=GetThreadInfo(7)
tick1=GetThreadInfo(6)
'do something
tick2=GetThreadInfo(6)
dim dif as Long 'The difference of the part of milliseconds
dif=((tick2-tick1) Mod tps)/tps*1000
可是由于clock tick表示的是系统时钟自开机以来的时钟周期数。并不能由它直接确定当前时间,所以不能用在我们上面的函数以获得更高的时间精度。
为了彻底解决本文所说的问题,仅仅有在每次输出前附上一个序列号。
为此须要将PrintMsg函数包装在一个对象里,从而能够操作作为对象字段的序列号。
Private printNum As Integer 'Used for distinguish printing same contents
Public Function PrintMsg(msg As Variant)
Dim strTime As String
strTime=Format(Now, "hh:mm:ss")
Dim hs As Long
hs=Timer Mod 100
strTime=strTime & ":" & hs
printNum=printNum+1
Print("[" & printNum & "]" & strTime & " - " & msg)
End Function
调用它输出反复内容的效果例如以下:
[1]16:52:36:24 – 81
[2]16:52:36:24 - 81
[3]16:52:36:24 - 81
我把这种方法加入到曾经曾介绍过的Log4Dom类里,当然诸位也能够单独为它创建一个更精简的类。
Class Log4Dom
public logLevel As Integer
public module As String 'module
'the Log Destination, set as a variant then depending on the log type,
'set as either a LogDB, logNotesFile, logStatus or logPrompt
Private logFile As Variant Private s As NotesSession
Private db As NotesDatabase 'current database
Private profile As NotesDocument 'Log4Dom profile document
public logName As String 'log name from the profile Private printNum As Integer 'Used for distinguish printing same contents Sub New ()
Set s=New NotesSession
logLevel = LEVEL_DEBUG
End Sub %REM
Add a log destination.
As the de facto only used log destination is Notes DB,
I didn't handle the case of multiple log destinations of different types.
%END REM
Public Function AddLogFile(file As Variant)
Set logFile = file If TypeName(file)="LOGDB" then
'read parameter from Log4Dom profile by starrow
Set db=s.CurrentDatabase
Set profile=db.GetProfileDocument("Log4DomProfile")
If Not profile Is Nothing Then
If profile.GetItemValue("LogLevel")(0)><"" then
logLevel=profile.GetItemValue("LogLevel")(0)
End if
logName=profile.GetItemValue("LogName")(0)
End If
'if no parameter provided, try the agent name
If logName="" Then
If Not s.CurrentAgent Is Nothing Then
logName=s.CurrentAgent.Name
End If
End If logFile.LogName=logName
End if
End Function 'logging at the different levels, INFO, WARN etc
Public Function Info(message As String) As Integer
Info = WriteLog(LEVEL_INFO, message)
End Function Public Function Warn(message As String) As Integer
Warn = WriteLog(LEVEL_WARN, message)
End Function Public Function Debug(message As String) As Integer
Debug = WriteLog(LEVEL_DEBUG, message)
End Function 'Can't use error as the function name because it's a reserved word.
'If used for logging a runtime error, leave the argument as an empty string.
Public Function LogError(message As String) As Integer
If message="" Then
'Generate the message for a runtime error.
'The GetThreadInfo(LSI_THREAD_CALLPROC) must be called here instead of
'calling an universal function to get the error message because that would
'always return LogError as the function raising the error.
'LSI_THREAD_CALLMODULE=11, LSI_THREAD_CALLPROC=10
message = GetThreadInfo(11) & ">" & GetThreadInfo(10) & ": " & _
"Error(" & Err() & "): " & Error() & " at line "& Erl()
End If
LogError = WriteLog(LEVEL_ERROR, message)
End Function Public Function Fatal(message As String) As Integer
Fatal = WriteLog(LEVEL_FATAL, message)
End Function 'user level logging, for specific level logging
'@param level integer - the level 10 is the most detail, 1 the lowest level
'message - a string to be logged. Number, boolean and date values would be
'automatically converted to strings by LotusScript. Other types should be manually converted.
Public Function WriteLog(level As Integer, message As String) As Integer
Dim theDate As String
Dim theLevel As String
Dim theMessage As String
theDate = Cstr(Now)
theLevel = "["+GetLevelString(level)+"] "
theMessage = theDate+" "+theLevel+" "+module+" - "+message
' check that logging is turned on for this level
' otherwise there is no need to log
If level <= logLevel Then
Call logFile.writelog(theMessage)
End If
End Function 'closes the log, saves notes doc or closes file
Public Function Close
logFile.close
End Function 'convert from level numbers into string
Private Function GetLevelString(level As Integer) As String
Select Case level
Case LEVEL_INFO : GetLevelString = LEVEL_INFO_STRING
Case LEVEL_DEBUG : GetLevelString = LEVEL_DEBUG_STRING
Case LEVEL_WARN : GetLevelString = LEVEL_WARN_STRING
Case LEVEL_ERROR : GetLevelString = LEVEL_ERROR_STRING
Case LEVEL_FATAL : GetLevelString = LEVEL_FATAL_STRING
Case Else : GetLevelString = "LEVEL "+Cstr(level)
End Select
End Function %REM
If the argument is the same, multiple calls to Print are executed only once.
This function appends the current time before the message to be printed. The
time is rounded to the nearest hundredth of second. However, for some circumstances,
this is still not enough to avoid the same content to be printed. Thus, a serial
number is appended.
%END REM
Public Function PrintMsg(msg As Variant)
Dim strTime As String
strTime=Format(Now, "hh:mm:ss")
Dim hs As Long
hs=Timer Mod 100
strTime=strTime & ":" & hs
printNum=printNum+1
Print("[" & printNum & "]" & strTime & " - " & msg)
End Function
End Class
'Get a logger instance that writes to the specified db.
Public Function GetLogger(db As NotesDatabase) As log4Dom
Dim logger As log4dom
Set logger = New log4dom()
Dim logFile As New LogDB(db)
Call logger.AddLogFile(logFile)
Set GetLogger=logger
End Function
Dim logger As Log4Dom
Set logger=GetLogger(Nothing)
call logger.PrintMsg(81)
call logger.PrintMsg(81)
call logger.PrintMsg(81)
版权声明:本文博客原创文章。博客,未经同意,不得转载。
82. NotesclientPrint相同的信息,以状态栏的问题的更多相关文章
- iOS获取状态栏和导航栏尺寸(宽度和高度)
iPhone开发当中,有时需要获取状态栏和导航栏高度.宽度信息,方便布局其他控件.下面介绍一下如何获取这些信息: // 状态栏(statusbar) CGRect rectStatus = [[UIA ...
- MFC之窗体改动工具栏编程状态栏编程程序启动画面
1窗体外观的改动 (1)改动在CMainFrame::preCreateWindow(CREATESTRUCT& cs) 改动标题:cs.style&=FWS_ADDTOTITLE; ...
- iOS - 获取状态栏和导航栏尺寸(宽度和高度)
iPhone开发当中,有时需要获取状态栏和导航栏高度.宽度信息,方便布局其他控件.下面介绍一下如何获取这些信息: // 状态栏(statusbar) CGRect rectStatus = [[UIA ...
- 【转】iPhone获取状态栏和导航栏尺寸(宽度和高度)
原文网址:http://blog.csdn.net/chadeltu/article/details/42708605 iPhone开发当中,有时需要获取状态栏和导航栏高度.宽度信息,方便布局其他控件 ...
- 实用的 atom 插件
推荐几款我喜欢的Atom插件 时间 2017-05-05 09:00:00 Hi Linux 原文 http://www.hi-linux.com/posts/28459.html 主题 Atom ...
- Python _PyQt5 【总】
http://www.cnblogs.com/archisama/p/5442071.html QtCore QtGui QtWidgets QtMultimedia QtBluetooth QtNe ...
- ASP.NET Web API 入门示例详解
REST服务已经成为最新的服务端开发趋势,ASP.NET Web API即为.NET平台的一种轻量级REST架构. ASP.NET Web API直接借鉴了ASP.NET MVC的设计,两者具有非常类 ...
- JS 中的 Window 对象
窗口对象的属性和方法: 在js最外层写的function可以还可以理解为window对象的一个方法.定义的变量也可以称之为window对象的一个属性.例如:window.alert("--- ...
- iOS开发UI篇—UITableviewcell的性能问题
iOS开发UI篇—UITableviewcell的性能问题 一.UITableviewcell的一些介绍 UITableView的每一行都是一个UITableViewCell,通过dataSource ...
随机推荐
- The JSR-133 Cookbook for Compiler Writers(an unofficial guide to implementing the new JMM)
The JSR-133 Cookbook for Compiler Writers by Doug Lea, with help from members of the JMM mailing lis ...
- 【HTML5游戏开发小技巧】RPG情形对话中,令文本逐琢夸出
从前用JAVAscript完成过令文本逐琢夸出的效果,明天嗡炒用html5中的canvas完成一下.canvas里的内容可没有像<p>那样好操做,起首,您需求懂得一些html5的API才气 ...
- Codeforces Round #253 (Div. 1) B. Andrey and Problem
B. Andrey and Problem time limit per test 2 seconds memory limit per test 256 megabytes input standa ...
- Android 4.0新组件:GridLayout详细说明
于Android 4.0(API 14)它提供了一个新的组件GridLayout,它继承自Linearlayout,用于执行网络格样式布局. 在某些方面,GridLayout与TableLayout和 ...
- cocos2dx 遮罩层 android 手机上 失败
1.CCClippingNode使用(在模拟器上ok,在手机上不行),实现多个剪切区域 local layer=CCLayerColor:create(ccc4(0,0,0,110)) --/ ...
- ZOJ - 3822 Domination (DP)
Edward is the headmaster of Marjar University. He is enthusiastic about chess and often plays chess ...
- String类疑虑
Java String类疑虑: 创 拼接 String是java的经常使用类之中的一个,本质是字符数组char[].String类是final类,不可被继承. 关于String的创建,能够通过new来 ...
- C++结构体之统计最高最低分
[Submit][Status][Web Board] Description 输入学生的姓名和成绩,统计出最高分的学生和最低分的学生. Input 输入5个学生的姓名和分数,用结构体完成 Outpu ...
- lua、groovy嵌入到java中的性能对比(转)
lua和groovy都是可以嵌入到java中的脚本语言.lua以高性能著称,与C/C++在游戏开放中有较多使用,groovy是一个基于Java虚拟机(JVM)的敏捷动态语言,在jvm下有着不错的性能. ...
- Nexon由Xsolla全球支付服务
韩国游戏公司纳克森决Nexon定从今年10月1日起,与Xsolla开展Playspan的合作,向全球提供更好的服务. 当Nexon的玩家随时想购买NX点数的时候.Xsolla的服务能够进入程序,让您的 ...