Imports System
Imports System.Runtime.InteropServices
Imports Microsoft.Win32
Imports System.IO
Imports System.IO.Compression
Imports System.Text
Namespace WindowScriptingObject
<Guid("7448E08D-ED0F-4E23-B528-91937BB41756"), _
InterfaceType(ComInterfaceType.InterfaceIsIDispatch)> _
Public Interface _WindowScriptingObject
<DispId(1)> Function Decompress(ByVal value as String) As String
End Interface
<Guid("B146BF9E-78FC-4DB0-ABFE-9FF026B43E4D"), _
ClassInterface(ClassInterfaceType.None), _
ProgId("WindowScriptingObject")> Public Class WindowScriptingObject
Implements _WindowScriptingObject
Public WindowScriptingObject()
Public Function Decompress(ByVal value as string) As String Implements _WindowScriptingObject.Decompress
Dim x As String
' on error resume next
Dim xstream As New MemoryStream(Encoding.Unicode.GetBytes(value))
Dim mem2 As New IO.MemoryStream()
'Dim streamMe As New StreamWriter(mem2,Encoding.UTF8)
'streamMe.Write(value)
'StreamMe.Close()
'mem2.Position=0
Dim gz As New System.IO.Compression.GZipStream(xstream, IO.Compression.CompressionMode.Decompress)
Dim sr As New IO.StreamReader(gz)
x = sr.ReadLine
sr.Close()
'End Using
Decompress = x
End Function
End Class
End Namespace
我验证了发送过来的字符串包含来自VBScript的正确值。但是,它说标题是错误的。
上面的代码必须经过编译才能进行测试
"C:\Windows\Microsoft.NET\Framework\v4.0.30319\vbc.exe" /target:library /out:"%userprofile%\desktop\t.dll" "%userprofile%\desktop\t.txt" /verbose
然后注册
"C:\Windows\Microsoft.NET\Framework\v4.0.30319\regasm" /codebase "%userprofile%\desktop\t.dll" /tlb:"%userprofile%\desktop\t.tlb" /v
然后调用
c:\windows\SysWOW64\cscript.exe old.vbs
即使不是最终目标,我也将代码放入文件中以读取内容。当我这样做时,文件将正确解压缩。
Dim xstream As New MemoryStream(Encoding.Unicode.GetBytes(value))
此行听到的声音似乎错误地将我的字符串转换为流。
目标是发送压缩的字符串并返回未压缩的字符串。
上面的代码与此代码一起调用
Const adTypeBinary = 1
Set wso = CreateObject("WindowScriptingObject")
Dim objStream
Set objStream = CreateObject("ADODB.Stream")
objStream.Type = adTypeBinary
objStream.Open
objStream.LoadFromFile "e:\download\result.gz"
'objStream.Charset = "Windows-1252"
x = objStream.Read(900)
objStream.Close
For i=1 To Len(x)
t = t & Chr(AscW(Mid(x, i, 1)) And 255)
t = t & Chr((AscW(Mid(x, i, 1)) And 65280)/256)
Next
MsgBox wso.Decompress(t), , "vbs"
我尝试了这个,甚至将字符串转换为base64以使其正常工作。
Dim gzBuffer As Byte() = Convert.FromBase64String(value)
Using ms As New MemoryStream()
Dim msgLength As Integer = BitConverter.ToInt32(gzBuffer, 0)
ms.Write(gzBuffer, 4, gzBuffer.Length - 4)
Dim buffer As Byte() = New Byte(msgLength - 1) {}
ms.Position = 0
Using zipStream As New System.IO.Compression.GZipStream(ms, System.IO.Compression.CompressionMode.Decompress)
zipStream.Read(buffer, 0, buffer.Length)
End Using
Decompress=System.Text.Encoding.Unicode.GetString(buffer, 0, buffer.Length)
End Using
数据没有正确转换,因为我在GZip标头中仍然有幻数不正确。
将base64编码值转储到在线解码器中,而我传入的字符串与解码值匹配。
版本2 迫使我对它进行base64编码,但随后它起作用了。 如何消除这种烦恼。
Imports System
Imports System.Runtime.InteropServices
Imports Microsoft.Win32
Imports System.IO
Imports System.IO.Compression
Imports System.Text
Namespace WindowScriptingObject
<Guid("7448E08D-ED0F-4E23-B528-91937BB41756"), _
InterfaceType(ComInterfaceType.InterfaceIsIDispatch)> _
Public Interface _WindowScriptingObject
<DispId(1)> Function Decompress(ByVal value as String) As String
End Interface
<Guid("B146BF9E-78FC-4DB0-ABFE-9FF026B43E4D"), _
ClassInterface(ClassInterfaceType.None), _
ProgId("WindowScriptingObject")> Public Class WindowScriptingObject
Implements _WindowScriptingObject
Public WindowScriptingObject()
Public Function Decompress(ByVal value as string) As String Implements _WindowScriptingObject.Decompress
Dim x As String
' on error resume next
Dim gzBuffer As Byte() = Convert.FromBase64String(value)
Using ms As New MemoryStream()
Dim msgLength As Integer = BitConverter.ToInt32(gzBuffer, 0)
ms.Write(gzBuffer, 0, gzBuffer.Length)
Dim buffer As Byte() = New Byte(msgLength - 1) {}
ms.Position = 0
Using zipStream As New System.IO.Compression.GZipStream(ms, System.IO.Compression.CompressionMode.Decompress)
zipStream.Read(buffer, 0, buffer.Length)
End Using
Decompress=System.Text.Encoding.ASCII.GetString(buffer, 0, buffer.Length)
End Using
' Dim xstream As New MemoryStream(value.ToArray())
Dim mem2 As New IO.MemoryStream()
'Dim streamMe As New StreamWriter(mem2,Encoding.UTF8)
'streamMe.Write(value)
'StreamMe.Close()
'mem2.Position=0
'Dim gz As New System.IO.Compression.GZipStream(xstream, IO.Compression.CompressionMode.Decompress)
'Dim sr As New IO.StreamReader(gz)
' x = sr.ReadLine
'sr.Close()
'End Using
'Decompress = x
End Function
End Class
End Namespace
更新此代码有效,但输出大小为500K,并且只有3100字节的文本。
Imports System
Imports System.Runtime.InteropServices
Imports Microsoft.Win32
Imports System.IO
Imports System.IO.Compression
Imports System.Text
Namespace WindowScriptingObject
<Guid("7448E08D-ED0F-4E23-B528-91937BB41756"), _
InterfaceType(ComInterfaceType.InterfaceIsIDispatch)> _
Public Interface _WindowScriptingObject
<DispId(1)> Function Decompress(ByVal value as string) As String
End Interface
<Guid("B146BF9E-78FC-4DB0-ABFE-9FF026B43E4D"), _
ClassInterface(ClassInterfaceType.None), _
ProgId("WindowScriptingObject")> Public Class WindowScriptingObject
Implements _WindowScriptingObject
Public WindowScriptingObject()
Public Function Decompress(ByVal value as string) As String Implements _WindowScriptingObject.Decompress
' on error resume next
Dim gzBuffer() As Byte = System.Text.Encoding.Default.Getbytes(value)
Using ms As New MemoryStream()
Dim msgLength As Integer = BitConverter.ToInt32(gzBuffer, 0)
ms.Write(gzBuffer, 0, gzBuffer.Length)
msgbox(msgLength)
Dim buffer As Byte() = New Byte(msgLength - 1) {}
ms.Position = 0
Using zipStream As New System.IO.Compression.GZipStream(ms, System.IO.Compression.CompressionMode.Decompress)
zipStream.Read(buffer, 0, buffer.Length)
End Using
Decompress=System.Text.Encoding.Default.GetString(buffer, 0, buffer.Length)
End Using
End Function
End Class
End Namespace
由于某些原因,msgLength的大小为559,903,解压缩后的文本大约为3100字节。这意味着BitConverter.toint32出现故障,因为gzBuffer为865字节。最终输出大小仅对于GZIPStream函数是已知的,因为文本被压缩,而输入大小与输出大小无关。
其他问题
输出大小似乎基于错误的信息。
intOutputLength=zipStream.Read(buffer, 0, buffer.Length)
End Using
Decompress=System.Text.Encoding.Default.GetString(buffer, 0, intOutputLength)
至少这减少了返回主程序的数据量。
Dim msgLength As Integer = BitConverter.ToInt32(gzBuffer, 0)
如果我没看错,msgLength是否由输入流的前4个字符确定?由于GZip标头始终为1f 8b 08 00,这似乎是一个可怕的主意。如果输出中的每一个大于559k,则似乎只是缓冲区溢出而已。
我认为这解决了可怕的缓冲区大小问题。
Imports System
Imports System.Runtime.InteropServices
Imports Microsoft.Win32
Imports System.IO
Imports System.IO.Compression
Imports System.Text
Namespace WindowScriptingObject
<Guid("7448E08D-ED0F-4E23-B528-91937BB41756"), _
InterfaceType(ComInterfaceType.InterfaceIsIDispatch)> _
Public Interface _WindowScriptingObject
<DispId(1)> Function Decompress(ByVal value as string) As String
End Interface
<Guid("B146BF9E-78FC-4DB0-ABFE-9FF026B43E4D"), _
ClassInterface(ClassInterfaceType.None), _
ProgId("WindowScriptingObject")> Public Class WindowScriptingObject
Implements _WindowScriptingObject
Public WindowScriptingObject()
Public Function Decompress(ByVal value as string) As String Implements _WindowScriptingObject.Decompress
' on error resume next
Dim gzBuffer() As Byte = System.Text.Encoding.Default.Getbytes(value)
dim intOutputLength as integer
Dim intBlock as integer
Decompress=""
Using ms As New MemoryStream()
Dim msgLength As Integer = 4096
ms.Write(gzBuffer, 0, gzBuffer.Length)
Dim buffer As Byte() = New Byte(4096) {}
ms.Position = 0
Using zipStream As New System.IO.Compression.GZipStream(ms, System.IO.Compression.CompressionMode.Decompress)
intOutputLength=0
intBlock=4096
while intBlock=4096
intBlock=zipStream.Read(buffer, 0, buffer.Length)
Decompress+=System.Text.Encoding.Default.GetString(buffer, 0, intBlock)
intOutputLength+=intBlock
end while
End Using
End Using
End Function
End Class
End Namespace
答案 0 :(得分:3)
通过更改VB.NET函数和界面使其看起来像这样(主要是更改参数类型),我可以使您的代码正常工作:
<Guid("7448E08E-ED0F-4E23-B528-91937BB41756"),
InterfaceType(ComInterfaceType.InterfaceIsIDispatch)>
Public Interface _WindowScriptingObject
<DispId(1)> Function Decompress(ByVal value As Byte()) As String
End Interface
Public Function Decompress(ByVal value As Byte()) As String Implements _WindowScriptingObject.Decompress
Using xstream As New MemoryStream(value)
Using gz As New System.IO.Compression.GZipStream(xstream, IO.Compression.CompressionMode.Decompress)
Using sr As New IO.StreamReader(gz)
Return sr.ReadLine()
End Using
End Using
End Using
End Function
我的测试VBS看起来像这样
Const adTypeBinary = 1
Dim wso
Set wso = CreateObject("WindowScriptingObject")
Dim objStream, x
Set objStream = CreateObject("ADODB.Stream")
objStream.Type = adTypeBinary
objStream.Open
objStream.LoadFromFile "c:\users\bluem\desktop\Notes.txt.gz"
x = objStream.Read(342737)
objStream.Close
WScript.StdOut.WriteLine wso.Decompress((x))
我不完全确定为什么需要将x参数放在两组括号中,但是我认为这与强制将参数通过值而不是通过引用传递有关,并有助于将其转换为a字节数组。在添加额外的一对括号之前,我遇到了错误。
编辑: 要回答您的其他一些问题:
答案 1 :(得分:0)
自从我写了vbscript以来已经很久了,所以我已经不知道要提供修复了。但是,我可以在此代码的vbscript部分指出一些严重缺陷。
首先从.gz
文件中读取900个字节,而不管文件的实际长度如何。长度超过900字节的任何内容都不会被读取。
它以二进制模式执行此读取。二进制模式将忽略任何字符集或编码信息,仅读取原始字节,这适用于.gz
文件。但是,此数据发生的下一件事是使用Len()
函数,该函数用于字符串,而不是二进制数据; Len()
在此不是适当的功能。此外,接下来将通过For
函数在Mid()
循环中使用数据。 Mid()
同样旨在仅用于字符串,而x
变体不是字符串。 vbscript字符串对象不仅仅是原始字符。它们包括诸如编码,长度和字符缓冲区之类的元数据,而这些字符串函数依赖于使用所有元数据正确构造的对象。
该vbscript不可能 产生正确的结果。在解决该问题之前,即使查看vb.net代码也没有任何意义。再次,我太过分地建议一个真正的解决方案,但是我建议尝试将一个未更改的字节数组而不是字符串传递给.Net端。