2

DBGHELP.DLLから起動しようとしてSymSrvStoreFileWいます (以前に作業に失敗した後SymSrvGetFileIndexInfoW)。重要な関数は、MSDN で次のように定義されています。

BOOL WINAPI SymInitialize(
  _In_      HANDLE hProcess,
  _In_opt_  PCTSTR UserSearchPath, // null is documented as fine
  _In_      BOOL fInvadeProcess // false
);

PCTSTR WINAPI SymSrvStoreFile(
  _In_      HANDLE hProcess,
  _In_opt_  PCTSTR SrvPath, // e.g. "srv*C:\symbols"
  _In_      PCTSTR File, // e.g. "C:\myapp.pdb"
  _In_      DWORD Flags // I am using SYMSTOREOPT_RETURNINDEX (0x04)
);

BOOL WINAPI SymCleanup(
  _In_  HANDLE hProcess
);

hProcessは少し奇妙です。私が収集したドキュメントによると、一貫性を保つ限り、何を渡すかは問題ではありません。現在のプロセス ID と「任意の古い値」ID の両方を使用しました。どちらも機能しませんでした。

私は以下を作りましたexterns

[DllImport("dbghelp.dll", EntryPoint = "SymInitializeW", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
public static extern bool SymInitialize(
    IntPtr process,
    [param: MarshalAs(UnmanagedType.LPTStr)]
    string searchPath, 
    bool invadeProcess);

[DllImport("dbghelp.dll", EntryPoint = "SymCleanup", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
public static extern bool SymCleanup(IntPtr process);

[DllImport("dbghelp.dll", EntryPoint = "SymSrvStoreFileW", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
[return: MarshalAs(UnmanagedType.LPTStr)]
public static extern string SymSrvStoreFile(
    IntPtr process,
    [param: MarshalAs(UnmanagedType.LPTStr)]
    string srvPath,
    [param: MarshalAs(UnmanagedType.LPTStr)]
    string file,
    SymStoreOpt options);

enum SymStoreOpt : uint
{
    None = 0x00,
    Compress = 0x01,
    Overwrite = 0x02,
    Pointer = 0x08,
    ReturnIndex = 0x04,
    PassIfExists = 0x40,
}

そして電話を試みました:

var processId = IntPtr.Zero;
try
{
    // This succeeds.
    processId = new IntPtr(Process.GetCurrentProcess().Id);
    if (!NativeMethods.SymInitialize(processId, null, false))
    {
        processId = IntPtr.Zero;
        throw new Win32Exception(Marshal.GetLastWin32Error());
    }

    // This fails.
    var storageLocation = NativeMethods.SymSrvStoreFile(processId, "srv*C:\\vssym", "C:\\test\\mscorlib.pdb", SymStoreOpt.ReturnIndex);
    if (storageLocation == null)
    {
        // Errors under various circumstances.
        // - The operation completed successfully (but storageLocation is still null)
        // - The specified module could not be found
        throw new Win32Exception(Marshal.GetLastWin32Error());
    }
}
finally
{
    if (processId != IntPtr.Zero)
        NativeMethods.SymCleanup(processId);
}

私のextern宣言に間違いはありますか?または、PDB/PE (.Net だけでなく) のシンボル格納場所を取得する方法を知っている人はいますか? 他のフラグも試しましたSymStoreOptが、どこにも行きませんでした。

ある時点で (何をしたか思い出せません)、ファイルがシンボルの保存場所に表示されました (ReturnIndex使用されていたとしても) が、その時点でプロセスがクラッシュしました (デバッガーがキャッチさえしない場所の 1 つ)。 、再度実行すると、戻り値なしで「操作は成功しました」という結果になります。

編集: C++でこれを試してみましたが、同じ動作が得られます。明らかに、P/Invoke にはアーキテクチャの中立性という利点があるため、そのルートには行きたくありません。

4

0 に答える 0