views:

332

answers:

3
 public partial class Form1 : Form
{
  [DllImport("coredll.dll")]
    static extern int SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong);

  [DllImport("coredll.dll")]
  static extern IntPtr CallWindowProc(IntPtr lpPrevWndFunc, IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);

  [DllImport("coredll.dll")]
  public static extern IntPtr GetWindowLong(IntPtr hWnd, int nIndex);


  //public struct tagSHCHANGENOTIFYENTRY
  //{
  //    [MarshalAs(UnmanagedType.SysUInt)]
  //    public ulong dwEventMask;

  //    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4096)]
  //    public string WatchDir;

  //    [MarshalAs(UnmanagedType.Bool)]
  //    public bool fRecursive;
  //}
  //tagSHCHANGENOTIFYENTRY test;

  //[DllImport("aygshell.dll")]
  //static extern bool SHChangeNotifyRegister(IntPtr hwnd, ref tagSHCHANGENOTIFYENTRY test);

  const int GWL_WNDPROC = -4;

  public delegate int WindProc(IntPtr hWnd, int msg, IntPtr Wparam, IntPtr lparam);

  static private WindProc SampleProc;
  IntPtr OldDefProc = IntPtr.Zero;

  public enum SHCNE : uint
  {
      SHCNE_RENAMEITEM = 0x00000001,
      SHCNE_CREATE = 0x00000002,
      SHCNE_DELETE = 0x00000004,
      SHCNE_MKDIR = 0x00000008,
      SHCNE_RMDIR = 0x00000010,
      SHCNE_MEDIAINSERTED = 0x00000020,
      SHCNE_MEDIAREMOVED = 0x00000040,
      SHCNE_DRIVEREMOVED = 0x00000080,
      SHCNE_DRIVEADD = 0x00000100,
      SHCNE_NETSHARE = 0x00000200,
      SHCNE_NETUNSHARE = 0x00000400,
      SHCNE_ATTRIBUTES = 0x00000800,
      SHCNE_UPDATEDIR = 0x00001000,
      SHCNE_UPDATEITEM = 0x00002000,
      SHCNE_SERVERDISCONNECT = 0x00004000,
      SHCNE_UPDATEIMAGE = 0x00008000,
      SHCNE_DRIVEADDGUI = 0x00010000,
      SHCNE_RENAMEFOLDER = 0x00020000,
      SHCNE_FREESPACE = 0x00040000,
      SHCNE_EXTENDED_EVENT = 0x04000000,
      SHCNE_ASSOCCHANGED = 0x08000000,
      SHCNE_DISKEVENTS = 0x0002381F,
      SHCNE_GLOBALEVENTS = 0x0C0581E0,
      SHCNE_ALLEVENTS = 0x7FFFFFFF,
      SHCNE_INTERRUPT = 0x80000000,
  }

  public enum SHCNF
  {
      SHCNF_IDLIST = 0x0000,
      SHCNF_PATHA = 0x0001,
      SHCNF_PRINTERA = 0x0002,
      SHCNF_DWORD = 0x0003,
      SHCNF_PATHW = 0x0005,
      SHCNF_PRINTERW = 0x0006,
      SHCNF_TYPE = 0x00FF,
      SHCNF_FLUSH = 0x1000,
      SHCNF_FLUSHNOWAIT = 0x2000
  }

  public const uint WM_SHNOTIFY = 0x0401;

  private const int WM_FILECHANGEINFO = (0x8000 + 0x101);

  public struct SHChangeNotifyEntry
  {
      public IntPtr pIdl;
      [MarshalAs(UnmanagedType.Bool)]
      public Boolean Recursively;
  }



  [DllImport("coredll.dll", EntryPoint = "#2", CharSet = CharSet.Auto)]
  private static extern uint SHChangeNotifyRegister(
      IntPtr hWnd,
      SHCNF fSources,
      SHCNE fEvents,
      uint wMsg,
      int cEntries,
      ref SHChangeNotifyEntry pFsne);

  [DllImport("Ceshell.dll", CharSet = CharSet.Auto)]
  private static extern uint SHGetSpecialFolderLocation(
      IntPtr hWnd,
      CSIDL nFolder,
      out IntPtr Pidl);

  public enum CSIDL
  {
      /// <summary>
      /// Desktop
      /// </summary>
      CSIDL_DESKTOP = 0x0000,
      /// <summary>
      /// Internet Explorer (icon on desktop)
      /// </summary>
      CSIDL_INTERNET = 0x0001,
      /// <summary>
      /// Start Menu\Programs
      /// </summary>
      CSIDL_PROGRAMS = 0x0002,
      /// <summary>
      /// My Computer\Control Panel
      /// </summary>
      CSIDL_CONTROLS = 0x0003,
      /// <summary>
      /// My Computer\Printers
      /// </summary>
      CSIDL_PRINTERS = 0x0004,
      /// <summary>
      /// My Documents
      /// </summary>
      CSIDL_PERSONAL = 0x0005,
      /// <summary>
      /// user name\Favorites
      /// </summary>
      CSIDL_FAVORITES = 0x0006,
      /// <summary>
      /// Start Menu\Programs\Startup
      /// </summary>
      CSIDL_STARTUP = 0x0007,
      /// <summary>
      /// user name\Recent
      /// </summary>
      CSIDL_RECENT = 0x0008,
      /// <summary>
      /// user name\SendTo
      /// </summary>
      CSIDL_SENDTO = 0x0009,
      /// <summary>
      /// desktop\Recycle Bin
      /// </summary>
      CSIDL_BITBUCKET = 0x000a,
      /// <summary>
      /// user name\Start Menu
      /// </summary>
      CSIDL_STARTMENU = 0x000b,
      /// <summary>
      /// logical "My Documents" desktop icon
      /// </summary>
      CSIDL_MYDOCUMENTS = 0x000c,
      /// <summary>
      /// "My Music" folder
      /// </summary>
      CSIDL_MYMUSIC = 0x000d,
      /// <summary>
      /// "My Videos" folder
      /// </summary>
      CSIDL_MYVIDEO = 0x000e,
      /// <summary>
      /// user name\Desktop
      /// </summary>
      CSIDL_DESKTOPDIRECTORY = 0x0010,
      /// <summary>
      /// My Computer
      /// </summary>
      CSIDL_DRIVES = 0x0011,
      /// <summary>
      /// Network Neighborhood (My Network Places)
      /// </summary>
      CSIDL_NETWORK = 0x0012,
      /// <summary>
      /// user name>nethood
      /// </summary>
      CSIDL_NETHOOD = 0x0013,
      /// <summary>
      /// windows\fonts
      /// </summary>
      CSIDL_FONTS = 0x0014,
      CSIDL_TEMPLATES = 0x0015,
      /// <summary>
      /// All Users\Start Menu
      /// </summary>
      CSIDL_COMMON_STARTMENU = 0x0016,
      /// <summary>
      /// All Users\Start Menu\Programs
      /// </summary>
      CSIDL_COMMON_PROGRAMS = 0X0017,
      /// <summary>
      /// All Users\Startup
      /// </summary>
      CSIDL_COMMON_STARTUP = 0x0018,
      /// <summary>
      /// All Users\Desktop
      /// </summary>
      CSIDL_COMMON_DESKTOPDIRECTORY = 0x0019,
      /// <summary>
      /// user name\Application Data
      /// </summary>
      CSIDL_APPDATA = 0x001a,
      /// <summary>
      /// user name\PrintHood
      /// </summary>
      CSIDL_PRINTHOOD = 0x001b,
      /// <summary>
      /// user name\Local Settings\Applicaiton Data (non roaming)
      /// </summary>
      CSIDL_LOCAL_APPDATA = 0x001c,
      /// <summary>
      /// non localized startup
      /// </summary>
      CSIDL_ALTSTARTUP = 0x001d,
      /// <summary>
      /// non localized common startup
      /// </summary>
      CSIDL_COMMON_ALTSTARTUP = 0x001e,
      CSIDL_COMMON_FAVORITES = 0x001f,
      CSIDL_INTERNET_CACHE = 0x0020,
      CSIDL_COOKIES = 0x0021,
      CSIDL_HISTORY = 0x0022,
      /// <summary>
      /// All Users\Application Data
      /// </summary>
      CSIDL_COMMON_APPDATA = 0x0023,
      /// <summary>
      /// GetWindowsDirectory()
      /// </summary>
      CSIDL_WINDOWS = 0x0024,
      /// <summary>
      /// GetSystemDirectory()
      /// </summary>
      CSIDL_SYSTEM = 0x0025,
      /// <summary>
      /// C:\Program Files
      /// </summary>
      CSIDL_PROGRAM_FILES = 0x0026,
      /// <summary>
      /// C:\Program Files\My Pictures
      /// </summary>
      CSIDL_MYPICTURES = 0x0027,
      /// <summary>
      /// USERPROFILE
      /// </summary>
      CSIDL_PROFILE = 0x0028,
      /// <summary>
      /// x86 system directory on RISC
      /// </summary>
      CSIDL_SYSTEMX86 = 0x0029,
      /// <summary>
      /// x86 C:\Program Files on RISC
      /// </summary>
      CSIDL_PROGRAM_FILESX86 = 0x002a,
      /// <summary>
      /// C:\Program Files\Common
      /// </summary>
      CSIDL_PROGRAM_FILES_COMMON = 0x002b,
      /// <summary>
      /// x86 Program Files\Common on RISC
      /// </summary>
      CSIDL_PROGRAM_FILES_COMMONX86 = 0x002c,
      /// <summary>
      /// All Users\Templates
      /// </summary>
      CSIDL_COMMON_TEMPLATES = 0x002d,
      /// <summary>
      /// All Users\Documents
      /// </summary>
      CSIDL_COMMON_DOCUMENTS = 0x002e,
      /// <summary>
      /// All Users\Start Menu\Programs\Administrative Tools
      /// </summary>
      CSIDL_COMMON_ADMINTOOLS = 0x002f,
      /// <summary>
      /// user name\Start Menu\Programs\Administrative Tools
      /// </summary>
      CSIDL_ADMINTOOLS = 0x0030,
      /// <summary>
      /// Network and Dial-up Connections
      /// </summary>
      CSIDL_CONNECTIONS = 0x0031,
      /// <summary>
      /// All Users\My Music
      /// </summary>
      CSIDL_COMMON_MUSIC = 0x0035,
      /// <summary>
      /// All Users\My Pictures
      /// </summary>
      CSIDL_COMMON_PICTURES = 0x0036,
      /// <summary>
      /// All Users\My Video
      /// </summary>
      CSIDL_COMMON_VIDEO = 0x0037,
      /// <summary>
      /// Resource Direcotry
      /// </summary>
      CSIDL_RESOURCES = 0x0038,
      /// <summary>
      /// Localized Resource Direcotry
      /// </summary>
      CSIDL_RESOURCES_LOCALIZED = 0x0039,
      /// <summary>
      /// Links to All Users OEM specific apps
      /// </summary>
      CSIDL_COMMON_OEM_LINKS = 0x003a,
      /// <summary>
      /// USERPROFILE\Local Settings\Application Data\Microsoft\CD Burning
      /// </summary>
      CSIDL_CDBURN_AREA = 0x003b,
      /// <summary>
      /// Computers Near Me (computered from Workgroup membership)
      /// </summary>
      CSIDL_COMPUTERSNEARME = 0x003d,
      /// <summary>
      /// combine with CSIDL_ value to force folder creation in SHGetFolderPath()
      /// </summary>
      CSIDL_FLAG_CREATE = 0x8000,
      /// <summary>
      /// combine with CSIDL_ value to return an unverified folder path
      /// </summary>
      CSIDL_FLAG_DONT_VERIFY = 0x4000,
      /// <summary>
      /// combine with CSIDL_ value to insure non-alias versions of the pidl
      /// </summary>
      CSIDL_FLAG_NO_ALIAS = 0x1000,
      /// <summary>
      /// combine with CSIDL_ value to indicate per-user init (eg. upgrade)
      /// </summary>
      CSIDL_FLAG_PER_USER_INIT = 0x0800,
      /// <summary>
      /// mask for all possible 
      /// </summary>
      CSIDL_FLAG_MASK = 0xFF00,
  }

  public enum SHGetFolderLocationReturnValues : uint
  {
      /// <summary>
      /// Success
      /// </summary>
      S_OK = 0x00000000,
      /// <summary>
      /// The CSIDL in nFolder is valid but the folder does not exist
      /// </summary>
      S_FALSE = 0x00000001,
      /// <summary>
      /// The CSIDL in nFolder is not valid
      /// </summary>
      E_INVALIDARG = 0x80070057
  }

  public static IntPtr GetPidlFromFolderID(IntPtr hWnd, CSIDL Id)
  {
      IntPtr pIdl = IntPtr.Zero;
      SHGetFolderLocationReturnValues res = (SHGetFolderLocationReturnValues)
          SHGetSpecialFolderLocation(
          hWnd,
          Id,
          out pIdl);
      return (pIdl);
  }


    public Form1()
    {
        InitializeComponent();

         SampleProc = new WindProc (SubclassWndProc);

         OldDefProc = GetWindowLong(this.Handle, GWL_WNDPROC);

        SetWindowLong(this.Handle, GWL_WNDPROC, Marshal.GetFunctionPointerForDelegate(SampleProc)/*SampleProc.Method.MethodHandle.Value.ToInt32()*/);

        //tagSHCHANGENOTIFYENTRY changeentry = new tagSHCHANGENOTIFYENTRY();
        //changeentry.dwEventMask = (ulong)SHCNE.SHCNE_ALLEVENTS;
        //changeentry.fRecursive = true;
        //changeentry.WatchDir = null;

        //SHChangeNotifyRegister(this.Handle, ref changeentry);

        SHChangeNotifyEntry changeentry = new SHChangeNotifyEntry();




        changeentry.pIdl = GetPidlFromFolderID(this.Handle, CSIDL.CSIDL_DESKTOP);
        changeentry.Recursively = true;

        try
        {
            uint notifyid = SHChangeNotifyRegister(
            this.Handle,
            SHCNF.SHCNF_TYPE | SHCNF.SHCNF_IDLIST,
            SHCNE.SHCNE_ALLEVENTS,
            WM_FILECHANGEINFO,
            1, ref changeentry);


        }

        catch (Exception ee)
        {

        }

i am failing in SHChangeNotifyRegister please help me.. tell me the reason why i am crashing..same code work fine for desktop.. please help

Thanks.

A: 

SHChangeNotifyRegister is not declared properly, the code below returns successfully, not sure if I get a notification when I create a file though :)

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            SHChangeNotifyEntry changeEntry = new SHChangeNotifyEntry();

            changeEntry.dwEventMask = (uint)SHCNE.SHCNE_CREATE;
            changeEntry.Recursive = false;
            changeEntry.pszWatchDir = "\\My Documents\\";

            try
            {
                bool result = SHChangeNotifyRegister(this.Handle, ref changeEntry);
            }
            catch (Exception ee)
            {

            }
        }

        [DllImport("aygshell.dll")]
        private static extern bool SHChangeNotifyRegister(IntPtr hwnd, ref SHChangeNotifyEntry test);

        private void Form1_Load(object sender, EventArgs e)
        {

        }
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    struct SHChangeNotifyEntry
    {
        public uint dwEventMask;
        [MarshalAs(UnmanagedType.LPWStr)]
        public string pszWatchDir;
        public bool Recursive;
    }
}
Matt
Thanks Matt..code worked.. i got notifications.. thank u..but you might have done some changes @ u have removed na..but at the very first what u have posted i am using.. its workin nicely :-).. thank u
Shadow
A: 

Hey Solitaire,

I need a similar event i.e. a event on file creation. I have made all changes said by Matt in the code you have posted, but I'm unable to receive events. The call is successfully completed, but on addition of a file wndproc does not receive event. Can you pls post your code after changes?

AgNO3
For getting the file change notification in windows mobile, you need to, write the window proc in win32, handle "WM_FILECHANGEINFO" event. the sample application is provided in your windows mobile SDK folder check it. i have forgotten the name. if you want to use it in c#, you need to make the DLL in win32, use it in C#..the way to use in C# is provided in the above answer..if you have any problem ask me..
Shadow
A: 

I am developing the application in C#.Net CF. I have already implemented the wndproc. I receive paint events and others during form load. But when i add a file to the "\" folder which I'm monitoring, wndproc does not receive any events at all.

I have pasted the code below. I'm trying to monitor the root folder on Windows Mobile for file addition.

public delegate int WindowProcCallback(IntPtr hwnd, uint msg, uint wParam, uint lParam);


public partial class Form1 : Form
{
    [DllImport("coredll.dll")]
    public extern static int CallWindowProc(IntPtr lpPrevWndFunc, IntPtr hwnd, uint msg, uint wParam,
                                            uint lParam);

    [DllImport("coredll.dll")]
    public extern static IntPtr SetWindowLong(IntPtr hwnd, int nIndex,
                                              IntPtr dwNewLong);


    [DllImport("coredll.dll")]
    public static extern IntPtr GetWindowLong(IntPtr hWnd, int nIndex);

    private WindowProcCallback m_delegate;
    private IntPtr m_wndprocReal;

    const int GWL_WNDPROC = -4;
    public delegate int WindProc(IntPtr hWnd, int msg, IntPtr Wparam, IntPtr lparam); 

    public const uint WM_SHNOTIFY = 0x0401;

    private const int WM_FILECHANGEINFO = (0x8000 + 0x101);

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    struct SHChangeNotifyEntry
    {
        public uint dwEventMask;
        [MarshalAs(UnmanagedType.LPWStr)]
        public string pszWatchDir;
        public bool Recursive;
    }      


    [DllImport("aygshell.dll")]
    private static extern bool SHChangeNotifyRegister(IntPtr hwnd, ref SHChangeNotifyEntry test);

    public enum SHCNE : uint
    {
        SHCNE_RENAMEITEM = 0x00000001,
        SHCNE_CREATE = 0x00000002,
        SHCNE_DELETE = 0x00000004,
        SHCNE_MKDIR = 0x00000008,
        SHCNE_RMDIR = 0x00000010,
        SHCNE_MEDIAINSERTED = 0x00000020,
        SHCNE_MEDIAREMOVED = 0x00000040,
        SHCNE_DRIVEREMOVED = 0x00000080,
        SHCNE_DRIVEADD = 0x00000100,
        SHCNE_NETSHARE = 0x00000200,
        SHCNE_NETUNSHARE = 0x00000400,
        SHCNE_ATTRIBUTES = 0x00000800,
        SHCNE_UPDATEDIR = 0x00001000,
        SHCNE_UPDATEITEM = 0x00002000,
        SHCNE_SERVERDISCONNECT = 0x00004000,
        SHCNE_UPDATEIMAGE = 0x00008000,
        SHCNE_DRIVEADDGUI = 0x00010000,
        SHCNE_RENAMEFOLDER = 0x00020000,
        SHCNE_FREESPACE = 0x00040000,
        SHCNE_EXTENDED_EVENT = 0x04000000,
        SHCNE_ASSOCCHANGED = 0x08000000,
        SHCNE_DISKEVENTS = 0x0002381F,
        SHCNE_GLOBALEVENTS = 0x0C0581E0,
        SHCNE_ALLEVENTS = 0x7FFFFFFF,
        SHCNE_INTERRUPT = 0x80000000,
    }


    public Form1()
    {
        InitializeComponent();

        m_delegate = new WindowProcCallback(this.WnProc);
        m_wndprocReal = SetWindowLong(this.Handle, GWL_WNDPROC, Marshal.GetFunctionPointerForDelegate(m_delegate));

        SHChangeNotifyEntry changeEntry = new SHChangeNotifyEntry();

        changeEntry.dwEventMask = (uint)SHCNE.SHCNE_CREATE;
        changeEntry.Recursive = false;
        changeEntry.pszWatchDir = "\\";           

        try
        {
            bool result = SHChangeNotifyRegister(this.Handle, ref changeEntry);

        }
        catch (Exception ee)
        {

        }

    }

    private int WnProc(IntPtr hwnd, uint msg, uint wParam, uint lParam)
    {
        int ret = 0;

        if (msg != WM_FILECHANGEINFO)
            ret = CallWindowProc(m_wndprocReal, hwnd, msg, wParam, lParam);
        else
        {

        }

        return ret;
    }

}

Will appreciate your help.

Thanks.

AgNO3
Did you get the sample example present in your windows mobile SDK..there they register for WM_DEVICE change Event.. just make a DLL, and call your .net binary from the DLL..it is not possible to register for filechange event in C#..
Shadow
No. I did not get it. If it cannot be achieved n C#, then what does your code mentioned above in this post do? Can you provide an explanation? I thought it is for the same purpose.
AgNO3
the code which is present above is for how to receive the window proc event from an win32 DLL.. my code was present in DLL, dll was getting the notification.. it inturn passing the message to C#..you see the sample app File Change Notification present in SDK,follow up this link "http://msdn.microsoft.com/en-us/library/bb158663.aspx" its in win32.. itself..make it DLL and register your c# app handle in C++ and pass the same event which you recive in win32 DLL to C# app..
Shadow