UNLHA32.DLLを使用した基本的な圧縮・解凍のサンプルプログラム(32bit)

icon 項目のみ表示/展開表示の切り替え

概要

ある業務ソフトのアップデート処理のための専用のソフトを開発するために、LZHファイルの解凍をサポートする必要がありました。
本プログラムは、LZHファイルの圧縮・解凍を行います。
圧縮するファイル及び圧縮結果のLZHファイル、解凍するLZHファイル、解凍先はソースコードの文字列で記述しています。
現在、LHAはサポートを中止しているので、過去の遺産を処理する以外の新規採用は推奨しない。
UNLHA32.DLLは以下のホームページよりダウンロードできる。
Micco's HomePage http://micco.mars.jp/mysoft/unlha32.htm

テスト環境

コンパイラ

Visual C++ 2008/2013 Express 32bit マルチバイト/UNICODE

実行環境

Windows 7 Enterprise Service Pack 1 64bit(Sandy Bridge-E)

プログラムソースの概要

本プログラムは、UNLHA32.DLLを動的に呼び出しますので、DLLのロードや関数へのポインタの取得などが必要となります。
定形処理なので、クラス化しました。
カレントフォルダーにある1.txt 2.txt ファイルを圧縮しtest.lzhに保存します。
test.lzhファイルを解凍し、D:\testフォルダーに解凍します。

UNLHA32.DLLの使い方

DLLを動的に呼び出す場合、LoadLibrary APIによりDLLを呼び出し、GetProcAddress APIにより関数へのポインタを取得します。
圧縮や解凍はUnLha関数を呼び出すことにより実行します。
UnLha(const HWND _hwnd, LPCSTR _szCmdLine, LPSTR _szOutput, const DWORD _dwSize);
戻り値は0の場合正常終了です。

hWnd

親ウィンドウのハンドルです。親ハンドルがない場合は0を指定します。

szCmdLine

lha.exeと同形式のコマンドラインオプションを指定します。UNICODE文字列の場合はシフトJISに変換してから渡します。
オプションの詳細は、lha.exeを検索してください。
圧縮する場合
以下の様に記述します。ソースファイルは空白で複数指定できます。空白を含むファイル名の場合はダブルコーテーションでくくります。uが圧縮を示し、-a1はファイルの属性を保存することを指定しています。

u -a1 LZHファイル名 ソースファイル
解凍する場合
以下の様に記述します。空白を含むファイル名の場合はダブルコーテーションでくくります。eが解凍示し、-a1はファイルの属性を再現(日付等)することを指定しています。

e -a1 LZHファイル名 展開先フォルダー

szOutput

UNLHA32.DLLの実行結果の文字列が保存されます。

dwSize

szOutputの大きさを設定します。

クラス UnLhaLib

DLLのロード・解放及び関数へのポインタの取得及びUNICODE/マルチバイトによる圧縮・解凍をサポートします。

コンストラクター UnLhaLib

UnLhaLibのオブジェクトの初期化時に自動的に呼び出されます。
DLLロード及び関数へのポインタの取得を行います。

Init

UNLHA32.DLL及び関数が使用可能どうかを返します。

圧縮 pack

srcDirフォルダとsrcFilesで指定された複数のファイルを圧縮し、lzhFileで指定したファイルに保存します。
すでにLZHファイルが存在する場合は、ファイルを追加します。
複数のファイルをダブルコーテーションで囲まれ空白で区切られた1つの文字列に変換するために必要なメモリサイズを引数szで指定します。
ファイルが大量に存在する場合、かなりのメモリ容量が必要なので、動的に確保するようにしました。szを省略した場合4096バイトとなります。
UNICODEでコンパイルした場合、WideCharToMultiByte APIによりSJISに変換して、UnLha関数を呼び出します。 outstr配列はUnLha関数の実行時のメッセージが保存されます。

解凍 extract

srcFileで指定されたLZHファイルをdtcDirフォルダに解凍します。
dtcDirフォルダが存在しない場合は、ダイアログボックスが表示され、フォルダを作成するかどうか尋ねてきます。
UNICODEでコンパイルした場合、WideCharToMultiByte APIによりSJISに変換して、UnLha関数を呼び出します。 outstr配列はUnLha関数の実行時のメッセージが保存されます。

デストラクタ ~UnLhaLib

UnLhaLibオブジェクトが解放される前に自動的に呼び出されます。
ライブラリの解放を行います。

_tWinMain

UnLhaLibオブジェクトを作成し、Initメンバ関数によりUNLHA32.DLLが使用可能かどうかを確認します。
packメンバー関数により圧縮、extractメンバー関数により解凍を行います。

ソースコード


//      UNLHA32.DLLを使用した基本的な圧縮・解凍のサンプルプログラム
//      Visual C++ 2008/2013 Unicode/マルチバイト 32bit専用

//      UNLHA32.DLL ダウンロード先 http://micco.mars.jp/mysoft/unlha32.htm
//      インストルール先 Windows 32bit C:\Program Files\ArchiverDll\UNLHA32
//      インストルール先 Windows 64bit C:\Program Files (x86)\ArchiverDll\UNLHA32

#ifdef _WIN64
        #error 64bitでコンパイルするとUNLHA32.DLLが使用できません
#endif


#include <windows.h>
#include <stdio.h>
#include <tchar.h>

class UnLhaLib{
        typedef int (WINAPI *UNLHAFUNC)(const HWND _hwnd, LPCSTR _szCmdLine, LPSTR _szOutput, const DWORD _dwSize);
        HINSTANCE hMod;
        UNLHAFUNC UnlhaFunc;
public:
        UnLhaLib(){
                UnlhaFunc=0;
                hMod = LoadLibrary(_TEXT("unlha32.dll"));
                if(hMod==0)
                        UnlhaFunc=0;
                else
                        UnlhaFunc = (UNLHAFUNC)GetProcAddress(hMod,"Unlha");
        }
        //      UNLHA.DLLが使用可能かチェックする
        bool Init(void){
                return UnlhaFunc==0 ? false : true;
        }
        ~UnLhaLib(){
                if(hMod)
                        FreeLibrary(hMod);
        }
        
        //      圧縮
        int pack(HWND hWnd,TCHAR* lzhFile,TCHAR* srcDir,TCHAR** srcFiles,int sz=0){
                char outstr[32768];
                int ret;
                outstr[0]='\0';

                if(sz==0)
                        sz=4096;
                TCHAR* cmd=new TCHAR[sz];
                if(cmd==0)
                        return -1;

                _stprintf_s(cmd,sz,_TEXT("u -a1 \"%s\" \"%s\""),lzhFile,srcDir);
                TCHAR** p=srcFiles;
                TCHAR file[MAX_PATH+2];
                while(*p){
                        _stprintf_s(file,sizeof(file)/sizeof(TCHAR),_TEXT(" \"%s\""),*p);
                        _tcscat_s(cmd,sz,file);
                        ++p;
                }
#ifdef UNICODE
                char* cmd_sjis=new char[sz];

                if(cmd_sjis==0){
                        delete []cmd;
                        return -1;
                }
                WideCharToMultiByte(932,0,cmd,-1,cmd_sjis,sizeof(cmd_sjis),NULL,NULL);

                ret= (*UnlhaFunc)(hWnd, cmd_sjis, outstr ,32767);
                delete []cmd_sjis;
#else
                ret= (*UnlhaFunc)(hWnd, cmd, outstr ,32767);
#endif
                delete []cmd;
                return ret;
        }

        //      解凍
        int extract(HWND hWnd,TCHAR* dtcDir,TCHAR* srcFile){
                char outstr[32768];
                outstr[0] = '\0';
                TCHAR cmd[MAX_PATH*2+8];

                _stprintf_s(cmd,sizeof(cmd)/sizeof(TCHAR),_TEXT("e -a1 \"%s\" \"%s\""),srcFile,dtcDir);

#ifdef UNICODE
                char cmd_sjis[sizeof(cmd)];
                WideCharToMultiByte(932,0,cmd,-1,cmd_sjis,sizeof(cmd_sjis),NULL,NULL);

                return (*UnlhaFunc)(hWnd, cmd_sjis, outstr ,32767);
#else
                return (*UnlhaFunc)(hWnd, cmd, outstr ,32767);
#endif
        }
};


//      圧縮するファイルを指定
TCHAR* packSrcFiles[]={ _TEXT("1.txt"),_TEXT("2.txt"),0 };

//      圧縮結果を保存するLZHファイルを指定
TCHAR* packLzhFile=_TEXT("test.lzh");

//      圧縮するファイルのディレクトリを指定
TCHAR* packSrcDir=_TEXT("");

//      解凍するLZHファイルを指定
TCHAR* extractSrcFile=_TEXT("test.lzh");

//      解凍先ディレクトリを指定
TCHAR* extractDtcDir=_TEXT("d:\\test\\");


int WINAPI _tWinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst,TCHAR* lpsCmdLine, int nCmdShow){
        UnLhaLib lha;

        if(lha.Init()==false){
                MessageBox(0,_TEXT("UNLHA32.DLLが使用できません。"),_TEXT("エラー"),MB_OK);
                return 1;
        }
        if(lha.pack(0,packLzhFile,packSrcDir,packSrcFiles,0)!=0){
                MessageBox(0,_TEXT("UNLHA32.DLL::Unlha関数 圧縮中にエラーが発生しました。"),_TEXT("エラー"),MB_OK);
                return 2;
        }

        if(lha.extract(0,extractDtcDir,extractSrcFile)!=0){
                MessageBox(0,_TEXT("UNLHA32.DLL::Unlha関数 解凍中にエラーが発生しました。"),_TEXT("エラー"),MB_OK);
                return 3;
        }
        return 0;
}

実行ファイルとソースファイルのダウンロード