こんにちわ。VB初心者です。
ディレクトリを作成するツールを作成していますが、CreateDirectory ()APIを使用すると、コンパイル時にユーザ定義型は定義されていませんというエラーが発生します。これを回避するには、どうしたら良いのでしょうか?
APIは次のように定義しています。'Public Declare Function CreateDirectory Lib "kernel32" Alias "CreateDirectoryA" (ByVal lpPathName As String, lpSecurityAttributes As SECURITY_ATTRIBUTES) As Long
何か他にも良い案がありましたらお願いします。
簡単な質問かもしれませんが宜しくお願いします。
【開発環境】XP、VB(ver6.0)
> ユーザ定義型は定義されていませんというエラーが発生します
おそらくは、『SECURITY_ATTRIBUTES』というユーザー定義型の宣言が抜けているのでしょう。
必要となるユーザ定義型の宣言を行ってみてください。
> ディレクトリを作成するツールを作成していますが
ところで、MkDirステートメントでは駄目なのでしょうか?
セキュリティ記述子を指定する必要がある場合や、
Unicode文字のフォルダを作りたいという事であれば
APIを使う必要がありますが、そうでなければ、
VBの標準ステートメントで十分かと思います。
MakeSureDirectoryPathExists なんかいかがでしょうか?
簡単な宣言で子階層を含むフォルダを一発で作成できますよ。
MkDirステートメントで十分と思います、
dt01 = D:\123\123 ----------作成したいホルダー
Sub dir作成01(dt01)
Dim dt02, dt03
dt02 = dt01
If InStr(dt02, ":\") <> 0 Then ' --------------------- 最初
dt03 = Mid(dt02, 1, InStr(dt02, ":\") + 1)
dt02 = Mid(dt02, InStr(dt02, ":\") + 2, Len(dt02))
End If
Do ' --------------------- 途中
If InStr(dt02, "\") = 0 Then Exit Do
dt03 = dt03 & Mid(dt02, 1, InStr(dt02, "\"))
dt02 = Mid(dt02, InStr(dt02, "\") + 1, Len(dt02))
Call dir作成02(dt03)
Loop
If dt02 <> "" Then ' --------------------- 最後
Call dir作成02(dt01)
End If
End Sub
Sub dir作成02(dt)
Dim fairu
fairu = Dir(dt, 16)
If fairu = "" Then
' Form_Text1.Text5 = "作成 " & dt
MkDir dt
Else
' Form_Text1.Text5 = " " & dt
End If
' Form_Text1.Text5.Refresh
End Sub
ご回答あろがとうございます。
①CreateDirectory ()APIについては、前回のエラーは回避できましたが、今度は、『ByRef引数の型が一致しません』というエラーがでます。引数には、「Null」や、「0」で試しましたがうまくいきません。XPではできないのでしょうか・・・。
②MakeSureDirectoryPathExists()APIについては、APIビューアで見つかりませんでしたが、やってみたらできました。
③MkDirステートメントについては、成功しました。(既存チェックとか無しの簡単なもので試しました。)
たまたま、APIの勉強をしていたので、まずAPIからやってみましたが、処理方法はいろいろあるのですね。
> ByRef引数の型が一致しません
ByRef指定の時は、呼び出し側と呼び出し元のデータ型を一致させる必要があります。
Declare宣言側を変更する(例えばAs Anyに)か、もしくは、
呼び出し側のデータ型を見直すようにしてみてください。
> 「Null」や、「0」で試しましたがうまくいきません
C言語でいう所のnullと、VBのNullは意味が異なります。
「null」を渡したい場合は、
宣言側がByVal X As Longの時: ByVal 0& を渡す
宣言側がByVal X As Stringの時: vbNullString を渡す
などのようにします。
> MakeSureDirectoryPathExists()APIについては
環境によっては、このAPIが正しく動作しない事があるようです。
http://groups.yahoo.co.jp/group/bccompiler/messages/164?expand=1
魔界の仮面弁士さん、ありがとうございます。
CreateDirectory ()APIのByRef引数の型についてですが、以下のようにしてもうまくいきませんでした。
>宣言側がByVal X As Longの時: ByVal 0& を渡す
実際のソースは以下になります。
(標準モジュール)
Public Declare Function CreateDirectory Lib "kernel32" _ Alias "CreateDirectoryA" (ByVal lpPathName As String, _ lpSecurityAttributes As SECURITY_ATTRIBUTES) As Long
'-------------
Type SECURITY_ATTRIBUTES
nLength As Long
lpSecurityDescriptor As Long
bInheritHandle As Long
End Type
(イベントソース)
'DirPath(作成したいディレクトリとパス)
DirPath = Text1.Text & "\" & Text2(I).Text & "\"
Dim MODORITI As Long
MODORITI = CreateDirectory(DirPath, 0&)
私はByRef型は使用していないように思うのですが・・・。
どうでしょう。
> 私はByRef型は使用していないように思うのですが・・・。
実は使われていたりします。
ヘルプでByRefについて調べて見ると
『その引数が、参照渡しで渡されることを示します。
Visual Basic では、既定値はキーワード ByRef です。』
という記述を発見できたかと思います。
つまり、「ByRef」も「ByVal」も指定していない場合、
VB6においては「ByRef」と認識されるというわけです。
先の回答にも少し書きましたが、もし、第二引数に 0&を指定したいのであれば、
Declare側を ByVal lpSecurityAttributes As Long で宣言してください。
あるいは、ByRef lpSecurityAttributes As SECURITY_ATTRIBUTES にしておきたいなら、
第2引数に、SECURITY_ATTRIBUTES型の変数を渡すようにしてください。
(この場合、.nLengthにSECURITY_ATTRIBUTES型のサイズを指定するのを忘れずに)
>先の回答にも少し書きましたが、もし、第二引数に 0&を指定したいのであれば、
Declare側を ByVal lpSecurityAttributes As Long で宣言してください。
魔界の仮面弁士さん、ありがとうございます。
As Longで宣言したらできました。前回は認識違いで他のところをAs Longにしていました・・・。
とりあえず、皆さんのおかげで、3つの方法でフォルダを作成することに成功しました。
どうもありがとうございました。