Board logo

标题: [问题求助] [已解决]VBS如何读取unicode编码的inf文件里等号后面的内容 [打印本页]

作者: yuanyannian    时间: 2014-10-28 07:47     标题: [已解决]VBS如何读取unicode编码的inf文件里等号后面的内容

本帖最后由 pcl_test 于 2016-8-14 11:48 编辑

求助---VBS如何读取 inf 文件等号后面的内容 并赋给变量

问题描述:还是处理 unicode 格式的 inf 文件,比如:

  aaa.inf
   [Strings]
   BIOS = "abcd-abcd"
   TIDS  = ABCD

用 vbs (也要求是 unicode 格式)读取 BIOS 及 TIDS 等号后面的内容,并分别赋给变量 str1 和 str2

谢谢!
作者: yuanyannian    时间: 2014-10-28 13:26

回复 1# yuanyannian

是不是这个问题太幼稚?
作者: yu2n    时间: 2014-10-28 14:30

VBA、VBS读写INI文件
http://blog.sina.com.cn/s/blog_6163bdeb0102e5ki.html
  1. ' 读INI文件
  2. strIniFile = ".\test.inf"
  3. strBIOS = ReadINI(strIniFile, "Strings", "BIOS")
  4. strTIDS = ReadINI(strIniFile, "Strings", "TIDS")
  5. MsgBox "BIOS = " & strBIOS & vbCrLf & "TIDS  = " & strTIDS, vbInformation
  6. ' read函数
  7. Function ReadINI(FilePath, Bar, PrimaryKey)
  8. Dim fso, sReadLine, i, j, ss
  9. Set fso = CreateObject("Scripting.FileSystemObject")
  10. Set IniFile = fso.opentextfile(FilePath, 1,-1)
  11. Do Until IniFile.atendofstream
  12.     sReadLine = IniFile.readline
  13.     If sReadLine = "" Then
  14.         IniFile.skipline
  15.     ElseIf Trim(sReadLine) = "[" & Bar & "]" Then       '找到小节名
  16.         '查找该小节名下的键名
  17.         Do Until IniFile.atendofstream
  18.             sReadLine = IniFile.readline                '读取小节名后的行
  19.             j = InStr(sReadLine, "=")
  20.             If j > 0 Then                               '小节名后的文本行存在
  21.                 If InStr(Left(sReadLine, j), PrimaryKey) > 0 Then                       '从"="左边字符串找到键名
  22.                     ss = Trim(Right(sReadLine, Len(sReadLine) - InStr(sReadLine, "="))) '读取等号后的部分
  23.                     Exit Do
  24.                 End If
  25.             End If
  26.         Loop
  27.     End If
  28. Loop
  29. IniFile.Close
  30. Set fso = Nothing
  31. ReadINI = ss
  32. End Function
复制代码

作者: yuanyannian    时间: 2014-10-28 17:24

回复 3# yu2n

谢谢,试了一下,但读不出啊。
作者: zz100001    时间: 2014-10-28 17:51

这种情况你就把你实际的那个文件和vbs都放到附件里面来
他发这么一个东西可能自己也试过一下的
有可能你那编码就不是unicode,而是utf-8之类的
作者: yuanyannian    时间: 2014-10-28 19:48

回复 3# yu2n

上传需要处理的原文件,请老师给看一下。
文件大点,给个地址:

HIVESFT.rar

http://pan.baidu.com/s/1mgl24dy
作者: yu2n    时间: 2014-10-28 22:40

回复 6# yuanyannian

思密达文字可能不兼容中文系统的 fso.opentextfile(file, 1,-1) Unicode 编码,我换 ADODB.Stream  Unicode 测试OK。
  1. strIniFile = "V:\HIVESFT.INF"
  2. strBIOS = ReadINI(strIniFile, "Strings", "BIOS")
  3. strTIDS = ReadINI(strIniFile, "Strings", "NDIS")
  4. strInfo = "BIOS = " & strBIOS & vbCrLf & "NDIS  = " & strTIDS
  5. Msgbox strInfo, vbInformation
  6. Function ReadIni(strIniFilePath, strPrimary, strSubKey)
  7.   Dim objStream
  8.   Set objStream = CreateObject("ADODB.Stream")
  9.   With objStream
  10.       .Type = 2
  11.       .Mode = 3
  12.       .Open
  13.       .Charset = "Unicode"
  14.       .LoadFromFile strIniFilePath
  15.        strText = .ReadText
  16.       .Close
  17.   End With
  18.   Set objStream = Nothing
  19.   arrText = Split(strText, vbCrLf)
  20.   For Each strLine In arrText
  21.     If intCount = 0 Then
  22.       If strLine = "[" & strPrimary & "]" Then
  23.           intCount = 1
  24.       End If
  25.     Else
  26.       If Left(strLine,1) = "[" Then Exit For
  27.       j = InStr(strLine, "=")
  28.       If j > 0 Then                               '小节名后的文本行存在
  29.         If InStr(Left(strLine, j), strSubKey) > 0 Then                       '从"="左边字符串找到键名
  30.           ReadIni = Trim(Right(strLine, Len(strLine) - InStr(strLine, "="))) '读取等号后的部分
  31.           Exit For
  32.         End If
  33.       End If
  34.     End If
  35.   Next
  36. End Function
复制代码

作者: yuanyannian    时间: 2014-10-29 06:27

本帖最后由 yuanyannian 于 2014-10-29 06:30 编辑

回复 7# yu2n

再次感谢了。
这样可以了,但问题又来了:就思密达而言,将读出的变量写入注册表,都成了“?????????”,请老师给看一下。
另外,不能读如:STANGDARD_NAME、KLT_63 等格式的变量。
作者: yu2n    时间: 2014-10-29 11:37

回复 8# yuanyannian

1. 你是如何写入注册表的?
   建议注册表使用 regedit.exe /s abc.reg 的形式写入,其中 abc.reg 为Unicode编码。
2. 你将代码14行的Unicode编码改为其他编码试试。
作者: yuanyannian    时间: 2014-10-29 12:23

本帖最后由 yuanyannian 于 2014-10-29 12:29 编辑

回复 9# yu2n

直接在 vbs 中:
    Set Reg=WScript.CreateObject("WScript.Shell")
    Reg.RegWrite "HKCU\yyn\Desktop\Wallpaper",strBIOS,"REG_SZ"
   
如果用 .reg ,需要用vbs先写入到 .reg 文件,而且必须是 unicode 格式,这个我不会,老师可否帮一帮?
作者: yu2n    时间: 2014-10-29 14:01

回复 10# yuanyannian

读写Unicode文本:
  1. Function WriteUnicodeText(File, TextString)
  2. With CreateObject("ADODB.Stream")
  3. .Type = 2 :  .Mode = 3 :  .Charset = "Unicode" :  .Open
  4. .WriteText TextString  :  .SaveToFile File, 2 :  .Close
  5. End With
  6. End Function
  7. Function ReadUnicodeText(File)
  8. With CreateObject("ADODB.Stream")
  9. .Type = 2 :  .Mode = 3 :  .Charset = "Unicode" :  .Open
  10. .LoadFromFile File :  ReadUTF8Text = .ReadText :  .Close
  11. End With
  12. End Function
复制代码

作者: yuanyannian    时间: 2014-10-29 17:40

回复 11# yu2n

抱歉,看不太懂,请帮写一个代码?
作者: yu2n    时间: 2014-10-29 19:03

回复 12# yuanyannian

函数 WriteUnicodeText(File, TextString)
功能:将字符串以Unicode编码写入文本文件。
参数:File 为文本文件路径,TextString 为字符串。

函数 ReadUnicodeText(File, TextString)

……你一定是在逗我,这个就不解释了。
作者: yuanyannian    时间: 2014-10-29 21:25

回复 13# yu2n

抱歉,我是真的不会,前一阵子还在论坛中求助过,是可以创建一个文件,但只能全新覆盖写入,不能追加写入。
请老师帮忙,谢谢!
作者: yu2n    时间: 2014-10-29 23:47

回复 14# yuanyannian

追加写入?
1. 读取旧文本,保存为字符串 str1
2. 将要保存的字符串 str2 与字符串 str1 合并为 str3 。(字符串使用 & 连接符)
3. 向文件写入 str3 ,即完成追加写入。
  1. File = "d:\abc.txt"
  2. str1 = ReadUnicodeText(File)    ' 读取
  3. str2 = " 我是新字符串 "              ' 新字符串
  4. str3 = str1 & str2                    ' 合并新旧字符串(追加)
  5. WriteUnicodeText File, str3       ' 写入文件
复制代码

作者: apang    时间: 2014-10-30 00:33

本帖最后由 apang 于 2014-10-30 09:40 编辑

我这里ws.regwrite写入是问号,wmi写入正常,试试看
  1. Dim fso, txt, re, m, regPath, regValue, regData
  2. Set fso = CreateObject("Scripting.FileSystemObject")
  3. txt = fso.OpenTextFile("HIVESFT.INF", 1, false, -1).ReadAll
  4. txt = txt & vbCrLf & "["
  5. Set re = New RegExp
  6. re.Pattern = "^ *\[Strings] *$[\s\S]*?(?=^ *\[)"
  7. re.IgnoreCase = true
  8. re.Global = true
  9. re.MultiLine = true
  10. If Not re.Test(txt) Then WScript.Quit
  11. txt = re.Execute(txt)(0)
  12. re.Pattern = "^ *(BIOS|NDIS) *= *(.+)"
  13. For Each m in re.Execute(txt)
  14.         regPath = "yyn\Desktop"
  15.         regData = Replace(m.SubMatches(1), chr(34), "")
  16.         If UCase(m.SubMatches(0)) = "BIOS" Then
  17.                 regValue = "yyn1"
  18.         Else
  19.                 regValue = "yyn2"
  20.         End If
  21.         WriteToRegValue regPath, regValue, regData
  22. Next
  23. Sub WriteToRegValue(ByVal regPath, ByVal regValue, ByVal regData)
  24.         Const HKCU = &H80000001
  25.         Dim regWMI
  26.         Set regWMI = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\Default:StdRegProv")
  27.         regWMI.CreateKey HKCU, regPath
  28.         regWMI.SetStringValue HKCU, regPath, regValue, regData
  29. End Sub
复制代码

作者: yuanyannian    时间: 2014-10-30 06:46

本帖最后由 yuanyannian 于 2014-10-30 06:51 编辑

回复 16# apang

谢谢 apang 老师出手,读、写均正常。
不过,我的需求是:只读出 =  后面的内容作为变量,写入注册表中的路径、键值是需要自定义的,比如 HKCU\yyn\Desktop, yyn(键值), BIOS 或 NDIS (还有很多其它的) = 后面的内容(数据), 或者如注册表文件:

[HKEY_CURRENT_USER\yyn\Desktop]
"yyn1"="대한민국 표준시"
"yyn2"="한국어"

或:
[HKEY_CURRENT_USER\yyn\System\Test]
"yyn3"="한국어 입력 시스템 (IME 2000)"
"yyn4"="한"

或者将读出的数据分别写成注册表文件,再自行导入注册表也可。比如写成注册表文件 (unicode 格式):

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\yyn\Desktop]
"yyn1"="대한민국 표준시"
"yyn2"="한국어"

[HKEY_CURRENT_USER\yyn\System\Test]
"yyn3"="한국어 입력 시스템 (IME 2000)"
"yyn4"="한"

有劳 apang 老师了。
作者: apang    时间: 2014-10-30 09:43

回复 17# yuanyannian


    已修改,如果想自定义,更改相应变量的值即可
作者: yuanyannian    时间: 2014-10-30 11:55

回复 18# apang

是这样吗?
  1. Dim fso, txt, re, m, regPath, regValue, regData
  2. Set fso = CreateObject("Scripting.FileSystemObject")
  3. txt = fso.OpenTextFile("HIVESFT.INF", 1, false, -1).ReadAll
  4. txt = txt & vbCrLf & "["
  5. Set re = New RegExp
  6. re.Pattern = "^ *\[Strings] *$[\s\S]*?(?=^ *\[)"
  7. re.IgnoreCase = true
  8. re.Global = true
  9. re.MultiLine = true
  10. If Not re.Test(txt) Then WScript.Quit
  11. txt = re.Execute(txt)(0)
  12. re.Pattern = "^ *(BIOS|NDIS|NETWORK_DDE|NETWORK_DDE_DESCRIPTION|NETWORK_DDE_DSDM) *= *(.+)"
  13. For Each m in re.Execute(txt)
  14.     regData = Replace(m.SubMatches(1), chr(34), "")
  15.     If UCase(m.SubMatches(0)) = "BIOS" Then
  16.         regPath = "yyn\Desktop"
  17.         regValue = "yyn1"
  18.     End If
  19.     If UCase(m.SubMatches(0)) = "NDIS" Then
  20.         regPath = "yyn\Desktop\yyn"
  21.         regValue = "yyn2"
  22.     End If
  23.     If UCase(m.SubMatches(0)) = "NETWORK_DDE" Then
  24.         regPath = "yyn\Test"
  25.         regValue = "yyn3"
  26.     End If
  27.     If UCase(m.SubMatches(0)) = "NETWORK_DDE_DESCRIPTION" Then
  28.         regPath = "yyn\Test\yyn"
  29.         regValue = "yyn4"
  30.     End If
  31.     If UCase(m.SubMatches(0)) = "NETWORK_DDE_DSDM" Then
  32.         regPath = "yyn\yyn\yyn"
  33.         regValue = "yyn5"
  34.     End If
  35.     WriteToRegValue regPath, regValue, regData
  36. Next
  37. Sub WriteToRegValue(ByVal regPath, ByVal regValue, ByVal regData)
  38.     Const HKCU = &H80000001
  39.     Dim regWMI
  40.     Set regWMI = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\Default:StdRegProv")
  41.     regWMI.CreateKey HKCU, regPath1
  42.     regWMI.SetStringValue HKCU, regPath, regValue, regData
  43. End Sub
复制代码
但提示:

另外,在 re.Pattern = "^ *(BIOS|NDIS|NETWORK_DDE|NETWORK_DDE_DESCRIPTION|NETWORK_DDE_DSDM) *= *(.+)" 中,如果需要几十个变量,该如何处理?
作者: yuanyannian    时间: 2014-10-30 13:32

提示现象是我把 regWMI.CreateKey HKCU, regPath1 搞错了。

另外,我把 HKCU 改成 HKLM ,把  Const HKCU = &H80000001 改为     Const HKLM = &H80000002,失败。
作者: apang    时间: 2014-10-30 17:18

回复 19# yuanyannian


    还是保存到reg文件吧,少一点弯弯绕
  1. Dim s1, s2, strSection, arField, arValue, arPath
  2. s1 = "HKEY_CURRENT_USER\"
  3. s2 = "HKEY_LOCAL_MACHINE\"
  4. strSection = "Strings"
  5. arField = Array("BIOS", "NDIS", "GULIM")
  6. arValue = Array("yyn1", "yyn2", "yyn3")
  7. arPath = Array(s1 & "yyn\Desktop", s1 & "yyn\Test", s2 & "Software\Test\yyn")
  8. Dim fso, txt, re, i, regData
  9. Set fso = CreateObject("Scripting.FileSystemObject")
  10. txt = fso.OpenTextFile("HIVESFT.INF", 1, false, -1).ReadAll
  11. txt = txt & vbCrLf & "["
  12. Set re = New RegExp
  13. re.Pattern = "^ *\[" & strSection & "] *$[\s\S]*?(?=^ *\[)"
  14. re.IgnoreCase = true
  15. re.Global = true
  16. re.MultiLine = true
  17. If Not re.Test(txt) Then WScript.Quit
  18. txt = re.Execute(txt)(0)
  19. For i = 0 to UBound(arField)
  20.         re.Pattern = "^ *" & arField(i) & " *= *("".*"")"
  21.         If re.Test(txt) Then
  22.                 regData = re.Execute(txt)(0).SubMatches(0)
  23.                 s = s & "[" & arPath(i) & "]" & vbCrLf
  24.                 s = s & """" & arValue(i) & """=" & regData & vbCrLf
  25.                 s = s & vbCrLf
  26.         End If
  27. Next
  28. s = "Windows Registry Editor Version 5.00" & vbCrLf & vbCrLf & s
  29. fso.OpenTextFile("Result.reg", 2, true, -1).Write s
复制代码

作者: yuanyannian    时间: 2014-10-30 17:50

这样也好,19楼的代码不能写入 HKLM 应该是对该根键没有权限造成的,路径写入 HKLM 的子键中是则可以。
再次谢谢 apang 老师。

再请问,如果不需要搜索 [strings], 去掉那些代码?
作者: apang    时间: 2014-10-30 18:17

回复 22# yuanyannian


    代码是先找到 Strings 节,再在Strings节中找相应的字段。
比如 BIOS 字段,在Strings中有,在其它节也可能有。
如果去掉Strings节名,找到的可能就不正确,你希望这样吗?
作者: yuanyannian    时间: 2014-10-30 19:31

回复 23# apang

有道理,那我采用写入注册表文件。
作者: yuanyannian    时间: 2014-10-31 07:46

回复 23# apang

再麻烦 apang 老师,测试中发现一个问题:当源文件等号后面的数据没有 "" 情况下,无法读出及写入注册表文件。
作者: apang    时间: 2014-10-31 10:00

回复 25# yuanyannian


    不带双引号还是 REG_SZ 类型吗?你不说清楚那我只考虑一种类型,不考虑其它类型或其它特殊情况
作者: yuanyannian    时间: 2014-10-31 10:21

回复 26# apang

是的,都是字符串 - REG_SZ 的。
作者: apang    时间: 2014-10-31 11:44

回复 27# yuanyannian


    第25行下面插入一行:
  1. regData = chr(34) & Replace(regData, chr(34), "") & chr(34)
复制代码
第23行改成:
  1. re.Pattern = "^ *" & arField(i) & " *= *([^\r\n]+)"
复制代码

作者: yuanyannian    时间: 2014-10-31 12:00

回复 28# apang

可以了,非常感谢!




欢迎光临 批处理之家 (http://bbs.bathome.net/) Powered by Discuz! 7.2