1

Windows Mobile 6 を使用してスマートフォン用の小さなアプリを作成しています。現在実行中のすべての processec を取得しようとしていますが、CreateToolhelp32Snapshot メソッドは常に -1 を返します。だから今私は立ち往生しています。GetLastError() メソッドを呼び出してエラーを取得しようとしましたが、そのメソッドは 0 値を返します。これが私のコードのスニペットです。

private const int TH32CS_SNAPPROCESS = 0x00000002;
[DllImport("toolhelp.dll")]
public static extern IntPtr CreateToolhelp32Snapshot(uint flags, 
                                                     uint processid);

public static Process[] GetProcesses()
    {
        ArrayList procList = new ArrayList();
        IntPtr handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

        if ((int)handle > 0)
        {
            try
            {
                PROCESSENTRY32 peCurr;
                PROCESSENTRY32 pe32 = new PROCESSENTRY32();

                // get byte array to pass to API call
                byte[] peBytes = pe32.ToByteArray();
                // get the first process
                int retval = Process32First(handle, peBytes);
4

4 に答える 4

5
  • まず、ハンドルチェックが間違っています。ハンドルの上位ビットがオンになっているのが一般的であり、signedintにキャストすると負の数のように見えます。NULL(0)またはINVALID_HANDLE_VALUE(-1 / 0xffffffff)ではないことを確認する必要があります。
  • 「GetLastErrorを呼び出す」のではなく、Marshal.GetLastWin32Error()を呼び出す必要があります。
  • P/Invoke宣言でSetLastError属性を設定していません。C#ではデフォルトでfalseになり、VBではデフォルトでtrueになります。
  • PROCESS32の実装はどこにありますか?ドキュメントには、呼び出しの前にdwLengthメンバーを設定する必要があることが明確に記載されており、それが発生しているかどうかはここでは明確ではありません。

ちなみに、Smart Device FrameworkOpenNETCF.ToolHelp名前空間には、これらすべてが実装され、機能しています(車輪の再発明をしたくない場合に備えて)。

于 2008-12-26T17:23:02.893 に答える
0

これは、MSDN ドキュメントに基づく適切な実装です。

private const int INVALID_HANDLE_VALUE = -1;

[Flags]
private enum SnapshotFlags : uint
{
    HeapList = 0x00000001,
    Process = 0x00000002,
    Thread = 0x00000004,
    Module = 0x00000008,
    Module32 = 0x00000010,
    Inherit = 0x80000000,
    All = 0x0000001F,
    NoHeaps = 0x40000000
}

[DllImport("toolhelp.dll"]
private static extern IntPtr CreateToolhelp32Snapshot(SnapshotFlags dwFlags, int th32ProcessID);

[StructLayout(LayoutKind.Sequential)]
public struct PROCESSENTRY32
{
    public uint dwSize;
    public uint cntUsage;
    public uint th32ProcessID;
    public IntPtr th32DefaultHeapID;
    public uint th32ModuleID;
    public uint cntThreads;
    public uint th32ParentProcessID;
    public int pcPriClassBase;
    public uint dwFlags;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] public string szExeFile;
};


IntPtr hSnap = CreateToolhelp32Snapshot(SnapshotFlags.Process, 0);

if (hSnap.ToInt64() != INVALID_HANDLE_VALUE)
{
    PROCESSENTRY32 procEntry = new PROCESSENTRY32();
    procEntry.dwSize = (uint)Marshal.SizeOf(typeof(PROCESSENTRY32));

    if (Process32First(hSnap, ref procEntry))
    {
        do
        {

            //do whatever you want here

        } while (Process32Next(hSnap, ref procEntry));
    }
}

CloseHandle(hSnap);

procEntry のサイズを設定する必要があるため、最も重要なのは次の行です。

procEntry.dwSize = (uint)Marshal.SizeOf(typeof(PROCESSENTRY32));

于 2020-04-17T01:15:27.533 に答える
0

有効な「最後のエラー」情報が表示されない場合は、API の DllImport 属性に「SetLastError」属性を追加する必要があるかもしれません ( MSDN リファレンスとコード例)。この属性のドキュメントによると、SetLastError を次のように設定する必要があります...

...呼び出し先が SetLastError を呼び出すことを示す場合は true。それ以外の場合は false。デフォルトは false です。

ランタイム マーシャラーは GetLastError を呼び出し、返された値をキャッシュして、他の API 呼び出しによって上書きされないようにします。GetLastWin32Error を呼び出すと、エラー コードを取得できます。

あなたが目にしている API の失敗に関しては、私は明らかな不自然な点は何も見つけていません。あなたが持っているコードは、こちらのサンプルコードに非常に似ているようです。

于 2008-12-26T16:05:20.367 に答える