DOBON.NET DOBON.NETプログラミング掲示板過去ログ

短い形式のパス名を取得

環境/言語:[WindowsXP]
分類:[.NET]

kageです。お世話になります。

vb.netで短い形式のパス名を取得したいのですが、うまくできません。
vb6では、apiの
Declare Function GetShortPathName Lib "kernel32.dll" _
Alias "GetShortPathNameA" _
(ByVal lpszLongPath As String, _
ByVal lpszShortPath As String, _
ByVal cchBuffer As Long) As Long
を使用していました。
このまま.netに張りつけましたが、lpszShortPathにnullが返ってしまいます。

よろしくお願いします。
Long (Int64) -> Intger (Int32)
  • 題名: Re[1]: 短い形式のパス名を取得
  • 著者: 魔界の仮面弁士
  • 日時: 2005/04/15 12:17:56
  • ID: 10432
  • この記事の返信元:
  • この記事への返信:
    • (なし)
  • ツリーを表示
> Declare Function GetShortPathName Lib "kernel32.dll" _

VB6は、Integer=16bit整数型, Long=32bit整数型 でしたが、
VB.NETでは、Short=16bit整数型、Integer=32bit整数型、Long=64bit整数型として
実装されているため、引数の型を変更する必要があります。また、
文字列の扱いなどにも変更がありますので、SDKで確認してみてください。

なお、VB6のDeclareを、VB.NETに変更する際には、下記が参考になるかと思います。

[GetPrivateProfileStringにみるAPIの使用方法]
http://www5b.biglobe.ne.jp/~yone-ken/VBNET/special/sp06_GetPrivateProfileString.html

[GetPrivateProfileString関数の様々な宣言法によるWin2000、Win98での実行結果の成否]
http://www5b.biglobe.ne.jp/~yone-ken/VBNET/Reference/ref2_GetPrivateProfileString.html
はいこーんさん、魔界の仮面弁士さん、お世話になります。

' 入力パスの短い形式を取得する関数の宣言
Declare Function GetShortPathName Lib "kernel32.dll" _
Alias "GetShortPathNameA" _
(ByVal lpszLongPath As String, _
ByVal lpszShortPath As String, _
ByVal cchBuffer As Int32) As System.UInt32

以上のように書き換えてみましたが動きません。
最後のSystem.UInt32はInt32でも同じです。

書き忘れましたがVB6のコードは
Function ShortName(Fn As String) As String
Dim strLongPathName As String
Dim strShortPathName As String * 516
Dim lngWin32apiResultCode As Long

strLongPathName = Fn
lngWin32apiResultCode = _
GetShortPathName(strLongPathName, _
strShortPathName, _
Len(strShortPathName))
ShortName = Left(strShortPathName, InStr(strShortPathName, vbNullChar) - 1)
End Function

strShortPathNameの長さが指定されています。.netでは単に As Stringに変更しています。
このあたりが関係しているのでしょうか?

よろしくお願いします。
> 以上のように書き換えてみましたが動きません。
文字列の書き換えを忘れてますよ。
先ほどのURLをもう一度見てください。

LPCTSTR 型の引数なら String でも良いですが、
LPTSTR 型の引数は、StringBuilder にしましょう。

つまり、
Private Declare Auto Function GetShortPathName Lib "kernel32" _
(ByVal lpszLongPath As String, _
ByVal lpszShortPath As System.Text.StringBuilder, _
ByVal cchBuffer As Integer) As Integer
として、
Dim S As New System.Text.StringBuilder(516)
GetShortPathName("C:\Program Files\", S, 512)
MessageBox.Show(S.ToString())
という感じで。


必要に応じて、Alias の指定や、引数に <MarshalAs(UnmanagedType.LPTStr)> や
<MarshalAs(UnmanagedType.U4)> などの属性を併記してみてください。
魔界の仮面弁士さん、お世話になります。

> LPCTSTR 型の引数なら String でも良いですが、
> LPTSTR 型の引数は、StringBuilder にしましょう。
>
> つまり、
> Private Declare Auto Function GetShortPathName Lib "kernel32" _
> (ByVal lpszLongPath As String, _
> ByVal lpszShortPath As System.Text.StringBuilder, _
> ByVal cchBuffer As Integer) As Integer

StringBuilderをそのまま書いたのでエラーになってしまったのです。
System.Text.StringBuilder ですか・・・、なるほど。

> として、
> Dim S As New System.Text.StringBuilder(516)
> GetShortPathName("C:\Program Files\", S, 512)
> MessageBox.Show(S.ToString())
> という感じで。

お蔭さまでうまくいきました。ありがとうございました。
ところでこのShortNameを使うのは、Shell関数の引数がLongネームでは受けてくれないからです。
.netでは、もう少しましな方法があるのではと探しましたが見付かりませんでした。
この点についてご存知でしたら、再度よろしくお願いいたします。
2005/04/15(Fri) 15:22:00 編集(投稿者)

こんにちは、じゃんぬ です。

■No10436に返信(kageさんの記事)
> .netでは、もう少しましな方法があるのではと探しましたが見付かりませんでした。
> この点についてご存知でしたら、再度よろしくお願いいたします。

.NET Framework 的には、System.Diagnostics.Process クラスの Start() メソッドでしょう。

http://jeanne.wankuma.com/tips/process/08-start.html
http://dobon.net/vb/dotnet/process/openfile.html

ん? 引数?
もし半角スペースを含む引数があるのならば、それはダブルコーテーションで括らなければいけませんよね。
じゃんぬさん、こんにちは。

> .NET Framework 的には、System.Diagnostics.Process クラスの Start() メソッドでしょう。

そうでした。Process.Start()でした。勉強になります。

> ん? 引数?
> もし半角スペースを含む引数があるのならば、それはダブルコーテーションで括らなければいけませんよね。

でも、これはShellと同じでした。Longネームはダブルコーテーションでくくってもだめでした。
■No10439に返信(kageさんの記事)
> でも、これはShellと同じでした。Longネームはダブルコーテーションでくくってもだめでした。

一体全体どういうアプリケーションを起動しようとしていますか?
それによって、引数の正しい渡し方は異なることがあります。
また、実際に渡したい引数は"C:\Program Files\"なのですか?
「引数」とは、Shellメソッドの引数であって、コマンドライン引数ではないですか?
実際、どのようなコードを書いて駄目だったのですか?
はいこーんさん、お手間を取らせました。

> 一体全体どういうアプリケーションを起動しようとしていますか?
> それによって、引数の正しい渡し方は異なることがあります。
> また、実際に渡したい引数は"C:\Program Files\"なのですか?
> 「引数」とは、Shellメソッドの引数であって、コマンドライン引数ではないですか?
> 実際、どのようなコードを書いて駄目だったのですか?

ちょっと現在開発中のものをそのまま出すわけに行かなかったものですから。
これだと、プロジェクトを開くことができません。
System.Diagnostics.Process.Start("C:\Program Files\Microsoft Visual Studio\VB98\vb6.exe", "H:\Visual Basic 6\API\Shell\Project1.vbp")
Basic と 6\API・・・ に分割してみてしまいます。

スタートするアプリケーションは問題ないようです。
System.Diagnostics.Process.Start("C:\Program Files\Microsoft Visual Studio\VB98\vb6.exe")
これで、VB6は立ち上がります。
2005/04/15(Fri) 17:14:33 編集(投稿者)

■No10441に返信(kageさんの記事)
> これだと、プロジェクトを開くことができません。

あなたは人の話が聞けないのですか?

じゃんぬさんの言う通り、このようにダブルクォーテーションで括ると起動しますよ。

"""H:\Visual Basic 6\API\Shell\Project1.vbp"""

括らないと「H:\Visual」までが1つの引数になるので起動しません。
はいこーんさん、お世話になります。

> あなたは人の話が聞けないのですか?

すみません、聞く耳が衰えているのかな?

> じゃんぬさんの言う通り、このようにダブルクォーテーションで括ると起動しますよ。
>
> """H:\Visual Basic 6\API\Shell\Project1.vbp"""
>
> 括らないと「H:\Visual」までが1つの引数になるので起動しません。

なるほどダブルコーテーションを3個ですか?? 確かに作動いたしました。

もう少しお付き合いをお願いいたします。

ただ現実には、引数の部分は変数になります。
Dim vbPath As String = "H:\Visual Basic 6\"
Dim fName As String = "fileName"

System.Diagnostics.Process.Start("C:\Program Files\Microsoft Visual Studio\VB98\vb6.exe",vbPath & fileName)

VB6的に書いてしまいましたが、これでは動きません。
意味合いは分かっていただけると思うのですが・・・。
■No10444に返信(kageさんの記事)
> すみません、聞く耳が衰えているのかな?

私の言葉も過ぎたものでしたが、あなたは、

> Longネームはダブルコーテーションでくくってもだめでした。

と発言しています。
じゃんぬさんの回答がムダになっていますね。

> なるほどダブルコーテーションを3個ですか?? 確かに作動いたしました。

もしかして、文字列の中の、ダブルクォーテーションを含ませる方法がわかりませんでしたか?
ならば、

> Longネームはダブルコーテーションでくくってもだめでした。

と発言したのは何故か疑問ですが。

> System.Diagnostics.Process.Start("C:\Program Files\Microsoft Visual Studio\VB98\vb6.exe", vbPath & fileName)
> VB6的に書いてしまいましたが、これでは動きません。
> 意味合いは分かっていただけると思うのですが・・・。

System.Diagnostics.Process.Start("C:\Program Files\Microsoft Visual Studio\VB98\vb6.exe", """" & vbPath & fileName & """")

文字列の中で、ダブルクォーテーションを表現する時は、「""」と2回書きます。
で、文字列は"〜〜〜〜"の中に含ませることで表現しますから。
"〜〜〜〜"の中に「""」を入れることになります。
つまり、「""""」ということになります。

わかりにくければ、

Public Const DoubleQuotation As String = """"

DoubleQuotation & vbPath & fileName & DoubleQuotation

ということです。
はいこーんさん、長々とお付き合いありがとうございました。

> じゃんぬさんの回答がムダになっていますね。

じゃんぬさん、失礼いたしました。

> もしかして、文字列の中の、ダブルクォーテーションを含ませる方法がわかりませんでしたか?
> ならば、
>
>>Longネームはダブルコーテーションでくくってもだめでした。
>
> と発言したのは何故か疑問ですが。

意味が分かっていませんでした。

> System.Diagnostics.Process.Start("C:\Program Files\Microsoft Visual Studio\VB98\vb6.exe", """" & vbPath & fileName & """")
>
> 文字列の中で、ダブルクォーテーションを表現する時は、「""」と2回書きます。
> で、文字列は"〜〜〜〜"の中に含ませることで表現しますから。
> "〜〜〜〜"の中に「""」を入れることになります。
> つまり、「""""」ということになります。
>
> わかりにくければ、
>
> Public Const DoubleQuotation As String = """"
>
> DoubleQuotation & vbPath & fileName & DoubleQuotation
>
> ということです。

よ〜く分かりました。これですべて分かりました。
文字列操作は確かに不勉強でした。勉強になりました。
ありがとうございました。m(__)m
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板