关于widechar的问题,用WideChar(12345),发现写返回的是?

njyaoer 2006-09-27 05:43:03
我在写程序的时候发现一个问题,不知道怎么办,
我有一个字符,他是unicode字符,ord(该字符)=12345,我用WideChar(12345),发现写入到文本是?,我看了文件内容,居然存的是?的Ascii,不知道是什么回事,望不吝剔教
...全文
112 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复
本书从函数功能、函数格式、参数说明、注意事项、Excel 版本提醒、案例应用、交叉参考7 个方面,全面、细致地介绍了Excel 2016/2013/2010/2007/2003 中公式和函数的使用方法、实际应用和操作技巧。最后3 章还将公式与函数的应用扩展到了条件格式、数据验证及图表中,以便使它们发挥更强大的功能。本书采用理论与实践相结合的方式,提供了457 个案例,涉及多个行业,读者可以根据书中的案例举一反三,将其直接应用到实际工作中,有效提高学习效果与实际应用能力。 本书既可以作为函数速查工具手册,又可以作为丰富的函数应用案例宝典,适合对Excel 公式与函数有需求的读者阅读。 第1章 公式与函数基础 1 1.1 了解公式 1 1.1.1 公式的组成部分 1 1.1.2 数据类型及其相互转换 2 1.1.3 运算符及其优先级 3 1.1.4 普通公式与数组公式 5 1.1.5 单个单元格公式与多个单元格公式 5 1.1.6 Excel对数字精度、公式与函数等方面的限制 5 1.2 输入与编辑公式 6 1.2.1 A1引用样式与R1C1引用样式 6 1.2.2 输入公式 8 1.2.3 修改公式 9 1.2.4 移动和复制公式 9 1.2.5 删除公式 12 1.2.6 改变公式的计算方式 13 1.3 在公式中使用函数 14 1.3.1 为什么使用函数 14 1.3.2 函数的类型 14 1.3.3 函数的参数 15 1.3.4 在公式中输入函数 16 1.4 在公式中使用名称 18 1.4.1 名称的作用范围 19 1.4.2 命名区域 19 1.4.3 命名公式 20 1.4.4 命名常量 21 1.4.5 将名称应用到公式中 21 1.5 使用数组公式 23 1.5.1 单个单元格数组公式与多单元格数组公式 23 1.5.2 数组的维数 24 1.5.3 输入数组公式 25 1.5.4 修改数组公式 25 1.5.5 扩展或缩小多单元格数组公式 26 1.5.6 选择数组公式所在区域 27 1.5.7 使用常量数组 27 1.6 创建跨工作表和跨工作簿引用的公式 28 1.6.1 创建引用其他工作表中的数据的公式 28 1.6.2 创建引用其他工作簿中的数据的公式 29 1.6.3 创建对多个工作表中相同单元格区域的三维引用 30 1.6.4 更新跨工作簿引用的公式 31 1.7 审核公式 31 1.7.1 使用公式错误检查器 32 1.7.2 定位特定类型的数据 33 1.7.3 追踪单元格之间的关系 33 1.7.4 监视单元格内容 35 1.7.5 使用公式求值器 36 1.8 处理公式中的错误 36 1.8.1 括号不匹配 37 1.8.2 单元格被#符号填满 37 1.8.3 空白但非空的单元格 37 1.8.4 显示值与实际值 38 1.8.5 返回错误值 39 1.8.6 循环引用 41 1.9 公式使用技巧 42 1.9.1 在多个单元格中输入同一个公式 42 1.9.2 显示公式而不是值 42 1.9.3 查看公式的中间结果 42 1.9.4 将公式转换为值 43 1.9.5 复制公式但不使用相对引用 43 1.9.6 隐藏公式 44 1.9.7 禁止用户修改公式 45 第2章 数学和三角函数 46 2.1 常规计算 48 2.1.1 SIGN——返回数字的符号 48 2.1.2 ABS——计算数字的绝对值 49 2.1.3 SUM——计算数字之和 50 2.1.4 PRODUCT——计算数字之积 52 2.1.5 SQRT——计算正平方根 52 2.1.6 MOD——返回商的余数 53 2.1.7 QUOTIENT——返回商的整数部分 55 2.1.8 GCD——计算最大公约数 56 2.1.9 LCM——计算最小公倍数 57 2.1.10 SUMIF——按给定条件对指定单元格求和 57 2.1.11 SUMIFS——按多个条件对指定单元格求和 59 2.1.12 SUMPRODUCT——计算数组元素的乘积之和 60 2.1.13 SUMSQ——计算参数的平方和 61 2.1.14 SUMXMY2——计算数组对应值之差的平方和 62 2.1.15 SUMX2MY2——计算数组对应值的平方差之和 63 2.1.16 SUMX2PY2——计算数组对应值的平方和之和 63 2.1.17 SERIESSUM——计算基于公式的幂级数之和 64 2.2 舍入计算 65 2.2.1 INT——返回永远小于等于原数字的最接近的整数 65 2.2.2 TRUNC——返回数字的整数部分 66 2.2.3 ROUND——按指定位数对数字进行四舍五入 67 2.2.4 ROUNDDOWN——以绝对值减小的方向按指定位数舍入数字 68 2.2.5 ROUNDUP——以绝对值增大的方向按指定位数舍入数字 69 2.2.6 MROUND——舍入到指定倍数的数字 70 2.2.7 CEILING——以绝对值增大的方向按指定倍数舍入 71 2.2.8 CEILING.PRECISE——以算数值增大的方向按指定倍数舍入 73 2.2.9 CEILING.MATH——以绝对值或算数值增大的方向按指定倍数舍入 73 2.2.10 FLOOR——以绝对值减小的方向按指定倍数舍入 74 2.2.11 FLOOR.PRECISE——以算数值减小的方向按指定倍数舍入 75 2.2.12 FLOOR.MATH——以绝对值或算数值减小的方向按指定倍数舍入 76 2.2.13 EVEN——以绝对值增大的方向舍入到最接近偶数 77 2.2.14 ODD——以绝对值增大的方向舍入到最接近奇数 78 2.3 指数与对数计算 79 2.3.1 POWER——计算数字的乘幂 79 2.3.2 EXP——计算e的n 次方 80 2.3.3 LN——计算自然对数 81 2.3.4 LOG——计算以指定数字为底的对数 81 2.3.5 LOG10——计算以10为底的对数 82 2.4 阶乘、矩阵与随机数 83 2.4.1 COMBIN——计算给定数目对象的组合数 83 2.4.2 COMBINA——计算给定数目对象具有重复项的组合数 84 2.4.3 FACT——计算数字的阶乘 84 2.4.4 FACTDOUBLE——计算数字的双倍阶乘 85 2.4.5 MULTINOMIAL——计算多个数字和的阶乘与各数字阶乘乘积的比值 86 2.4.6 MDETERM——计算数组的矩阵行列式的值 86 2.4.7 MINVERSE——计算数组的逆矩阵 87 2.4.8 MMULT——计算两个数组的矩阵乘积 88 2.4.9 MUNIT——返回指定维度的单位矩阵 89 2.4.10 RAND——返回0到1之间的一个随机数 89 2.4.11 RANDBETWEEN——返回某个范围内的随机数 91 2.5 三角函数计算 91 2.5.1 DEGREES——将弧度转换为角度 91 2.5.2 RADIANS——将角度转换为弧度 92 2.5.3 SIN——计算给定角度的正弦值 93 2.5.4 ASIN——计算数字的反正弦值 93 2.5.5 SINH——计算数字的双曲正弦值 94 2.5.6 ASINH——计算数字的反双曲正弦值 95 2.5.7 COS——计算给定角度的余弦值 95 2.5.8 ACOS——计算数字的反余弦值 96 2.5.9 COSH——计算数字的双曲余弦值 97 2.5.10 ACOSH——计算数字的反双曲余弦值 97 2.5.11 TAN——计算给定角度的正切值 98 2.5.12 ATAN——计算数字的反正切值 99 2.5.13 TANH——计算数字的双曲正切值 99 2.5.14 ATANH——计算数字的反双曲正切值 100 2.5.15 ATAN2——计算给定坐标的反正切值 101 2.5.16 ACOT——计算数字的反余切值 102 2.5.17 ACOTH——计算数字的反双曲余切值 102 2.5.18 COT——计算给定角度的余切值 103 2.5.19 COTH——计算数字的双曲余切值 104 2.5.20 SEC——计算给定角度的正割值 105 2.5.21 SECH——计算给定角度的双曲正割值 105 2.5.22 CSC——计算给定角度的余割值 106 2.5.23 CSCH——计算给定角度的双曲余割值 107 2.6 其他计算 108 2.6.1 PI——返回pi的值 108 2.6.2 SQRTPI——计算某数与pi的乘积的平方根 108 2.6.3 SUBTOTAL——返回指定区域的分类汇总结果 109 2.6.4 AGGREGATE——返回指定区域的分类汇总结果 111 2.6.5 ROMAN——将阿拉伯数字转为文本型罗马数字 113 2.6.6 ARABIC——将罗马数字转换为阿拉伯数字 114 2.6.7 BASE——将一个数转换为给定基数的文本格式 115 2.6.8 DECIMAL——将给定基数的文本转换为十进制数 116 第3章 日期和时间函数 117 3.1 了解Excel日期系统 118 3.1.1 Excel提供的两种日期系统 118 3.1.2 了解日期和时间序列号 119 3.1.3 输入与设置日期和时间 120 3.1.4 两位数年份问题 121 3.2 返回当前的日期、时间和指定的日期、时间 121 3.2.1 NOW——返回当前日期和时间 121 3.2.2 TODAY——返回当前日期 123 3.2.3 DATE——返回指定日期的序列号 124 3.2.4 TIME——返回指定时间的序列号 125 3.3 返回日期和时间的某个部分 126 3.3.1 YEAR——返回年份 126 3.3.2 MONTH——返回月份 127 3.3.3 DAY——返回日期中具体的某一天 129 3.3.4 WEEKDAY——返回当前日期是星期几 130 3.3.5 HOUR——返回小时数 131 3.3.6 MINUTE——返回分钟数 131 3.3.7 SECOND——返回秒数 132 3.4 文本与日期、时间格式间的转换 133 3.4.1 DATEVALUE——将文本格式的日期转换为序列号 133 3.4.2 TIMEVALUE——将文本格式的时间转换为序列号 134 3.5 其他日期函数 135 3.5.1 DATEDIF——计算开始和结束日期之间的时间间隔 135 3.5.2 DAYS360——以360天为准计算两个日期间天数 136 3.5.3 DAYS——计算两个日期之间的天数 137 3.5.4 EDATE——计算从指定日期向前或向后几个月的日期 138 3.5.5 DATESTRING——将指定日期的序列号转换为文本日期 139 3.5.6 EOMONTH——计算从指定日期向前或向后几个月后的那个月最后一天的日期 140 3.5.7 NETWORKDAYS——计算日期间的所有工作日数 141 3.5.8 NETWORKDAYS.INTL——计算日期间的所有工作日数,使用参数指明周末的日期和天数 142 3.5.9 WEEKNUM——返回日期在一年中是第几周 144 3.5.10 ISOWEEKNUM——返回日期在一年中的ISO周数 145 3.5.11 WORKDAY——计算与指定日期相隔数个工作日的日期 146 3.5.12 WORKDAY.INTL——计算与指定日期相隔数个工作日的日期,使用参数指明周末的日期和天数 147 3.5.13 YEARFRAC——计算从开始日期到结束日期所经历的天数占全年天数的百分比 149 第4章 逻辑函数 151 4.1 逻辑值函数 151 4.1.1 TRUE——返回逻辑值TRUE 151 4.1.2 FALSE——返回逻辑值FALSE 152 4.2 条件判断函数 153 4.2.1 NOT——对逻辑值求反 153 4.2.2 AND——判断多个条件是否同时成立 154 4.2.3 OR——判断多个条件中是否至少有一个条件成立 155 4.2.4 XOR——判断多个条件中是否有一个条件成立 156 4.2.5 IF——根据条件判断而返回不同结果 156 4.2.6 IFNA——判断公式是否出现#N/A错误 158 4.2.7 IFERROR——根据公式结果返回不同内容 158 第5章 文本函数 160 5.1 返回字符或字符编码 162 5.1.1 CHAR——返回与ANSI字符编码对应的字符 162 5.1.2 UNICHAR——返回与Unicode字符编码对应的字符 163 5.1.3 CODE——返回与字符对应的ANSI字符编码 163 5.1.4 UNICODE——返回与字符对应的Unicode字符编码 164 5.2 返回文本内容 165 5.2.1 LEFT——从文本左侧起提取指定个数的字符 165 5.2.2 LEFTB——从文本左侧起提取指定字节数字符 166 5.2.3 LEN——计算文本中的字符个数 167 5.2.4 LENB——计算文本中代表字符的字节数 168 5.2.5 MID——从文本指定位置起提取指定个数的字符 169 5.2.6 MIDB——从文本指定位置起提取指定字节数的字符 170 5.2.7 RIGHT——从文本右侧起提取指定个数的字符 170 5.2.8 RIGHTB——从文本右侧起提取指定字节数字符 171 5.2.9 REPT——生成重复的字符 172 5.3 合并文本 173 5.3.1 CONCATENATE——将多个文本合并到一处 173 5.4 转换文本格式 174 5.4.1 ASC——将全角字符转换为半角字符 174 5.4.2 WIDECHAR——将半角字符转换为全角字符 175 5.4.3 PHONETIC——返回文本中的拼音字符 176 5.4.4 BAHTTEXT——将数字转换为泰语文本 176 5.4.5 DOLLAR——将数字转换为带美元符号$的文本 176 5.4.6 RMB——将数字转换为带人民币符号¥的文本 177 5.4.7 NUMBERSTRING——将数值转换为大汉字 178 5.4.8 NUMBERVALUE——以与区域设置无关的方式将文本转换为数字 179 5.4.9 T——将参数转换为文本 179 5.4.10 LOWER——将文本转换为小 180 5.4.11 UPPER——将文本转换为大 180 5.4.12 PROPER——将文本中每个单词的首字母转换为大 181 5.4.13 VALUE——将文本型数字转换为数值 182 5.4.14 TEXT——多样化格式设置函数 183 5.4.15 FIXED——将数字按指定的小数位数取整 184 5.5 查找与替换文本 185 5.5.1 EXACT——比较两个文本是否相同 185 5.5.2 FIND——以字符为单位并区分大小地查找指定字符的位置 186 5.5.3 FINDB——以字节为单位并区分大小地查找指定字符的位置 187 5.5.4 REPLACE——以字符为单位根据指定位置进行替换 188 5.5.5 REPLACEB——以字节为单位根据指定位置进行替换 189 5.5.6 SEARCH——以字符为单位不区分大小地查找指定字符的位置 189 5.5.7 SEARCHB——以字节为单位不区分大小地查找指定字符的位置 191 5.5.8 SUBSTITUTE——以指定文本进行替换 191 5.6 删除文本中的字符 192 5.6.1 CLEAN——删除无法打印的字符 192 5.6.2 TRIM——删除多余的空格 193 第6章 查找和引用函数 194 6.1 查找表中数据 195 6.1.1 CHOOSE——根据序号从列表中选择对应的内容 195 6.1.2 LOOKUP——仅在单行单列中查找(向量形式) 200 6.1.3 LOOKUP——仅在单行单列中查找(数组形式) 203 6.1.4 HLOOKUP——在区域或数组的行中查找数据 204 6.1.5 VLOOKUP——在区域或数组的列中查找数据 205 6.1.6 MATCH——返回指定内容所在的位置 208 6.1.7 INDEX——返回指定位置中的内容(数组形式) 212 6.1.8 INDEX——返回指定位置中的内容(引用形式) 213 6.2 引用表中数据 214 6.2.1 ADDRESS——返回与指定行号和列号对应的单元格地址 214 6.2.2 AREAS——返回引用中包含的区域数量 217 6.2.3 COLUMN——返回单元格或单元格区域首列的列号 217 6.2.4 COLUMNS——返回数据区域包含的列数 235 6.2.5 ROW——返回单元格或单元格区域首行的行号 219 6.2.6 ROWS——返回数据区域包含的行数 221 6.2.7 OFFSET——根据给定的偏移量返回新的引用区域 223 6.2.8 TRANSPOSE——转置数据区域的行列位置 227 6.2.9 INDIRECT——返回由文本值指定的引用 227 6.2.10 FORMULATEXT——返回给定引用公式的文本形式 229 6.2.11 GETPIVOTDATA——返回数据透视表中的数据 230 6.2.12 HYPERLINK——为指定内容创建超链接 231 6.2.13 RTD——返回支持COM自动化程序的实时数据 233 第7章 信息函数 235 7.1 返回信息 236 7.1.1 CELL——返回单元格格式、位置或内容的信息 236 7.1.2 INFO——返回当前操作环境的相关信息 238 7.1.3 SHEET——返回引用工作表的工作表编号 239 7.1.4 SHEETS——返回引用中的工作表总数 239 7.2 返回各类型的值 240 7.2.1 ERROR.TYPE——返回对应于错误类型的数字 240 7.2.2 N——返回转换为数字的值 241 7.2.3 NA——返回错误值#N/A 242 7.2.4 TYPE——返回表示数据类型的数字 243 7.3 使用IS函数进行各种判断 244 7.3.1 ISBLANK——判断单元格是否为空 244 7.3.2 ISLOGICAL——判断值是否为逻辑值 245 7.3.3 ISNUMBER——判断值是否为数字 245 7.3.4 ISTEXT——判断值是否为文本 246 7.3.5 ISNONTEXT——判断值是否为非文本 246 7.3.6 ISFORMULA——判断单元格是否包含公式 247 7.3.7 ISEVEN——判断数字是否为偶数 248 7.3.8 ISODD——判断数字是否为奇数 249 7.3.9 ISNA——判断值是否为错误值#N/A 249 7.3.10 ISREF——判断值是否为单元格引用 250 7.3.11 ISERR——判断值是否为除#N/A以外的其他错误值 250 7.3.12 ISERROR——判断值是否为错误值 251 第8章 统计函数 252 8.1 统计数量与频率 255 8.1.1 COUNT——计算参数中包含数字的个数 255 8.1.2 COUNTA——计算参数中包含非空值的个数 257 8.1.3 COUNTBLANK——计算区域中空白单元格的个数 259 8.1.4 COUNTIF——计算满足给定条件的单元格的个数 259 8.1.5 COUNTIFS——计算满足多个给定条件的单元格的个数 262 8.1.6 FREQUENCY——以垂直数组形式返回数据的频率分布 263 8.2 统计均值和众数 264 8.2.1 AVEDEV——计算一组数据与其平均值的绝对偏差的平均值 264 8.2.2 AVERAGE——计算参数的平均值 265 8.2.3 AVERAGEA——计算参数中非空值的平均值 266 8.2.4 AVERAGEIF——计算满足给定条件的所有单元格的平均值 267 8.2.5 AVERAGEIFS——计算满足多个给定条件的所有单元格的平均值 268 8.2.6 GEOMEAN——计算几何平均值 269 8.2.7 HARMEAN——计算调和平均值 270 8.2.8 TRIMMEAN——计算内部平均值 271 8.2.9 MEDIAN——返回中值 272 8.2.10 MODE.SNGL——返回数据中出现次数最多的值 273 8.2.11 MODE.MULT——返回数据中出现频率最高或重复出现的数值的垂直数组 275 8.3 统计极值与排位 276 8.3.1 MAX——返回一组数字中的最大值 276 8.3.2 MAXA——返回一组非空值中的最大值 277 8.3.3 MIN——返回一组数字中的最小值 278 8.3.4 MINA——返回一组非空值中的最小值 279 8.3.5 LARGE——返回数据集中第k个最大值 279 8.3.6 SMALL——返回数据集中第k个最小值 280 8.3.7 RANK.EQ——返回一个数字在一组数字中的排位 281 8.3.8 RANK.AVG——返回一个数字在一组数字中的排位 282 8.3.9 PERCENTRANK.INC——返回数据集中值的百分比排位 283 8.3.10 PERCENTRANK.EXC——返回数据集中值的百分比排位 284 8.3.11 QUARTILE.INC——返回数据集的四分位数 285 8.3.12 QUARTILE.EXC——返回数据集的四分位数 286 8.3.13 PERCENTILE.INC——返回区域中数值的第k个百分点的值 287 8.3.14 PERCENTILE.EXC——返回区域中数值的第k个百分点的值 288 8.3.15 PERMUT——返回给定数目对象的排列数 288 8.3.16 PERMUTATIONA——返回给定数目对象(含重复)的排列数 289 8.4 统计数据的散布度 290 8.4.1 DEVSQ——计算偏差的平方和 290 8.4.2 STDEV.S——估算基于样本的标准偏差,忽略文本和逻辑值 290 8.4.3 STDEVA——估算基于样本的标准偏差,包括文本和逻辑值 291 8.4.4 STDEV.P——估算基于整个样本总体的标准偏差,忽略文本和逻辑值 292 8.4.5 STDEVPA——估算基于整个样本总体的标准偏差,包括文本和逻辑值 293 8.4.6 VAR.S——计算基于给定样本的方差,忽略文本和逻辑值 294 8.4.7 VARA——计算基于给定样本的方差,包括文本和逻辑值 295 8.4.8 VAR.P——计算基于整个样本总体的方差,忽略文本和逻辑值 296 8.4.9 VARPA——计算基于整个样本总体的方差,包括文本和逻辑值 297 8.4.10 KURT——返回数据集的峰值 298 8.4.11 SKEW——返回分布的不对称度 299 8.4.12 SKEW.P——返回某一分布相对其平均值的不对称度 300 8.5 统计概率分布 300 8.5.1 BINOM.DIST——返回一元二项式分布的概率 300 8.5.2 BINOM.INV——返回使累积二项式分布小于或等于临界值的最小值 301 8.5.3 BINOM.DIST.RANGE——返回二项式分布试验结果的概率 302 8.5.4 NEGBINOM.DIST——返回负二项式分布的概率 303 8.5.5 PROB——返回区域中的数值落在指定区间内的概率 304 8.5.6 GAUSS——返回比标准正态累积分布函数小0.5的值 305 8.5.7 PHI——返回标准正态分布的密度函数值 306 8.5.8 NORM.DIST——返回正态累积分布函数 306 8.5.9 NORM.INV——返回标准正态累积分布的反函数值 307 8.5.10 NORM.S.DIST——返回标准正态累积分布函数 308 8.5.11 NORM.S.INV——返回标准正态累积分布函数的反函数值 309 8.5.12 STANDARDIZE——返回正态化数值 310 8.5.13 LOGNORM.DIST——返回对数累积分布函数 311 8.5.14 LOGNORM.INV——返回对数累积分布函数的反函数 312 8.5.15 HYPGEOM.DIST——返回超几何分布 313 8.5.16 POISSON.DIST——返回泊松分布 314 8.5.17 EXPON.DIST——返回指数分布 315 8.5.18 WEIBULL.DIST——返回韦伯分布 316 8.5.19 GAMMA——返回伽玛函数值 317 8.5.20 GAMMA.DIST——返回伽玛分布函数 318 8.5.21 GAMMA.INV——返回伽玛累积分布函数的反函数值 319 8.5.22 GAMMALN——返回伽玛函数的自然对数 320 8.5.23 GAMMALN.PRECISE——返回伽玛函数的自然对数 320 8.5.24 BETA.DIST——返回β累积分布函数 321 8.5.25 BETA.INV——返回指定β累积分布函数的反函数值 322 8.5.26 CONFIDENCE.NORM——返回总体平均值的置信区间 323 8.5.27 CONFIDENCE.T——返回总体平均值的置信区间 324 8.6 检验数据的倾向性 325 8.6.1 CHISQ.DIST.RT——返回x2分布的右尾概率 325 8.6.2 CHISQ.DIST——返回x2分布 326 8.6.3 CHISQ.INV.RT——返回x2分布的右尾概率的反函数值 326 8.6.4 CHISQ.INV——返回x2分布的左尾概率的反函数值 327 8.6.5 CHISQ.TEST——返回独立性检验值 328 8.6.6 F.DIST.RT——返回F概率分布 329 8.6.7 F.DIST——返回F概率分布 330 8.6.8 F.INV.RT——返回F概率分布的反函数值 330 8.6.9 F.INV——返回F概率分布的反函数值 331 8.6.10 T.DIST.2T——返回t分布的双尾概率 332 8.6.11 T.DIST.RT——返回t分布的右尾概率 333 8.6.12 T.DIST——返回t分布 333 8.6.13 T.INV.2T——返回t分布的双尾反函数值 334 8.6.14 T.INV——返回t分布的左尾反函数值 335 8.6.15 F.TEST——返回F检验的结果 335 8.6.16 T.TEST——返回与t检验相关的概率 336 8.6.17 Z.TEST——返回z检验的单尾概率 337 8.7 统计协方差、相关系数与回归 338 8.7.1 COVARIANCE.P——计算总体协方差,即成对偏差乘积的平均值 338 8.7.2 COVARIANCE.S——计算样本协方差,即成对偏差乘积的平均值 339 8.7.3 CORREL——返回两个数据集之间的相关系数 340 8.7.4 FISHER——返回Fisher变换值 340 8.7.5 FISHERINV——返回Fisher变换的反函数值 341 8.7.6 PEARSON——返回皮尔生乘积矩相关系数 342 8.7.7 RSQ——返回皮尔生乘积矩相关系数的平方 343 8.7.8 FORECAST——根据现有的数据计算或预测未来值 344 8.7.9 GROWTH——根据现有的数据计算或预测指数增长值 345 8.7.10 TREND——计算一条线性回归线的值 346 8.7.11 LINEST——返回线性回归线的参数 347 8.7.12 LOGEST——返回指数回归线的参数 348 8.7.13 SLOPE——返回线性回归线的斜率 349 8.7.14 INTERCEPT——返回线性回归线的截距 350 8.7.15 STEYX——返回通过线性回归法预测每个x的y值时所产生的标准误差 351 第9章 财务函数 352 9.1 了解货币的时间价值 354 9.2 计算本金和利息 355 9.2.1 PMT——计算贷款的每期付款额 355 9.2.2 IPMT——计算贷款在给定期间内支付的利息 356 9.2.3 PPMT——计算贷款在给定期间内偿还的本金 357 9.2.4 ISPMT——计算特定投资期内支付的利息 358 9.2.5 CUMIPMT——计算两个付款期之间累积支付的利息 358 9.2.6 CUMPRINC——计算两个付款期之间累积支付的本金 360 9.2.7 EFFECT——将名义年利率转换为实际年利率 361 9.2.8 NOMINAL——将实际年利率转换为名义年利率 362 9.2.9 RATE——计算年金的各期利率 362 9.3 计算投资预算 363 9.3.1 FV——计算一笔投资的未来值 363 9.3.2 FVSCHEDULE——使用一系列复利率计算初始本金的未来值 364 9.3.3 NPER——计算投资的期数 365 9.3.4 PDURATION——计算投资到达指定值所需的期数 366 9.3.5 PV——计算投资的现值 367 9.3.6 NPV——基于一系列定期的现金流和贴现率计算投资的净现值 367 9.3.7 XNPV——计算一组未必定期发生的现金流的净现值 368 9.3.8 RRI——计算某项投资增长的等效利率 369 9.4 计算收益率 370 9.4.1 IRR——计算一系列现金流的内部收益率 370 9.4.2 MIRR——计算正负现金流在不同利率下支付的内部收益率 371 9.4.3 XIRR——计算一组未必定期发生的现金流的内部收益率 372 9.5 计算折旧值 373 9.5.1 AMORDEGRC——根据资产的耐用年限,计算每个结算期间的折旧值 373 9.5.2 AMORLINC——计算每个结算期间的折旧值 374 9.5.3 DB——使用固定余额递减法,计算一笔资产在给定期间内的折旧值 375 9.5.4 DDB——使用双倍余额递减法或其他指定方法,计算一笔资产在给定期间内的折旧值 376 9.5.5 VDB——使用余额递减法,计算一笔资产在给定期间或部分期间内的折旧值 377 9.5.6 SYD——计算某项资产按年限总和折旧法计算的指定期间的折旧值 378 9.5.7 SLN——计算某项资产在一个期间内的线性折旧值 379 9.6 计算证券与国库券 379 9.6.1 ACCRINT——计算定期支付利息的有价证券的应计利息 379 9.6.2 ACCRINTM——计算在到期日支付利息的有价证券的应计利息 380 9.6.3 COUPDAYBS——计算当前付息期内截止到成交日的天数 382 9.6.4 COUPDAYS——计算成交日所在的付息期的天数 383 9.6.5 COUPDAYSNC——计算从成交日到下一个付息日之间的天数 384 9.6.6 COUPNCD——计算成交日之后的下一个付息日 385 9.6.7 COUPNUM——计算成交日和到期日之间的应付利息次数 386 9.6.8 COUPPCD——计算成交日之前的上一付息日 387 9.6.9 DISC——计算有价证券的贴现率 389 9.6.10 DURATION——计算定期支付利息的有价证券的修正期限 390 9.6.11 PRICE——计算定期付息的面值¥100的有价证券的价格 391 9.6.12 PRICEDISC——计算折价发行的面值¥100的有价证券的价格 392 9.6.13 PRICEMAT——计算到期付息的面值¥100的有价证券的价格 393 9.6.14 ODDFPRICE——计算首期付息日不固定的面值¥100的有价证券价格 395 9.6.15 ODDFYIELD——计算首期付息日不固定的有价证券的收益率 396 9.6.16 ODDLPRICE——计算末期付息日不固定的面值¥100的有价证券价格 397 9.6.17 ODDLYIELD——计算末期付息日不固定的有价证券的收益率 399 9.6.18 MDURATION——计算假设面值为¥100的有价证券的Macauley修正期限 400 9.6.19 INTRATE——计算一次性付息证券的利率 401 9.6.20 RECEIVED——计算一次性付息的有价证券到期收回的金额 403 9.6.21 TBILLEQ——计算国库券的等价债券收益 404 9.6.22 TBILLPRICE——计算面值¥100的国库券的价格 405 9.6.23 TBILLYIELD——计算国库券的收益率 406 9.6.24 YIELD——计算定期支付利息的有价证券的收益率 406 9.6.25 YIELDDISC——计算折价发行的有价证券的年收益率 408 9.6.26 YIELDMAT——计算到期付息的有价证券的年收益率 409 9.7 转换美元价格的格式 410 9.7.1 DOLLARDE——将以分数表示的美元价格转换为以小数表示的美元价格 410 9.7.2 DOLLARFR——将以小数表示的美元价格转换为以分数表示的美元价格 411 第10章 工程函数 412 10.1 比较数据函数 414 10.1.1 DELTA——测试两个值是否相等 414 10.1.2 GESTEP——测试某个值是否大于等于阈值 415 10.2 转换数制 416 10.2.1 BIN2OCT——将二进制数转换为八进制数 416 10.2.2 BIN2DEC——将二进制数转换为十进制数 417 10.2.3 BIN2HEX——将二进制数转换为十六进制数 418 10.2.4 OCT2BIN——将八进制数转换为二进制数 419 10.2.5 OCT2DEC——将八进制数转换为十进制数 420 10.2.6 OCT2HEX——将八进制数转换为十六进制数 420 10.2.7 DEC2BIN——将十进制数转换为二进制数 421 10.2.8 DEC2OCT——将十进制数转换为八进制数 422 10.2.9 DEC2HEX——将十进制数转换为十六进制数 423 10.2.10 HEX2BIN——将十六进制数转换为二进制数 424 10.2.11 HEX2OCT——将十六进制数转换为八进制数 425 10.2.12 HEX2DEC——将十六进制数转换为十进制数 426 10.3 计算复数 427 10.3.1 COMPLEX——将实系数和虚系数转换为复数 427 10.3.2 IMREAL——返回复数的实系数 427 10.3.3 IMAGINARY——返回复数的虚系数 428 10.3.4 IMCONJUGATE——返回复数的共轭复数 429 10.3.5 IMABS——计算复数的绝对值(模数) 429 10.3.6 IMPOWER——计算复数的整数幂 430 10.3.7 IMSQRT——计算复数的平方根 431 10.3.8 IMARGUMENT——返回以弧度表示的角 432 10.3.9 IMEXP——计算复数的指数 432 10.3.10 IMLN——计算复数的自然对数 433 10.3.11 IMLOG10——计算复数以10为底的对数 433 10.3.12 IMLOG2——计算复数以2为底的对数 434 10.3.13 IMSUM——计算多个复数的总和 435 10.3.14 IMSUB——计算两个复数的差 435 10.3.15 IMPRODUCT——计算多个复数的乘积 436 10.3.16 IMDIV——计算两个复数的商 437 10.3.17 IMSIN——计算复数的正弦值 437 10.3.18 IMSINH——计算复数的双曲正弦值 438 10.3.19 IMCOS——计算复数的余弦值 439 10.3.20 IMCOSH——计算复数的双曲余弦值 440 10.3.21 IMTAN——计算复数的正切值 440 10.3.22 IMSECH——计算复数的双曲正切值 441 10.3.23 IMCOT——计算复数的余切值 442 10.3.24 IMSEC——计算复数的正割值 442 10.3.25 IMCSC——计算复数的余割值 443 10.3.26 IMCSCH——计算复数的双曲余割值 444 10.4 其他工程函数 445 10.4.1 CONVERT——将数字从一种度量系统转换为另一种度量系统 445 10.4.2 BESSELJ——返回贝赛尔函数Jn(x) 446 10.4.3 BESSELY——返回贝赛尔函数Yn(x) 447 10.4.4 BESSELI——返回修正的贝赛尔函数In(x) 448 10.4.5 BESSELK——返回修正的贝赛尔函数Kn(x) 449 10.4.6 ERF——返回误差函数 450 10.4.7 ERF.PRECISE——返回误差函数 450 10.4.8 ERFC——返回补余误差函数 451 10.4.9 ERFC.PRECISE——返回补余误差函数 451 10.4.10 BITAND——返回两个数按位“与”的结果 452 10.4.11 BITOR——返回两个数按位“或”的结果 453 10.4.12 BITXOR——返回两个数按位“异或”的结果 454 10.4.13 BITLSHIFT——返回向左移动指定位数后的值 455 10.4.14 BITRSHIFT——返回向右移动指定位数后的值 456 第11章 数据库函数 458 11.1 计算数据库中的数据 458 11.1.1 DPRODUCT——计算满足条件的数字的乘积 458 11.1.2 DSUM——计算满足条件的数字的总和 460 11.2 对数据库中的数据进行常规统计 461 11.2.1 DAVERAGE——计算满足条件的数值的平均值 461 11.2.2 DCOUNT——计算满足条件的包含数字的单元格的个数 463 11.2.3 DCOUNTA——计算满足条件的非空单元格的个数 464 11.2.4 DGET——返回符合条件的单个值 465 11.2.5 DMAX——返回满足条件的列表中的最大值 467 11.2.6 DMIN——返回满足条件的列表中的最小值 468 11.3 对数据库中的数据进行散布度统计 469 11.3.1 DSTDEV——返回满足条件的数字作为一个样本估算出的样本标准偏差 469 11.3.2 DSTDEVP——返回满足条件的数字作为样本总体计算出的总体标准偏差 471 11.3.3 DVAR——返回满足条件的数字作为一个样本估算出的样本总体方差 472 11.3.4 DVARP——返回满足条件的数字作为样本总体计算出的总体方差 473 第12章 Web函数与宏表函数 475 12.1 Web函数 475 12.1.1 ENCODEURL——将文本转换为URL编码 475 12.1.2 WEBSERVICE——从Web服务中获取网络数据 476 12.1.3 FILTERXML——在XML结构化内容中获取指定路径下的信息 476 12.2 宏表函数 477 12.2.1 GET.WORKBOOK——返回工作簿的相关信息 477 12.2.2 GET.CELL——返回单元格的相关信息 478 12.2.3 EVALUATE——计算包含文本的表达式的值 480 第13章 在条件格式中使用公式 482 13.1 条件格式简介 482 13.2 在条件格式中公式的使用 483 13.2.1 创建基于公式的条件格式的原则 483 13.2.2 条件格式公式示例 485 第14章 在数据验证中使用公式 489 14.1 数据验证简介 489 14.2 在数据验证中公式的使用 491 14.2.1 创建基于公式的数据验证的原则 491 14.2.2 数据验证公式示例 491 第15章 在图表中使用公式 496 15.1 图表简介 496 15.1.1 图表类型 496 15.1.2 图表元素 501 15.1.3 创建图表 502 15.1.4 图表在工作簿中的位置 504 15.2 使用公式与控件创建动态图表 505 15.2.1 在图表中使用公式 505 15.2.2 在图表中使用控件 505 15.2.3 了解数据系列的SERIES公式 506 15.2.4 动态图表示例 507 附录1 Excel快捷键 518 1.工作簿基本操作的快捷键 518 2.在工作表中移动和选择的快捷键 518 3.在工作表中编辑的快捷键 519 4.在工作表中设置格式的快捷键 521 附录2 Excel函数速查表 522 1.逻辑函数 522 2.信息函数 522 3.文本函数 523 4.数学和三角函数 523 5.统计函数 526 6.查找和引用函数 529 7.日期和时间函数 529 8.财务函数 530 9.工程函数 532 10.数据库函数 533 11.多维数据集函数 534 12.Web函数 534 13.加载宏和自动化函数 534 14.兼容性函数 534
dw2xls已升级至pb11.5 dw2xls已经开发了好几年了,最近也把这个程序开源了,由于自已一直以来都是用pb9开发程序,还没有升级到更高的版本,所以一直都没去 升级这个程序.这两年经常会收到一些朋友的来信,询问如何把dw2xls升级到pb10或以上更高的版本,甚至部分用反编译程序的朋友,为了这个功能,都 愿意付费购买.考虑到一些朋友在升级过程中,还是会碰过一些困难,为了方便大家,所以决定还是自已把程序升级到pb11.5,并提供给大家下载.如果使用 pb10, pb10.5, pb11版本的朋友,请使用开发工具直接进行升级,然后再把附件中的n_cst_unicode.sru, n_cst_dw2excel.sru两个文件,导入到dw2xls.pbl文件即可. 在这里,随便说一下pb10以下版本的程序,如果升级到pb10以上版本,需要注意的地方: PB10 以下版本的程序,字符串使用的ANSI编码,pb10或以上版本,使用的是Unicode编码,所以在API函数定义上,会有些出入.大部分在参数或返回 值中使用了字符串的Windows API函数,都提供了两个版本的API,一个是支持ANSI的,一般在函数后面加个A作为标记,一个是支持Unicode的,一般在函数后面加 W(WideChar)作为标记.如GetWindowTextA和GetWindowTextW,所以在pb9时,定义API函数一般使用的是ANSI 版本(因为PB9使用的是ANSI编码),如果是升级到PB10或以后版本,则可以把API函数定义为使用Unicode版本即可,而不是使用PB程序直 接升级的那样,继续采用Ansi版本. 此外,PB在定义Windows Api时,大小是敏感的,这个跟PBScript不同,也是需要注意的地方.
说明 一、受限制库Dll和lib说明: 库文件G-TcpServer.lib、G-TcpServer.Dll是受限制的试用版本和Demo配套。 1、最大连接不能超过50 2、发送字节数不能超过50 3、不能设置0读投递、无超时机制 4、其他功能限制 二、版本解读说明 1、版本名带T的表示是受限制的试用版 2、版本名带bata表示非正式版 3、版本名带WChar表示支持WideChar 4、版本号以时间格式累加计数(60进1)和显示 三、文件“G-TcpServer无限制体验版.exe”是无限制的体验版。 四、文件夹 1、Demos文件夹是VC Lib、Dll库及Delphi2010的例程源码,供开发学习 2、G-Sockets文件夹是Lib和Dll库的Delphi和VC的头文件 3、Release\G-Sockets\Dll文件夹是动态库的输出文件夹 4、Release\G-Sockets\Lib文件夹是静态库的输出文件夹 1、模块包含处理线程、工作线程和看守线程。 工作线程负责IO投递工作,并响应投递返回,再把接收的数据投递给处理线程,处理线程调用回调函数给应用层,以此可以在通讯层和应用层之间现实0拷贝数据的功能。模块只有一个看守线程,负责:a、响应Accept事件并投递接受队列;b、效验接受超时(即只连接不发数据)断开连接,防止空连接;c、效验空闲超时(即心跳超时)断开连接。 按工作量来分,最繁重的是处理线程,其次是工作线程,最闲的是看守线程。可通过OnThread事件回调函数设置线程权限。在此线程模式下,应用层可以在回调函数里处理数据而不必再建立另外的数据处理线程池。 2、线程平衡 为使连接能平衡使用处理线程,每个连接同时只有一个处理线程处理工作线程投递过来的IO返回事件并调用回调函数通知应用层。 3、收发平衡 为使连接能平衡使用IO设备,每个连接同时只能投递一个读请求,并通过线程平衡机制保证接收的数据是按顺序的被处理线程处理及通过回调函数传递给应用层;同时也只能投递一个请求,其余请求都按顺序放在队列里面。读同步都使用临界段。 4、0拷贝技术 接收数据0拷贝看1项;提供GTcpSvr_AllocGBuf()、GTcpSvr_FreeGBuf()和GTcpSvr_PostSendGBuf()三个函数实现发送数据的0拷贝。 5、0读投递 为避免内核锁定分页内存过多,可通过设置来采用0读投递来降低吞吐性能从而实现大连接量。 6、HndData回收 HndData回收有多种方法,但额外会在收发数据这两个频率操作上增加工作量,因此尽量避免在这两个操作时做太多的工作是有必要的。模块均不采用“投递计数”或“投递链表”的方式来判断回收HndData的时机,而是一旦断线立即回收,其他未决投递继续返回时只处理IoData,不对HndData做任何操作。同时为避免HndData刚收回来但其未决投递还没有完全返回之前就立即被利用的可能性,HndData池采用了FIFO双锁并发链表,该链表通过ExNumber值来实现在最大连接情况下HndData池还有ExNumber个数量使链表不为NULL,通过设置ExNumber数量可实现控制链表末端的HndData出列时间,在这个时间内可以保证断开刚回收的HndData的未决投递能够完全返回。 HndData池,初始时如下: HD1 + HD2 + HD... + HDMaxConnection + HDEx1 + HDEx2 + HDEx... + HDExNumber | | Head------------------------------------------------------------------Tail 达到最大连接时如下: HDEx1 + HDEx2 + HDEx... + HDExNumber | | Head---------------------------Tail 断开回收一个HndData(HD)后如下: HDEx1 + HDEx2 + HDEx... + HDExNumber + HD | | Head-------(需要T时间HD才能出列)------Tail 注:T可以通过控制ExNumber值来实现,假定每秒最大可以处理C个连接和断开,需要延时T秒所有未决投递才会完全回收,那么:ExNumber = T * (MaxConnection / C)。实际上每个连接未决投递非常少(因为读是单投递的),并且工作线程并不处理数据工作量不大,因此T很短,模块默认是3秒。对于服务器而已,一秒能接受的连接量是可知预计的,模块默认是1万,假定MaxConnection=C所以ExNumber是3万。但实际应用中,正常情况下连接率远少于1万/S,尤其是长连接的服务器,即使是短连接的服务器也不会发生这样的连接率。可能的情况是DOS,如果是影响也不大,因为还有MaxConnection控制,超过这个数的连接就立即被CloseSocket了。和频率高的数据收发相比,断线、连接的频率远少于它,在频率低的地方上多做多点工作总比在频率高的地方多做一点工作的好。 7、可伸缩性 IoData数量可根据初始需要设置,资源不足时模块自动向系统申请内存。为保证HndData的安全性,HndData池还设置了延时出列,刚回收的HndData入列时间必须超过3(或更长)秒钟,如果未达到3秒的,模块自动向系统申请内存。 8、内存管理 IoData和HndData均采用VirtualAlloc和VirtualFree来向系统操作内存。IoData池采用原子函数InterlockedCompareExchange来操作进出栈。HndData采用单向FIFO双锁并发链表来管理出入列操作。其他小内存需求的均采用静态数组或new操作。 五、内存需求 每个IoData等于一个分页内存大小,信息头大小为36Byte,有效使用内存是4060Byte,因此对GTcpSvr_AllocGBuf获得的内存入时不应该超过4060(调用GTcpSvr_GetGbufSize获得),所有IoData占用系统内存是:IoDataCount * PageSize(4096)。每个HndData大小是128Byte,加上每个Socket分配时耗内存约是:540Bytes(此为估计值,应以MS技术文档为准),所有HndData耗系统内存是:HndDataCount * MAX_HNDDATA_AND_SOCKET_SIZE(128 + 540)。其他变量和数组可能耗得内存在10M之下。 综上,整个模块需求内存量是:UseMemSize = IoDataCount * PageSize + HndDataCount * MAX_HNDDATA_AND_SOCKET_SIZE + 10M。
说明 一、本压缩包含: 1、Demo源码,位于:\Demos\G-TcpServerLibDemo\G-TcpServerLibDemo.vcproj 2、G-TcpServer模块头文件文件,位于:\G-Sockets\G-TcpServer.h(模块核心文件) 3、G-TcpServer模块Lib文件,位于:\G-Sockets\G-TcpServer.lib(模块核心文件) 4、无限制Demo exe文件:G-TcpServerLibDemo1.0.exe 二、受限制库G-TcpServer.lib说明: 库文件G-TcpServer.lib是受限制的试用版本和Demo配套。 1、最大连接不能超过100 2、发送字节数不能超过128 3、不能设置0读投递 4、其他功能限制 三、版本解读说明 1、版本名带T的表示是受限制的试用版,参阅二 2、版本名带bata表示非正式版 3、版本名带WChar表示支持WideChar 4、版本号以时间格式累加计数(60进1)和显示 四、技术说明 1、模块包含处理线程、工作线程和看守线程。 工作线程负责IO投递工作,并响应投递返回,再把接收的数据投递给处理线程,处理线程调用回调函数给应用层,以此可以在通讯层和应用层之间现实0拷贝数据的功能。模块只有一个看守线程,负责:a、响应Accept事件并投递接受队列;b、效验接受超时(即只连接不发数据)断开连接,防止空连接;c、效验空闲超时(即心跳超时)断开连接。 按工作量来分,最繁重的是处理线程,其次是工作线程,最闲的是看守线程。可通过OnThread事件回调函数设置线程权限。在此线程模式下,应用层可以在回调函数里处理数据而不必再建立另外的数据处理线程池。 2、线程平衡 为使连接能平衡使用处理线程,每个连接同时只有一个处理线程处理工作线程投递过来的IO返回事件并调用回调函数通知应用层。 3、收发平衡 为使连接能平衡使用IO设备,每个连接同时只能投递一个读请求,并通过线程平衡机制保证接收的数据是按顺序的被处理线程处理及通过回调函数传递给应用层;同时也只能投递一个请求,其余请求都按顺序放在队列里面。读同步都使用临界段。 4、0拷贝技术 接收数据0拷贝看1项;提供GTcpSvr_AllocGBuf()、GTcpSvr_FreeGBuf()和GTcpSvr_PostSendGBuf()三个函数实现发送数据的0拷贝。 5、0读投递 为避免内核锁定分页内存过多,可通过设置来采用0读投递来降低吞吐性能从而实现大连接量。 6、HndData回收 HndData回收有多种方法,但额外会在收发数据这两个频率操作上增加工作量,因此尽量避免在这两个操作时做太多的工作是有必要的。模块均不采用“投递计数”或“投递链表”的方式来判断回收HndData的时机,而是一旦断线立即回收,其他未决投递继续返回时只处理IoData,不对HndData做任何操作。同时为避免HndData刚收回来但其未决投递还没有完全返回之前就立即被利用的可能性,HndData池采用了FIFO双锁并发链表,该链表通过ExNumber值来实现在最大连接情况下HndData池还有ExNumber个数量使链表不为NULL,通过设置ExNumber数量可实现控制链表末端的HndData出列时间,在这个时间内可以保证断开刚回收的HndData的未决投递能够完全返回。 HndData池,初始时如下: HD1 + HD2 + HD... + HDMaxConnection + HDEx1 + HDEx2 + HDEx... + HDExNumber | | Head------------------------------------------------------------------Tail 达到最大连接时如下: HDEx1 + HDEx2 + HDEx... + HDExNumber | | Head---------------------------Tail 断开回收一个HndData(HD)后如下: HDEx1 + HDEx2 + HDEx... + HDExNumber + HD | | Head-------(需要T时间HD才能出列)------Tail
远程注入DLL方法有很多种,也是很多木马病毒所使用的隐藏进程的方法,因为通过程序加载的DLL在进程管理器是没有显示的.这里介绍一种用 CreateRemoteThread 远程建立线程的方式注入DLL. 首先,我们要提升自己的权限,因为远程注入必不可免的要访问到目标进程的内存空间,如果没有足够的系统权限,将无法作任何事.下面是这个函数是用来提升我们想要的权限用的. function EnableDebugPriv: Boolean; var hToken: THandle; tp: TTokenPrivileges; rl: Cardinal; begin Result := false; //打开进程令牌环 OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, hToken); //获得进程本地唯一ID if LookupPrivilegeValue(nil, 'SeDebugPrivilege', tp.Privileges[0].Luid) then begin tp.PrivilegeCount := 1; tp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED; //调整权限 Result := AdjustTokenPrivileges(hToken, false, tp, SizeOf(tp), nil, rl); end; end; 关于 OpenProcessToken() 和 AdjustTokenPrivileges() 两个 API 的简单介绍: OpenProcessToken():获得进程访问令牌的句柄. function OpenProcessToken( ProcessHandle: THandle; //要修改访问权限的进程句柄 DesiredAccess: DWORD; //指定你要进行的操作类型 var TokenHandle: THandle//返回的访问令牌指针 ): BOOL; AdjustTokenPrivileges() :调整进程的权限. function AdjustTokenPrivileges( TokenHandle: THandle; // 访问令牌的句柄 DisableAllPrivileges: BOOL; // 决定是进行权限修改还是除能(Disable)所有权限 const NewState: TTokenPrivileges; { 指明要修改的权限,是一个指向TOKEN_PRIVILEGES结构的指针,该结构包含一个数组, 数据组的每个项指明了权限的类型和要进行的操作; } BufferLength: DWORD; //结构PreviousState的长度,如果PreviousState为空,该参数应为 0 var PreviousState: TTokenPrivileges; // 指向TOKEN_PRIVILEGES结构的指针,存放修改前的访问权限的信息 var ReturnLength: DWORD //实际PreviousState结构返回的大小 ) : BOOL; 远程注入DLL其实是通过 CreateRemoteThread 建立一个远程线程调用 LoadLibrary 函数来加载我们指定的DLL,可是如何能让远程线程知道我要加载DLL呢,要知道在Win32系统下,每个进程都拥有自己的4G虚拟地址空间,各个进程之间都是相互独立的。所我们需要在远程进程的内存空间里申请一块内存空间,入我们的需要注入的 DLL 的路径. 需要用到的 API 函数有: OpenProcess():打开目标进程,得到目标进程的操作权限,详细参看MSDN function OpenProcess( dwDesiredAccess: DWORD; // 希望获得的访问权限 bInheritHandle: BOOL; // 指明是否希望所获得的句柄可以继承 dwProcessId: DWORD // 要访问的进程ID ): THandle; VirtualAllocEx():用于在目标进程内存空间中申请内存空间以入DLL的文件名 function VirtualAllocEx( hProcess: THandle; // 申请内存所在的进程句柄 lpAddress: Pointer; // 保留页面的内存地址;一般用nil自动分配 dwSize, // 欲分配的内存大小,字节单位;注意实际分 配的内存大小是页内存大小的整数倍 flAllocationType: DWORD; flProtect: DWORD ): Pointer; WriteProcessMemory():往申请到的空间中入DLL的文件名 function WriteProcessMemory( hProcess: THandle; //要入内存数据的目标进程句柄 const lpBaseAddress: Pointer; //要入的目标进程的内存指针, 需以 VirtualAllocEx() 来申请 lpBuffer: Pointer; //要入的数据 nSize: DWORD; //入数据的大小 var lpNumberOfBytesWritten: DWORD //实际入的大小 ): BOOL; 然后就可以调用 CreateRemoteThread 建立远程线程调用 LoadLibrary 函数来加载我们指定的DLL. CreateRemoteThread() //在一个远程进程中建立线程 function CreateRemoteThread( hProcess: THandle; //远程进程的句柄 lpThreadAttributes: Pointer; //线程安全描述字,指向SECURITY_ATTRIBUTES结构的指针 dwStackSize: DWORD; //线程栈大小,以字节表示 lpStartAddress: TFNThreadStartRoutine; // 一个TFNThreadStartRoutine类型的指针,指向在远程进程中执行的函数地址 lpParameter: Pointer; //传入参数的指针 dwCreationFlags: DWORD; //创建线程的其它标志 var lpThreadId: DWORD //线程身份标志,如果为0, 则不返回 ): THandle; 整个远程注入DLL的具体实现代码如下: function InjectDll(const DllFullPath: string; const dwRemoteProcessId: Cardinal): Boolean; var hRemoteProcess, hRemoteThread: THandle; pszLibFileRemote: Pointer; pszLibAFilename: PwideChar; pfnStartAddr: TFNThreadStartRoutine; memSize, WriteSize, lpThreadId: Cardinal; begin Result := false; // 调整权限,使程序可以访问其他进程的内存空间 if EnableDebugPriv then begin //打开远程线程 PROCESS_ALL_ACCESS 参数表示打开所有的权限 hRemoteProcess := OpenProcess(PROCESS_ALL_ACCESS, false, dwRemoteProcessId); try // 为注入的dll文件路径分配内存大小,由于为WideChar,故要乘2 GetMem(pszLibAFilename, Length(DllFullPath) * 2 + 1); // 之所以要转换成 WideChar, 是因为当DLL位于有中文字符的路径下时不会出错 StringToWideChar(DllFullPath, pszLibAFilename, Length(DllFullPath) * 2 + 1); // 计算 pszLibAFilename 的长度,注意,是以字节为单元的长度 memSize := (1 + lstrlenW(pszLibAFilename)) * SizeOf(WCHAR); //使用VirtualAllocEx函数在远程进程的内存地址空间分配DLL文件名空间 pszLibFileRemote := VirtualAllocEx(hRemoteProcess, nil, memSize, MEM_COMMIT, PAGE_READWRITE); if Assigned(pszLibFileRemote) then begin //使用WriteProcessMemory函数将DLL的路径名入到远程进程的内存空间 if WriteProcessMemory(hRemoteProcess, pszLibFileRemote, pszLibAFilename, memSize, WriteSize) and (WriteSize = memSize) then begin lpThreadId := 0; // 计算LoadLibraryW的入口地址 pfnStartAddr := GetProcAddress(LoadLibrary('Kernel32.dll'), 'LoadLibraryW'); // 启动远程线程LoadLbraryW,通过远程线程调用创建新的线程 hRemoteThread := CreateRemoteThread(hRemoteProcess, nil, 0, pfnStartAddr, pszLibFileRemote, 0, lpThreadId); // 如果执行成功返回 True; if (hRemoteThread 0) then Result := true; // 释放句柄 CloseHandle(hRemoteThread); end; end; finally // 释放句柄 CloseHandle(hRemoteProcess); end; end; end; 接下来要说的是如何卸载注入目标进程中的DLL,其实原理和注入DLL是完全相同的,只是远程调用调用的函数不同而已,这里要调用的是FreeLibrary,代码如下: function UnInjectDll(const DllFullPath: string; const dwRemoteProcessId: Cardinal): Boolean; // 进程注入和取消注入其实都差不多,只是运行的函数不同而已 var hRemoteProcess, hRemoteThread: THandle; pszLibFileRemote: PChar; pszLibAFilename: PwideChar; pfnStartAddr: TFNThreadStartRoutine; memSize, WriteSize, lpThreadId, dwHandle: Cardinal; begin Result := false; // 调整权限,使程序可以访问其他进程的内存空间 if EnableDebugPriv then begin //打开远程线程 PROCESS_ALL_ACCESS 参数表示打开所有的权限 hRemoteProcess := OpenProcess(PROCESS_ALL_ACCESS, false, dwRemoteProcessId); try // 为注入的dll文件路径分配内存大小,由于为WideChar,故要乘2 GetMem(pszLibAFilename, Length(DllFullPath) * 2 + 1); // 之所以要转换成 WideChar, 是因为当DLL位于有中文字符的路径下时不会出错 StringToWideChar(DllFullPath, pszLibAFilename, Length(DllFullPath) * 2 + 1); // 计算 pszLibAFilename 的长度,注意,是以字节为单元的长度 memSize := (1 + lstrlenW(pszLibAFilename)) * SizeOf(WCHAR); //使用VirtualAllocEx函数在远程进程的内存地址空间分配DLL文件名空间 pszLibFileRemote := VirtualAllocEx(hRemoteProcess, nil, memSize, MEM_COMMIT, PAGE_READWRITE); if Assigned(pszLibFileRemote) then begin //使用WriteProcessMemory函数将DLL的路径名入到远程进程的内存空间 if WriteProcessMemory(hRemoteProcess, pszLibFileRemote, pszLibAFilename, memSize, WriteSize) and (WriteSize = memSize) then begin // 计算GetModuleHandleW的入口地址 pfnStartAddr := GetProcAddress(LoadLibrary('Kernel32.dll'), 'GetModuleHandleW'); //使目标进程调用GetModuleHandleW,获得DLL在目标进程中的句柄 hRemoteThread := CreateRemoteThread(hRemoteProcess, nil, 0, pfnStartAddr, pszLibFileRemote, 0, lpThreadId); // 等待GetModuleHandle运行完毕 WaitForSingleObject(hRemoteThread, INFINITE); // 获得GetModuleHandle的返回值,存在dwHandle变量中 GetExitCodeThread(hRemoteThread, dwHandle); // 计算FreeLibrary的入口地址 pfnStartAddr := GetProcAddress(LoadLibrary('Kernel32.dll'), 'FreeLibrary'); // 使目标进程调用FreeLibrary,卸载DLL hRemoteThread := CreateRemoteThread(hRemoteProcess, nil, 0, pfnStartAddr, Pointer(dwHandle), 0, lpThreadId); // 等待FreeLibrary卸载完毕 WaitForSingleObject(hRemoteThread, INFINITE); // 如果执行成功返回 True; if hRemoteProcess 0 then Result := true; // 释放目标进程中申请的空间 VirtualFreeEx(hRemoteProcess, pszLibFileRemote, Length(DllFullPath) + 1, MEM_DECOMMIT); // 释放句柄 CloseHandle(hRemoteThread); end; end; finally // 释放句柄 CloseHandle(hRemoteProcess); end; end; end;

16,748

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 语言基础/算法/系统设计
社区管理员
  • 语言基础/算法/系统设计社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧