Extract ZIP to RAM?

Get help with using AutoHotkey and its commands and hotkeys
User avatar
TheDewd
Posts: 1391
Joined: 19 Dec 2013, 11:16
Location: USA

Extract ZIP to RAM?

29 Oct 2019, 08:25

How can I extract a file from a zip archive to memory without writing anything to the harddrive?

If possible, I would prefer to use one of the 7zip dll files.

I want to unpack a single file from a zip archive into RAM, and then be able to read the contents of the file from RAM.

Any ideas? I know it's possible, but I'm not sure where to start...
Image Bulldozer - Sokoban inspired game from 1994 recreated in AutoHotkey.
User avatar
Capn Odin
Posts: 1308
Joined: 23 Feb 2016, 19:45
Location: Denmark

Re: Extract ZIP to RAM?

29 Oct 2019, 08:42

I guess you could extract it to a named pipe.
Please excuse my spelling I am dyslexic.
User avatar
TheDewd
Posts: 1391
Joined: 19 Dec 2013, 11:16
Location: USA

Re: Extract ZIP to RAM?

29 Oct 2019, 09:49

Capn Odin wrote:
29 Oct 2019, 08:42
I guess you could extract it to a named pipe.

Thanks! I'll reference keywords "Named Pipe" and "CreateNamedPipe" in my Google searches to see if I can figure out a solution.

My goal is to read the raw binary of the compressed file without extracting the file to the hard disk.

If anyone can provide a simple example, it would be greatly appreciated!
Image Bulldozer - Sokoban inspired game from 1994 recreated in AutoHotkey.
White_Whale
Posts: 73
Joined: 27 Sep 2019, 01:44

Re: Extract ZIP to RAM?

29 Oct 2019, 11:07

sounds good
If you found nice answer please let me know too, that is the item I was looking for long time.
Regards
White_Whale
Posts: 73
Joined: 27 Sep 2019, 01:44

Re: Extract ZIP to RAM?

29 Oct 2019, 12:18

just 1 minute Googling
I will check it out with time

https://www.autohotkey.com/boards/viewtopic.php?t=9858
User avatar
TheDewd
Posts: 1391
Joined: 19 Dec 2013, 11:16
Location: USA

Re: Extract ZIP to RAM?

29 Oct 2019, 12:30

White_Whale wrote:
29 Oct 2019, 12:18
just 1 minute Googling
I will check it out with time

https://www.autohotkey.com/boards/viewtopic.php?t=9858
Please let me know if you figure out how to do this.

I have attached an example for extracting a file using the 7Zip DLL file, however I don't know how to set the output to the named pipe.

Code: Select all

SevenZip
SevenZipCheckArchive
SevenZipClearOwnerWindow
SevenZipCloseArchive
SevenZipConfigDialog
SevenZipFindFirst
SevenZipFindNext
SevenZipGetAccessTime
SevenZipGetAccessTimeEx
SevenZipGetArcAccessTimeEx
SevenZipGetArcCompressedSize
SevenZipGetArcCompressedSizeEx
SevenZipGetArcCreateTimeEx
SevenZipGetArcDate
SevenZipGetArcFileName
SevenZipGetArcFileSize
SevenZipGetArcFileSizeEx
SevenZipGetArchiveType
SevenZipGetArcOriginalSize
SevenZipGetArcOriginalSizeEx
SevenZipGetArcOSType
SevenZipGetArcRatio
SevenZipGetArcTime
SevenZipGetArcWriteTimeEx
SevenZipGetAttribute
SevenZipGetBackGroundMode
SevenZipGetCompressedSize
SevenZipGetCompressedSizeEx
SevenZipGetCRC
SevenZipGetCreateTime
SevenZipGetCreateTimeEx
SevenZipGetCursorInterval
SevenZipGetCursorMode
SevenZipGetDate
SevenZipGetDefaultPassword
SevenZipGetFileCount
SevenZipGetFileName
SevenZipGetMethod
SevenZipGetOriginalSize
SevenZipGetOriginalSizeEx
SevenZipGetOSType
SevenZipGetRatio
SevenZipGetRunning
SevenZipGetSubVersion
SevenZipGetTime
SevenZipGetVersion
SevenZipGetWriteTime
SevenZipGetWriteTimeEx
SevenZipIsSFXFile
SevenZipKillOwnerWindowEx
SevenZipKillOwnerWindowEx64
SevenZipOpenArchive
SevenZipPasswordDialog
SevenZipQueryFunctionList
SevenZipSetBackGroundMode
SevenZipSetCursorInterval
SevenZipSetCursorMode
SevenZipSetDefaultPassword
SevenZipSetOwnerWindow
SevenZipSetOwnerWindowEx
SevenZipSetOwnerWindowEx64
SevenZipSetPriority
SevenZipSetUnicodeMode

7-Zip DLL Related: https://www.autohotkey.com/boards/viewtopic.php?f=76&t=68074
Attachments
7ZipExtract_Example.zip
(1000.29 KiB) Downloaded 59 times
Image Bulldozer - Sokoban inspired game from 1994 recreated in AutoHotkey.
White_Whale
Posts: 73
Joined: 27 Sep 2019, 01:44

Re: Extract ZIP to RAM?

30 Oct 2019, 05:58

I just Googled once
Found nothing meaningful yet, I am kind of busy.

Regards
tmplinshi
Posts: 1561
Joined: 01 Oct 2013, 14:57

Re: Extract ZIP to RAM?

30 Oct 2019, 06:22

The 7zip dll from 7-zip32_ungarbled has a SevenZipExtractMem function, source:

Code: Select all

int WINAPI SevenZipExtractMem(HWND _hwnd, LPCSTR _szCmdLine, LPBYTE _szBuffer, const DWORD _dwSize, time_t * _lpTime, LPWORD _lpwAttr, LPDWORD _lpdwWriteSize){
	HANDLE readPipe = NULL, writePipe=NULL, readTemp=NULL;
	HANDLE savedStdOut = GetStdHandle(STD_OUTPUT_HANDLE);

	::CreatePipe(&readTemp, &writePipe, NULL, INFINITE);
	::DuplicateHandle(::GetCurrentProcess(), readTemp, ::GetCurrentProcess(), &readPipe, 0, FALSE, DUPLICATE_SAME_ACCESS);
	::CloseHandle(readTemp);
	::SetStdHandle(STD_OUTPUT_HANDLE, writePipe);

	int saved_stdout = dup(1);
	int fd = ::_open_osfhandle((intptr_t)::GetStdHandle(STD_OUTPUT_HANDLE), 0);
	::dup2(fd, 1);

	g_StdOut.SetStdOutMode(TRUE);
	SevenZip(_hwnd, _szCmdLine, NULL, 0);

	DWORD availBytes = 0, readBytes = 0;
	if (! (::PeekNamedPipe(readPipe, NULL, 0, NULL, &availBytes, NULL) && availBytes && ::ReadFile(readPipe, _szBuffer, _dwSize, &readBytes, NULL)))
		return ERROR_CANNOT_READ;

	::dup2(saved_stdout, 1);
	::_close(fd);
	::SetStdHandle(STD_OUTPUT_HANDLE, savedStdOut);
	return 0;
}

Example of using SevenZipExtractMem function:

Code: Select all

#NoEnv
SetWorkingDir %A_ScriptDir%

; 7-zip32.dll and 7-zip64.dll can be downloaded at http://frostmoon.sakura.ne.jp/7-zip32_ungarbled/index.html

global 7zipDll := (A_PtrSize = 8) ? "7-zip64.dll" : "7-zip32.dll"
if !hModule := DllCall("LoadLibrary", "str", 7zipDll, "ptr")
	throw "LoadLibrary fail"

msgbox % SevenZip_ExtractMem("test.zip", "test2.txt")


SevenZip_ExtractMem(archive_name, file_name) {
	msgbox % nSize := SevenZip_GetOriginalSize(archive_name, file_name)

	VarSetCapacity(data, nSize)
	sCmdLine = x -hide "%archive_name%" "%file_name%"
	DllCall(7zipDll . "\SevenZipExtractMem", "ptr", 0, "astr", sCmdLine, "ptr", &data, "uint", nSize)

	; CRC := DllCall("ntdll.dll\RtlComputeCrc32", "uint", CRC, "ptr", &data, "uint", nSize, "uint")
	; MsgBox % "CRC = " Format("{:X}", CRC)

	return StrGet(&data, "cp0")
}

SevenZip(sCmdLine, _hwnd:=0) {
	nSize := 32768
	VarSetCapacity(output, nSize)
	DllCall(7zipDll . "\SevenZip", "ptr", _hwnd, "astr", sCmdLine, "ptr", &output, "uint", nSize)
	return StrGet(&output, nSize, "cp0")
}

SevenZip_GetOriginalSize(archive_name, file_name) {
	CmdLine = l -slt "%archive_name%" "%file_name%"
	out := SevenZip(CmdLine)
	if RegExMatch(out, "`am)^Size = \K\d+", size)
		return size
}

/*
SevenZip_GetOriginalSize(ArchiveFile, sSearch := "") {
	if !hArc := DllCall(7zipDll . "\SevenZipOpenArchive", "ptr", 0, "astr", ArchiveFile, "int", 0)
		throw "SevenZipOpenArchive fail"

	VarSetCapacity(info, 558, 0)
	ret := DllCall(7zipDll . "\SevenZipFindFirst", "ptr", hArc, "astr", sSearch, "ptr", &info)
	oriSize := NumGet(info, 0, "uint")
	; msgbox % filename := StrGet(&info+26, 513, "CP0")

	DllCall(7zipDll . "\SevenZipCloseArchive", "ptr", hArc)
	return oriSize
}
*/

SevenZipExtractMem Example.zip

However it will crash if I double-click the script. It works if I drag the script onto the AutoHotkey.exe icon.
User avatar
TheDewd
Posts: 1391
Joined: 19 Dec 2013, 11:16
Location: USA

Re: Extract ZIP to RAM?

30 Oct 2019, 12:40

@tmplinshi,

Wow! Thank you for providing this example!

I will experiment with the sample code and try to prevent the crashing.
Image Bulldozer - Sokoban inspired game from 1994 recreated in AutoHotkey.
White_Whale
Posts: 73
Joined: 27 Sep 2019, 01:44

Re: Extract ZIP to RAM?

30 Oct 2019, 21:23

nice tip
though not tested yet...
I was hoping that I'd like to accomplish without extra codes of outside...
User avatar
hasantr
Posts: 497
Joined: 05 Apr 2016, 14:18
Location: İstanbul

Re: Extract ZIP to RAM?

31 Oct 2019, 07:00

tmplinshi wrote:
30 Oct 2019, 06:22
The 7zip dll from 7-zip32_ungarbled has a SevenZipExtractMem function, source:

Code: Select all

int WINAPI SevenZipExtractMem(HWND _hwnd, LPCSTR _szCmdLine, LPBYTE _szBuffer, const DWORD _dwSize, time_t * _lpTime, LPWORD _lpwAttr, LPDWORD _lpdwWriteSize){
	HANDLE readPipe = NULL, writePipe=NULL, readTemp=NULL;
	HANDLE savedStdOut = GetStdHandle(STD_OUTPUT_HANDLE);

	::CreatePipe(&readTemp, &writePipe, NULL, INFINITE);
	::DuplicateHandle(::GetCurrentProcess(), readTemp, ::GetCurrentProcess(), &readPipe, 0, FALSE, DUPLICATE_SAME_ACCESS);
	::CloseHandle(readTemp);
	::SetStdHandle(STD_OUTPUT_HANDLE, writePipe);

	int saved_stdout = dup(1);
	int fd = ::_open_osfhandle((intptr_t)::GetStdHandle(STD_OUTPUT_HANDLE), 0);
	::dup2(fd, 1);

	g_StdOut.SetStdOutMode(TRUE);
	SevenZip(_hwnd, _szCmdLine, NULL, 0);

	DWORD availBytes = 0, readBytes = 0;
	if (! (::PeekNamedPipe(readPipe, NULL, 0, NULL, &availBytes, NULL) && availBytes && ::ReadFile(readPipe, _szBuffer, _dwSize, &readBytes, NULL)))
		return ERROR_CANNOT_READ;

	::dup2(saved_stdout, 1);
	::_close(fd);
	::SetStdHandle(STD_OUTPUT_HANDLE, savedStdOut);
	return 0;
}

Example of using SevenZipExtractMem function:

Code: Select all

#NoEnv
SetWorkingDir %A_ScriptDir%

; 7-zip32.dll and 7-zip64.dll can be downloaded at http://frostmoon.sakura.ne.jp/7-zip32_ungarbled/index.html

global 7zipDll := (A_PtrSize = 8) ? "7-zip64.dll" : "7-zip32.dll"
if !hModule := DllCall("LoadLibrary", "str", 7zipDll, "ptr")
	throw "LoadLibrary fail"

msgbox % SevenZip_ExtractMem("test.zip", "test2.txt")


SevenZip_ExtractMem(archive_name, file_name) {
	msgbox % nSize := SevenZip_GetOriginalSize(archive_name, file_name)

	VarSetCapacity(data, nSize)
	sCmdLine = x -hide "%archive_name%" "%file_name%"
	DllCall(7zipDll . "\SevenZipExtractMem", "ptr", 0, "astr", sCmdLine, "ptr", &data, "uint", nSize)

	; CRC := DllCall("ntdll.dll\RtlComputeCrc32", "uint", CRC, "ptr", &data, "uint", nSize, "uint")
	; MsgBox % "CRC = " Format("{:X}", CRC)

	return StrGet(&data, "cp0")
}

SevenZip(sCmdLine, _hwnd:=0) {
	nSize := 32768
	VarSetCapacity(output, nSize)
	DllCall(7zipDll . "\SevenZip", "ptr", _hwnd, "astr", sCmdLine, "ptr", &output, "uint", nSize)
	return StrGet(&output, nSize, "cp0")
}

SevenZip_GetOriginalSize(archive_name, file_name) {
	CmdLine = l -slt "%archive_name%" "%file_name%"
	out := SevenZip(CmdLine)
	if RegExMatch(out, "`am)^Size = \K\d+", size)
		return size
}

/*
SevenZip_GetOriginalSize(ArchiveFile, sSearch := "") {
	if !hArc := DllCall(7zipDll . "\SevenZipOpenArchive", "ptr", 0, "astr", ArchiveFile, "int", 0)
		throw "SevenZipOpenArchive fail"

	VarSetCapacity(info, 558, 0)
	ret := DllCall(7zipDll . "\SevenZipFindFirst", "ptr", hArc, "astr", sSearch, "ptr", &info)
	oriSize := NumGet(info, 0, "uint")
	; msgbox % filename := StrGet(&info+26, 513, "CP0")

	DllCall(7zipDll . "\SevenZipCloseArchive", "ptr", hArc)
	return oriSize
}
*/

SevenZipExtractMem Example.zip

However it will crash if I double-click the script. It works if I drag the script onto the AutoHotkey.exe icon.
It's what I've been looking for for a long time. Thank you very much.


Running it with AHK-Studio succeeds. but when you have a separate script, it's a crash.
Can the file read into memory be read as UTF-8?
tmplinshi
Posts: 1561
Joined: 01 Oct 2013, 14:57

Re: Extract ZIP to RAM?

31 Oct 2019, 07:59

hasantr wrote:
31 Oct 2019, 07:00
Can the file read into memory be read as UTF-8?
just change StrGet(&data, "cp0") to StrGet(&data, "utf-8")
User avatar
hasantr
Posts: 497
Joined: 05 Apr 2016, 14:18
Location: İstanbul

Re: Extract ZIP to RAM?

31 Oct 2019, 09:09

tmplinshi wrote:
31 Oct 2019, 07:59
hasantr wrote:
31 Oct 2019, 07:00
Can the file read into memory be read as UTF-8?
just change StrGet(&data, "cp0") to StrGet(&data, "utf-8")
Thanks. Hopefully we can handle the crash problem.
tmplinshi
Posts: 1561
Joined: 01 Oct 2013, 14:57

Re: Extract ZIP to RAM?

01 Nov 2019, 23:46

Code: Select all

SetWorkingDir %A_ScriptDir%

global 7zipDll := (A_PtrSize=8) ? "7-zip64.dll" : "7-zip32.dll"
DllCall("LoadLibrary", "str", 7zipDll, "ptr")

MsgBox % SevenZip_ExtractMem2("test.zip", "test2.txt")
ExitApp

SevenZip_ExtractMem2(archive_name, file_name) {
	DllCall("CreatePipe", "ptr*", readTemp, "ptr*", writePipe, "ptr", 0, "uint", 0)
	hcp := DllCall("GetCurrentProcess", "ptr")
	DllCall("DuplicateHandle", "ptr", hcp, "ptr", readTemp, "ptr", hcp, "ptr*", readPipe, "uint", 0, "int", false, "uint", 2)
	DllCall("CloseHandle", "ptr", readTemp)
	DllCall("SetStdHandle", "uint", -11, "ptr", writePipe)

	sCmdLine = x -so -hide "%archive_name%" "%file_name%"
	DllCall(7zipDll . "\SevenZip", "ptr", 0, "astr", sCmdLine, "ptr", 0, "uint", 0)

	if DllCall("PeekNamedPipe", "ptr", readPipe, "ptr", 0, "uint", 0, "ptr", 0, "uint*", availBytes, "ptr", 0)
	{
		if availBytes {
			VarSetCapacity(_szBuffer, availBytes)
			DllCall("ReadFile", "ptr", readPipe, "ptr", &_szBuffer, "uint", availBytes, "ptr*", readBytes, "ptr", 0)
			return StrGet(&_szBuffer, availBytes, "utf-8")
		} else {
			MsgBox, no availBytes
			ExitApp
		}
	}
}
No crash, but still doesn't work if the script was started by double-clicking in the explorer, the script displays "no availBytes".
A workaround is to reload the scirpt at the beginning.

Code: Select all

if (A_Args[1] != "<Fix>") {
	Run, %A_ScriptFullPath% "<Fix>", % A_ScriptDir
	ExitApp
}
SevenZip_ExtractMem2 Example.zip
User avatar
hasantr
Posts: 497
Joined: 05 Apr 2016, 14:18
Location: İstanbul

Re: Extract ZIP to RAM?

03 Nov 2019, 16:48

tmplinshi wrote:
01 Nov 2019, 23:46

Code: Select all

SetWorkingDir %A_ScriptDir%

global 7zipDll := (A_PtrSize=8) ? "7-zip64.dll" : "7-zip32.dll"
DllCall("LoadLibrary", "str", 7zipDll, "ptr")

MsgBox % SevenZip_ExtractMem2("test.zip", "test2.txt")
ExitApp

SevenZip_ExtractMem2(archive_name, file_name) {
	DllCall("CreatePipe", "ptr*", readTemp, "ptr*", writePipe, "ptr", 0, "uint", 0)
	hcp := DllCall("GetCurrentProcess", "ptr")
	DllCall("DuplicateHandle", "ptr", hcp, "ptr", readTemp, "ptr", hcp, "ptr*", readPipe, "uint", 0, "int", false, "uint", 2)
	DllCall("CloseHandle", "ptr", readTemp)
	DllCall("SetStdHandle", "uint", -11, "ptr", writePipe)

	sCmdLine = x -so -hide "%archive_name%" "%file_name%"
	DllCall(7zipDll . "\SevenZip", "ptr", 0, "astr", sCmdLine, "ptr", 0, "uint", 0)

	if DllCall("PeekNamedPipe", "ptr", readPipe, "ptr", 0, "uint", 0, "ptr", 0, "uint*", availBytes, "ptr", 0)
	{
		if availBytes {
			VarSetCapacity(_szBuffer, availBytes)
			DllCall("ReadFile", "ptr", readPipe, "ptr", &_szBuffer, "uint", availBytes, "ptr*", readBytes, "ptr", 0)
			return StrGet(&_szBuffer, availBytes, "utf-8")
		} else {
			MsgBox, no availBytes
			ExitApp
		}
	}
}
No crash, but still doesn't work if the script was started by double-clicking in the explorer, the script displays "no availBytes".
A workaround is to reload the scirpt at the beginning.

Code: Select all

if (A_Args[1] != "<Fix>") {
	Run, %A_ScriptFullPath% "<Fix>", % A_ScriptDir
	ExitApp
}
SevenZip_ExtractMem2 Example.zip
Thank you, it's great that you've come up with a solution. Does using multiple files in this way reduce performance?
tmplinshi
Posts: 1561
Joined: 01 Oct 2013, 14:57

Re: Extract ZIP to RAM?

04 Nov 2019, 01:29

hasantr wrote:
03 Nov 2019, 16:48
Does using multiple files in this way reduce performance?
I think so. Might doing it in this way:

Code: Select all

#NoEnv
SetWorkingDir %A_ScriptDir%

if (A_Args[1] != "<Fix>") {
	Run, %A_ScriptFullPath% "<Fix>", % A_ScriptDir
	ExitApp
}

global 7zipDll := (A_PtrSize=8) ? "7-zip64.dll" : "7-zip32.dll"
DllCall("LoadLibrary", "str", 7zipDll, "ptr")

for i, info in SevenZip_ExtractMemMulti("test.zip", "*.txt")
	MsgBox % info.filename . "`n" . info.data
	
ExitApp

SevenZip_ExtractMemMulti(archive_name, file_name := "*") {
	DllCall("CreatePipe", "ptr*", readTemp, "ptr*", writePipe, "ptr", 0, "uint", 0)
	hcp := DllCall("GetCurrentProcess", "ptr")
	DllCall("DuplicateHandle", "ptr", hcp, "ptr", readTemp, "ptr", hcp, "ptr*", readPipe, "uint", 0, "int", false, "uint", 2)
	DllCall("CloseHandle", "ptr", readTemp)
	DllCall("SetStdHandle", "uint", -11, "ptr", writePipe)

	sCmdLine = x -so -hide "%archive_name%" "%file_name%"
	DllCall(7zipDll . "\SevenZip", "ptr", 0, "astr", sCmdLine, "ptr", 0, "uint", 0)

	if DllCall("PeekNamedPipe", "ptr", readPipe, "ptr", 0, "uint", 0, "ptr", 0, "uint*", availBytes, "ptr", 0)
	&& availBytes
	{
		VarSetCapacity(_szBuffer, availBytes)
		DllCall("ReadFile", "ptr", readPipe, "ptr", &_szBuffer, "uint", availBytes, "ptr*", readBytes, "ptr", 0)
		; return StrGet(&_szBuffer, availBytes, "utf-8")

		info := SevenZip_GetOriginalSizeMulti(archive_name, file_name)
		offset := 0
		for i, o in info
		{
			o.data := StrGet(&_szBuffer+offset, o.size, "utf-8")
			offset += o.size
		}
		return info
	}
}

SevenZip_GetOriginalSizeMulti(archive_name, file_name := "*") {
	if !hArc := DllCall(7zipDll . "\SevenZipOpenArchive", "ptr", 0, "astr", archive_name, "int", 0)
		throw "SevenZipOpenArchive fail"

	VarSetCapacity(info, 558, 0)
	ret := DllCall(7zipDll . "\SevenZipFindFirst", "ptr", hArc, "astr", file_name, "ptr", &info)

	result := []
	while (ret = 0) {
		result[A_Index, "size"    ] := NumGet(info, 0, "uint")
		result[A_Index, "filename"] := StrGet(&info+26, 513, "cp0")
		ret := DllCall(7zipDll . "\SevenZipFindNext", "ptr", hArc, "ptr", &info)
	}

	DllCall(7zipDll . "\SevenZipCloseArchive", "ptr", hArc)
	return result.MaxIndex() ? result : ""
}
SevenZip_ExtractMemMulti Example.zip
User avatar
hasantr
Posts: 497
Joined: 05 Apr 2016, 14:18
Location: İstanbul

Re: Extract ZIP to RAM?

04 Nov 2019, 02:20

tmplinshi wrote:
04 Nov 2019, 01:29
hasantr wrote:
03 Nov 2019, 16:48
Does using multiple files in this way reduce performance?
I think so. Might doing it in this way:

Code: Select all

#NoEnv
SetWorkingDir %A_ScriptDir%

if (A_Args[1] != "<Fix>") {
	Run, %A_ScriptFullPath% "<Fix>", % A_ScriptDir
	ExitApp
}

global 7zipDll := (A_PtrSize=8) ? "7-zip64.dll" : "7-zip32.dll"
DllCall("LoadLibrary", "str", 7zipDll, "ptr")

for i, info in SevenZip_ExtractMemMulti("test.zip", "*.txt")
	MsgBox % info.filename . "`n" . info.data
	
ExitApp

SevenZip_ExtractMemMulti(archive_name, file_name := "*") {
	DllCall("CreatePipe", "ptr*", readTemp, "ptr*", writePipe, "ptr", 0, "uint", 0)
	hcp := DllCall("GetCurrentProcess", "ptr")
	DllCall("DuplicateHandle", "ptr", hcp, "ptr", readTemp, "ptr", hcp, "ptr*", readPipe, "uint", 0, "int", false, "uint", 2)
	DllCall("CloseHandle", "ptr", readTemp)
	DllCall("SetStdHandle", "uint", -11, "ptr", writePipe)

	sCmdLine = x -so -hide "%archive_name%" "%file_name%"
	DllCall(7zipDll . "\SevenZip", "ptr", 0, "astr", sCmdLine, "ptr", 0, "uint", 0)

	if DllCall("PeekNamedPipe", "ptr", readPipe, "ptr", 0, "uint", 0, "ptr", 0, "uint*", availBytes, "ptr", 0)
	&& availBytes
	{
		VarSetCapacity(_szBuffer, availBytes)
		DllCall("ReadFile", "ptr", readPipe, "ptr", &_szBuffer, "uint", availBytes, "ptr*", readBytes, "ptr", 0)
		; return StrGet(&_szBuffer, availBytes, "utf-8")

		info := SevenZip_GetOriginalSizeMulti(archive_name, file_name)
		offset := 0
		for i, o in info
		{
			o.data := StrGet(&_szBuffer+offset, o.size, "utf-8")
			offset += o.size
		}
		return info
	}
}

SevenZip_GetOriginalSizeMulti(archive_name, file_name := "*") {
	if !hArc := DllCall(7zipDll . "\SevenZipOpenArchive", "ptr", 0, "astr", archive_name, "int", 0)
		throw "SevenZipOpenArchive fail"

	VarSetCapacity(info, 558, 0)
	ret := DllCall(7zipDll . "\SevenZipFindFirst", "ptr", hArc, "astr", file_name, "ptr", &info)

	result := []
	while (ret = 0) {
		result[A_Index, "size"    ] := NumGet(info, 0, "uint")
		result[A_Index, "filename"] := StrGet(&info+26, 513, "cp0")
		ret := DllCall(7zipDll . "\SevenZipFindNext", "ptr", hArc, "ptr", &info)
	}

	DllCall(7zipDll . "\SevenZipCloseArchive", "ptr", hArc)
	return result.MaxIndex() ? result : ""
}
SevenZip_ExtractMemMulti Example.zip
I'm sorry. I'm in trouble with English. I think I asked the question wrong. Does performance decrease when you need to open more than one Zip file? That's what I meant.
tmplinshi
Posts: 1561
Joined: 01 Oct 2013, 14:57

Re: Extract ZIP to RAM?

04 Nov 2019, 02:43

I don't know :problem:
User avatar
hasantr
Posts: 497
Joined: 05 Apr 2016, 14:18
Location: İstanbul

Re: Extract ZIP to RAM?

05 Nov 2019, 02:13

tmplinshi wrote:
04 Nov 2019, 02:43
I don't know :problem:
Thanks. It's quite useful as it is.
User avatar
hasantr
Posts: 497
Joined: 05 Apr 2016, 14:18
Location: İstanbul

Re: Extract ZIP to RAM?

21 Nov 2019, 13:37

tmplinshi wrote:
01 Nov 2019, 23:46

Code: Select all

SetWorkingDir %A_ScriptDir%

global 7zipDll := (A_PtrSize=8) ? "7-zip64.dll" : "7-zip32.dll"
DllCall("LoadLibrary", "str", 7zipDll, "ptr")

MsgBox % SevenZip_ExtractMem2("test.zip", "test2.txt")
ExitApp

SevenZip_ExtractMem2(archive_name, file_name) {
	DllCall("CreatePipe", "ptr*", readTemp, "ptr*", writePipe, "ptr", 0, "uint", 0)
	hcp := DllCall("GetCurrentProcess", "ptr")
	DllCall("DuplicateHandle", "ptr", hcp, "ptr", readTemp, "ptr", hcp, "ptr*", readPipe, "uint", 0, "int", false, "uint", 2)
	DllCall("CloseHandle", "ptr", readTemp)
	DllCall("SetStdHandle", "uint", -11, "ptr", writePipe)

	sCmdLine = x -so -hide "%archive_name%" "%file_name%"
	DllCall(7zipDll . "\SevenZip", "ptr", 0, "astr", sCmdLine, "ptr", 0, "uint", 0)

	if DllCall("PeekNamedPipe", "ptr", readPipe, "ptr", 0, "uint", 0, "ptr", 0, "uint*", availBytes, "ptr", 0)
	{
		if availBytes {
			VarSetCapacity(_szBuffer, availBytes)
			DllCall("ReadFile", "ptr", readPipe, "ptr", &_szBuffer, "uint", availBytes, "ptr*", readBytes, "ptr", 0)
			return StrGet(&_szBuffer, availBytes, "utf-8")
		} else {
			MsgBox, no availBytes
			ExitApp
		}
	}
}
No crash, but still doesn't work if the script was started by double-clicking in the explorer, the script displays "no availBytes".
A workaround is to reload the scirpt at the beginning.

Code: Select all

if (A_Args[1] != "<Fix>") {
	Run, %A_ScriptFullPath% "<Fix>", % A_ScriptDir
	ExitApp
}
SevenZip_ExtractMem2 Example.zip
I have a strange problem.
D:\Folder\test.zip work
but
D:\Folder\inFolder\test.zip not work.
It does not open zip files in the internal folder as above.
The proposal is there a solution?
I thank you. I'm sorry I went to so much trouble.

Return to “Ask For Help”

Who is online

Users browsing this forum: Bing [Bot], Clemens375, Google [Bot] and 234 guests