PInvoke und Interop-Code am Beispiel ShGetFileInfo
Frank Dzaebel, erstellt am: 24.05.2005, zuletzt geändert:  24.05.2005
Kategorie: Interop, .NET-Version: 1.1

Der folgende Code stellt Kommunikations-Möglichkeiten zwischen .NET-C# und der Windows API beispielhaft anhand der SHGetFileInfo-Funktion, SHFILEINFO-struct und dem Enum SHGFI dar. Die Funktion wurde auf XP/Prof und Windows98 getestet. Relevante Interop-Links werden aufgeführt.

Weiterführende Artikel über C# und Interop-Techniken:
   Lernprogramm für die Plattformaktivierung
   COM-Interop Teil 1: C#-Clientlernprogramm
   C# Tipps - Interoperabilität mit nicht verwaltetem Code
   Mit C# arbeiten - Verwenden von Win32 und anderen Bibliotheken
   So arbeitet .NET mit Win32 und COM zusammen
   Marshal-Klasse, PInvoke.NET

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Runtime.InteropServices;
using System.Reflection;

namespace MarshalSizeof
{
  public class Form1 : System.Windows.Forms.Form
  {
    private System.Windows.Forms.Button btnByVal;
    private System.ComponentModel.Container components = null;

    public Form1()
    {
      InitializeComponent();
    }

    protected override void Dispose( bool disposing )
    { if(disposing) if (components != null) components.Dispose();
      base.Dispose(disposing);
    }

    #region Vom Windows Form-Designer generierter Code

    private void InitializeComponent()
    {
      this.btnByVal = new System.Windows.Forms.Button();
      this.SuspendLayout();
      // 
      // btnByVal
      // 
      this.btnByVal.Location = new System.Drawing.Point(26, 31);
      this.btnByVal.Name = "btnByVal";
      this.btnByVal.Size = new System.Drawing.Size(53, 24);
      this.btnByVal.TabIndex = 0;
      this.btnByVal.Text = "ByVal";
      this.btnByVal.Click += new System.EventHandler(this.btnByVal_Click);
      // 
      // Form1
      // 
      this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
      this.ClientSize = new System.Drawing.Size(292, 266);
      this.Controls.Add(this.btnByVal);
      this.Name = "Form1";
      this.Text = "Form1";
      this.ResumeLayout(false);

    }
    #endregion

    [STAThread]
    static void Main() 
    {
      Application.Run(new Form1());
    }


    private void btnByVal_Click(object sender, System.EventArgs e)
    {
      string path = Application.ExecutablePath;
      SHFILEINFO fi; 
      SHGetFileInfo(path, 0, out fi, 
        (uint)Marshal.SizeOf(typeof(SHFILEINFO)), 
        SHGFI.DisplayName);
      MessageBox.Show("Displayname = " + fi.szDisplayName);
    }
    
      [DllImport("shell32.dll", CharSet=CharSet.Auto)]
      private static extern int  SHGetFileInfo(
        string pszPath         ,
        int    dwFileAttributes,
        out    SHFILEINFO psfi ,
        uint   cbfileInfo      ,
        SHGFI  uFlags );

        [Flags]
        enum SHGFI : int
        {
          /// <summary>get icon</summary>
          Icon             = 0x000000100,   
          /// <summary>get display name</summary>
          DisplayName      = 0x000000200, 
          /// <summary>get type name</summary>
          TypeName         = 0x000000400, 
          /// <summary>get attributes</summary>
          Attributes       = 0x000000800, 
          /// <summary>get icon location</summary>
          IconLocatin      = 0x000001000,  
          /// <summary>return exe type</summary>
          ExeType          = 0x000002000,  
          /// <summary>get system icon index</summary>
          SysIconIndex     = 0x000004000,  
          /// <summary>put a link overlay on icon</summary>
          LinkOverlay      = 0x000008000,  
          /// <summary>show icon in selected state</summary>
          Selected         = 0x000010000,  
          /// <summary>get only specified attributes</summary>
          Attr_Specified   = 0x000020000,  
          /// <summary>get large icon</summary>
          LargeIcon        = 0x000000000,  
          /// <summary>get small icon</summary>
          SmallIcon        = 0x000000001,  
          /// <summary>get open icon</summary>
          OpenIcon         = 0x000000002,  
          /// <summary>get shell size icon</summary>
          ShellIconize     = 0x000000004,  
          /// <summary>pszPath is a pidl</summary>
          PIDL             = 0x000000008,  
          /// <summary>use passed dwFileAttribute</summary>
          UseFileAttributes= 0x000000010,  
          /// <summary>apply the appropriate overlays</summary>
          AddOverlays      = 0x000000020,  
          /// <summary>Get the index of the overlay in the upper 8 bits of the iIcon</summary>
          OverlayIndex     = 0x000000040,  
        }                                                 

        /// <summary>Maximal Length of unmanaged Windows-Path-strings</summary>
        private const int MAX_PATH = 260;
        /// <summary>Maximal Length of unmanaged Typename</summary>
        private const int MAX_TYPE = 80 ;

        [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
        private struct SHFILEINFO
        {
          public SHFILEINFO(bool b)
          {
            hIcon=IntPtr.Zero;
            iIcon=0;
            dwAttributes=0;
            szDisplayName="";
            szTypeName="";
          }
          public IntPtr hIcon;
          public int iIcon;
          public uint dwAttributes;
          [MarshalAs(UnmanagedType.ByValTStr, SizeConst=MAX_PATH)]
          public string szDisplayName;
          [MarshalAs(UnmanagedType.ByValTStr, SizeConst=MAX_TYPE)]
          public string szTypeName;
        };
  }
}