2011-07-13 18 views
1

64ビット.NETアセンブリでDllImport(PInvoke)を使用してPathCanonicalize関数を使用しようとしていますが、メモリの破損が原因であらゆる種類の不良動作(クラッシュ、等...)。 (例:System.AccessViolationException:読み取りまたは書き込み保護されているメモリをしようとしましたこれは、多くの場合、他のメモリが破損していることを示しています。)DllImport PathCanonicalize 64ビットでメモリ破損が発生する

[DllImport("shlwapi", CharSet = CharSet.Auto, EntryPoint="PathCanonicalize", SetLastError = true)] 
    private static extern bool PathCanonicalize([Out] StringBuilder lpszDst,[In] string lpszSrc); 

    public static string MyPathCanonicalize(string path) 
    { 
     StringBuilder builder = new StringBuilder(); 
     if (!PathCanonicalize(builder, path)) 
      return path; 
     return builder.ToString(); 
    } 

は私は私はおそらくのIntPtrの代わりに、直接文字列を使用すべきことであるが、this threadで見ました。 PathCanonicalizeの入力文字列と出力文字列をマーシャリングする方法を誰かに教えてもらえますか?

プロトタイプである:PathCanonicalizeためMSDN当たり

BOOL PathCanonicalize(
    __out LPTSTR lpszDst, 
    __in LPCTSTR lpszSrc 
); 

答えて

5

(無視は、でたり[Out]せずに罰金、それを処理するために表示されます):

lpszDst
[出力] 正規化のパスを受けた文字列へのポインタ。 このバッファのサイズをMAX_PATH に設定して、返される文字列を保持するのに十分な大きさにする必要があります。

あなたはしていませんでした。修正:

StringBuilder builder = new StringBuilder(260); 
+0

ありがとうございますそれ! – decasteljau

3

(強調鉱山):

lpszDst[OUT]

型:LPTSTR

ポインタにその文字列を受け取る文字列正規化されたパス。 返される文字列を保持するのに十分な大きさにするには、このバッファのサイズをMAX_PATHに設定する必要があります。

あなたはbuilder呼び出しの前に初期化する必要があります。また

public static readonly int MaxPath = 260; 

public static string MyPathCanonicalize(string path) 
{ 
    StringBuilder builder = new StringBuilder(MaxPath); 
    if (!PathCanonicalize(builder, path)) 
     return path; 
    return builder.ToString(); 
} 

は、呼び出されたメソッドはあなたにポインタを返すされていないため、これは、 lpszDstには [Out]はありません注意してください、むしろ正規化されたパスを書くためのメモリへのポインタを与えています。 SDKのドキュメントから

+0

+1なぜlpszSrcに[In]を挿入するのですか?それは暗黙のうちにマーシャル協定のためです。 –

+0

コピー貼り付けに失敗しましたが、私は '[Out]'属性で動作するように見えるので、これを削除しました。 – user7116

+0

'[in]'と '[out]'アノテーションはC/C++ヘッダーのためのもので、C#にコピーしないでください。 –

関連する問題