OSDN Git Service

AppliStation-all,Copyright年を更新
[applistation/AppliStation.git] / na-get-lib / NaGet.InteropServices / CommonArchiverExtracter.cs
1 using System;\r
2 using System.Runtime.InteropServices;\r
3 using System.IO;\r
4 \r
5 namespace NaGet.InteropServices\r
6 {\r
7         /// <summary>\r
8         /// CommonArchiverDllの設定\r
9         /// </summary>\r
10         public struct CommonArchiverDllConfig\r
11         {\r
12                 public CommonArchiverDllConfig(string dllName, string cmdName, string cmdLineFmt, int versionreq)\r
13                 {\r
14                         DllName = dllName;\r
15                         CmdName = cmdName;\r
16                         CmdLineFmt = cmdLineFmt;\r
17                         VersionMoreThan = versionreq;\r
18                 }\r
19                 \r
20                 /// <summary>\r
21                 /// DLLの名称。LoadLibraryに渡される\r
22                 /// </summary>\r
23                 public string DllName;\r
24                 /// <summary>\r
25                 /// コマンド名称。\r
26                 /// </summary>\r
27                 public string CmdName;\r
28                 /// <summary>\r
29                 /// コマンドライン形式"{0}"がアーカイブ名、"{1}"が展開先\r
30                 /// </summary>\r
31                 public string CmdLineFmt;\r
32                 /// <summary>\r
33                 /// 最低バージョン要求\r
34                 /// </summary>\r
35                 public int VersionMoreThan;\r
36         }\r
37         \r
38         /// <summary>\r
39         /// アーカイバDLLを使った書庫展開器\r
40         /// </summary>\r
41         public class CommonArchiverExtracter\r
42         {\r
43                 \r
44                 #region DLL関数のdelegate\r
45                 \r
46                 /// <summary>\r
47                 /// DLL の版の取得\r
48                 /// </summary>\r
49                 private delegate ushort ArcGetVersion();\r
50                 \r
51                 /// <summary>\r
52                 /// DLL の実行状況の取得\r
53                 /// </summary>\r
54                 private delegate bool ArcGetRunning();\r
55                 \r
56                 /// <summary>\r
57                 /// 書庫のチェック\r
58                 /// </summary>\r
59                 private delegate bool ArcCheckArchive(string szFileName, ArchCheckFlag iMode);\r
60                 \r
61                 /// <summary>\r
62                 /// 書庫のチェックの精度\r
63                 /// </summary>\r
64                 private enum ArchCheckFlag {\r
65                         /// <summary>\r
66                         /// 簡易モード。先頭の数個のヘッダのみ確認\r
67                         /// </summary>\r
68                         RAPID = 0,\r
69                         /// <summary>\r
70                         /// 通常モード。すべてのヘッダを確認\r
71                         /// </summary>\r
72                         BASIC = 1,\r
73                         /// <summary>\r
74                         /// 厳密モード。CRCも含めすべて確認\r
75                         /// </summary>\r
76                         FULLCRC = 2,\r
77                         //RECOVERY = 4,\r
78                         //SFX = 8,\r
79                         //ALL = 16,\r
80                 }\r
81                 \r
82                 /// <summary>\r
83                 /// 格納ファイル数の取得\r
84                 /// </summary>\r
85                 private delegate int ArcGetFileCount(string szFileName);\r
86                 \r
87                 /// <summary>\r
88                 /// 書庫操作一般\r
89                 /// </summary>\r
90                 private delegate int ArcMain(IntPtr hWnd,\r
91                                             [MarshalAs(UnmanagedType.LPStr)] string szCmdLine,\r
92                                             [MarshalAs(UnmanagedType.LPStr)] System.Text.StringBuilder szOutput, uint dwSize);\r
93                 \r
94                 #endregion\r
95                 \r
96                 /// <summary>\r
97                 /// アーカイバDLLの設定\r
98                 /// </summary>\r
99                 public static readonly CommonArchiverDllConfig[] Configs = {\r
100                         new CommonArchiverDllConfig("7-ZIP32", "SevenZip", "x -y \"{0}\" \"-o{1}\"", 423),\r
101                         new CommonArchiverDllConfig("UNZIP32", "UnZip", "-x -o \"{0}\" \"{1}\" *", 541),\r
102                         new CommonArchiverDllConfig("UNLHA32", "Unlha", "x \"{0}\" \"{1}\" *", 240),\r
103                         new CommonArchiverDllConfig("CAB32", "Cab", "-x \"{0}\" \"{1}\" *", 98),\r
104                         new CommonArchiverDllConfig("TAR32", "Tar", "-x \"{0}\" -o \"{1}\"", 218),\r
105                         new CommonArchiverDllConfig("UNGCA32", "UnGCA", "e \"{0}\" \"{1}\"", 10), // いるかな?\r
106                         \r
107                         //new CommonArchiverDllConfig("UNRAR32", "Unrar", "x -y \"{0}\" \"{1}\" *", -1),\r
108                 };\r
109                 \r
110                 /// <summary>\r
111                 /// アーカイブを展開する。適切なDLLで自動的に展開する。\r
112                 /// </summary>\r
113                 /// <param name="arcFile">アーカイブのパス</param>\r
114                 /// <param name="targetDir">展開先ディレクトリ</param>\r
115                 /// <param name="output">アーカイバDLLの展開時の標準出力を格納する</param>\r
116                 /// <param name="hWnd">親フレーム</param>\r
117                 /// <returns>アーカイバDLLの展開時のエラーコード(0なら正常終了)</returns>\r
118                 public static int ExtractArchive(string arcFile, string targetDir, System.Text.StringBuilder output, IntPtr hWnd)\r
119                 {\r
120                         foreach (CommonArchiverDllConfig config in Configs) {\r
121                                 try {\r
122                                         return ExtractArchiveWith(arcFile, targetDir, config, output, hWnd);\r
123                                 } catch (DllNotFoundException) {\r
124                                 } catch (ApplicationException) {\r
125                                 }\r
126                         }\r
127                         throw new DllNotFoundException("Not found dll matched for " + arcFile);\r
128                 }\r
129                 \r
130                 /// <summary>\r
131                 /// 指定したDLLの設定を使ってアーカイブを展開する\r
132                 /// </summary>\r
133                 /// <param name="arcFile">アーカイブのパス</param>\r
134                 /// <param name="targetDir">展開先ディレクトリ</param>\r
135                 /// <param name="config">使用するアーカイバDLLの設定</param>\r
136                 /// <param name="output">アーカイバDLLの展開時の標準出力を格納する</param>\r
137                 /// <param name="hWnd">親フレーム</param>\r
138                 /// <returns>アーカイバDLLの展開時のエラーコード(0なら正常終了)</returns>\r
139                 public static int ExtractArchiveWith(string arcFile, string targetDir, CommonArchiverDllConfig config, System.Text.StringBuilder output, IntPtr hWnd)\r
140                 {\r
141                         if (! File.Exists(arcFile) ) {\r
142                                 throw new FileNotFoundException("File not found: ", arcFile);\r
143                         }\r
144                         if (! Directory.Exists(targetDir)) {\r
145                                 throw new DirectoryNotFoundException("Directory not found: " + targetDir);\r
146                         }\r
147                         \r
148                         // 統合アーカイバDLLの解凍先ディレクトリは\で終わらないといけない(重要)\r
149                         if (! targetDir.EndsWith("\\")) {\r
150                                 targetDir += "\\";\r
151                         }\r
152                         \r
153                         // DLLバージョンチェック\r
154                         using (DllAccess dll = new DllAccess(config.DllName)) {\r
155                                 ArcGetVersion GetVersion = (ArcGetVersion) dll.GetFunction(config.CmdName+"GetVersion", typeof(ArcGetVersion));\r
156                                 ushort version = GetVersion();\r
157                                 if (version < config.VersionMoreThan) {\r
158                                         throw new DllNotFoundException("Dll version is too old.");\r
159                                 }\r
160                         }\r
161                         \r
162                         string cmdLine = string.Format(config.CmdLineFmt, arcFile, targetDir);\r
163                         return ExtractArchiveWith(config.DllName, config.CmdName, cmdLine, arcFile, output, hWnd);\r
164                 }\r
165                 \r
166                 protected static int ExtractArchiveWith(string dllName, string cmdName, string cmdLine, string arcFile, System.Text.StringBuilder output, IntPtr hWnd)\r
167                 {\r
168                         using (DllAccess dll = new DllAccess(dllName)) {\r
169                                 ArcGetRunning GetRunning = (ArcGetRunning) dll.GetFunction(cmdName+"GetRunning", typeof(ArcGetRunning));\r
170                                 if ( GetRunning() ) { // マルチスレッド対応でないのでビジー時には例外\r
171                                         throw new SystemException(dllName + " is busy");\r
172                                 }\r
173                                 \r
174                                 ArcCheckArchive CheckArchive = (ArcCheckArchive) dll.GetFunction(cmdName+"CheckArchive", typeof(ArcCheckArchive));\r
175                                 if (! CheckArchive(arcFile, ArchCheckFlag.BASIC)) {\r
176                                         throw new ApplicationException(dllName + " could not treat the archive file");\r
177                                 }\r
178                                 \r
179                                 ArcMain Exec = (ArcMain) dll.GetFunction(cmdName, typeof(ArcMain));\r
180                                 int retVal = Exec(hWnd, cmdLine, output, (uint)((output != null)? output.Capacity : 0) );\r
181                                 \r
182                                 return retVal;\r
183                         }\r
184                 }\r
185         }\r
186 }\r