フリーソフト

« C. Useful Scripts - NSIS Users Manual | トップページ | AppendixE »

D. Useful Information

これはNSIS Users Manualの非公式な日本語ドキュメントです。本コンテンツの利用によって生じたいかなる損害も、著者は一切の責任をとることができませんので、自己責任での利用をお願いします。読みやすさを重視するため必ずしも原文に忠実でない部分があります。また、誤りが含まれている可能性もあります。必ず原文をご確認ください。 訳者:Kawai

前へ | 目次 | 次へ

付録 D: 役に立つ情報

D.1 エラーレベル

[原文]

他のアプリケーションと同様に、NSIS インストーラは実行結果としてエラーレベルを返します。他のアプリケーションや他のインストーラから、 NSIS インストーラを呼び出した場合には、エラーレベルをチェックすることは有用です。

  • 0 - 通常の実行 (エラーなし)
  • 1 - ユーザによるインストールの中断 (キャンセルボタン)
  • 2 - スクリプトによるインストールの中断

NSIS 2.01 以降では、SetErrorLevel を利用して、エラーレベルを設定することができます。

注意: アンインストーラ自身を削除できるようにするため、アンインストーラは自分自身を一時フォルダにコピーした後、そこから実行します。そのため、アンインストーラが設定したエラーレベルは実行プロセスから利用することができません。エラーレベルを得るためには、このコピー処理をシミュレートして、実行する必要があります。具体的には、以下のようにします。

CopyFiles $INSTDIR\uninstaller.exe $TEMP
ExecWait '"$TEMP\uninstaller.exe" _?=$INSTDIR' $0
DetailPrint "uninstaller set error level $0"

このようにしないと、アンインストーラは自分自身を一時ディレクトリにコピーすることができません。

D.2 プログラムの追加と削除へのアンインストール情報の追加

HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall の下に、製品名のキーを作成すると、コントロールパネルの「プログラムの追加と削除」にエントリーを追加することができます。Windows NT (NT4/2000/XP) においては、HKCUにキーを作成することで、カレントユーザにのみ表示されるようにすることもできます。いくつかの値をキーに記述することによって、アプリケーションやアンインストーラに関する情報を与えることができます。WriteRegStr コマンド(文字列用)や WriteRegDWORD コマンド(DWORD 値用)を利用して値を書き込みます。例を示します。

WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Product" "DisplayName" "Application Name"

記述が必要な値

DisplayName (string) - アプリケーションの名前
UninstallString (string) - アンインストーラのパスとファイル名。空白でパスが分割されないようにするため、パスは常にクォートすべきです。

オプション値

以下の値のうちのいくつかは、古い Windows では使用されません。

InstallLocation (string) - インストールディレクトリ ($INSTDIR)
DisplayIcon (string) - アプリケーション名の次に表示される、パス、ファイル名、アイコンのインデクス

Publisher (string) - 発行元の(会社の)名前

ModifyPath (string) - アプリケーション更新プログラムのパスとファイル名
InstallSource (string) - アプリケーションのインストール元の場所

ProductID (string) - アプリケーションの製品 ID
RegOwner (string) - アプリケーションの登録ユーザ
RegCompany (string) - アプリケーションの登録企業

HelpLink (string) - サポートのウェブサイトへのリンク
HelpTelephone (string) - サポートのための電話番号

URLUpdateInfo (string) - アプリケーションのアップデートのためのウェブサイトへのリンク
URLInfoAbout (string) - アプリケーションのホームページへのリンク

DisplayVersion (string) - アプリケーションの表示バージョン
VersionMajor (DWORD) - アプリケーションのメジャーバージョン番号
VersionMinor (DWORD) - アプリケーションのマイナーバージョン番号

NoModify (DWORD) - アンインストーラがアプリケーションを更新するためのオプションを持っていない場合は 1
NoRepair (DWORD) - アンインストーラがインストールを修復するためのオプションを持っていない場合は 1

NoModify と NoRepair の両方が 1 に設定された場合、「変更/削除」の代わりに「削除」というボタンが表示されます。

D.3 System.dll プラグインを利用した外部 DLL の呼び出し

インストール処理において、サードパーティの DLL を内部に含む関数を呼び出す必要がある場合があります。代表的な例は、Palm(TM) コンジットをインストールするときです。

System.dll について
System.dll プラグイン(Brainsucker 氏)によって、外部の DLL を "Call" 関数で呼び出すことが可能となります。System.dll には、そのほかにも沢山の関数が含まれていますが、ここでは取り上げません。その他の関数の詳細については、System readme を参照してください。

データ型
System.dll は以下のデータ型を認識します。

  • v - void 型(返り値として一般的)
  • i - 整数型 (char, byte, short, ハンドル, ポインタなどを含む)
  • l - 大きな整数型 (int64 として知られているもの)
  • t - テキスト、文字列型 (LPCSTR、一文字目へのポインタ)
  • b - 論理型 ('true'、'false') - 実際は、この型は無意味です -> 普通の整数を使うこともできます('0'、'1')
  • k - コールバック型。system.html のコールバックの節を参照してください。
  • * - ポインタ指定子 -> 型へのポインタ、次の文字(引数)に影響します [例: '*i' - 整数へのポインタ]

System.dll 変数の NSIS スクリプト変数へのマッピング
外部の関数を呼び出すことができたとしても、返り値を取得することができないと意味がありません。System.dll は、次のように、関数の変数を NSIS スクリプト変数にマップします。

NSIS の $0..$9 は、System.dll の r0..r9 に、NSIS の $R0..$R9 は、 System.dll の r10..r19 になります。

各引数は、型や入力、出力によって特定されます。入力や出力をスキップするには、ドットを利用します。例を示します。

文字列(文字配列へのポインタ)。入力は 'happy calling'。

t 'happy calling'

文字列(文字配列へのポインタ)。入力は $5 から取得し、呼び出しによる変更は $R8 に保存する。

t r5R8

整数へのポインタ。 $1 から値を取得し $2 に格納する。

*i r1r2

64 ビット整数へのポインタ。出力はスタックにプッシュ。入力はなし。

*l .s

System.dll::Call を利用すると、サードパーティの DLL 内にある関数を呼び出すことができます。Call 関数は次のように使用します。

System::Call 'YourDllName::YourDllFunction(i, *i, t) i(r0, .r1, r2) .r3'

最後の '(r0, .r1, r2) .r3' の部分は、DLL と NSIS スクリプトの間で渡されるパラメータです。このパラメータリストから分かるように、型と入力、出力を分けることができます。"(parms list) return value" の各ブロックは最後のもので、上書きされたり追加されたりします。上記の例では、最初のブロックは型を指定し、2番目は入力と出力を指定しています。

NSIS スクリプトをコーディングし始める前に
NSIS スクリプトをコーディングするには、呼び出そうとしている関数の完全なプロトタイプを知っている必要があります。例として、Palm の 'CondMgr.dll' から、'CmGetHotSyncExecPath' を利用する場合を考えます。この関数は、'HotSync.exe' のフルパスを返すために利用されます。

関数の定義

int CmGetHotSyncExecPath(TCHAR *pPath, int *piSize);

ここで、

  • pPath は、文字バッファへのポインタです。HotSync マネージャのパスとファイル名が返されます。
  • piSize は、pPath 引数によって参照されるバッファの(TCHAR での)サイズを指定します。

返り値

  • 0: エラーなし
  • -1: 特定できないエラーが発生
  • ERR_REGISTRY_ACCESS(-1006):Palm コンフィギュレーションエントリにアクセスできない
  • ERR_BUFFER_TOO_SMALL(-1010): 要求された情報を格納するには、バッファが小さすぎる
  • ERR_INVALID_POINTER(-1013):指定されたポインタは、有効なポインタではない

また、バッファが小さすぎる場合は、必要なバッファサイズが *int の値に設定されます(TCHAR でのサイズ)。

この関数定義は、以下の System.dll 定義にマップされます。

CmGetHotSyncExecPath(t, *i) i

つまり、これは、テキスト変数と、整数へのポインタを引数として、整数値を返します。

外部 DLL 関数の使用
Now that we've sorted out what the function does, and how it maps to the System.dll format, we can use the function in a NSIS script.

First, you have to change the output directory to that where the DLL you want to use is. It may also work if the DLL is on the system path, but this hasn't been tested.

The following code fragment will install 'condmgr.dll' to a temporary directory, execute the CmGetHotSyncExecPath function and display returned data. Save this script

; **** snip ****
Function loadDll

  SetOutPath $TEMP\eInspect             ; create temp directory
  File bin\CondMgr.dll                  ; copy dll there
  StrCpy $1 ${NSIS_MAX_STRLEN}          ; assign memory to $0
  System::Call 'CondMgr::CmGetHotSyncExecPath(t, *i) i(.r0, r1r1).r2'
  DetailPrint 'Path: "$0"'
  DetailPrint "Path length: $1"
  DetailPrint "Return value: $2"

FunctionEnd
; **** snip ****

and this function produces the following output in the 'details' page:

Output folder: c:\windows\TEMP\eInspect
Extract: CondMgr.dll
Path: "C:\Dave\palm\Hotsync.exe"
Path length: 24
Return value: 0

Written by djc

Acknowledgements & Thanks
Lots of thanks go to kichik and Sunjammer for spending a lot of time assisting in solving this problem. Also to brainsucker for creating the System.dll plug-in in the first place. Good Luck!

D.4 Dump Content of Log Window to File

This function will dump the log of the installer (installer details) to a file of your choice. I created this function for Afrow_UK who requested a way to dump the log to a file in this forum thread.

To use it, push a file name and call it. It will dump the log to the file specified. For example:

GetTempFileName $0
Push $0
Call DumpLog

Here is the function:

!define LVM_GETITEMCOUNT 0x1004
!define LVM_GETITEMTEXT 0x102D

Function DumpLog
  Exch $5
  Push $0
  Push $1
  Push $2
  Push $3
  Push $4
  Push $6

  FindWindow $0 "#32770" "" $HWNDPARENT
  GetDlgItem $0 $0 1016
  StrCmp $0 0 error
  FileOpen $5 $5 "w"
  StrCmp $5 0 error
    SendMessage $0 ${LVM_GETITEMCOUNT} 0 0 $6
    System::Alloc ${NSIS_MAX_STRLEN}
    Pop $3
    StrCpy $2 0
    System::Call "*(i, i, i, i, i, i, i, i, i) i \
      (0, 0, 0, 0, 0, r3, ${NSIS_MAX_STRLEN}) .r1"
    loop: StrCmp $2 $6 done
      System::Call "User32::SendMessageA(i, i, i, i) i \
        ($0, ${LVM_GETITEMTEXT}, $2, r1)"
      System::Call "*$3(&t${NSIS_MAX_STRLEN} .r4)"
      FileWrite $5 "$4$\r$\n"
      IntOp $2 $2 + 1
      Goto loop
    done:
      FileClose $5
      System::Free $1
      System::Free $3
      Goto exit
  error:
    MessageBox MB_OK error
  exit:
    Pop $6
    Pop $4
    Pop $3
    Pop $2
    Pop $1
    Pop $0
    Exch $5
FunctionEnd

written by KiCHiK

D.5 How to Read REG_MULTI_SZ Values

I wrote this script to help rpetges in this forum thread. It reads a registry value of the type REG_MULTI_SZ and prints it out. Don't forget to edit where it says "Edit this!" when you test this script. The values must point to a REG_MULTI_SZ value or the example will spit out an error.

OutFile "REG_MULTI_SZ Reader.exe"

Name "REG_MULTI_SZ Reader"

ShowInstDetails show

!define HKEY_CLASSES_ROOT        0x80000000
!define HKEY_CURRENT_USER        0x80000001
!define HKEY_LOCAL_MACHINE       0x80000002
!define HKEY_USERS               0x80000003
!define HKEY_PERFORMANCE_DATA    0x80000004
!define HKEY_PERFORMANCE_TEXT    0x80000050
!define HKEY_PERFORMANCE_NLSTEXT 0x80000060
!define HKEY_CURRENT_CONFIG      0x80000005
!define HKEY_DYN_DATA            0x80000006

!define KEY_QUERY_VALUE          0x0001
!define KEY_ENUMERATE_SUB_KEYS   0x0008

!define REG_NONE                 0
!define REG_SZ                   1
!define REG_EXPAND_SZ            2
!define REG_BINARY               3
!define REG_DWORD                4
!define REG_DWORD_LITTLE_ENDIAN  4
!define REG_DWORD_BIG_ENDIAN     5
!define REG_LINK                 6
!define REG_MULTI_SZ             7

!define RegOpenKeyEx     "Advapi32::RegOpenKeyExA(i, t, i, i, *i) i"
!define RegQueryValueEx  "Advapi32::RegQueryValueExA(i, t, i, *i, i, *i) i"
!define RegCloseKey      "Advapi32::RegCloseKeyA(i) i"

####### Edit this!

!define ROOT_KEY         ${HKEY_CURRENT_USER}
!define SUB_KEY          "Software\Joe Software"
!define VALUE            "Strings"

####### Stop editing

Section "Read"
  StrCpy $0 ""
  StrCpy $1 ""
  StrCpy $2 ""
  StrCpy $3 ""
  System::Call "${RegOpenKeyEx}(${ROOT_KEY}, '${SUB_KEY}', \
    0, ${KEY_QUERY_VALUE}|${KEY_ENUMERATE_SUB_KEYS}, .r0) .r3"
 
  StrCmp $3 0 goon
    MessageBox MB_OK|MB_ICONSTOP "Can't open registry key! ($3)"
    Goto done
goon:

  System::Call "${RegQueryValueEx}(r0, '${VALUE}', 0, .r1, 0, .r2) .r3"
 
  StrCmp $3 0 read
    MessageBox MB_OK|MB_ICONSTOP "Can't query registry value size! ($3)"
    Goto done
 
read:
 
  StrCmp $1 ${REG_MULTI_SZ} multisz
    MessageBox MB_OK|MB_ICONSTOP "Registry value no REG_MULTI_SZ! ($3)"
    Goto done
 
multisz:
 
  StrCmp $2 0 0 multiszalloc
    MessageBox MB_OK|MB_ICONSTOP "Registry value empty! ($3)"
    Goto done
 
multiszalloc:

  System::Alloc $2
  Pop $1
 
  StrCmp $1 0 0 multiszget
    MessageBox MB_OK|MB_ICONSTOP "Can't allocate enough memory! ($3)"
    Goto done
 
multiszget:
 
  System::Call "${RegQueryValueEx}(r0, '${VALUE}', 0, n, r1, r2) .r3"
 
  StrCmp $3 0 multiszprocess
    MessageBox MB_OK|MB_ICONSTOP "Can't query registry value data! ($3)"
    Goto done
 
multiszprocess:
 
  StrCpy $4 $1
 
  loop:
 
    System::Call "*$4(&t${NSIS_MAX_STRLEN} .r3)"
    StrCmp $3 "" done
    DetailPrint $3
    StrLen $5 $3
    IntOp $4 $4 + $5
    IntOp $4 $4 + 1
    Goto loop
 
done:
 
  System::Free $1
 
  StrCmp $0 0 noClose
    System::Call "${RegCloseKey}(r0)"
 
noClose:

SectionEnd

written by KiCHiK

前へ | 目次 | 次へ


SourceForge Logo

« C. Useful Scripts - NSIS Users Manual | トップページ | AppendixE »

技術文書」カテゴリの記事