Sign in to follow this  
Followers 0
dany

7z UDF WIP: Can 7z.dll be used in AutoIt?

5 posts in this topic

Well I spent my lazy and rainy sunday afternoon trying to wrap the native 7z.dll in an AutoIt UDF.

I searched the forum and found that it only works with a third party DLL wrapper (rasim's UDF). However, I also came across this codeproject with the following statement:

Important Update: Starting from 7-Zip 4.46 alpha Igor did necessary changes in the code. So, from this version forward, you can use format DLLs directly, without applying any patch. Superb!

I figured this meant that the problems involving COM and Interfaces was solved and that a third party wrapper was no longer necessary. Then I came across the following prototypes exported by 7z.dll:

UInt32 WINAPI CreateObject(const GUID *clsID, const GUID *interfaceID, void **outObject);
UInt32 WINAPI GetNumberOfMethods(UInt32 *numMethods);
UInt32 WINAPI GetMethodProperty(UInt32 index, PROPID propID, PROPVARIANT *value);
UInt32 WINAPI GetNumberOfFormats(UInt32 *numFormats);
UInt32 WINAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value);
UInt32 WINAPI GetHandlerProperty2(UInt32 index, PROPID propID, PROPVARIANT *value);
UInt32 WINAPI SetLargePageMode();

I wrote AutoIt equivalents and used the latest 7z.dll. Here's a sample of _7z_GetNumberOfMethods:

Func _7z_GetNumberOfMethods()
    If Not _7z_Startup() Then Return SetError(@error, 0, 0)
    Local $aRes = DllCall($__7z_hDLL, 'uint', 'GetNumberOfMethods', 'uint*', 0)
    If @error Then Return SetError(@error, 0, 0)
    Return $aRes[1]
EndFunc   ;==>_7z_GetNumberOfMethods

The entire UDF is attached below btw.

Anyway, it works. Kinda. _7z_GetNumberOfMethods() returns 21 and _7z_GetNumberOfFormats() 42.

But I can't get _7z_CreateObject() to work... It returns a pointer type as defined but it's always 0. Mind you, I'm not even sure the 7z GUID's are used correctly or that the DllCall() is using the right parameter types...

Because 7zip uses COM objects I suspected that DllCall wasn't the right way so I didn't put too much research in it. Instead I read up on ObjGet and the likes and did another forum search. It became clear that in order to work at all, the DLL in question needs to be registered. But unfortunately 7z.dll neither exports a DllRegisterServer nor a DllInstall method. So the DLL can't be registered...

Below is the UDF I came up with. It's still lots of boilerplate code but atleast I got a partial success. However, I feel like I'm in over my head here and before putting any more time in it I want to know if it's a dead-end I'm pursuing.

And if it's not a dead-end, then how to continue? Is there a workaround for the DllRegisterServer problem that I can exploit to use Obj* functions? Or maybe I can use DllCallAddress() in any way? Maybe use a different DLL from the 7zip package? Any feedback would be much appreciated!

The UDF:

7z.au3

A simple example:

_7z_Startup() ; _7z_Startup('C:PathTo7z.dll')
Global $sVersion = _7z_GetVersion() ; Works.
Global $iNumMethods = _7z_GetNumberOfMethods() ; Works.
Global $iNumFormats = _7z_GetNumberOfFormats() ; Works.
; $7Z_INTERFACE_UNKNOWN = '00000000-0000-0000-C000-000000000046'
; $7Z_INTERFACE_IN_ARCHIVE = '23170F69-40C1-278A-0000-006000060000'
Global $o7zObj = _7z_CreateObject($7Z_INTERFACE_UNKNOWN, $7Z_INTERFACE_IN_ARCHIVE) ; FAIL.
MsgBox(0, '', '7zip version: ' & $sVersion & @CRLF _
    & 'Number of 7zip methods: ' & $iNumMethods & @CRLF _
    & 'Number of 7zip formats: ' & $iNumFormats & @CRLF _
    & '_7z_CreateObject result: ' & VarGetType($o7zObj) & ' value: ' & $o7zObj)

NB: The example uses _7z_Startup() without any parameters. On line 273 in 7z.au3 the path is set to:

Global $__7z_sDLLDir = @ScriptDir & 'Res'

It's very likely your 7z.dll is located elsewhere, so pass the full path including 7z.dll filename to _7z_Startup().

Also make sure that the 7z.dll used is 64-bit when running 64-bit AutoIt. Same applies to 32-bit, the UDF has a function that checks for this.

1 person likes this

[center]Spiderskank Spiderskank[/center]GetOpt Parse command line options UDF | AU3Text Program internationalization UDF | Identicon visual hash UDF

Share this post


Link to post
Share on other sites



Thanks for your reply, but you misunderstood. I mentioned rasim's UDF.

I wanted to know if I can use the native 7z.dll and not a third-party dll. Also, jak's website is dead and gone (unfortunately) but I found this new one here: http://www.csdinc.co.jp/archiver/lib/7-zip32.html

I'll look into it but it's not what I meant.


[center]Spiderskank Spiderskank[/center]GetOpt Parse command line options UDF | AU3Text Program internationalization UDF | Identicon visual hash UDF

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

Hello dany, after reading your post and code, I do some search about native 7zip dll.

If we read the 7Zip FAQ, we can read this :

How can I add support for 7z archives to my application?

One way is to use the 7z.dll or 7za.dll (available from sf.net for download). The 7za.dll works via COM interfaces. It, however, doesn't use standard COM interfaces for creating objects. You can find a small example in "CPP7zipUIClient7z" folder in the source code. A full example is 7-Zip itself, since 7-Zip works via this dll also. There are other applications that use 7za.dll such as WinRAR, PowerArchiver and others.

The other way is to call the command line version: 7za.exe.

If I remember well, the use of 7za.exe in already realized but there is no 64 bit version.

So after searching again, on this page http://7-zip.org/download.html , I'll take the source code for reading the small exemple above (CPP7zipUIClient7z) and if you take a look on the file just down (7z Library, SFXs for installers, Plugin for FAR Manager), you can find a 32 bit and a 64 bit version of the 7za.dll !!!

Thus, can be that instead of using 7z.dll, it would be more sensible to use 7za.dll. I have read the file Client7z.cpp, but, unfortunately, I do not know C language ...

Maybe someone here can help us to translate the C code on AutoIt and like this we can have a good start point. ;)

Edited by Tlem

Best Regards.Thierry

Share this post


Link to post
Share on other sites

#5 ·  Posted (edited)

Hi Tlem, thanks for replying and your suggestions. However, tried them already. Here's what I found:

Neither dll exposes it's COM interface in a standard way afaik.

I've tried a DllCall on the exported CreateObject function, but the return value isn't an object or pointer that can be used by AutoIt. I've already tried dozens of combinations porting example code from Client7z.cpp but no results. I've even tried DllCallAddress only to have AutoIt crash on me.

Using AutoIts ObjCreate also doesn't work. For COM objects to be used that way a dll must be registered first with rgsvr32. That fails as the dll doesn't export a DllRegisterServer function. So that route is closed too afaik.

These two issues are the whole problem in a nutshell and the reason why Minoru Akita wrote his 7Zip32.dll. Thusfar I've found no way to use original 7zip dll's in AutoIt. Thanks anyway for putting your thoughts into it, much appreciated.

edit: fixd typo's.

Edited by dany

[center]Spiderskank Spiderskank[/center]GetOpt Parse command line options UDF | AU3Text Program internationalization UDF | Identicon visual hash UDF

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0