bookmark_borderPoco C++库简介 (转)

学习一个框架前,要先明白它的是什么,为什么,怎么用.下面这些文字,是从中文poco官网上转过来的,正如poco c++库的特点,非常清晰,代码风格更是一目了然.

   poco开发库的特点,非常适合写后台处理程序,效率也是很高的.前台界面程序使用Qt框架库,非常好,两个库相辅相成,可解决项目上的大部分问题.

注:更多详情可以访问Poco官方网站:https://pocoproject.org

Poco C++库是:

  • 一系列C++类库,类似Java类库,.Net框架,Apple的Cocoa;

  • 侧重于互联网时代的网络应用程序

  • 使用高效的,现代的标准ANSI/ISO C++,并基于STL

  • 高可移值性,并可在多个平台下可用

  • 开源,并使用Boost Software License发布

  • 不管是否商用,都完全免费

特性:

  • DynamicAny与Any类

  • Cache框架

  • 基于OpenSSL的密码系统

  • 日期,时间类库

  • 事件和通知框架

  • FTP客户端

  • 跨平台的文件系统类库

  • HTML表单类库

  • HTTP客户端和服务端(支持SSL),C++ 服务器页面编译器

  • 日志框架

  • 多线程框架(线程池,活动对象,工作队列等)

  • POP3客户端类库

  • 跨平台,一次编写,多平台编译和运行

  • 进程管理和进程间通信类库

  • 反射框架

  • 基于PCRE的正则表达式

  • SMTP客户端类库

  • 数据库访问类库(SQLite,MySQL, ODBC)

  • 支持SSL/TLS,基于OpenSSL

  • 动态类库加载

  • 先进的内存和指针管理(Buffer, Pool)

  • Socket类库

  • 网络数据流类库,支持Base64,HexBinary编解码,压缩等等

  • 字符串格式化和其它字符串工具类库

  • TCP服务器框架(多线程)

  • 文本编码和转换

  • Tuples

  • URI支持

  • 支持UTF8和Unicode编码

  • UUID生成器

  • XML生成和解析器

  • Zip文件操作类库

Poco的使命

  • Poco是一个强大的类库,并易于构建自己的应用程序

  • Poco帮助你创建跨平台的应用程序(一次编写,多平台编译和运行)

  • 模块化和可扩展,可应用于嵌入式到企业级程序

  • 提供全面,易懂的编程接口

  • 使用C++语言,快速且高效

  • Poco崇尚简易

  • 在设计,代码风格和文档上保持一致

  • Poco强调代码质量,包括可读性,综合性,一致性,编码风格和可测试性

  • Poco使得C++编程更加容易

指导方针

  • 高度关注代码质量,编码风格,一致性,可读性

  • 高度关注测试

  • 注重实用性

  • 基于现有的,可靠的组件开发

版本历史

  • Summer 2004: Günter Obiltschnig started development

  • February 2005: First release on SourceForge

  • (Release 0.91 under Sleepycat license)

  • May 2005: First contributions by Aleksandar Fabijanic

  • January 2006: Release 1.0

  • March 2006: Release 1.1

  • July 2006: Moved to Boost license, POCO Community Website

  • August 2006: Release 1.2

  • May 2007: Release 1.3

  • July 2010: Stable Release 1.3.7,

  • about 20 contributors, used in 100s of projects

支持平台

  • Microsoft Windows

  • Linux

  • Mac OS X

  • HP-UX, Solaris, AIX*

  • Embedded Linux (uClibc, glibc)

  • iOS

  • Windows Embedded CE

  • QNX

Poco应用场景

  • 创建自动化的中间件和设备

  • 工业自动化和工业设备

  • 流量控制系统

  • 健康系统

  • 测量,数据收集和测试系统

  • 消费电子产品和家庭自动化产品

  • 测量

  • 航空交通管理系统

  • VoIP

  • 票务和入口控制系统

  • 包装应用程序

Poco的优势

  • 全面的,完整的C++框架,可减少开发工作,快速让产品走向市场

  • 易学易使用,以及相当多的示例代码和良好的文档

  • 原生的C++代码,性能优秀,低内存占用

  • 平台无关,一处编写,跨平台编译和运行

    • 大多数情况下,可以开发机上完成开发和调试工作

    • 可以非常容易的迁移到新平台

       

 

设计 & 实现

   基于现代的、标准的ANSI C++编写,使用C++ STL库。模块化设计,极少的外部依赖,易于编译和使用。结合传统的面向对象与现代的C++设计,代码易读,代码风格统一,以及相当全面的测试用例。

支持平台

  • 桌面/服务器: Windows, Linux, Mac OS X, Solaris, HP-UX, AIX

  • 嵌入式系统: Windows Embedded CE, Embedded Linux (uClibc or glibc), iOS, QNX, VxWorks, Android

  • 最低系统要求: 75 MHz ARM9, 8 MB RAM (Embedded Linux).

License

  • Boost Software License 1.0

核心特性

  • 支持Any 和 DynamicAny 的动态类型

  • 提供缓存框架

  • 日期和时间

  • 事件与通知框架

  • (libPoco.com翻译,转载请注明)

  • 基于PCRE的正则表达式

  • 动态库加载

  • 完美的指针和内存管理 (buffer, pool)

  • 字符串格式化和工具

  • tuples

压缩

  • 基于zlib的压缩/解压类

  • 创建和解压ZIP文件

加密

  • 支持多种hash算法

  • 支持X509数字证书

  • 对称的和 RSA算法

  • 支持streams加解密

  • 基于OpenSSL

数据库

  • 不同的数据库提供了统一的访问接口(SQLite, MySQL, ODBC)

  • 自动数据类型匹配

  • 支持集合类 (std::vector, std::set, std::map, etc.)

  • 支持记录集和tuples

  • 支持连接池

文件系统

  • 跨平台的文件路径操作

  • 目录列表

  • 通配符支持

  • 文件属性管理

日志

  • 可扩展的日志框架,可拔插的日志通道和消息格式化

  • 日志可输出到终端,日志文件,syslog,远程syslog,Windows事件服务

多线程

  • 线程和线程同步类库

  • 线程池

  • 工作队列

  • 活动对象

  • 任务管理

  • 定时器

网络

  • 流,数据报,多播,服务器和原生socket.

  • TCP服务器框架(多线程)

  • 反射服务器框架

  • HTTP(S)客户和服务器框架

  • HTTP认证

  • CSP(C++ Server Page)编译器

  • FTP客户端

  • SMTP和POP3客户端

  • (libPoco.com翻译,转载请注明)

  • 支持URI, UUID

  • HTML表单处理

  • MIME支持

  • 基于 OpenSSL支持SSL/TLS

  • WebSocket (RFC 6455) 客户和服务器

进程管理和 IPC

  • 进程启停

  • 进程间同步

  • 共享内存

  • Base64 和 HexBinary 编解码

  • 压缩(zlib)

  • 行结束符车换

  • 内存stream

  • 文本编码转换

  • URI流读取

文本编码

  • 支持UTF-8 和 Unicode

  • 文本编码和转换

  • 字符分类

工具类

  • 支持命令行和服务器程序框架

  • 命令行参数解析器

  • 配置文件解析

  • 支持Unix和Windows后台服务

XML

  • 基于 Expat 的XML解析

  • SAX2 (Simple API for XML, version 2) 解析器

  • DOM (Document Object Model, Level 1-3) 解析器

  • XML生成器

bookmark_borderunique_ptr、weak_ptr与shared_ptr的主要区别

使用C++11引入的智能指针的新特性来开发程序,我们使用最多的应该就是shared_ptr,而unique_ptr与weak_ptr多数人用得比较少。那么他们有哪些主要的区别,使用场合有什么不同呢?

unique_ptr、shared_ptr与weak_ptr等智能指针(smart pointer),都定义在<memory>中。

可以对动态资源进行管理,保证任何情况下,已构造的对象最终会销毁,即它的析构函数最终会被调用。

unique_ptr

unique_ptr持有对对象的独有权,同一时刻只能有一个unique_ptr指向给定对象(通过禁止拷贝语义、只有移动语义来实现)。

unique_ptr指针本身的生命周期:从unique_ptr指针创建时开始,直到离开作用域。

离开作用域时,若其指向对象,则将其所指对象销毁(默认使用delete操作符,用户可指定其他操作)。

shared_ptr

shared_ptr允许多个该智能指针共享第“拥有”同一堆分配对象的内存,这通过引用计数(reference counting)实现,会记录有多少个shared_ptr共同指向一个对象,一旦最后一个这样的指针被销毁,也就是一旦某个对象的引用计数变为0,这个对象会被自动删除。

weak_ptr

weak_ptr是为配合shared_ptr而引入的一种智能指针来协助shared_ptr工作,它可以从一个shared_ptr或另一个weak_ptr对象构造,它的构造和析构不会引起引用计数的增加或减少。没有重载 * 和 -> 但可以使用lock获得一个可用的shared_ptr对象

weak_ptr的使用更为复杂一点,它可以指向shared_ptr指针指向的对象内存,却并不拥有该内存,而使用weak_ptr成员lock,则可返回其指向内存的一个share_ptr对象,且在所指对象内存已经无效时,返回指针空值nullptr。

weak_ptr具有弱引用特性,不拥有对象,只有延迟到尝试调用Lock()时才会有可能临时拥有对象:

只是持有一个没有拥有权的被shared_ptr托管的对象.

只有调用lock()创建shared_ptr指针时才会引用实际对象.

在lock()成功时会延长shared_ptr对象的生命周期,因为它递增了一个引用计数.

在shared_ptr主指针结束后,如果std::weak_ptr的lock()成功的指针还存在,那么这时候还有lock()的代码调用,引用计数仍然递增.

经常用在解除循环引用问题.看以下例子如果Man和Woman各自包含一个std::shared_ptr,那么就会出现内存泄漏,因为Woman,Main的计数实际是2.Woman成员变量是必须是Woman的析构调用后才会调用,而Woman的析构必须是引用计数为0时才会调用,这导致成员变量Man一直没有析构.

例子1:std::shared_ptr 和 std::weak_ptr的用法以及引用计数的循环引用问题

用于在延迟使用主导权的场景, 比如线程A是重要,A完成之后B,C线程可做可不做.这时候B,C就可以使用weak_ptr指针来控制.

bookmark_borderVC开发DLL工程在什么情况下只生成DLL,不生成LIB

DLL程序中必须导出至少一个函数/变量/类。
没有导出的话就不生成LIB。


如果LIB是静态库则不需要DLL 。
如果LIB是动态链接的,那么就必须找到DLL 。
动态链接时,LIB只包含简单的DLL导出定义和辅助链接,并不包含可执行实体。


动态链接与静态链接的不同之处在于:
动态链接允许可执行模块(.dll 文件或 .exe 文件)仅包含在运行时定位 DLL 函数的可执行代码所需的信息。
在静态链接中,链接器从静态链接库获取所有被引用的函数,并将库同代码一起放到可执行文件中。


lib后缀的库文件有两种:
一种为静态链接库(Static Libary,简称"静态库");
另一种为动态连接库的导入库(Import Libary,简称"导入库")。


bookmark_border通过vbs调用bat文件达到隐藏cmd窗口的效果

1. 创建一个如下所示的call-bat.vbs文件:

Dim cmdStr
cmdStr = WScript.Arguments(0)
 
Set WsShell = CreateObject("Wscript.Shell") 
WsShell.Run cmdStr & " /start", 0

2. 假设同一级目录下有一个test.bat 的批处理文件:

@echo off
ping -n 3600 127.0.0.1 > nul

3.打开命令行提示窗口,输入如下命令:

cscript call-bat.vbs test.bat >> test-bat.log

bookmark_bordervbs script批量执行程序

代码如下:

     
  
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''  
' The function used to check whether the given file exists.                     '  
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''  
Function CheckFileExists(strFilePath)   
    set oFSO = createObject("Scripting.FileSystemObject")   
    boolFileExists = oFSO.fileExists(strFilePath)    
    set oFSO = Nothing    
      
    CheckFileExists = boolFileExists   
End Function  
 
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''  
' The function used to print log                                                '  
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''  
Function PrintLog(strLog, logFileName)  
	if not CheckFileExists(logFileName) then
		Set fso = CreateObject("Scripting.FileSystemObject") 
		fso.CreateTextFile logFileName, true
		Set fso = nothing
	end if
	
	Set fso = CreateObject("Scripting.FileSystemObject") 
	Const ForAppending = 8
	Set objLogFile = fso.OpenTextFile(logFileName, ForAppending, True)	
	
	strMsg = Date() & " " & Time() & " " & strLog  
    objLogFile.WriteLine strMsg  
	
	objLogFile.Close()
	Set fso = nothing
End Function 
 
  
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''  
' The RunCommandlineTool function execute the specified command-line exe,       '  
' and redirect the command-line print messages to the given log file,           '  
' then analyze the log file to determine whether there are some errors.         '  
'                                                                               '  
' PARAMETERS:                                                                   '  
'   @strCommand: Specify the command string,                                    '  
'   @strRedirectLogFilenamePath: Specify the log file,                          '  
' RETURN:                                                                       '  
'   True : process succeed without any error,                                   '  
'   False: process complete with some errors                                    '                                             
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''  
Function RunCommandlineTool(strCommand, logFileName)  
    PrintLog """" & strCommand & """" & " Start!", logFileName     
      
    Set WsShell = CreateObject("Wscript.Shell")   
    Dim strShellCommand   
    Dim processNoError  
      
    strShellCommand = "%comspec% /c " & Chr(34) & strCommand & " >> " & logFileName & Chr(34)  
    WsShell.Run strShellCommand, 0, True                                          
    
End Function   
 
 
Dim scriptFileName
Dim logFileName
scriptFileName = WScript.Arguments(0)  
logFileName = WScript.Arguments(1)  
  
Set fso1 = createobject("scripting.filesystemobject")  
Set textStream = fso1.OpenTextFile(scriptFileName, 1)  
  
Do While Not textStream.AtEndOfStream  
	cmdLine = trim(textStream.readline)		
	i=i + 1   	
	  
	RunCommandlineTool cmdLine, logFileName   
Loop   
  
Set textStream = Nothing  
Set fso1 = Nothing

bookmark_border使用vbs shell在指定时间自动结束进程

以下vbs代码段实现在特定时间将指定的进程kill掉:

'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Usage:														'
' 	cscript AutoTerminateTicCopyBat.vbs >> terminatecopy.log	'
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
 
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Global Constants Initialization								'
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
COMMAND_TO_TERMINATE = "copy-data.bat"
HOUR_OF_ENDTIME_IN_GMT8 = 16
 
 
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Terminates the specific process during the given time range	'
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function TerminatesCmdProcess(strProcess)
	Dim objProcesses
	strComputer = "."
	Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
	Set colProcesses = objWMIService.ExecQuery("Select * from Win32_Process Where Name ='cmd.exe' and "_
											   & " CommandLine like '%" & COMMAND_TO_TERMINATE & "%'")
 
	For Each objProcess in colProcesses
		objProcess.Terminate()
		
		WScript.Echo Now() & " Automatically terminated the process " & objProcess.CommandLine 
	Next			
 
End Function
 
 
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Check if it is the time to terminate the specific process 	'
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function IsTime2Terminate
	Dim bRet
	Dim hourOfCurUtcTime
	Dim hourOfCurTimeInGMT8
	
	bRet = False
	
	'Get current UTC time on the machine
	strComputer = "."
	Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
	Set colItems = objWMIService.ExecQuery("Select * from Win32_UTCTime")
	
	For Each objItem in colItems
		hourOfCurUtcTime = objItem.Hour
		hourOfCurTimeInGMT8 = hourOfCurUtcTime + 8
	Next
	
	If hourOfCurTimeInGMT8 >= HOUR_OF_ENDTIME_IN_GMT8 Then
		bRet = True
	End If
 
	IsTime2Terminate = bRet
End Function
 
 
'Main Process
Dim bFlag 
bFlag = True
 
Do While bFlag
	
	If IsTime2Terminate() Then
		TerminatesCmdProcess strProcess
	End If
 
	WScript.Sleep 1000*60
Loop

bookmark_border使用vbs shell调用命令行exe的方法

有时候我们需要用.bat或其他脚本快速灵活的实现对其他exe的调用,实现一些数据转换、搬迁等批处理工作,在windows上vbs shell是一种不错的选择,不仅灵活而且功能强大。

本文给出了一些自己封装的用于调用exe的vbs函数。

'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' The function used to print log                                                '
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function PrintLog(strLog)
    strMsg = Date() & " " & Time() & " " & strLog
    logFile.WriteLine strMsg
End Function    
 
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' The function used to check whether the given file exists.                        '
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function CheckFileExists(strFilePath) 
    set oFSO = createObject("Scripting.FileSystemObject") 
    boolFileExists = oFSO.fileExists(strFilePath)  
    set oFSO = Nothing  
    
    CheckFileExists = boolFileExists 
End Function
 
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' The function used to delete file.                                                '
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function DeleteTempFile(strFilePath) 
    set oFSO = createObject("Scripting.FileSystemObject") 
    
    If oFSO.FileExists(strFilePath) Then        
        oFSO.DeleteFile strFilePath, True 
    End If 
    
    set oFSO = Nothing  
End Function
 
 
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' To read the input parameters, return an array                                    '
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function ReadInputParam(strFilePath) 
    Dim retArray 
    retArray = Array(50, 3)
 
    set oFSO = createObject("Scripting.FileSystemObject") 
    
    If oFSO.FileExists(strFilePath) Then        
        Set textStream = oFSO.OpenTextFile(strFilePath)
        
        Dim i
        i = 0
        Do While Not textStream.AtEndOfStream
            inputLine = ucase(trim(textStream.readline))
            
            tempArray = Split(inputLine, " ", -1, 1)
            If UBound(tempArray) = 2 Then
                retArray(i) = tempArray
                i = i + 1
            End If 
        Loop 
        
        Set textStream = Nothing
    
    End If 
    
    set oFSO = Nothing 
    
    ReadInputParam = retArray
End Function
 
 
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' The GetSortedFiles function get a filename list of a specified directory      '
' ordered by ascending filename                                                 '                                            
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function GetSortedFiles(strPath) 
    Dim rs
    Dim folder
    Dim File 
    Const adVarChar = 200 
    Set fso = CreateObject("Scripting.FileSystemObject")  
    Set rs = CreateObject("ADODB.Recordset") 
    Set folder = fso.GetFolder(strPath) 
    Set FSO = nothing
    
    rs.fields.append "FileName", adVarChar, 255
    rs.fields.append "OrderBy", adVarChar, 255 
    rs.Open 
    
    For Each File In folder.Files
        If InStr(1, File.Name, ".edb", 1) <> 0 And InStr(1, UCase(File.Name), "TIC", 1) = 1 Then  
            rs.AddNew 
            rs("FileName") = File.Name 
            strNameWithoutExt = Left(UCase(File.Name), Len(File.Name) - 4)
            strArray = Split(strNameWithoutExt, "_", -1, 1)
            strYMD = strArray(0)
            
            If UBound(strArray) = 0 Then
                strNO = "00"
            Else
                strNO = strArray(1)
                If Len(strNO) = 1 Then
                    strNO = "0" & strNO
                End If    
            End If 
            
            strOrderBy = strYMD & "_" & strNO
            
            rs("OrderBy") = strOrderBy
            
            rs.Update 
        End If 
    Next 
    
    'Sort by acending file name  
    rs.Sort = "OrderBy ASC" 
 
    rs.MoveFirst 
    Set folder = Nothing 
    Set GetSortedFiles = rs 
End Function 
 
 
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' The RunCommandlineTool function execute the specified command-line exe,       '
' and redirect the command-line print messages to the given log file,              '
' then analyze the log file to determine whether there are some errors.            '
'                                                                                '
' PARAMETERS:                                                                    '
'    @strCommand: Specify the command string,                                    '
'     @strRedirectLogFilenamePath: Specify the log file,                            '
' RETURN:                                                                        '
'    True : process succeed without any error,                                     '
'    False: process complete with some errors                                     '                                            
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function RunCommandlineTool(strCommand, strRedirectLogFilenamePath)
    PrintLog """" & strCommand & """" & " Start!"    
    
    Set WsShell = CreateObject("Wscript.Shell") 
    Dim strShellCommand 
    Dim processNoError
    
    strShellCommand = "%comspec% /c " & Chr(34) & strCommand & " >> " & strRedirectLogFilenamePath & Chr(34)
    WsShell.Run strShellCommand, 0, True                                     
    
    'Parse the log to determine whether there are some errors                
    processNoError = True                         
    WScript.Sleep 200
 
    Set fso1 = createobject("scripting.filesystemobject")
    Set textStream = fso1.OpenTextFile(strRedirectLogFilenamePath, 1)
    
    Do While Not textStream.AtEndOfStream
        logLine = ucase(trim(textStream.readline))
        i=i + 1    
        
        If InStr(logLine, "FAILED") Then
            PrintLog(logLine)
            processNoError = false                        
            Exit Do 
        End If 
    Loop 
    
    Set textStream = Nothing
    Set fso1 = Nothing 
    
    Dim strProcEndMsg
    If processNoError = True Then 
        strProcEndMsg = " Done Successfully"
    Else
        strProcEndMsg = "Complete with Some Errors!"
    End If 
    
    strProcEndMsg = """" + strCommand + """ " + strProcEndMsg
    
    PrintLog strProcEndMsg
    
    RunCommandlineTool = processNoError
End Function

bookmark_border批量设置excel条件格式改变整行的填充色的方法

1. 选中需要应用“条件格式”的所有行。

2. Conditional Format > formula填入如下公式:

    =IF($D2="Failed",1,0) 

3. 并点击"Format", 设置Fill为红色,保存即可。

设置好后,当第4列设置为Failed时,颜色变为红色。

以下是几个判断时间的条件格式表达式:

=IF(TIME(HOUR($F2), MINUTE($F2), SECOND($F2)) > TIME(8,40,0),1,0)
=IF(TIME(HOUR($G2), MINUTE($G2), SECOND($G2)) > TIME(17,30,0),1,0)
=IF(TIME(HOUR($G2-$F2), MINUTE($G2-$F2), SECOND($G2-$F2)) >= TIME(9,0,0),1,0)

bookmark_borderWindows批处理脚本中实现循环计数的方法

Windows批处理脚本中循环计数可以参考以下代码实现:

setlocal EnableDelayedExpansion 
set ii=1 6 M% l( R( a% _/ S* `: yfor /R %%i in (*.txt) do ( 6 S3 O  y% }, Y4 x  set  /a  sum+=!ii! 
    @echo  %TIME% 已完成!sum! 个补丁,继续安装中... 
)
pause

bookmark_borderMS SQLSERVER使用TVP进行批量更新

1.  创建用户自定义的表类型(Table Type)

CREATE TYPE [dbo].[TVPGameDataItem] AS TABLE (

[UserID] [BIGINT] NULL,

[DBID] [INT] NULL,

[Wins] [INT] NULL,

[Balances] [INT] NULL,

[Loses] [INT] NULL,

[Escapes] [INT] NULL,

[Score] [INT] NULL,

[Money] [BIGINT] NULL,

[Experience] [INT] NULL

)

 

2.  存储过程中使用TVP (Table Valued Parameter)

CREATE  PROCEDURE [dbo].[xp_User_ChangeGameResources]  

     @GameID         int,

@Items  dbo.TVPGameDataItem READONLY

AS 

SET NOCOUNT ON

BEGIN TRAN 

更新game_data记录

MERGE INTO tb_game_data t1 USING @Items t2 ON t1.GameID = @GameID AND t1.UserID = t2.UserID

WHEN MATCHED THEN 

UPDATE SET

t1.Wins  =  t1.Wins  + t2.Wins,     

t1.Balances    =  t1.Balances + t2.Balances,

t1.Loses       =  t1.Loses  + t2.Loses, 

t1.Escapes     =  t1.Escapes  + t2.Escapes,

t1.Score       =  t1.Score  + t2.Score,  

t1.Money       =  t1.Money  + t2.Money,  

t1.Experience =  t1.Experience + t2.Experience

WHEN NOT MATCHED THEN  

INSERT (UserID, GameID, Wins, Balances, Loses, Escapes, Score, Money, Experience)

VALUES (t2.UserID, @GameID, t2.Wins, t2.Balances, t2.Loses, t2.Escapes, t2.Score, t2.Money, t2.Experience);

 

更新user信息

UPDATE tb_user_BaseInfo_0

SET tb_user_BaseInfo_0.Money = t1.Money + t2.Money

FROM tb_user_BaseInfo_0 t1

INNER JOIN @Items t2 ON t1.UserID = t2.UserID

COMMIT TRAN

RETURN @@error

 

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

CREATE  PROC [dbo].[xp_UserLog_GameResChange]

     @DataType            int,

@GameResChangeType   int,

     @GameID              int,

 @IsPlaying           int,

@Items  dbo.TVPGameLogItem READONLY

AS 

 

SET NOCOUNT ON

 

DECLARE @BattleID BIGINT

 

SET @BattleID = 0

 

BEGIN TRAN 

IF (@IsPlaying = 1)

        BEGIN

            SELECT @BattleID = Intvalue FROM tb_LGSystermParam WHERE SysID = 1

            if @BattleID = 0

               BEGIN

                  SET @BattleID = 1

               END

            

             UPDATE tb_LGSystermParam SET Intvalue = (@BattleID + 1) WHERE SysID = 1

        END

 

INSERT INTO tb_game_log  

(

UserID             ,

GameID            ,

GameResult         ,

cashChanged        ,

scoreChanged       ,

ExperienceChanged  ,

TableFee           ,

ChangingType       ,

BattleID           ,

ChangingTime

)

SELECT 

UserID, 

@GameID, 

Result, 

Money, 

Score, 

Experience, 

TableFee, 

@GameResChangeType, 

@BattleID,

GETDATE() 

FROM @Items

 

COMMIT TRAN

RETURN @@error


 3.  程序中使用ODBC向存储过程的TVP参数绑定多行数据

1) 绑定TVP参数时,参数类型(第5个参数为SQL_SS_TABLE

// Bind TVP parameter

SQLLEN cbTVP;

 m_cbValue[++m_nBindParam] = 0;

 SQLBindParameter(m_hstmt,

   m_nBindParam,  // ParameterNumber

  SQL_PARAM_INPUT, // InputOutputType

 SQL_C_DEFAULT,   // ValueType

 SQL_SS_TABLE,   // Parametertype

  MAX_CHAIRS,          // ColumnSize – for a TVP this the row array size

  0,               // DecimalDigits – for a TVP this is the number of columns in the TVP

  NULL,               // ParameterValuePtr – for a TVP this is the type name of the TVP

                               // (not needed with stored proc)

NULL,             // BufferLength – for a TVP this is the length of the type name or SQL_NTS

                                // (not needed with stored proc)

 &cbTVP);    // StrLen_or_IndPtr – for a TVP this is the number of rows available

 

2) TVP参数内的每个Column绑定数据(实际就是一个包含该Column多行数据的数组)分2步:

– 先使用SQLSetStmtAttr(m_hstmt, SQL_SOPT_SS_PARAM_FOCUS …)  聚焦到TVP参数,

– 然后调用SQLBindParameter依次绑定TVP内部的各个Column

SQLSetStmtAttr(m_hstmt, SQL_SOPT_SS_PARAM_FOCUS, (SQLPOINTER)m_nBindParam, SQL_IS_INTEGER);

 

SQLBindParameter(m_hstmt, 1, SQL_PARAM_INPUT, SQL_C_SBIGINT, SQL_BIGINT, 0, 0, items.userid, sizeof(SQLBIGINT), NULL);

SQLBindParameter(m_hstmt, 2, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, items.dbid, sizeof(SQLINTEGER), NULL);

SQLBindParameter(m_hstmt, 3, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, items.result, sizeof(SQLINTEGER), NULL);

SQLBindParameter(m_hstmt, 4, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, items.score, sizeof(SQLINTEGER), NULL);

SQLBindParameter(m_hstmt, 5, SQL_PARAM_INPUT, SQL_C_SBIGINT, SQL_BIGINT, 0, 0, items.money, sizeof(SQLBIGINT), NULL);

SQLBindParameter(m_hstmt, 6, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, items.experience, sizeof(SQLINTEGER), NULL);

SQLBindParameter(m_hstmt, 7, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, items.tablefee, sizeof(SQLINTEGER), NULL);

 

3) 绑定完TVP内部字段后,再次调用SQLSetStmtAttr(m_hstmt, SQL_SOPT_SS_PARAM_FOCUS …)  重置Focus.

// Reset param focus

 SQLSetStmtAttr(m_hstmt, SQL_SOPT_SS_PARAM_FOCUS, (SQLPOINTER)0, SQL_IS_INTEGER);

 

// Initialize TVP row count

 cbTVP = (SQLUINTEGER)uicts;

 

4.  注意事项

1) TVP (Table Valued Parameter)SQL Server 2008 R2引入的新特性,之前的版本不支持。

2) ODBC驱动的版本是从10.0开始支持TVP参数,所以使用TVP操作SQL Server的程序运行环境上需要安装10.0或以上版本的数据库连接驱动。

注:可以通过运行odbc数据源管理程序查看本机安装的odbc驱动版本。

图片1.png

3) 关于odbc错误“[Microsoft][ODBC SQL Server Driver]无效的参数类型”

出现该错误,说明我们的程序使用的是10.0以前的odbc驱动访问的SQL Server,需要在创建DB连接的地方,将DB连接串中DRIVER指定10.0或以上版本,如下所示:

图片2.png

"DRIVER={SQL Server Native Client 10.0};SERVER=x.x.x.x;DATABASE=MiniGameLogNewDB;UID=sa;PWD=123456;"

4)     关于” [Microsoft][SQL Server Native Client 10.0]Dialog failed”错误

当出现该错误时,请将SQLDriverConnect()函数的最后一个参数由SQL_DRIVER_COMPLETE改为SQL_DRIVER_NOPROMPT