Code: Select all
MsgBox % SevenZip_ExtractMem2("D:\Folder\test.zip", "test2.txt")
MsgBox % SevenZip_ExtractMem2("D:\Folder\inFolder\test.zip", "test2.txt")
Code: Select all
MsgBox % SevenZip_ExtractMem2("D:\Folder\test.zip", "test2.txt")
MsgBox % SevenZip_ExtractMem2("D:\Folder\inFolder\test.zip", "test2.txt")
@tmplinshitmplinshi wrote: ↑21 Nov 2019, 23:10@hasantr That shoudn't be happen, but I tested anyway. I created the folder D:\Folder\inFolder, and copied test.zip to both D:\Folder\ and D:\Folder\inFolder\, the code just works fine.Did you get any error messages?Code: Select all
MsgBox % SevenZip_ExtractMem2("D:\Folder\test.zip", "test2.txt") MsgBox % SevenZip_ExtractMem2("D:\Folder\inFolder\test.zip", "test2.txt")
Code: Select all
size := UnzipToBuffer(buff, "C:\Users\User\Desktop\test.zip", "Folder\Subfolder\notes.txt")
; test
File := FileOpen(A_Desktop . "\notes.txt", "w", "cp0")
File.RawWrite(buff, size)
File.Close()
UnzipToBuffer(ByRef buff, zipFile, pathInsideZip) {
static STREAM_SEEK_SET := 0, STREAM_SEEK_END := 2
Parent_IShellFolder := IShellFolder.Create()
pidl := Parent_IShellFolder.ParseDisplayName(zipFile)
arPath := StrSplit(pathInsideZip, "\")
for k, v in arPath {
Isf := Parent_IShellFolder.BindToObject(pidl)
DllCall("ole32\CoTaskMemFree", "Ptr", pidl)
pidl := Isf.ParseDisplayName(v)
if (k = arPath.MaxIndex()) {
IStream := Isf.BindToStorage(pidl)
DllCall("ole32\CoTaskMemFree", "Ptr", pidl)
size := IStream.Seek(0, STREAM_SEEK_END)
IStream.Seek(0, STREAM_SEEK_SET)
VarSetCapacity(buff, size, 0)
IStream.Read(buff, size)
break
}
Parent_IShellFolder := Isf
}
Return size
}
CLSIDFromString(IID, ByRef CLSID) {
VarSetCapacity(CLSID, 16, 0)
if res := DllCall("ole32\CLSIDFromString", "WStr", IID, "Ptr", &CLSID, "UInt")
throw Exception("CLSIDFromString failed. Error: " . Format("{:#x}", res))
Return &CLSID
}
class InterfaceBase {
__New(ptr) {
this.ptr := ptr
}
__Delete() {
ObjRelease(this.ptr)
}
VTable(idx) {
Return NumGet(NumGet(this.ptr + 0) + A_PtrSize*idx)
}
IsError(method, result, exc := true) {
if (result = 0)
Return 0
this.error := method . " failed. Result: " . (result = "" ? "No result" : Format("{:#x}", result & 0xFFFFFFFF))
if !exc
Return this.error
throw Exception(this.error)
}
}
class IShellFolder extends InterfaceBase { ; shobjidl.h
Create() {
DllCall("shell32\SHGetDesktopFolder", "PtrP", pIShellFolder)
Return new IShellFolder(pIShellFolder)
}
ParseDisplayName(pszDisplayName, pdwAttributes := 0, hwnd := 0, pbc := 0, pchEaten := 0) {
hr := DllCall(this.VTable(3), "Ptr", this.ptr, "Ptr", hwnd, "Ptr", pbc, "WStr", pszDisplayName
, "Ptr", pchEaten, "PtrP", pidl, "UIntP", pdwAttributes)
this.IsError("IShellFolder::ParseDisplayName", hr)
Return pidl
}
BindToObject(pidl) {
static IID_IShellFolder := "{000214E6-0000-0000-C000-000000000046}"
riid := CLSIDFromString(IID_IShellFolder, pIID_IShellFolder)
hr := DllCall(this.VTable(5), "Ptr", this.ptr, "Ptr", pidl, "Ptr", 0, "Ptr", riid, "PtrP", pIShellFolder)
this.IsError("IShellFolder::BindToObject", hr)
Return new IShellFolder(pIShellFolder)
}
BindToStorage(pidl, objType := "IStream", pbc := 0) {
static IID_IStream = "{0000000c-0000-0000-C000-000000000046}"
if (objType = "IStream")
riid := CLSIDFromString(IID_IStream, pIID_IStream)
hr := DllCall(this.VTable(6), "Ptr", this.ptr, "Ptr", pidl, "Ptr", pbc, "Ptr", riid, "PtrP", ppv)
this.IsError("IShellFolder::BindToStorage", hr)
if (objType = "IStream")
Return new IStream(ppv)
}
}
class IStream extends InterfaceBase { ; ObjIdl.h
Read(ByRef buff, cb) {
hr := DllCall(this.VTable(3), "Ptr", this.ptr, "Ptr", &buff, "UInt", cb, "UIntP", read)
this.IsError("IStream::Read", hr)
Return read
}
Seek(dlibMove, dwOrigin) {
if (A_PtrSize = 8)
hr := DllCall(this.VTable(5), "Ptr", this.ptr, "Ptr", dlibMove, "UInt", dwOrigin, "PtrP", libNewPosition)
else
hr := DllCall(this.VTable(5), "Ptr", this.ptr, "UInt", dlibMove >> 32
, "UInt", dlibMove & 0xFFFFFFFF
, "UInt", dwOrigin, "PtrP", libNewPosition)
this.IsError("IStream::Seek", hr)
Return libNewPosition
}
}
Fixed.teadrinker wrote: ↑For some reason currently works only for 64-bit AHK.
It sometimes crashes, and refuses to run directly. You can read the previous thread replies to find out more. Very strange bugs.teadrinker wrote:Doesn't the code @tmplinshi provided work well enough? I haven't tested it yet.
This was awesome. Thank you very much.teadrinker wrote: ↑10 Jan 2020, 10:34My try to implement extraction to the buffer without external libraries:Code: Select all
size := UnzipToBuffer(buff, "C:\Users\User\Desktop\test.zip", "Folder\Subfolder\notes.txt") ; test File := FileOpen(A_Desktop . "\notes.txt", "w", "cp0") File.RawWrite(buff, size) File.Close() UnzipToBuffer(ByRef buff, zipFile, pathInsideZip) { static STREAM_SEEK_SET := 0, STREAM_SEEK_END := 2 Parent_IShellFolder := IShellFolder.Create() pidl := Parent_IShellFolder.ParseDisplayName(zipFile) arPath := StrSplit(pathInsideZip, "\") for k, v in arPath { Isf := Parent_IShellFolder.BindToObject(pidl) DllCall("ole32\CoTaskMemFree", "Ptr", pidl) pidl := Isf.ParseDisplayName(v) if (k = arPath.MaxIndex()) { IStream := Isf.BindToStorage(pidl) DllCall("ole32\CoTaskMemFree", "Ptr", pidl) size := IStream.Seek(0, STREAM_SEEK_END) IStream.Seek(0, STREAM_SEEK_SET) VarSetCapacity(buff, size, 0) IStream.Read(buff, size) break } Parent_IShellFolder := Isf } Return size } CLSIDFromString(IID, ByRef CLSID) { VarSetCapacity(CLSID, 16, 0) if res := DllCall("ole32\CLSIDFromString", "WStr", IID, "Ptr", &CLSID, "UInt") throw Exception("CLSIDFromString failed. Error: " . Format("{:#x}", res)) Return &CLSID } class InterfaceBase { __New(ptr) { this.ptr := ptr } __Delete() { ObjRelease(this.ptr) } VTable(idx) { Return NumGet(NumGet(this.ptr + 0) + A_PtrSize*idx) } IsError(method, result, exc := true) { if (result = 0) Return 0 this.error := method . " failed. Result: " . (result = "" ? "No result" : Format("{:#x}", result & 0xFFFFFFFF)) if !exc Return this.error throw Exception(this.error) } } class IShellFolder extends InterfaceBase { ; shobjidl.h Create() { DllCall("shell32\SHGetDesktopFolder", "PtrP", pIShellFolder) Return new IShellFolder(pIShellFolder) } ParseDisplayName(pszDisplayName, pdwAttributes := 0, hwnd := 0, pbc := 0, pchEaten := 0) { hr := DllCall(this.VTable(3), "Ptr", this.ptr, "Ptr", hwnd, "Ptr", pbc, "WStr", pszDisplayName , "Ptr", pchEaten, "PtrP", pidl, "UIntP", pdwAttributes) this.IsError("IShellFolder::ParseDisplayName", hr) Return pidl } BindToObject(pidl) { static IID_IShellFolder := "{000214E6-0000-0000-C000-000000000046}" riid := CLSIDFromString(IID_IShellFolder, pIID_IShellFolder) hr := DllCall(this.VTable(5), "Ptr", this.ptr, "Ptr", pidl, "Ptr", 0, "Ptr", riid, "PtrP", pIShellFolder) this.IsError("IShellFolder::BindToObject", hr) Return new IShellFolder(pIShellFolder) } BindToStorage(pidl, objType := "IStream", pbc := 0) { static IID_IStream = "{0000000c-0000-0000-C000-000000000046}" if (objType = "IStream") riid := CLSIDFromString(IID_IStream, pIID_IStream) hr := DllCall(this.VTable(6), "Ptr", this.ptr, "Ptr", pidl, "Ptr", pbc, "Ptr", riid, "PtrP", ppv) this.IsError("IShellFolder::BindToStorage", hr) if (objType = "IStream") Return new IStream(ppv) } } class IStream extends InterfaceBase { ; ObjIdl.h Read(ByRef buff, cb) { hr := DllCall(this.VTable(3), "Ptr", this.ptr, "Ptr", &buff, "UInt", cb, "UIntP", read) this.IsError("IStream::Read", hr) Return read } Seek(dlibMove, dwOrigin) { if (A_PtrSize = 8) hr := DllCall(this.VTable(5), "Ptr", this.ptr, "Ptr", dlibMove, "UInt", dwOrigin, "PtrP", libNewPosition) else hr := DllCall(this.VTable(5), "Ptr", this.ptr, "UInt", dlibMove >> 32 , "UInt", dlibMove & 0xFFFFFFFF , "UInt", dwOrigin, "PtrP", libNewPosition) this.IsError("IStream::Seek", hr) Return libNewPosition } }
size := UnzipToBuffer(buff, "C:\Users\User\Desktop\test.udf", "Folder\Subfolder\notes.txt")
Code: Select all
Error: IShellFolder::BindToObject failed. Result: 0x80004005
Windows considers the file with zip extension a comressed folder, without one not, so I'm not sure there is a way to ignore the extension.
After UnzipToBuffer(buff, "C:\Users\User\Desktop\test.zip", "Folder\Subfolder\notes.txt") content of notes.txt is in the buff variable as binary data. To get it as text you need to know the file encoding. Assuming that encoding is CP0
Code: Select all
size := UnzipToBuffer(buff, "C:\Users\User\Desktop\test.zip", "notes.txt")
MsgBox, % StrGet(&buff, "cp0")
Bad. It was again disappointing that Zip didn't work out of the extension.teadrinker wrote: ↑11 Jan 2020, 09:08Windows considers the file with zip extension a comressed folder, without one not, so I'm not sure there is a way to ignore the extension.After UnzipToBuffer(buff, "C:\Users\User\Desktop\test.zip", "Folder\Subfolder\notes.txt") content of notes.txt is in the buff variable as binary data. To get it as text you need to know the file encoding. Assuming that encoding is CP0Code: Select all
size := UnzipToBuffer(buff, "C:\Users\User\Desktop\test.zip", "notes.txt") MsgBox, % StrGet(&buff, "cp0")
It didn't make any sense to me either.
Code: Select all
#MaxMem 4095
SetBatchLines, -1
zipFile := A_Desktop . "\test.7z"
pathInsideZip := "Folder\SubFolder\test.txt"
7ZipDLL := "7-zip" . A_PtrSize*8 . ".dll"
if !FileExist(7ZipDLL) {
MsgBox, %7ZipDLL% not found
ExitApp
}
size := GetFileSize(zipFile, pathInsideZip, 7ZipDLL)
script := CreateScript(zipFile, pathInsideZip, 7ZipDLL)
DynaRunReadStdOutToBuff(script, buff, size)
MsgBox, % StrGet(&buff, "cp0")
CreateScript(zipFile, pathInsideZip, 7ZipDLL) {
script =
(
#NoTrayIcon
7ZipDLL := "%7ZipDLL%"
zipFile := "%zipFile%"
pathInsideZip := "%pathInsideZip%"
If !hModule := DllCall("LoadLibrary", "Str", 7ZipDLL, "Ptr")
Throw, "LoadLibrary fail"
ret := 7Zip_SevenZip(7ZipDLL, "e -hide """ . zipFile . """ """ . pathInsideZip . """ -so")
DllCall("FreeLibrary", "Ptr", hModule)
if (ret ~= "i)error|no files")
MsgBox, `% ret
ExitApp
7Zip_SevenZip(7ZipDLL, sCommand) {
nSize := 1024
VarSetCapacity(tOutBuffer, nSize)
res := DllCall(7ZipDLL . "\SevenZip", "Ptr", hWnd, "AStr", sCommand, "Ptr", &tOutBuffer, "Int", nSize)
return StrGet(&tOutBuffer, nSize, "CP0") . (res != 0 ? "``n``nResult: " . res : "")
}
)
Return script
}
GetFileSize(zipFile, pathInsideZip, 7ZipDLL) {
if !hModule := DllCall("Kernel32.dll\LoadLibrary", "Str", 7ZipDLL, "Ptr")
Throw, "LoadLibrary fail"
hArc := DllCall(7ZipDLL . "\SevenZipOpenArchive", "Ptr", 0, "AStr", zipFile, "Int", 0)
VarSetCapacity(INDIVIDUALINFO, 558, 0)
DllCall(7ZipDLL . "\SevenZipFindFirst", "Ptr", hArc, "AStr", pathInsideZip, "Ptr", &INDIVIDUALINFO)
DllCall(7ZipDLL . "\SevenZipCloseArchive", "Ptr", hArc)
DllCall("FreeLibrary", "Ptr", hModule)
Return NumGet(INDIVIDUALINFO, "UInt")
}
DynaRunReadStdOutToBuff(script, ByRef buff, buffSize := 0)
{
static HANDLE_FLAG_INHERIT := 0x00000001, flags := HANDLE_FLAG_INHERIT
, STARTF_USESTDHANDLES := 0x100, CREATE_NO_WINDOW := 0x08000000
, params := [ "UInt", PIPE_ACCESS_OUTBOUND := 0x2, "UInt", 0
, "UInt", PIPE_UNLIMITED_INSTANCES := 255, "UInt", 0
, "UInt", 0, "Ptr", 0, "Ptr", 0, "Ptr" ]
, BOM := Chr(0xFEFF)
, HEAP_ZERO_MEMORY := 0x8
, hHeap := DllCall("GetProcessHeap", "Ptr")
DllCall("CreatePipe", "PtrP", hPipeRead, "PtrP", hPipeWrite, "Ptr", 0, "UInt", buffSize)
DllCall("SetHandleInformation", "Ptr", hPipeWrite, "UInt", flags, "UInt", HANDLE_FLAG_INHERIT)
VarSetCapacity(STARTUPINFO , siSize := A_PtrSize*4 + 4*8 + A_PtrSize*5, 0)
NumPut(siSize , STARTUPINFO)
NumPut(STARTF_USESTDHANDLES, STARTUPINFO, A_PtrSize*4 + 4*7)
NumPut(hPipeWrite , STARTUPINFO, A_PtrSize*4 + 4*8 + A_PtrSize*3)
NumPut(hPipeWrite , STARTUPINFO, A_PtrSize*4 + 4*8 + A_PtrSize*4)
VarSetCapacity(PROCESS_INFORMATION, A_PtrSize*2 + 4*2, 0)
pipeName := "AHK_" . A_TickCount
for k, v in ["pipeGA", "pipe"]
%v% := DllCall("CreateNamedPipe", "Str", "\\.\pipe\" . pipeName, params*)
sCmd := A_AhkPath . " ""\\.\pipe\" . pipeName . """"
if !DllCall("CreateProcess", "UInt", 0, "Str", sCmd, "UInt", 0, "UInt", 0, "Int", true, "UInt", CREATE_NO_WINDOW
, "UInt", 0, "UInt", 0, "Ptr", &STARTUPINFO, "Ptr", &PROCESS_INFORMATION)
{
DllCall("CloseHandle", "Ptr", hPipeRead)
DllCall("CloseHandle", "Ptr", hPipeWrite)
for k, v in ["pipeGA", "pipe"]
DllCall("CloseHandle", "Ptr", %v%)
throw Exception("CreateProcess is failed")
}
DllCall("CloseHandle", "Ptr", hPipeWrite)
for k, v in ["pipeGA", "pipe"]
DllCall("ConnectNamedPipe", "Ptr", %v%, "Ptr", 0)
tempScript := BOM . script
tempScriptSize := ( StrLen(tempScript) + 1 ) << !!A_IsUnicode
DllCall("WriteFile", "Ptr", pipe, "Str", tempScript, "UInt", tempScriptSize, "UIntP", 0, "Ptr", 0)
for k, v in ["pipeGA", "pipe"]
DllCall("CloseHandle", "Ptr", %v%)
nSize := fullSize := 0, heapSize := buffSize = 0 ? 4096 : buffSize
pHeap := DllCall("HeapAlloc", "Ptr", hHeap, "UInt", HEAP_ZERO_MEMORY, "Ptr", heapSize, "Ptr")
Loop {
Sleep, 10
DllCall("PeekNamedPipe", "Ptr", hPipeRead, "Ptr", 0, "UInt", 0, "Ptr", 0, "UIntP", avail, "Ptr", 0)
} until (buffSize && avail = buffSize) || (!buffSize && avail) || A_Index = 100
while DllCall("ReadFile", "Ptr", hPipeRead, "Ptr", pHeap + fullSize, "UInt", heapSize, "UIntP", nSize, "UInt", 0) {
fullSize += nSize
if (fullSize > heapSize - nSize) {
heapSize *= 2
pHeap := DllCall("HeapReAlloc", "Ptr", hHeap, "UInt", HEAP_ZERO_MEMORY, "Ptr", pHeap, "Ptr", heapSize, "Ptr")
}
}
DllCall("CloseHandle", "Ptr", NumGet(PROCESS_INFORMATION))
DllCall("CloseHandle", "Ptr", NumGet(PROCESS_INFORMATION, A_PtrSize))
DllCall("CloseHandle", "Ptr", hPipeRead)
VarSetCapacity(buff, fullSize)
DllCall("RtlMoveMemory", "Ptr", &buff, "Ptr", pHeap, "Ptr", fullSize)
DllCall("HeapFree", "Ptr", hHeap, "UInt", 0, "Ptr", pHeap)
Return fullSize
}
Thanks. It's the solution for my application. But I want to use it in a single exe.teadrinker wrote: ↑12 Jan 2020, 15:19The code for 7-zip32.dll/7-zip64.dll:To prevent crashes I launch the extraction as another process and read its StdOut to the buffer.Code: Select all
#MaxMem 4095 SetBatchLines, -1 zipFile := A_Desktop . "\test.7z" pathInsideZip := "Folder\SubFolder\test.txt" 7ZipDLL := "7-zip" . A_PtrSize*8 . ".dll" if !FileExist(7ZipDLL) { MsgBox, %7ZipDLL% not found ExitApp } size := GetFileSize(zipFile, pathInsideZip, 7ZipDLL) script := CreateScript(zipFile, pathInsideZip, 7ZipDLL) DynaRunReadStdOutToBuff(script, buff, size) MsgBox, % StrGet(&buff, "cp0") CreateScript(zipFile, pathInsideZip, 7ZipDLL) { script = ( #NoTrayIcon 7ZipDLL := "%7ZipDLL%" zipFile := "%zipFile%" pathInsideZip := "%pathInsideZip%" If !hModule := DllCall("LoadLibrary", "Str", 7ZipDLL, "Ptr") Throw, "LoadLibrary fail" ret := 7Zip_SevenZip(7ZipDLL, "e -hide """ . zipFile . """ """ . pathInsideZip . """ -so") DllCall("FreeLibrary", "Ptr", hModule) if (ret ~= "i)error|no files") MsgBox, `% ret ExitApp 7Zip_SevenZip(7ZipDLL, sCommand) { nSize := 1024 VarSetCapacity(tOutBuffer, nSize) res := DllCall(7ZipDLL . "\SevenZip", "Ptr", hWnd, "AStr", sCommand, "Ptr", &tOutBuffer, "Int", nSize) return StrGet(&tOutBuffer, nSize, "CP0") . (res != 0 ? "``n``nResult: " . res : "") } ) Return script } GetFileSize(zipFile, pathInsideZip, 7ZipDLL) { if !hModule := DllCall("Kernel32.dll\LoadLibrary", "Str", 7ZipDLL, "Ptr") Throw, "LoadLibrary fail" hArc := DllCall(7ZipDLL . "\SevenZipOpenArchive", "Ptr", 0, "AStr", zipFile, "Int", 0) VarSetCapacity(INDIVIDUALINFO, 558, 0) DllCall(7ZipDLL . "\SevenZipFindFirst", "Ptr", hArc, "AStr", pathInsideZip, "Ptr", &INDIVIDUALINFO) DllCall(7ZipDLL . "\SevenZipCloseArchive", "Ptr", hArc) DllCall("FreeLibrary", "Ptr", hModule) Return NumGet(INDIVIDUALINFO, "UInt") } DynaRunReadStdOutToBuff(script, ByRef buff, buffSize := 0) { static HANDLE_FLAG_INHERIT := 0x00000001, flags := HANDLE_FLAG_INHERIT , STARTF_USESTDHANDLES := 0x100, CREATE_NO_WINDOW := 0x08000000 , params := [ "UInt", PIPE_ACCESS_OUTBOUND := 0x2, "UInt", 0 , "UInt", PIPE_UNLIMITED_INSTANCES := 255, "UInt", 0 , "UInt", 0, "Ptr", 0, "Ptr", 0, "Ptr" ] , BOM := Chr(0xFEFF) , HEAP_ZERO_MEMORY := 0x8 , hHeap := DllCall("GetProcessHeap", "Ptr") DllCall("CreatePipe", "PtrP", hPipeRead, "PtrP", hPipeWrite, "Ptr", 0, "UInt", buffSize) DllCall("SetHandleInformation", "Ptr", hPipeWrite, "UInt", flags, "UInt", HANDLE_FLAG_INHERIT) VarSetCapacity(STARTUPINFO , siSize := A_PtrSize*4 + 4*8 + A_PtrSize*5, 0) NumPut(siSize , STARTUPINFO) NumPut(STARTF_USESTDHANDLES, STARTUPINFO, A_PtrSize*4 + 4*7) NumPut(hPipeWrite , STARTUPINFO, A_PtrSize*4 + 4*8 + A_PtrSize*3) NumPut(hPipeWrite , STARTUPINFO, A_PtrSize*4 + 4*8 + A_PtrSize*4) VarSetCapacity(PROCESS_INFORMATION, A_PtrSize*2 + 4*2, 0) pipeName := "AHK_" . A_TickCount for k, v in ["pipeGA", "pipe"] %v% := DllCall("CreateNamedPipe", "Str", "\\.\pipe\" . pipeName, params*) sCmd := A_AhkPath . " ""\\.\pipe\" . pipeName . """" if !DllCall("CreateProcess", "UInt", 0, "Str", sCmd, "UInt", 0, "UInt", 0, "Int", true, "UInt", CREATE_NO_WINDOW , "UInt", 0, "UInt", 0, "Ptr", &STARTUPINFO, "Ptr", &PROCESS_INFORMATION) { DllCall("CloseHandle", "Ptr", hPipeRead) DllCall("CloseHandle", "Ptr", hPipeWrite) for k, v in ["pipeGA", "pipe"] DllCall("CloseHandle", "Ptr", %v%) throw Exception("CreateProcess is failed") } DllCall("CloseHandle", "Ptr", hPipeWrite) for k, v in ["pipeGA", "pipe"] DllCall("ConnectNamedPipe", "Ptr", %v%, "Ptr", 0) tempScript := BOM . script tempScriptSize := ( StrLen(tempScript) + 1 ) << !!A_IsUnicode DllCall("WriteFile", "Ptr", pipe, "Str", tempScript, "UInt", tempScriptSize, "UIntP", 0, "Ptr", 0) for k, v in ["pipeGA", "pipe"] DllCall("CloseHandle", "Ptr", %v%) nSize := fullSize := 0, heapSize := buffSize = 0 ? 4096 : buffSize pHeap := DllCall("HeapAlloc", "Ptr", hHeap, "UInt", HEAP_ZERO_MEMORY, "Ptr", heapSize, "Ptr") Loop { Sleep, 10 DllCall("PeekNamedPipe", "Ptr", hPipeRead, "Ptr", 0, "UInt", 0, "Ptr", 0, "UIntP", avail, "Ptr", 0) } until (buffSize && avail = buffSize) || (!buffSize && avail) || A_Index = 100 while DllCall("ReadFile", "Ptr", hPipeRead, "Ptr", pHeap + fullSize, "UInt", heapSize, "UIntP", nSize, "UInt", 0) { fullSize += nSize if (fullSize > heapSize - nSize) { heapSize *= 2 pHeap := DllCall("HeapReAlloc", "Ptr", hHeap, "UInt", HEAP_ZERO_MEMORY, "Ptr", pHeap, "Ptr", heapSize, "Ptr") } } DllCall("CloseHandle", "Ptr", NumGet(PROCESS_INFORMATION)) DllCall("CloseHandle", "Ptr", NumGet(PROCESS_INFORMATION, A_PtrSize)) DllCall("CloseHandle", "Ptr", hPipeRead) VarSetCapacity(buff, fullSize) DllCall("RtlMoveMemory", "Ptr", &buff, "Ptr", pHeap, "Ptr", fullSize) DllCall("HeapFree", "Ptr", hHeap, "UInt", 0, "Ptr", pHeap) Return fullSize }
I used not modified 7-zip.dll.
Code: Select all
#MaxMem 4095
SetBatchLines, -1
zipFile := A_ScriptDir . "\test.7z"
pathInsideZip := "Folder\SubFolder\test.txt"
7ZipDLL := "7-zip" . A_PtrSize*8 . ".dll"
7zip := new 7zipToBuff(7ZipDLL, zipFile, pathInsideZip)
7zip.UnzipToBuff(buff)
output := 7zip.output
7zip := ""
MsgBox, % output
MsgBox, % Clipboard := StrGet(&buff, "cp0")
class 7zipToBuff {
__New(7ZipDLL, zipFile, pathInsideZip) {
static STD_OUTPUT_HANDLE := -11, DUPLICATE_SAME_ACCESS := 0x2
if !FileExist(7ZipDLL)
throw 7ZipDLL . " not found"
if !this.hModule := DllCall("LoadLibrary", "Str", 7ZipDLL, "Ptr")
throw "LoadLibrary failed"
this.7ZipDLL := 7ZipDLL
this.zipFile := zipFile
this.pathInsideZip := pathInsideZip
this.savedStdOut := DllCall("GetStdHandle", "UInt", STD_OUTPUT_HANDLE, "Ptr")
this.buffSize := this.GetBuffSize()
DllCall("CreatePipe", "PtrP", hReadTemp, "PtrP", hPipeWrite, "Ptr", 0, "UInt", this.buffSize)
hProc := DllCall("GetCurrentProcess")
DllCall("DuplicateHandle", "Ptr", hProc, "Ptr", hReadTemp, "Ptr", hProc, "PtrP", hReadPipe, "UInt", 0, "UInt", false, "UInt", DUPLICATE_SAME_ACCESS)
this.hReadPipe := hReadPipe
DllCall("CloseHandle", "Ptr", hReadTemp)
DllCall("SetStdHandle", "UInt", STD_OUTPUT_HANDLE, "Ptr", hPipeWrite)
this.saved_stdout := DllCall("msvcrt\_dup", "Int", 1)
this.fd := DllCall("msvcrt\_open_osfhandle", "Ptr", DllCall("GetStdHandle", "UInt", STD_OUTPUT_HANDLE, "Ptr"), "Int", 0)
DllCall("msvcrt\_dup2", "Int", this.fd, "Int", 1)
}
__Delete() {
DllCall("FreeLibrary", "Ptr", this.hModule)
DllCall("msvcrt\_dup2", "Int", this.saved_stdout, "Int", 1)
DllCall("msvcrt\_close", "Int", this.fd)
DllCall("SetStdHandle", "UInt", STD_OUTPUT_HANDLE := -11, "Ptr", this.savedStdOut)
}
UnzipToBuff(ByRef buff) {
VarSetCapacity(buff, this.buffSize)
this.output := this.SevenZip("e -hide """ . this.zipFile . """ """ . this.pathInsideZip . """ -so")
Loop {
Sleep, 10
DllCall("PeekNamedPipe", "Ptr", this.hReadPipe, "Ptr", 0, "UInt", 0, "Ptr", 0, "UIntP", avail, "Ptr", 0)
} until avail = this.buffSize || A_Index = 100
fullSize := 0
Loop {
res := DllCall("ReadFile", "Ptr", this.hReadPipe, "Ptr", &buff + fullSize, "UInt", this.buffSize, "UIntP", nSize, "UInt", 0)
fullSize += nSize
} until !res || fullSize = this.buffSize
}
GetBuffSize() {
hArc := DllCall(this.7ZipDLL . "\SevenZipOpenArchive", "Ptr", 0, "AStr", this.zipFile, "Int", 0)
VarSetCapacity(INDIVIDUALINFO, 558, 0)
DllCall(this.7ZipDLL . "\SevenZipFindFirst", "Ptr", hArc, "AStr", this.pathInsideZip, "Ptr", &INDIVIDUALINFO)
DllCall(this.7ZipDLL . "\SevenZipCloseArchive", "Ptr", hArc)
Return NumGet(INDIVIDUALINFO, "UInt")
}
SevenZip(sCommand) {
VarSetCapacity(output, size := 1024)
res := DllCall(this.7ZipDLL . "\SevenZip", "Ptr", 0, "AStr", sCommand, "Ptr", &output, "Int", size)
return StrGet(&output, nSize, "CP0")
}
}