Marshal.SizeOf

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Howard Kaikow

    Marshal.SizeOf

    Given:

    [StructLayout(La youtKind.Sequen tial, CharSet=CharSet .Auto)]
    private struct PROCESSENTRY32
    {
    public int dwSize;
    public int cntUsage;
    public int th32ProcessID;
    public int th32DefaultHeap ID;
    public int th32ModuleID;
    public int cntThreads;
    public int th32ParentProce ssID;
    public int pcPriClassBase;
    public int dwFlags;
    [MarshalAs(Unman agedType.ByValT Str, SizeConst=MAX_P ATH)]
    public char szExeFile;
    }

    and

    PROCESSENTRY32 pe32 = new PROCESSENTRY32( );

    I was using the following:

    pe32.dwSize =sizeof(PROCESS ENTRY32);

    But that returned the wrong value 40 instead of the correct value 296, as
    MAX_PATH is 260.

    So I tried the following:

    pe32.dwSize = Marshal.SizeOf( PROCESSENTRY32) ;

    Which results in the following error at build time:

    D:\Visual Basic
    Code\API\EnumPr ocesses\Code-GetUsageCount\C sharpGetUsageCo unt\Form1.cs(34 0):
    'CsharpGetUsage Count.Form1.MOD ULEENTRY32' denotes a 'class' where a
    'variable' was expected

    So, I tried

    pe32.dwSize = Marshal.SizeOf( pe32);

    Alas, that ended up causing an exception, with the message:

    "Type PROCESSENTRY32 can not be marshaled as an unmanaged structure; no
    meaningful size or offset can be computed."

    What do I need to do to correct the problem?


  • Bart Mermuys

    #2
    Re: Marshal.SizeOf

    Hi,
    [Inline]

    "Howard Kaikow" <kaikow@standar ds.com> wrote in message
    news:eQhiN9HaFH A.2996@TK2MSFTN GP10.phx.gbl...[color=blue]
    > Given:
    >
    > [StructLayout(La youtKind.Sequen tial, CharSet=CharSet .Auto)]
    > private struct PROCESSENTRY32
    > {
    > public int dwSize;
    > public int cntUsage;
    > public int th32ProcessID;
    > public int th32DefaultHeap ID;
    > public int th32ModuleID;
    > public int cntThreads;
    > public int th32ParentProce ssID;
    > public int pcPriClassBase;
    > public int dwFlags;
    > [MarshalAs(Unman agedType.ByValT Str, SizeConst=MAX_P ATH)]
    > public char szExeFile;
    > }[/color]

    The last part should be:
    [MarshalAs(Unman agedType.ByValT Str, SizeConst=MAX_P ATH)]
    public string szExeFile;

    [color=blue]
    >
    > and
    >
    > PROCESSENTRY32 pe32 = new PROCESSENTRY32( );
    >
    > I was using the following:
    >
    > pe32.dwSize =sizeof(PROCESS ENTRY32);[/color]

    use Marshal.SizeOf
    [color=blue]
    >
    > But that returned the wrong value 40 instead of the correct value 296, as
    > MAX_PATH is 260.[/color]

    Yeah, but since you chosen Auto for charset, strings will be wide on nt
    versions of windows. So the struct would be at least 260*2, this doesn't
    have to be a problem though.
    [color=blue]
    >
    > So I tried the following:
    >
    > pe32.dwSize = Marshal.SizeOf( PROCESSENTRY32) ;[/color]

    Should be :
    pe32.dwSize = Marshal.SizeOf( typeof(PROCESSE NTRY32));
    [color=blue]
    >
    > Which results in the following error at build time:
    >
    > D:\Visual Basic
    > Code\API\EnumPr ocesses\Code-GetUsageCount\C sharpGetUsageCo unt\Form1.cs(34 0):
    > 'CsharpGetUsage Count.Form1.MOD ULEENTRY32' denotes a 'class' where a
    > 'variable' was expected
    >
    > So, I tried
    >
    > pe32.dwSize = Marshal.SizeOf( pe32);[/color]

    That should work now.

    HTH,
    greetings
    [color=blue]
    >
    > Alas, that ended up causing an exception, with the message:
    >
    > "Type PROCESSENTRY32 can not be marshaled as an unmanaged structure; no
    > meaningful size or offset can be computed."
    >
    > What do I need to do to correct the problem?
    >
    >[/color]


    Comment

    • Howard Kaikow

      #3
      Re: Marshal.SizeOf

      "Bart Mermuys" <bmermuys.nospa m@hotmail.com> wrote in message
      news:ufR283JaFH A.3488@tk2msftn gp13.phx.gbl...

      Thanx.

      Your suggestion worked.
      Now the following

      Process32First( hProcessSnap, pe32)

      Results in the error

      //Object reference not set to an instance of an object.

      Where I have:

      [DllImport("kern el32", EntryPoint="Pro cess32First", ExactSpelling=f alse,
      CharSet=CharSet .Ansi, SetLastError=tr ue)]
      private static extern bool Process32First( int hSnapshot, PROCESSENTRY32
      lppe);

      For your information, the goal is to convert the code at



      I already have the code running in C++ .NET 2003


      GetUsageCount.z ip

      Goal is to get code working in C#, VB .NET and VB 6.


      Comment

      • Bart Mermuys

        #4
        Re: Marshal.SizeOf

        Hi,

        "Howard Kaikow" <kaikow@standar ds.com> wrote in message
        news:%239E1uIMa FHA.2996@TK2MSF TNGP10.phx.gbl. ..[color=blue]
        > "Bart Mermuys" <bmermuys.nospa m@hotmail.com> wrote in message
        > news:ufR283JaFH A.3488@tk2msftn gp13.phx.gbl...
        >
        > Thanx.
        >
        > Your suggestion worked.
        > Now the following
        >
        > Process32First( hProcessSnap, pe32)
        >
        > Results in the error
        >
        > //Object reference not set to an instance of an object.
        >
        > Where I have:
        >
        > [DllImport("kern el32", EntryPoint="Pro cess32First", ExactSpelling=f alse,
        > CharSet=CharSet .Ansi, SetLastError=tr ue)]
        > private static extern bool Process32First( int hSnapshot, PROCESSENTRY32
        > lppe);[/color]


        - use IntPtr for C/C++ HANDLE types
        - since you declared PROCESSENTRY32 as a _struct_ and you need to pass a
        pointer, you have to use to ref keyword :
        - use the same CharSet on both the structure and the api

        [DllImport("kern el32", CharSet=CharSet .Auto, SetLastError=tr ue)]
        private static extern bool Process32First( IntPtr hSnapshot, ref
        PROCESSENTRY32 lppe);


        Example:

        [StructLayout(La youtKind.Sequen tial)]
        struct PROCESSENTRY32
        {
        public int dwSize;
        public int cntUsage;
        public int th32ProcessID;
        public int th32DefaultHeap ID;
        public int th32ModuleID;
        public int cntThreads;
        public int th32ParentProce ssID;
        public int pcPriClassBase;
        public int dwFlags;
        [MarshalAs(Unman agedType.ByValT Str, SizeConst=260)]
        public string szExeFile;
        }

        const uint TH32CS_SNAPPROC ESS = 0x00000002;

        [DllImport("kern el32.dll",SetLa stError=true)]
        public static extern IntPtr CreateToolhelp3 2Snapshot(
        uint dwFlags,
        uint th32ProcessID );

        [DllImport("kern el32.dll",SetLa stError=true)]
        public static extern bool Process32First(
        IntPtr hSnapshot,
        ref PROCESSENTRY32 lppe );

        [DllImport("kern el32.dll",SetLa stError=true)]
        public static extern bool Process32Next(
        IntPtr hSnapshot,
        ref PROCESSENTRY32 lppe );

        [DllImport("kern el32.dll",SetLa stError=true)]
        public static extern bool CloseHandle(
        IntPtr hObject // handle to object);


        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main(string[] args)
        {
        IntPtr p = CreateToolhelp3 2Snapshot( TH32CS_SNAPPROC ESS, 0 );

        PROCESSENTRY32 pe = new PROCESSENTRY32( );
        pe.dwSize = Marshal.SizeOf( pe);
        bool ret = Process32First( p, ref pe );

        while ( ret )
        {
        // show current
        Console.WriteLi ne( pe.szExeFile + "\t" + pe.th32ProcessI D + "\t" +
        pe.cntThreads );

        // get next
        pe.dwSize = Marshal.SizeOf( pe);
        ret = Process32Next( p, ref pe );
        }

        CloseHandle(p);
        Console.ReadLin e();
        }

        HTH,
        greetings
        [color=blue]
        >
        > For your information, the goal is to convert the code at
        >
        > http://msdn.microsoft.com/library/de..._processes.asp
        >
        > I already have the code running in C++ .NET 2003
        >
        > http://www.standards.com/OtherDownlo...s/UnmanagedC++
        > GetUsageCount.z ip
        >
        > Goal is to get code working in C#, VB .NET and VB 6.
        >
        >[/color]


        Comment

        • Howard Kaikow

          #5
          Re: Marshal.SizeOf

          Thanx.

          The problem appears to have been the missing ref.

          Note that the code did not work when I used IntPtr.

          What's the best book to address the type of questions I've asked?

          Previously, I had only:

          C# Essentials
          A Progranmmer's Introduction to C#

          This past week. I ordered:

          The MSFT Press Step by Step book (received yesterday).
          Liberty's Programming C#..
          Hejlsberg's book.

          Again, thanx, now it's on to do a VB .NET version.
          That task should be easier since the issue of the ref has been solved.

          At some point, I will be posting an article at my web site, goving the code
          for the C++, C#, VB .NET and VB 6 versions, and describing whether the
          intended problem has been solved, but I do not want to digress now.


          Comment

          • Willy Denoyette [MVP]

            #6
            Re: Marshal.SizeOf



            "Howard Kaikow" <kaikow@standar ds.com> wrote in message
            news:%239E1uIMa FHA.2996@TK2MSF TNGP10.phx.gbl. ..[color=blue]
            > "Bart Mermuys" <bmermuys.nospa m@hotmail.com> wrote in message
            > news:ufR283JaFH A.3488@tk2msftn gp13.phx.gbl...
            >
            > Thanx.
            >
            > Your suggestion worked.
            > Now the following
            >
            > Process32First( hProcessSnap, pe32)
            >
            > Results in the error
            >
            > //Object reference not set to an instance of an object.
            >
            > Where I have:
            >
            > [DllImport("kern el32", EntryPoint="Pro cess32First", ExactSpelling=f alse,
            > CharSet=CharSet .Ansi, SetLastError=tr ue)]
            > private static extern bool Process32First( int hSnapshot, PROCESSENTRY32
            > lppe);
            >
            > For your information, the goal is to convert the code at
            >
            > http://msdn.microsoft.com/library/de..._processes.asp
            >
            > I already have the code running in C++ .NET 2003
            >
            > http://www.standards.com/OtherDownlo...s/UnmanagedC++
            > GetUsageCount.z ip
            >
            > Goal is to get code working in C#, VB .NET and VB 6.
            >
            >[/color]

            Why convert and not simply use what's offered by the FCL, especially the
            System.Diagnost ics and System.Manageme nt namespace classes are just what you
            need to achieve what you are looking for.

            If you have to PInvoke that much in C#, it means you didn't check the FCL
            for a managed solution and you missed the point of .NET where the FCL is
            key, not the language you use to implement, or you might have chosen the
            wrong language.

            Willy.



            Comment

            • Howard Kaikow

              #7
              Re: Marshal.SizeOf

              "Willy Denoyette [MVP]" <willy.denoyett e@telenet.be> wrote in message
              news:Or3S1RSaFH A.2756@tk2msftn gp13.phx.gbl...
              [color=blue]
              > Why convert and not simply use what's offered by the FCL, especially the
              > System.Diagnost ics and System.Manageme nt namespace classes are just what[/color]
              you[color=blue]
              > need to achieve what you are looking for.
              >
              > If you have to PInvoke that much in C#, it means you didn't check the FCL
              > for a managed solution and you missed the point of .NET where the FCL is
              > key, not the language you use to implement, or you might have chosen the
              > wrong language.[/color]

              Yes, but the goal is to do the deed in VB 6.

              I was having difficulty with the task in VB 6, so I decided to try running
              the C code example at


              I first put the code thru MSFT C++ V6 Learning edition.
              Then I import that workspace into C++ .NET 2002, then into C++ .NET 2003.
              Then to C#, and I just finished converting to VB .NET this evening.

              I should be able to more easily implement a VB 6 version, using the VB .NET
              version as a guide.

              I do have a partial solution using the Framework stiff.
              I found 11 of the 12 APIs I'm using are alleged to have Framework
              equivalents.
              Other is CloseHandle, have not yet looked for that equivalent.


              Comment

              Working...