ab.com コミュニティ https://www.activebasic.com/forum/ |
|
[AB4] コマンドライン引数の分解 https://www.activebasic.com/forum/viewtopic.php?t=59 |
ページ 1 / 1 |
作成者: | Tomorrow [ 2005年6月04日(土) 10:33 ] |
記事の件名: | [AB4] コマンドライン引数の分解 |
以前に投稿した(↓)コマンドライン引数を分離する関数をクラスにしました。 http://www.discoversoft.net/wforum/wfor ... =past#1603 2005. 6/11編集 旧掲示板WebForumが閉鎖されたので、過去ログ集BackSearchABのトピック番号を書いておきます。 目次:1715-コマンドライン引数 タイトル:Re^6: コマンドライン引数 投稿時間:2004/05/03(Mon) 15:59 Iteratorパターンを使ったらわりとすっきりしたので、投稿してみます。 ついでにロジックの方も見直してみました。少し分かり易くなった...かな? ---以下ソース コード: 'コマンドライン引数を1つずつ切り出すクラス Declare Function GetLongPathName Lib "kernel32" Alias "GetLongPathNameA" (lpszShortPath As BytePtr, lpszLongPath As BytePtr, cchBuffer As DWord) As DWord TypeDef BOOL = Long Class CommandLineArgumentsIterator lpCmdLineArgs As BytePtr lpCurrentPos As BytePtr szCurrentArg[ELM(MAX_PATH)] As Byte Protected Function HasShortFileName() As BOOL Dim osver As OSVERSIONINFO osver.dwOSVersionInfoSize=SizeOf(OSVERSIONINFO) GetVersionEx(osver) If osver.dwPlatformId=VER_PLATFORM_WIN32_WINDOWS Then HasShortFileName=TRUE Else HasShortFileName=FALSE End If End Function Sub ConvertToLongFileName(lpArg As BytePtr) Dim buffer[ELM(MAX_PATH)] As Byte GetLongPathName(lpArg, buffer, MAX_PATH) lstrcpy(lpArg, buffer) End Sub Public Sub CommandLineArgumentsIterator(lpStr As BytePtr) lpCmdLineArgs=lpStr lpCurrentPos=lpCmdLineArgs End Sub Function HasNext() As BOOL If lpCurrentPos[0]<>NULL Then HasNext=TRUE Else HasNext=FALSE End If End Function Function GetNext() As BytePtr Dim i As Long, j As Long Dim c As Byte Dim bDqrt As BOOL If lpCurrentPos[0]=Asc(Ex"\q") Then bDqrt=TRUE Else bDqrt=FALSE End If '"の有無によって初期位置・終端文字を変更する If bDqrt Then i=1: c=Asc(Ex"\q") Else i=0: c=Asc(" ") End If 'パラメータひとつ分を抽出する j=0 While (lpCurrentPos<>c And lpCurrentPos<>NULL And j<MAX_PATH) szCurrentArg[j]=lpCurrentPos i=i+1: j=j+1 Wend szCurrentArg[j]=NULL '長いファイル名に変換する If(HasShortFileName() And bDqrt=FALSE) Then ConvertToLongFileName(szCurrentArg) End If '次のパラメータの位置を格納 Select Case lpCurrentPos Case Asc(Ex"\q") Select Case lpCurrentPos[i+1] Case NULL lpCurrentPos=lpCurrentPos+i+1 ' "Param1"\0 Case Asc(" ") lpCurrentPos=lpCurrentPos+i+2 ' "Param1"_?Param2?... End Select Case Asc(" ") lpCurrentPos=lpCurrentPos+i+1 ' Param1_?Param2?... Case NULL lpCurrentPos=lpCurrentPos+i ' Param1\0 End Select GetNext=szCurrentArg End Function Sub Reset() lpCurrentPos=lpCmdLineArgs End Sub End Class ---使用法 コード: Dim arg As CommandLineArgumentsIterator(GetCommandLine()) While arg.HasNext() Dim buf As BytePtr buf=arg.GetNext() MessageBox(0, buf, "", MB_OK) Wend |
作成者: | Tomorrow [ 2005年9月25日(日) 15:59 ] |
記事の件名: | [AB4] コマンドライン引数を分解するクラスの改訂版 |
↑コマンドライン引数を分解するクラスの分解アルゴリズムの見直し、メソッドの追加・変更を行いました。 主な変更点・仕様は次の通り。 1.分解アルゴリズム(GetNext()メソッド)見直しについて ●前回のはエクスプローラでD&D起動したときに渡されるコマンドライン文字列を解析した結果から、それに見合うようコーディングしたが、 今回はコマンドラインインタプリタ(cmd.exe)の分解手順を「ダブルクォーテーションの外側にあるスペースを引数の区切り文字として扱う」 と仮定し、それに従いコーディングした。 ●エクスプローラからのD&D、関連付けによる実行はもちろん、コマンドラインからの複数のダブルクォーテーションを持つ場合や スペースが入るフォルダのみダブルクォーテーションで括った場合にも対応。 ●lpCurrentPosをBytePtr+添え字による配列アクセスからポインタ扱いとすることで多少コードをスリム化。 ●引数間に余分なスペースがあってもOK。 ●あと対応が必要といえば、Unicode、DBCS(全角文字)などがありますが、現状で特に問題ないため放置してます。(--); 不具合等あれば対応したいので御報告ください。m(__)m 2.追加・変更されたメソッドについて ●PublicメソッドGetCommandLine(), GetCurrentPos()を追加。詳細は下記のリファレンスを参照してください。 ●内部関数(Protectメソッド)を前の2つからConvertToLongFileName()1つに集約。 各メソッドのリファレンスも付けました↓ Sub CommandLineArgumentsIterator(lpStr As BytePtr) 説明:コンストラクタ 引数:lpStr …コマンドライン引数の文字列を指定します。 GetCommandLine()関数(API)で取得したり、PathGetArgs()関数で引数部分のみ取り出したものを指定できます。 Function HasNext() As BOOL 説明:次の引数があるかないかを返します。Iteratorパターン。 戻り値:次の引数があるときはTRUE(=1)、ないときはFALSE(=0)。 Function GetNext() As BytePtr 説明:引数を1つ分離しそれを返します。Iteratorパターン。 実行後、内部変数lpCurrentPosが次の引数の位置に移り、バッファszCurrentArgに分離した引数が格納されます。 戻り値:バッファszCurrentArgへのポインタが返ります。分離した引数をBytePtr文字列として使えます。 Sub Reset() 説明:次の引数の位置をコンストラクタで指定された文字列のアドレス位置に戻します。 Function GetCommandLine() As BytePtr 説明:コンストラクタで指定したコマンドライン引数の文字列を返します。 Function GetCurrentPos() As BytePtr 説明:次に分離されるの引数以下の文字列を返します。 コード: TypeDef BOOL = Long 'コマンドライン引数を1つずつ切り出すクラス Class CommandLineArgumentsIterator lpCmdLineArgs As BytePtr Protected lpCurrentPos As BytePtr szCurrentArg[ELM(MAX_PATH)] As Byte Sub ConvertToLongFileName(lpStr As BytePtr) Dim osver As OSVERSIONINFO osver.dwOSVersionInfoSize=SizeOf(OSVERSIONINFO) GetVersionEx(osver) If osver.dwMajorVersion=4 Then 'Windows 95/98/Me、Windows NT4.0 Dim buffer[ELM(MAX_PATH)] As Byte GetLongPathName(lpStr, buffer, MAX_PATH) lstrcpy(lpStr, buffer) End If End Sub Public Sub CommandLineArgumentsIterator(lpStr As BytePtr) lpCmdLineArgs=lpStr lpCurrentPos=lpCmdLineArgs End Sub Function HasNext() As BOOL If lpCurrentPos[0]<>NULL Then HasNext=TRUE Else HasNext=FALSE End If End Function Function GetNext() As BytePtr Dim i=0 As Long '引数ひとつ分を抽出する While (lpCurrentPos[0]<>Asc(" ") And lpCurrentPos[0]<>NULL And i<MAX_PATH-1) If lpCurrentPos[0]=Asc(Ex"\q") Then 'ダブルクォーテーションの内側 'ダブルクォーテーションを読み飛ばす lpCurrentPos=lpCurrentPos+1 '次のダブルクォーテーションまで読み込む While (lpCurrentPos[0]<>Asc(Ex"\q") And lpCurrentPos[0]<>NULL And i<MAX_PATH-1) szCurrentArg=lpCurrentPos[0] i=i+1: lpCurrentPos=lpCurrentPos+1 Wend If lpCurrentPos[0]=Asc(Ex"\q") Then lpCurrentPos=lpCurrentPos+1 Else 'ダブルクォーテーションの外側 szCurrentArg=lpCurrentPos[0] i=i+1: lpCurrentPos=lpCurrentPos+1 End If Wend szCurrentArg=NULL '長いファイル名に変換する ConvertToLongFileName(szCurrentArg) '次の引数の位置を格納(余分なスペースを読み飛ばす) While lpCurrentPos[0]=Asc(" ") lpCurrentPos=lpCurrentPos+1 Wend GetNext=szCurrentArg End Function Sub Reset() lpCurrentPos=lpCmdLineArgs End Sub Function GetCommandLine() As BytePtr GetCommandLine=lpCmdLineArgs End Function Function GetCurrentPos() As BytePtr GetCurrentPos=lpCurrentPos End Function End Class 使用例: こちらもただ使うだけから引数をまとめて表示するようグレードアップしました。 PathGetArgsを使い引数部分のみ表示するようにしています。 コード: Declare Function GetLongPathName Lib "kernel32" Alias "GetLongPathNameA" (lpszShortPath As BytePtr, lpszLongPath As BytePtr, cchBuffer As DWord) As DWord Declare Function PathGetArgs Lib "shlwapi" Alias "PathGetArgsA" (psz As BytePtr) As BytePtr Dim arg As CommandLineArgumentsIterator(PathGetArgs(GetCommandLine())) Dim str As String Dim buf As String Dim i As Long If arg.HasNext() Then i=1 Else MessageBox(0, "ファイルをドロップしてください。", "CommandLineArgumentsIterator", MB_OK) ExitProcess(0) End If While arg.HasNext() buf=Str$(i) + "個目:" + arg.GetNext() + Ex"\n" str=str+buf i=i+1 Wend MessageBox(0, str, "CommandLineArgumentsIterator", MB_OK) ExitProcess(0) |
作成者: | Tomorrow [ 2005年9月25日(日) 16:03 ] |
記事の件名: | [AB4] コマンドライン引数へのC言語風アクセスができるクラス |
C言語のmain()関数みたいにargc, argvによるコマンドライン引数へのアクセスを望む声もあったので、作ってみました。 内部で上のCommandLineArgumentsIteratorクラスの機能を使用しているので、そちらも同じsbpファイルにでも入れておいてください。 Function argc() As Long で要素数が返り、 Function argv(num As Long) As BytePtr で指定した要素番号に該当するコマンドライン引数が返ります。 コード: 'コマンドライン引数を配列として扱うクラス Class CommandLineArgV list As *BytePtr size As Long argbuf[ELM(MAX_PATH)] As Byte Public Sub CommandLineArgV(lpStr As BytePtr) Dim argitr As CommandLineArgumentsIterator(lpStr) size=0 '引数の数を調べる While argitr.HasNext() size=size+1 argitr.GetNext() Wend '各引数の位置を格納 list=malloc(size*SizeOf(BytePtr)) argitr.Reset() Dim i=0 As Long While argitr.HasNext() list=argitr.GetCurrentPos() argitr.GetNext() i=i+1 Wend End Sub Sub ~CommandLineArgV() free(list) End Sub Function argc() As Long argc=size End Function Function argv(num As Long) As BytePtr 'インデックスエラー If num>=size Then argv=NULL Exit Function End If '位置[num]にある引数を取り出して返す Dim argitr As CommandLineArgumentsIterator(list[num]) If argitr.HasNext() Then lstrcpy(argbuf, argitr.GetNext()) Else argbuf[0]=NULL End If argv=argbuf End Function End Class 使用例です。上のIteratorのものと同じ挙動をします。 コード: Declare Function GetLongPathName Lib "kernel32" Alias "GetLongPathNameA" (lpszShortPath As BytePtr, lpszLongPath As BytePtr, cchBuffer As DWord) As DWord Declare Function PathGetArgs Lib "shlwapi" Alias "PathGetArgsA" (psz As BytePtr) As BytePtr Dim arg As CommandLineArgV(PathGetArgs(GetCommandLine())) Dim str As String Dim buf As String Dim i As Long If arg.argc()=0 Then MessageBox(0, "ファイルをドロップしてください。", "CommandLineArgumentsIterator", MB_OK) ExitProcess(0) End If For i=0 To arg.argc()-1 buf=Str$(i+1) + "個目:" + arg.argv(i) + Ex"\n" str=str+buf Next MessageBox(0, str, "CommandLineArgV", MB_OK) ExitProcess(0) |
ページ 1 / 1 | 全ての表示時間は UTC+09:00 です |
Powered by phpBB® Forum Software © phpBB Limited https://www.phpbb.com/ |