欢迎从事游戏测试、测试管理 白盒及性能测试的朋友与我交流,共同进步,谢谢!

发布新日志

  • 和谐使用google搜索

    2011-09-16 10:13:40

    唉,自从Google退出国内之后,google.cn都自动定向到www.google.com.hk了。搜索起来慢得要死,还经常出现乱七八糟的无响应、访问失败等问题。。。。这边给大家分享一个和谐使用google搜索的方法:
    修改hosts文件,将google搜索指向google国内的服务器。hosts文件一般位于C:\WINDOWS\system32\drivers\etc,用linux的同学们自己找一下。。。

    将下列代码加入到hosts文件的最后面:
    1. #谷歌香港:
    2. 203.208.46.148 www.google.com.hk
    3. #你懂的:
    4. 203.208.46.148 www.google.ee
    5. #谷歌网页快照:
    6. 203.208.46.148 webcache.googleusercontent.com
    保存之后,你会发现,访问google搜索的速度快多了,无响应什么的最讨厌了。。。

    PS:
    1,google.com.hk往往还会有很多限制,结果过滤、关键词过滤等等都还有的;想用原滋原味的同学们不妨试下google.ee,满足你的一切需求;
    2,随着google退出国内市场,google的网页快照也都不能访问了。通过这个方法之后,就可以正常地使用了,如果还是不行的话,将链接改成https访问就可以了。。。
  • td中将new bug某字段设置为必填项,已验证ok

    2011-01-28 11:48:15

    1、某字段先得在提交new bug时显示出来

    用管理员账号登录customize,选择工作流set up workflow,选择script. generator-add defect field customization,将对应用户组的某字段项勾上

    2、设置某字段的必填属性

    选择customize project entities,点defect下的system fileds表,选择对应的字段,如:assigned to,将属性required勾上就行了

  • 连接td的两个小问题

    2011-01-25 09:48:04

    1、找不到bug数据库路径

    解决方案:看文件夹目录是否正确共享

    2、不能提交新的bug,提示CDBLock::ObjLock - unable to insert new lock

    解决方案:将bug数据库的上层文件夹全部设置为存档属性,并开通everyone完全控制权限。

  • netstat

    2010-09-10 16:12:49

    netstat -nat |grep "10021" |wc -l

    ---------------------------------------

    功能说明:显示网络状态。

    语  法:netstat [-acCeFghilMnNoprstuvVwx][-A<网络类型>][--ip]

    补充说明:利用netstat指令可让你得知整个Linux系统的网络情况。

    参  数:
      -a或--all   显示所有连线中的Socket。
      -A<网络类型>或--<网络类型>   列出该网络类型连线中的相关地址。
      -c或--continuous   持续列出网络状态。
      -C或--cache   显示路由器配置的快取信息。
      -e或--extend   显示网络其他相关信息。
      -F或--fib   显示FIB。
      -g或--groups   显示多重广播功能群组组员名单。
      -h或--help   在线帮助。
      -i或--interfaces   显示网络界面信息表单。
      -l或--listening   显示监控中的服务器的Socket。
      -M或--masquerade   显示伪装的网络连线。
      -n或--numeric   直接使用IP地址,而不通过域名服务器
      -N或--netlink或--symbolic   显示网络硬件外围设备的符号连接名称。
      -o或--timers   显示计时器。
      -p或--programs   显示正在使用Socket的程序识别码和程序名称。
      -r或--route   显示Routing Table。
      -s或--statistice   显示网络工作信息统计表。
      -t或--tcp   显示TCP传输协议的连线状况。
      -u或--udp   显示UDP传输协议的连线状况。
      -v或--verbose   显示指令执行过程。
      -V或--version   显示版本信息。
      -w或--raw   显示RAW传输协议的连线状况。
      -x或--unix   此参数的效果和指定"-A unix"参数相同。
      --ip或--inet   此参数的效果和指定"-A inet"参数相同。

  • 变速齿轮的原理

    2010-07-14 17:51:59

       最近,我在“大众软件”上看到一则关于软件“变速齿轮”的报道。我很少上网,所以对这方面了解比较少,不知道它在网上已经流行好几个月了。当时的感觉就是太惊奇了,很

    佩服王荣先生是怎么做到如此神奇的事,尤其是他如何保证各种游戏的兼容,他如何知道不同游戏对时间的处理。我立刻上网DOWN了个0.22b版,在试用的过程中,我发现“变速齿轮

    ”不但可以加速游戏,实际上,它可以加速任何windows程序(从某种程度上),我逐渐认识到它的工作原理,不一定对,仅是猜测而已。先声明一点,我是使用UNIX的,并不是很了

    解windows编程,所以只能给出概念上大体的认识,而无法说出具体的实现办法。

      首先,先看看计算机是如何有时间概念的。在主板上有一个时钟晶振,依靠电池供电,本质上就是一块电子表。计算机软件中所有的时间概念,归根结底都来自着个“硬件时间”

    ,换句话说,如果这个时间不对,则任何运行在该主板上的程序对时间的处理都不可能正确。(包扩各种操作系统)

      那么,操作系统是如何知道这个时间的呢?这是因为这个时钟每过一定时间都会产生一个硬件中断(INT)操作系统可以截取这个中断并做相应的处理,从而获得时间的概念。好象

    是20ms产生一次中断,一秒钟50次。具体的中断号我忘了,就称为 INT A 吧。对Dos而言,它在启动时就准备好了对INT A的中断处理程序(Dos核心的一部分),当我们使用DOs的时

    候,在提示符状态下,即使不做任何操作,Dos内部在一秒钟时间内,也会接受50次INT A,执行50次中断处理程序。只是这一过程在幕后完成,我们无法感受到。Dos的中断处理程序

    所做的,就是让Dos能够了解当前的时间。(如保留当前日期,时间在内部变量中等操作)。但很重要的一点,在INT A中断处理程序的末尾,又调用INT B。
    INT B是Dos为用户保留的软中断,在缺省情况下,Dos的INT B中断处理程序立即返回,不做任何事。而
    用户可以编写自己的INT B中断处理程序定时处理自己的操作,然后把它替换Dos原来的空INT B中断程序。比如我有一个程序需要在12:00运行,一种方法是写如下代码:
    for(;;){
    if(时间是12:00) break;
    sleep(5); /*休息5秒钟,这句在Dos中没有,意为让程序不做任何事,只是等待一段时间*/
    }
    {具体的处理程序}

      然后在提示符状态下运行。因为Dos没有多用户的概念,在程序12:00退出以前,无法在使用这台机器。另一种方法是,把要运行的程序写成TSR(长驻内存程序),运行后执行代

    码长驻在内存中,程序本身返回提示符,供用户使用。那么该执行码如何保证在12:00被执行呢,就要靠INT B,在长驻该程序时,也要编写新的INT B中断处理程序,内容大概是:
    {屏蔽INT B中断} /*这一步是因为Dos的大部分中断是不可重入的,
    即在中断还未处理完时,再次*/
    /*被中断,这一般会让Dos死掉*/
    {执行旧的INT B中断处理程序} /*这一步的目的是防止自己的TSR影响其他TSR程序*/
    if(时间是12:00){
    把处理转向TSR程序的入口;
    } else {
    {恢复被屏蔽的中断}
    退出;
    }
    综合上面讲到的,Dos下的时间处理大概是:

    机器时间------->INT A(操作系统用)-------->INT B(用户用)-------->TSR程序

    当然,由于Dos对运行级别几乎没有控制,用户也可以绕过INT A,INT B直接访问硬件。这时我们即使改变操作系统的时间,用户程序也能得到正确的时间。
    在windows中,情况也很类似。但程序不会直接访问硬件,而是通过叫VxD的虚拟设备驱动程序来工作。由VxD来和硬件打交道,而应用程序只和VxD交流信息。对时钟中断的处理也是一

    样,windows有专门的时钟虚拟设备驱动来捕获来自晶振的硬件中断,并为windows提供时间和定时的功能。这与Dos下的INT A功能基本是一致的,但更强大,功能更广。
    我们在来看应用程序需要怎样的时间处理机制。一个典型的游戏,如射击游戏,如果没有时间控制,敌人的飞机如果要连开10枪,程序应该是:
    for(i=0;i<10;i++){
    开枪;
    }
    但是有一个问题,机器的速度可能太快,以至于只需要0.1秒十枪就完成了,另外在不同的机器上,这段程会有不同的运行时间。为了解决这个问题,我们改进这段程序:
    for(i=0;i<10;i++){
    开枪;
    sleep(1); /*休息1秒,不做任何事*/
    }
    这样我们至少保证一秒只开一枪。但还有一个问题,就是可能屏幕上有多个敌人,不可能在一个敌人开10枪的过程中其他敌人不动(而且自己也不动)。所以我认为,一般的游戏程序

    都是用定时器来实现主要功能的。即先为每一种动作编写相应的处理程序,如开枪,移动等,在为每个对象申请一个定时器,一旦定时器的时间到,就激活该对象相应动作的程序代码

    。如屏幕上的十个敌人对应十个定时器,定时器互不干涉,哪个时间到转向哪个处理程序,控制他是否该移动或射击。至于定时器的创建,由应用程序向系统申请。

    |--->用户定时器1------->用户程序1
    |--->用户定时器2------->用户程序2
    机器时间------>windows的时钟VxD---|--->用户定时器3------->用户程序3
    |--->系统接口------->系统应用

      这种机制可以保证星际争霸中的小狗在P100上和在PIII上奔跑的速度一样快,前提是这两台机器的硬件时间是一样准的,但是,如果有一台机器的时钟快或慢了,那问题就有变化

    了。(注意,这里的快或慢,并不是指两台机器的时间不一样,而是指在相同的现实时间下,他们产生硬件中断的次数不一样)

      那么,说了这么多,我认为“变速齿轮”的工作原理,就是修改用户申请的windows定时器中的等待时间。我不太了解windows编程,不好说这种修改是如何实现的。他没有修改Vx

    D因为windows系统的时间并没有因为启动“变速齿轮”而跑快或跑慢,某些应用,如双击桌面图标时的间隔时间上的设定(即两次击鼠标的间隔时间多长以内才算是“双击”)也没有

    变。通俗的描述是:在启动“变速齿轮”后,当应用程序(特别是游戏)向windows申请定时器时,“变速齿轮”修改了申请的等待时间参数,因次改变了程序正常的定时,才使程序

    有了不正长的
    速度(这个结论只是猜的)。只所以这样猜,是因为对已经启动的程序,他并不能改变速度,而只能先启动“变速齿轮”,再运行程序。另外,某些系统接口,也是无法修改的。

      所以,一旦启动“变速齿轮”,所有应用程序(申请了定时器,并要依靠定时器来做一些操作的程序)都会受到他的影响。在Word中,等待输入的光标会因为调成了加速而更快的

    闪动,各种提示信息的出现时间会变快(或变慢)很多,最夸张的是,当把速度调成最慢时,在同一位置,间隔十秒钟击一次鼠标会被系统认为是双击(发生在应用程序内,而不是桌

    面上)

      我很佩服王荣先生的想象力和编程能力。“变速齿轮”的出现,证明在虚拟的世界里:没有做不到的,只有想不到的。


     

  • NSIS Error --Installer integrity check has failed

    2010-07-03 09:51:48

    NSIS (Nullsoft Scriptable Install System) is a professional open source system to create Windows installers.

    NSIS developed the "envelope" that contains the software you are attempting to install, not the software itself. This allows any software developer to use NSIS to ease the process of installing software.

    NSIS Error Messages:
    - Installer integrity check has failed. Common causes include
    incomplete download and damaged media.
    - The installer you are trying to use is corrupted or incomplete.
    This could be the result of a damaged disk, a failed download or a virus.

    How to fix the problem?

    * If the software was obtained from the Internet:

    - Clear your browser's cache. 清空浏览器缓存
    - Disable any download accelerators or managers and download the installer again.  不要使用任何下载加速器,尝试重新下载
    - Rename the installer so it is a simple one-word name with no special characters (without removing the .exe suffix) Example: install.exe 重新命名安装包文件名
    - Download the installer from another source approved by the software developer or publisher. (It might be corrupted on the server, or the connection to the server is unreliable from your location.) 尝试引用其他地址的下载源
    - Update your anti-virus software (if installed) and download the installer again. 更新你的杀毒软件再重新下载
    - Disable your anti-virus software and download the installer again.  关闭你的杀毒软件再重新下载
    - Download the installer using another computer and copy it to the original computer. 用另一台机器下载
    - If you have the nVidia firewall installed, uninstall the program and download the installer again. 如果有nvidia防火墙,请卸载并重新下载
    - Scan for, and remove malware and viruses on your system.  从你的机器上移除杀毒软件
    - Scan the hard drive using scandisk, chkdsk, or any other hard drive repair tool. 尝试其他的硬件驱动或驱动修复工具

    ps:E文不好,尝试翻译一下

    出现这种情况,最好在官网提供md5码的验证和md5工具,如果有能力,最好能把md5的验证功能做到安装包里去

    -----------------------------

    * If the software was obtained from a CD, DVD, or other physical media:

    If you are receiving this problem from an installer located on a disc or other media besides the Internet, then the problem may be due to a hardware failure or more likely the physical media being damaged. Try reading files from other parts of the media. If you are receiving read errors with other files on the disc, then the problem is likely due to damaged media. You will need to contact the source of the physical media for a replacement.


    *-* Why do you get NSIS Error?

    The NSIS error message box basically means that the setup executable (.exe) or installer user is trying to run is corrupted, or incomplete. However, often it’s not the actual cause.

    One possible candidate is Windows Firewall which exists in Windows XP and later operating system such as Windows 2003, 2008 and Windows Vista. The solution is to disable the Windows Firewall and run the installer again.

    Other reported problem maker that trigger NSIS Error include integrated nVidia NIC (network interface card) that includes a firewall. In this case, user have to change the network adapter to one without firewall or switch to wireless network temporarily to get the installer installed, as disabling the network card will still cause NSIS Error.

  • web服务器IIS 模拟工具

    2010-06-07 20:39:19

    因为是exe后缀的缘故,即使手动改掉后缀名,也上传不了,只好给网页链接了。
    非常好用,强烈推荐。
  • setup.exe(by takiro)

    2010-06-03 22:33:40

    !define PRODUCT_NAME "softname"
    !define PRODUCT_VERSION "1.0"
    !define PRODUCT_PUBLISHER "company"
    !define PRODUCT_WEB_SITE "http://www.soft.com"
    !define PRODUCT_DIR_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\soft.exe" ;Machine
    !define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" ;Machine
    !define PRODUCT_UNINST_ROOT_KEY "HKLM"

    SetCompressor lzma


    !include "MUI.nsh"


    !define MUI_ABORTWARNING
    !define MUI_ICON "softicon.ico"
    !define MUI_UNICON "uninstall.ico"

    !define MUI_WELCOMEFINISHPAGE_BITMAP "wellcome.bmp"

    !insertmacro MUI_PAGE_WELCOME

    !define MUI_LICENSEPAGE_RADIOBUTTONS
    !insertmacro MUI_PAGE_LICENSE "LICENSE.txt"

    !insertmacro MUI_PAGE_DIRECTORY

    !insertmacro MUI_PAGE_INSTFILES

    !define MUI_FINISHPAGE_RUN "$INSTDIR\soft.exe"
    !define MUI_FINISHPAGE_SHOWREADME "$INSTDIR\readme.txt"

    !insertmacro MUI_PAGE_FINISH


    !insertmacro MUI_UNPAGE_INSTFILES


    !insertmacro MUI_LANGUAGE "SimpChinese"


    !insertmacro MUI_RESERVEFILE_INSTALLOPTIONS

    Name "${PRODUCT_NAME}"
    OutFile "setup.exe"
    InstallDir "$PROGRAMFILES\soft"
    InstallDirRegKey HKLM "${PRODUCT_UNINST_KEY}" "UninstallString"
    ShowInstDetails hide
    ShowUnInstDetails hide
    BrandingText "softname"

    Section "soft" SEC01
      SetOutPath "$INSTDIR"
      SetOverwrite on
      File /r "D:\soft\*.*"
      CreateDirectory "$SMPROGRAMS\soft"
      CreateShortCut "$SMPROGRAMS\soft\soft.lnk" "$INSTDIR\soft.exe"
      CreateShortCut "$DESKTOP\soft.lnk" "$INSTDIR\soft.exe"
      CreateShortCut "$QUICKLAUNCH\soft.lnk" "$INSTDIR\soft.exe"
    SectionEnd

    Section -AdditionalIcons
      WriteIniStr "$SMPROGRAMS\soft\soft website.url" "InternetShortcut" "URL" "${PRODUCT_WEB_SITE}"
      CreateShortCut "$SMPROGRAMS\soft\uninstall soft.lnk" "$INSTDIR\uninstall.exe"
     
      WriteRegBin HKCU "Software\Microsoft\Windows\CurrentVersion\Explorer\MenuOrder\Start Menu\Programs\soft" "Order" num(fe:08000000020000007a01000001000000030000007c000000020000006e0000004175674d02000000010000005c003600f3010000c23c1c86200078537d8ff182c496805f8b4e2e006c006e006b002c0003000400efbec23c1c86c23c1c861400000078537d8ff182c496805f8b4e2e006c006e006b00000022000e0000000a00efbe00000000220000000000000000007600000000000000680000004175674d0200000001000000560036009d020000c23c1c862000f182c496805f8b4e2e006c006e006b000000280003000400efbec23c1c86c23c1c8614000000f182c496805f8b4e2e006c006e006b00000020000e0000000a00efbe00000000200000000000000000007c000000010000006e0000004175674d02000000010000005c0036002f000000c23c1c862000f182c496805f8b4e985b517f2e00750072006c002c0003000400efbec23c1c86c23c1c8614000000f182c496805f8b4e985b517f2e00750072006c00000022000e0000000a00efbe0000000022000000000000000000)
    SectionEnd

    Section -Post
      WriteUninstaller "$INSTDIR\uninstall.exe"
      WriteRegStr HKLM "${PRODUCT_DIR_REGKEY}" "" "$INSTDIR\soft.exe"
      WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)"
      WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\uninstall.exe"
      WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayIcon" "$INSTDIR\soft.exe"
      WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}"
      WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "URLInfoAbout" "${PRODUCT_WEB_SITE}"
      WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}"
    SectionEnd

     

    Section Uninstall
      Delete "$INSTDIR\uninstall.exe"
      Delete "$INSTDIR\readme.txt"
      Delete "$INSTDIR\soft.exe"

      Delete "$SMPROGRAMS\soft\uninstall soft.lnk"
      Delete "$SMPROGRAMS\soft\soft website.url"
      Delete "$QUICKLAUNCH\soft.lnk"
      Delete "$DESKTOP\soft.lnk"
      Delete "$SMPROGRAMS\soft\soft.lnk"

      RMDir "$SMPROGRAMS\soft"

      RMDir "$INSTDIR"

      DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}"
      DeleteRegKey HKLM "${PRODUCT_DIR_REGKEY}"
     DeleteRegValue HKCU "Software\Microsoft\Windows\CurrentVersion\Explorer\MenuOrder\Start Menu\Programs\soft" "Order"
      SetAutoClose true
    SectionEnd

     

    Function un.onInit
      MessageBox MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON2 "are you sure delete $(^Name) ,and all components?" IDYES +2
      Abort
    FunctionEnd

    Function un.onUninstSuccess
      HideWindow
      MessageBox MB_ICONINFORMATION|MB_OK "$(^Name) has delete from your computer"
    FunctionEnd

    ---------------------------------------------------

    ps:1、有时候做得很混乱,不如另开一个,重头开始,一点一点整理思绪

    2、一定要知道自己做的东西,什么是必须的,可以少走很多弯路,先理清需求

    3、做的东西要从玩家的角度出发,傻瓜式虽然看起来很愚蠢,但往往是解决问题的最好办法

    4、不必刻意追求技术上的复杂,在技术和时间上做一个有效地平衡

  • 注册表下的HKEY_CURRENT_USER和HKEY_LOCAL_MACHINE区别

    2010-06-02 23:32:47

    由于工作内容的原因,要写注册表,所以就立马恶补下注册表的知识

    1、HKEY_CURRENT_USER

    包含当前登录用户的配置信息的根目录。用户文件夹、屏幕颜色和“控制面板”设置均存储在此处。该信息被称为用户配置文件。

    2、HKEY_LOCAL_MACHINE

    包含针对该计算机(对于任何用户)的配置信息。主要由HARDWARE、SAM、SECURITY、SOFTWARE、SYSTEM等项组成:

  • .pak格式文件

    2010-04-01 01:08:38

    第一次见到.搜索之.知为一种压缩格式,其历史比较久,现在早已很难找其官方的命令行下使用的PAK.EXE(压缩程序)和PKUNPAK.EXE(解压缩程序)

    简单来说一种少见的压缩文件格式;可以将多个文件压缩成一个文件,例如RAR将多个文件压缩成1个RAR文件。现在好多游戏的客户端都采用这种特殊的压缩包格式,以利于游戏的开发。由于是针对于游戏的设计和使用而采用的文件结构,所以与一般的压缩文件格式有所不同,它的特点如下:


    1.声音,地图,3D模型,材质贴图灯文件是按着保留目录路径结构的方式压缩入PAK文件的。
    2.压缩的时候可以令压缩也可以按照一定的压缩率压缩。  


    使用pak这种文件格式对于游戏的开发者和玩家都有著无以伦比的方便性和可塑性(或者說自定义性)。具体如何实现的,等一下我将举例说明。使用pak包这种形式有几点好处:


    1.对于程开发人员來说资源调用方便,易於管理;
    2.由于结构特殊,对初学者有屏蔽作用避免被乱改,对高手卻很容易修改,比较方便;
    3.所有模式都是利用这个特点做的;
    4.pak包被游戏的引擎视为一个目录,能利用外置pak文件的形式进行升级而无需刪除原有文件。利於增加效果包,新地圖,改进界面,增加model等扩展內容;
    5.修改还原便利,文件之间互不影响。

    一般来说使用easy unharc 或者unharc gui也可以对这种压缩格式文件进行提取.

  • inno setup相关

    2010-03-24 00:26:49

    1.修改安装包左侧位图,其大小一般为164x314px,在INNO脚本的[Setup]段添加如下代码:
    WizardImageFile=Res\WizardImage.bmp

    注:红色的标记为位图路径,可以用相对路径或绝对路径

    2.修改安装包右上角位图,其大小一般为55x55px,在INNO脚本的[Setup]段添加如下代码:
    WizardSmallImageFile=Res\WizardSmallImage.bmp

    3.修改安装包左下角的BeveledLabel内容,常见有两种方式:
    (1)临时性修改  在INNO脚本的[Messages]段添加如下代码:
    BeveledLabel=软件汉化:xxxx
      
    (2)永久性修改  用记事本打开INNO目录中的“Default.isl” 修改“BeveledLabel = ”后的内容:
    BeveledLabel=   软件汉化:xxxx

    4.修改安装包欢迎标签内容,即WelcomeLabel2
    用记事本打开INNO目录中的“Default.isl” 修改“WelcomeLabel2 = ”后的内容:
    WelcomeLabel2=正在准备安装 [name/ver]...%n%n推荐您在继续安装前关闭所有其它应用程序。%n%n软件汉化:xxxx %n%n电子邮件:xxxx@163.com%n%n

    注:%n在INNO脚本中为换行符

    5.安装结束后动行主程序或打开文件等,只需在INNO脚本的[Run]段修改代码:
    Filename: {app}\PDFUnlocker.exe; Description: 启动 PDF Unlocker; Flags: nowait postinstall shellexec;
    Filename: {app}\汉化说明.txt; Description: 查看说明; Flags: nowait postinstall shellexec
     
    6.写注册表信息示例
    [Registry]
    Root: HKCU; Subkey: "SoftwareMy Company"; Flags: uninsdeletekeyifempty
    Root: HKCU; Subkey: "SoftwareMy CompanyMy Program"; Flags: uninsdeletekey
    Root: HKLM; Subkey: "SoftwareMy Company"; Flags: uninsdeletekeyifempty
    Root: HKLM; Subkey: "SoftwareMy CompanyMy Program"; Flags: uninsdeletekey
    Root: HKLM; Subkey: "SoftwareMy CompanyMy Program"; ValueType: string; ValueName: "InstallPath"; ValueData: "{app}"
     

    --------------------------------------------------------

    1、报位图错误的问题已解决。

    2、原文件的大小是288M,inno setup压缩成安装包是240M,用installshiled压缩了一个安装包,254M,看来还是inno setup的压缩率稍高。


     
  • 功能测试辅助

    2010-03-06 00:57:07

    近期发现屏幕录像大师真的很好用,特别是一些需要跟踪鼠标轨迹的内容,录像可以轻易显示出来,对于重现和分析问题,是一个很好的辅助,强烈向大家推荐。
  • lua脚本

    2007-10-26 16:09:55

    由于测试有要求,自学了lua脚本,将自学的内容转过来,常温常新-

    Lua脚本语法说明(增加lua5.1部份特性)

      Lua 的语法比较简单,学习起来也比较省力,但功能却并不弱。
      所以,我只简单的归纳一下Lua的一些语法规则,使用起来方便好查就可以了。估计看完了,就懂得怎么写Lua程序了。

      在Lua中,一切都是变量,除了关键字。

    I.  首先是注释
      写一个程序,总是少不了注释的。
      在Lua中,你可以使用单行注释和多行注释。
      单行注释中,连续两个减号"--"表示注释的开始,一直延续到行末为止。相当于C++语言中的"//"。
      多行注释中,由"--[["表示注释开始,并且一直延续到"]]"为止。这种注释相当于C语言中的"/*...*/"。在注释当中,"[["和"]]"是可以嵌套的(在lua5.1中,中括号中间是可以加若干个"="号的,如 [==[ ... ]==]),见下面的字符串表示说明。

    II.  Lua编程
      经典的"Hello world"的程序总是被用来开始介绍一种语言。在Lua中,写一个这样的程序很简单:
      print("Hello world")
      在Lua中,语句之间可以用分号";"隔开,也可以用空白隔开。一般来说,如果多个语句写在同一行的话,建议总是用分号隔开。
      Lua 有好几种程序控制语句,如:

    控制语句 格式 示例
    If if 条件 then ... elseif 条件 then ... else ... end
    if 1+1=2 then print("true")
    elseif 1+2~=3 then print("true")
    else print("false"end

    While while 条件 do ... end
    while 1+1~=2 do print("true"end

    Repeat repeat ... until 条件
    repeat print("Hello"until 1+1~=2

    For for 变量=初值, 终点值, 步进 do ... end
    for i = 1102 do print(i) end

    For for 变量1, 变量2, ... 变量n in 表或枚举函数 do ... end
    for a,b in mylist do print(a, b) end


      注意一下,for的循环变量总是只作用于for的局部变量;当省略步进值时,for循环会使用1作为步进值。
      使用break可以用来中止一个循环。
      相对C语言来说,Lua有几个地方是明显不同的,所以面要特别注意一下:

      .语句块
        语句块在C中是用"{"和"}"括起来的,在Lua中,它是用do 和 end 括起来的。比如:
        do print("Hello") end
        可以在 函数 中和 语句块 中定局部变量。

      .赋值语句
        赋值语句在Lua被强化了。它可以同时给多个变量赋值。
        例如:
        a,b,c,d=1,2,3,4
        甚至是:
        a,b=b,a  -- 多么方便的交换变量功能啊。
        在默认情况下,变量总是认为是全局的。假如需要定义局部变量,则在第一次赋值的时候,需要用local说明。比如:
        local a,b,c = 1,2,3  -- a,b,c都是局部变量

      .数值运算
        和C语言一样,支持 +, -, *, /。但Lua还多了一个"^"。这表示指数乘方运算。比如2^3 结果为8, 2^4结果为16。
        连接两个字符串,可以用".."运处符。如:
        "This a " .. "string." -- 等于 "this a string"

      .比较运算
    比较符号 < > <= >= == ~=
    含义 小于 大于 小于或等于 大于或等于 相等 不相等

        所有这些操作符总是返回true或false。
        对于Table,Function和Userdata类型的数据,只有 == 和 ~=可以用。相等表示两个变量引用的是同一个数据。比如:

        a={1,2}
        b
    =a
        
    print(a==b, a~=b)  --输出 true, false
        a={1,2}
        b
    ={1,2}
        
    print(a==b, a~=b)  --输出 false, true



      .逻辑运算
        and, or, not
        其中,and 和 or 与C语言区别特别大。
        在这里,请先记住,在Lua中,只有false和nil才计算为false,其它任何数据都计算为true,0也是true!
        and 和 or的运算结果不是true和false,而是和它的两个操作数相关。
        a and b:如果a为false,则返回a;否则返回b
        a or b:如果 a 为true,则返回a;否则返回b

        举几个例子:

         print(4 and 5--输出 5
         print(nil and 13--输出 nil
         print(false and 13--输出 false
         print(4 or 5--输出 4
         print(false or 5--输出 5


        在Lua中这是很有用的特性,也是比较令人混洧的特性。
        我们可以模拟C语言中的语句:x = a? b : c,在Lua中,可以写成:x = a and b or c。
        最有用的语句是: x = x or v,它相当于:if not x then x = v end 。

      .运算符优先级,从低到高顺序如下:

         or
         and
         <     >     <=    >=    ~=    ==
         .. (字符串连接)
         +     -
         *     /     %
         not   #(lua5.1 取长度运算)     - (一元运算)
         ^
    和C语言一样,括号可以改变优先级。

    III.  关键字
      关键字是不能做为变量的。Lua的关键字不多,就以下几个:
        
    and break do else elseif
    end false for function if
    in local nil not or
    repeat return then true until while

    IV.  变量类型
      怎么确定一个变量是什么类型的呢?大家可以用type()函数来检查。Lua支持的类型有以下几种:
    Nil 空值,所有没有使用过的变量,都是nil。nil既是值,又是类型。
    Boolean 布尔值,只有两个有效值:true和false
    Number 数值,在Lua里,数值相当于C语言的double
    String 字符串,如果你愿意的话,字符串是可以包含"\0"字符的(这和C语言总是以"\0"结尾是不一样的)
    Table 关系表类型,这个类型功能比较强大,请参考后面的内容。
    Function 函数类型,不要怀疑,函数也是一种类型,也就是说,所有的函数,它本身就是一个变量。
    Userdata 嗯,这个类型专门用来和Lua的宿主打交道的。宿主通常是用C和C++来编写的,在这种情况下,Userdata可以是宿主的任意数据类型,常用的有Struct和指针。
    Thread 线程类型,在Lua中没有真正的线程。Lua中可以将一个函数分成几部份运行。如果感兴趣的话,可以去看看Lua的文档。
    现在回过头来看看,倒觉得不是线程类型。反而象是用来做遍历的,象是Iterator函数。
    如:
    function range(n)
      local
    = 0
      
    while(i < n) do
        coroutine.yield( i )
        i = i + 1
      
    end
    end
    可惜的是要继续运行,需要coroutine.resume函数,有点鸡肋。请指教。

    V.  变量的定义
      所有的语言,都要用到变量。在Lua中,不管在什么地方使用变量,都不需要声明,并且所有的这些变量总是全局变量,除非我们在前面加上"local"。这一点要特别注意,因为我们可能想在函数里使用局部变量,却忘了用local来说明。
      至于变量名字,它是大小写相关的。也就是说,A和a是两个不同的变量。
      定义一个变量的方法就是赋值。"="操作就是用来赋值的
      我们一起来定义几种常用类型的变量吧。
      A.  Nil
        正如前面所说的,没有使用过的变量的值,都是Nil。有时候我们也需要将一个变量清除,这时候,我们可以直接给变量赋以nil值。如:

        var1=nil  -- 请注意 nil 一定要小写


      B.  Boolean
        布尔值通常是用在进行条件判断的时候。布尔值有两种:true 和 false。在Lua中,只有false和nil才被计算为false,而所有任何其它类型的值,都是true。比如0,空串等等,都是true。不要被 C语言的习惯所误导,0在Lua中的的确确是true。你也可以直接给一个变量赋以Boolean类型的值,如:

        theBoolean = true


      C.  Number
        在Lua中,是没有整数类型的,也不需要。一般情况下,只要数值不是很大(比如不超过100,000,000,000,000),是不会产生舍入误差的。在WindowsXP能跑的当今主流PC上,实数的运算并不比整数慢。
        实数的表示方法,同C语言类似,如:
        4 0.4 4.57e-3 0.3e12 5e+20

      D.  String
        字符串,总是一种非常常用的高级类型。在Lua中,我们可以非常方便的定义很长很长的字符串。
        字符串在Lua中有几种方法来表示,最通用的方法,是用双引号或单引号来括起一个字符串的,如:
        "That's go!"
        或
        'Hello world!'

        和C语言相同的,它支持一些转义字符,列表如下:
        \a  bell
        \b  back space
        \f  form feed
        \n  newline
        \r  carriage return
        \t  horizontal tab
        \v  vertical tab
        \\  backslash
        \"  double quote
        \"  single quote
        \[  left square bracket
        \]  right square bracket

        由于这种字符串只能写在一行中,因此,不可避免的要用到转义字符。加入了转义字符的串,看起来实在是不敢恭维,比如:
        "one line\nnext line\n\"in quotes\", "in quotes""
        一大堆的"\"符号让人看起来很倒胃口。如果你与我有同感,那么,我们在Lua中,可以用另一种表示方法:用"[["和"]]"将多行的字符串括起来。(lua5.1: 中括号中间可以加入若干个"="号,如 [==[ ... ]==],详见下面示例
        示例:下面的语句所表示的是完全相同的字符串:

    = 'alo\n123"'
    = "alo\n123\""
    = '\97lo\10\04923"'
    = [[alo
    123"
    ]]
    = [==[
    alo
    123"
    ]==]


        值得注意的是,在这种字符串中,如果含有单独使用的"[["或"]]"就仍然得用"\["或"\]"来避免歧义。当然,这种情况是极少会发生的。

      E.  Table
        关系表类型,这是一个很强大的类型。我们可以把这个类型看作是一个数组。只是C语言的数组,只能用正整数来作索引;在Lua中,你可以用任意类型来作数组的索引,除了nil。同样,在C语言中,数组的内容只允许一种类型;在Lua中,你也可以用任意类型的值来作数组的内容,除了nil。
        Table的定义很简单,它的主要特征是用"{"和"}"来括起一系列数据元素的。比如:

        T1 = {}  -- 定义一个空表
        T1[1]=10  -- 然后我们就可以象C语言一样来使用它了。


     

        T1["John"]={Age=27, Gender="Male"}
        这一句相当于:
        T1
    ["John"]={}  -- 必须先定义成一个表,还记得未定义的变量是nil类型吗
        T1["John"]["Age"]=27
        T1
    ["John"]["Gender"]="Male"
        当表的索引是字符串的时候,我们可以简写成:
        T1.John
    ={}
        T1.John.Age
    =27
        T1.John.Gender
    ="Male"
        或
        T1.John{Age
    =27, Gender="Male"}

    这是一个很强的特性。

        在定义表的时候,我们可以把所有的数据内容一起写在"{"和"}"之间,这样子是非常方便,而且很好看。比如,前面的T1的定义,我们可以这么写:

        T1=
        {
          
    10,  -- 相当于 [1] = 10
          [100] = 40,
          John
    =  -- 如果你原意,你还可以写成:["John"] =
          {
            Age
    =27,   -- 如果你原意,你还可以写成:["Age"] =27
            Gender=Male   -- 如果你原意,你还可以写成:["Gender"] =Male
          },
          
    20  -- 相当于 [2] = 20
        }


        看起来很漂亮,不是吗?我们在写的时候,需要注意三点:
        第一,所有元素之间,总是用逗号","隔开;
        第二,所有索引值都需要用"["和"]"括起来;如果是字符串,还可以去掉引号和中括号;
        第三,如果不写索引,则索引就会被认为是数字,并按顺序自动从1往后编;

        表类型的构造是如此的方便,以致于常常被人用来代替配置文件。是的,不用怀疑,它比ini文件要漂亮,并且强大的多。

      F.  Function
        函数,在Lua中,函数的定义也很简单。典型的定义如下:

        function add(a,b)  -- add 是函数名字,a和b是参数名字
         return a+b  -- return 用来返回函数的运行结果
        end


        请注意,return语言一定要写在end之前。假如我们非要在中间放上一句return,那么就应该要写成:do return end。
        还记得前面说过,函数也是变量类型吗?上面的函数定义,其实相当于:

        add = function (a,b) return a+end

    当重新给add赋值时,它就不再表示这个函数了。我们甚至可以赋给add任意数据,包括nil (这样,赋值为nil,将会把该变量清除)。Function是不是很象C语言的函数指针呢?

        和C语言一样,Lua的函数可以接受可变参数个数,它同样是用"..."来定义的,比如:

        function sum (a,b,)

    如果想取得...所代表的参数,可以在函数中访问arg局部变量(表类型)得到 (lua5.1: 取消arg,并直接用"..."来代表可变参数了,本质还是arg)。
        如 sum(1,2,3,4)
        则,在函数中,a = 1, b = 2, arg = {3, 4}  (lua5.1:  a = 1, b = 2, ... = {3, 4})
        更可贵的是,它可以同时返回多个结果,比如:

        function s()
          
    return 1,2,3,4
        
    end
        a,b,c,d 
    = s()  -- 此时,a = 1, b = 2, c = 3, d = 4


        前面说过,表类型可以拥有任意类型的值,包括函数!因此,有一个很强大的特性是,拥有函数的表,哦,我想更恰当的应该说是对象吧。Lua可以使用面向对象编程了。不信?举例如下:

        t =
        {
         Age 
    = 27
         
    add = function(self, n) self.Age = self.Age+end
        }
        
    print(t.Age)  -- 27
        t.add(t, 10)
        
    print(t.Age)  -- 37


        不过,t.add(t,10) 这一句实在是有点土对吧?没关系,在Lua中,我们可以简写成:

        t:add(10)    -- 相当于 t.add(t,10)


      G.  Userdata 和 Thread
        这两个类型的话题,超出了本文的内容,就不打算细说了。

    VI.  结束语
      就这么结束了吗?当然不是,接下来,我们需要用Lua解释器,来帮助理解和实践了。相信这样会更快的对Lua上手了。
      就象C语言一样,Lua提供了相当多的标准函数来增强语言的功能。使用这些标准函数,可以很方便的操作各种数据类型,并处理输入输出。有关这方面的信息,我们可以参考《Programming in Lua 》一书,也可以在网络上直接观看电子版,网址为:http://www.lua.org/pil/index.html
      
    备注:本文的部份内容摘、译自lua随机文档。
    相关链接:
    1. Lua 官方网站: http://www.lua.org
    2. Lua Wiki网站,你可以在这里找到很多相关的资料,如文档、教程、扩展,以及C/C++的包装等: http://lua-users.org/wiki/
    3. Lua 打包下载(包括各种平台和编译器的工程文件如vs2003,vs2005):http://luabinaries.luaforge.net/download.html

Open Toolbar