DllImport PathCanonicalize на 64-битной основе приводит к повреждению памяти - PullRequest
1 голос
/ 14 июля 2011

Я пытаюсь использовать функцию PathCanonicalize, используя DllImport (PInvoke) в 64-битной сборке .NET, и это вызывает повреждение памяти, приводящее ко всем видам плохого поведения (сбой, исключения из ниоткуда и т. Д ...). (Например: System.AccessViolationException: попытка чтения или записи защищенной памяти. Это часто указывает на повреждение другой памяти.)

    [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 вместо прямых строк. Кто-нибудь может показать мне, как упорядочить их в строках ввода и вывода в PathCanonicalize?

Прототип:

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

Ответы [ 2 ]

5 голосов
/ 14 июля 2011

Из документации SDK:

lpszDst
[out] Указатель на строку, которая получает канонизированный путь. Вы должны установить размер этого буфера на MAX_PATH чтобы убедиться, что он достаточно большой, чтобы вместить возвращаемую строку.

Что вы не сделали. Fix:

    StringBuilder builder = new StringBuilder(260);
3 голосов
/ 14 июля 2011

В MSDN для PathCanonicalize (выделено):

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();
}

Кроме того, обратите внимание, что [Out] на lpszDst также нет, это потому, что вызываемый метод не возвращает вам указатель, скорее вы даете емууказатель на память для записи канонизированного пути. (не обращая внимания, он, кажется, справляется с этим нормально с или без [Out])

...