检测到 CallbackOnCollectedDelegate

发布于 2024-12-05 00:30:18 字数 16427 浏览 1 评论 0原文

我的代码运行 5-10 分钟后不断收到此错误

检测到 CallbackOnCollectedDelegate 消息:对“CashRecyclerTestapp!MessageMonitor+NativeMethods+WndProc::Invoke”类型的垃圾收集委托进行了回调。这可能会导致应用程序崩溃、损坏和数据丢失。将委托传递给非托管代码时,托管应用程序必须使它们保持活动状态,直到保证它们永远不会被调用。

我正在编写一个自动售货机应用程序,我有一个 dll 来发布我需要在我的应用程序中捕获的消息,

这是我的代码,我从互联网上获得了用于捕获消息的源代码,它在这里不断收到错误

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Globalization;
    using System.Reflection;
    using System.Runtime.InteropServices;
    using System.Security;
    using System.Threading;
    /// <summary>
    /// Event handler for the <see cref="MessageMonitor.MessageReceived"/> event.
    /// </summary>
    /// <param name="hwnd">Handle to the window procedure that received the message.</param>
    /// <param name="message">Specifies the message.</param>
    /// <param name="wParam">Specifies additional message information. The content of this parameter depends on the value of the Msg parameter.</param>
    /// <param name="lParam">Specifies additional message information. The content of this parameter depends on the value of the Msg parameter.</param>
    public delegate void MessageMonitorEventHandler(IntPtr hwnd, int message, IntPtr wParam, IntPtr lParam);

    /// <summary>
    /// MessageMonitor monitors window messages in a background thread and generates
    /// an event that is invoked in the context of the thread that called WatchMessage.
    /// </summary>
    /// <remarks>
    /// Code is based on Stephen Toub article in June 2007 MSDN Magazine.
    /// http://msdn.microsoft.com/en-us/magazine/cc163417.aspx
    /// 
    /// What's different here is that this code does not require the use of System.Windows.Forms.
    /// Using a Form and Application.Run for this task is like using a jack hammer to pound a
    /// finishing nail.
    /// </remarks>
    public static class MessageMonitor
    {
      /// <summary>
      /// Handle to the monitoring window. This can be passed for event callbacks, or registration methods.
      /// </summary>
      /// <exception cref="Win32Exception"/>
      public static IntPtr WindowHandle
      {
        get
        {
          EnsureMonitorWindowCreated();
          return monitorWindowHandle;
        }
      }

      /// <summary>
      /// Subscribes to a particular message.
      /// </summary>
      /// <remarks>
      /// Although you can call this from any thread, the MessageReceived event will only fire on the thread
      /// that first called WatchMessage, or WindowHandle if that was called first.
      /// </remarks>
      /// <param name="message">Specifies the Windows message to monitor.</param>
      /// <exception cref="Win32Exception"/>
      public static void WatchMessage(int message)
      {
        EnsureMonitorWindowCreated();

        messageSetLock.AcquireWriterLock(Timeout.Infinite);
        try
        {
          messageSet[message] = message;
        }
        finally
        {
          messageSetLock.ReleaseWriterLock();
        }
      }

      /// <summary>
      /// Fired when a monitored message is received by the MessageMonitor
      /// </summary>
      public static  event MessageMonitorEventHandler MessageReceived;

      private static object syncObject = new object();
      private static SynchronizationContext syncContext;
      private static IntPtr monitorWindowHandle = IntPtr.Zero;
      private static ReaderWriterLock messageSetLock;
      private static Dictionary<int, int> messageSet;

      private static void EnsureMonitorWindowCreated()
      {
        lock (syncObject)
        {
          if (messageSetLock == null)
            messageSetLock = new ReaderWriterLock();

          if (messageSet == null)
            messageSet = new Dictionary<int, int>();

          // Get the SynchronizationContext associated with the calling thread. This will be used to post-back
          //  the MessageReceived event.
          // SynchronizationContext.Current is not used because it can return null. AsyncOperationManager.SynchronizationContext
          //  creates a default context if one does not yet exist on the calling thread.
          if (syncContext == null)
            syncContext = AsyncOperationManager.SynchronizationContext;

          if (monitorWindowHandle == IntPtr.Zero)
          {
            int lastWin32Error = 0;

            // This wait event is used to wait for the thread to create the monitoring window.
            using (ManualResetEvent threadCreateSignal = new ManualResetEvent(false))
            {
              Thread thread = new Thread((ThreadStart)delegate
              {
                // Create the window on our background thread so that messages to it are 'seen' by our message pump.
                if ((monitorWindowHandle = CreateWindow()) == IntPtr.Zero)
                  // Access to lastWin32Error, a stack variable outside our scope, is made safe by the reset event.
                  lastWin32Error = Marshal.GetLastWin32Error();

                // Signal our creator that we have (or have not) created the message window.
                threadCreateSignal.Set();

                // Enter message loop only if we successfully created the message window.
                if (monitorWindowHandle != IntPtr.Zero)
                {
                  NativeMethods.MSG msg = new NativeMethods.MSG();
                  while (UnsafeNativeMethods.GetMessage(ref msg, IntPtr.Zero, 0, 0))
                    UnsafeNativeMethods.DispatchMessage(ref msg);
                }
              });
              thread.Name = "MessageMonitorThread";
              thread.IsBackground = true;
              thread.Start();
              threadCreateSignal.WaitOne();
            }

            if (lastWin32Error != 0)
              throw new Win32Exception(lastWin32Error);
          }
        }
      }

      private static IntPtr CreateWindow()
      {
        IntPtr hWnd = IntPtr.Zero;
        string className = RegisterWndClass();
        if (className != null)
          // Note that we do not use a "message only window" on purpose. Broadcast messages are never
          //  sent to them and so we just use a regular window to ensure that they too can be monitored.
          return UnsafeNativeMethods.CreateWindowEx(0, className, className, 0, 0, 0, 0, 0, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, null);
        return hWnd;
      }

      private static string RegisterWndClass()
      {
        NativeMethods.WNDCLASS wc = new NativeMethods.WNDCLASS();
        wc.lpfnWndProc = WndProc;

        // This will keep trying if it has to, varying the class name until it gets one. This
        //  assures that we will get our own window class object. Overkill, I know, but I like
        //  to leave no loose ends.
        for (int n = 1; n < int.MaxValue; n++)
        {
          wc.lpszClassName = String.Format(CultureInfo.InvariantCulture, "MessageMonitorWindow:{0}", n);
          short ret = UnsafeNativeMethods.RegisterClass(wc);
          if (ret != 0)
            return wc.lpszClassName;
          else if (Marshal.GetLastWin32Error() != NativeMethods.ERROR_CLASS_ALREADY_EXISTS)
            return null;
          // ret == 0 && ERROR_CLASS_ALREADY_EXISTS, try again
        }
        return null;
      }

      public  static IntPtr WndProc(IntPtr hwnd, int message, IntPtr wParam, IntPtr lParam)
      {
        messageSetLock.AcquireReaderLock(Timeout.Infinite);
        bool watchingThisMessage = messageSet.ContainsKey(message);
        messageSetLock.ReleaseReaderLock();

        if (watchingThisMessage)
        {
          // We have to package these values to a struct for the Post call, NativeMethods.MSG is
          //  just covenient. The handler doesn't use this structure because I don't want to 
          //  expose it, and since I don't want to create yet another message structure for the
          //  handler, I package them here, and unpack them when invoking the handler.
          NativeMethods.MSG msg = new NativeMethods.MSG();
          msg.hwnd = hwnd;
          msg.message = message;
          msg.wParam = wParam;
          msg.lParam = lParam;

          // Post the invocation of the event handler to the thread that is interested in the event.
          syncContext.Post(delegate(object state)
          {
            MessageMonitorEventHandler handler = MessageReceived;
            if (handler != null)
            {
              NativeMethods.MSG msgCopy = (NativeMethods.MSG)state;
              handler(msgCopy.hwnd, msgCopy.message, msgCopy.wParam, msgCopy.lParam);
            }
          }, msg);
        }

        return UnsafeNativeMethods.DefWindowProc(hwnd, message, wParam, lParam);
      }

      #region PInvoke

      private static class NativeMethods
      {
        public const int ERROR_CLASS_ALREADY_EXISTS = 0x582;

        public delegate IntPtr WndProc(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
        public class WNDCLASS
        {
          public int style;
          public WndProc lpfnWndProc;
          public int cbClsExtra;
          public int cbWndExtra;
          public IntPtr hInstance = IntPtr.Zero;
          public IntPtr hIcon = IntPtr.Zero;
          public IntPtr hCursor = IntPtr.Zero;
          public IntPtr hbrBackground = IntPtr.Zero;
          public string lpszMenuName;
          public string lpszClassName;
        }

        [Serializable, StructLayout(LayoutKind.Sequential)]
        public struct MSG
        {
          public IntPtr hwnd;
          public int message;
          public IntPtr wParam;
          public IntPtr lParam;
          public int time;
          public int pt_x;
          public int pt_y;
        }
      }

      [SuppressUnmanagedCodeSecurity]
      private static class UnsafeNativeMethods
      {
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern IntPtr CreateWindowEx(int dwExStyle, string lpszClassName, string lpszWindowName, int style, int x, int y, int width, int height, IntPtr hWndParent, IntPtr hMenu, IntPtr hInst, [MarshalAs(UnmanagedType.AsAny)] object pvParam);

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr DefWindowProc(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr DispatchMessage([In] ref NativeMethods.MSG msg);

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool GetMessage([In, Out] ref NativeMethods.MSG msg, IntPtr hWnd, int uMsgFilterMin, int uMsgFilterMax);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern short RegisterClass(NativeMethods.WNDCLASS wc);
      }

      #endregion
    }

现在这是我的应用程序代码,所有这些都是一个应用程序的一部分,

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

            [DllImport("PaymentManager.dll")]
            static extern int openpaymentmanager();

            [DllImport("PaymentManager.dll")]
            static extern int closepaymentmanager();

            [DllImport("PaymentManager.dll")]
            static extern int startpaymentmanager(IntPtr handle,int messageaddress,int devices,int protocol,int messageconfig);

            [DllImport("PaymentManager.dll")]
            static extern int stoppaymentmanager();

            [DllImport("PaymentManager.dll")]
            static extern int setpaymentmanager(int command, int selection, int info1, int info2);


            private void Form1_Load(object sender, EventArgs e)
            {
                int closepaymentmng = closepaymentmanager();

                const int WM_USER = 0x0400;
                MessageMonitor.MessageReceived += new MessageMonitorEventHandler(MessageMonitor_MessageReceived);
                MessageMonitor.WatchMessage(0x3B9); // MM_MCINOTIFY
                int openpaymentmng = openpaymentmanager();
                int startpaymentmnh = startpaymentmanager(MessageMonitor.WindowHandle , 0x3B9, 0, 0, 0);
                long setpaymentmng = setpaymentmanager(0, 0, 0, 0);
                textBoxprice.Text = "0";
                textBoxpaid.Text = "0";
            }



            private void MessageMonitor_MessageReceived(IntPtr hwnd, int message, IntPtr wParam, IntPtr lParam)
            {

                Console.WriteLine(string.Format ("message:{0} , wparam= {1} ,lparam = {2}", message,wParam,lParam));
                if (wParam.ToString() == "17")
                {
                    textBoxpaid.Text = (Convert.ToDecimal( textBoxpaid.Text)+ Convert.ToDecimal( lParam.ToString())/100).ToString();
                }
                if (wParam.ToString() == "18")
                {
                    textBoxpaid.Text = (Convert.ToDecimal(textBoxpaid.Text) + Convert.ToDecimal(lParam.ToString()) / 100).ToString();
                }
                if (wParam.ToString() == "33")
                {
                    textBoxpaid.Text = (Convert.ToDecimal(textBoxpaid.Text) - Convert.ToDecimal(lParam.ToString()) / 100).ToString();
                }
            }
     ect.....

我尝试了以下方法,但不起作用,

     public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
            private const string crashDllName = @"C:\Users\Chantelle\Documents\CashRecyclerTestapp\CashRecyclerTestapp\bin\Debug\PaymentManager.dll";

            [DllImport(crashDllName)]
            static extern int openpaymentmanager();

            [DllImport(crashDllName)]
            static extern int closepaymentmanager();

            [DllImport(crashDllName)]
            static extern int startpaymentmanager(IntPtr handle,int messageaddress,int devices,int protocol,int messageconfig);

            [DllImport(crashDllName)]
            static extern int stoppaymentmanager();

            [DllImport(crashDllName)]
            static extern int setpaymentmanager(int command, int selection, int info1, int info2);


            private static  IntPtr hndle;
            private static MessageMonitorEventHandler msgmntr;

            private void Form1_Load(object sender, EventArgs e)
            {
                int closepaymentmng = closepaymentmanager();

                const int WM_USER = 0x0400;
                msgmntr = new MessageMonitorEventHandler(MessageMonitor_MessageReceived);
                MessageMonitor.MessageReceived +=  msgmntr;
                MessageMonitor.WatchMessage(0x3B9); // MM_MCINOTIFY
                hndle = MessageMonitor.WindowHandle;

                int openpaymentmng = openpaymentmanager();
                int startpaymentmnh = startpaymentmanager(hndle, 0x3B9, 0, 0, 0);
                long setpaymentmng = setpaymentmanager(0, 0, 0, 0);
                textBoxprice.Text = "0";
                textBoxpaid.Text = "0";
            }



            public  void MessageMonitor_MessageReceived(IntPtr hwnd, int message, IntPtr wParam, IntPtr lParam)
            {

                Console.WriteLine(string.Format ("message:{0} , wparam= {1} ,lparam = {2}", message,wParam,lParam));
                if (wParam.ToString() == "17")
                {
                    textBoxpaid.Text = (Convert.ToDecimal( textBoxpaid.Text)+ Convert.ToDecimal( lParam.ToString())/100).ToString();
                }
                if (wParam.ToString() == "18")
                {
                    textBoxpaid.Text = (Convert.ToDecimal(textBoxpaid.Text) + Convert.ToDecimal(lParam.ToString()) / 100).ToString();
                }
                if (wParam.ToString() == "33")
                {
                    textBoxpaid.Text = (Convert.ToDecimal(textBoxpaid.Text) - Convert.ToDecimal(lParam.ToString()) / 100).ToString();
                }
            }

尝试了其他方法,但没有成功。所以我真的需要任何帮助,即使它以另一种方式捕获消息,但我非常沮丧,并且非常感谢任何帮助

I keep getting this error after my code has run between 5-10 min

CallbackOnCollectedDelegate was detected
Message: A callback was made on a garbage collected delegate of type 'CashRecyclerTestapp!MessageMonitor+NativeMethods+WndProc::Invoke'. This may cause application crashes, corruption and data loss. When passing delegates to unmanaged code, they must be kept alive by the managed application until it is guaranteed that they will never be called.

i'm writing a vending machine app and i have a dll that post messages i need to catch in my application

this is my code i got source code from the internet for catching the messages and its here it keeps getting the error

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Globalization;
    using System.Reflection;
    using System.Runtime.InteropServices;
    using System.Security;
    using System.Threading;
    /// <summary>
    /// Event handler for the <see cref="MessageMonitor.MessageReceived"/> event.
    /// </summary>
    /// <param name="hwnd">Handle to the window procedure that received the message.</param>
    /// <param name="message">Specifies the message.</param>
    /// <param name="wParam">Specifies additional message information. The content of this parameter depends on the value of the Msg parameter.</param>
    /// <param name="lParam">Specifies additional message information. The content of this parameter depends on the value of the Msg parameter.</param>
    public delegate void MessageMonitorEventHandler(IntPtr hwnd, int message, IntPtr wParam, IntPtr lParam);

    /// <summary>
    /// MessageMonitor monitors window messages in a background thread and generates
    /// an event that is invoked in the context of the thread that called WatchMessage.
    /// </summary>
    /// <remarks>
    /// Code is based on Stephen Toub article in June 2007 MSDN Magazine.
    /// http://msdn.microsoft.com/en-us/magazine/cc163417.aspx
    /// 
    /// What's different here is that this code does not require the use of System.Windows.Forms.
    /// Using a Form and Application.Run for this task is like using a jack hammer to pound a
    /// finishing nail.
    /// </remarks>
    public static class MessageMonitor
    {
      /// <summary>
      /// Handle to the monitoring window. This can be passed for event callbacks, or registration methods.
      /// </summary>
      /// <exception cref="Win32Exception"/>
      public static IntPtr WindowHandle
      {
        get
        {
          EnsureMonitorWindowCreated();
          return monitorWindowHandle;
        }
      }

      /// <summary>
      /// Subscribes to a particular message.
      /// </summary>
      /// <remarks>
      /// Although you can call this from any thread, the MessageReceived event will only fire on the thread
      /// that first called WatchMessage, or WindowHandle if that was called first.
      /// </remarks>
      /// <param name="message">Specifies the Windows message to monitor.</param>
      /// <exception cref="Win32Exception"/>
      public static void WatchMessage(int message)
      {
        EnsureMonitorWindowCreated();

        messageSetLock.AcquireWriterLock(Timeout.Infinite);
        try
        {
          messageSet[message] = message;
        }
        finally
        {
          messageSetLock.ReleaseWriterLock();
        }
      }

      /// <summary>
      /// Fired when a monitored message is received by the MessageMonitor
      /// </summary>
      public static  event MessageMonitorEventHandler MessageReceived;

      private static object syncObject = new object();
      private static SynchronizationContext syncContext;
      private static IntPtr monitorWindowHandle = IntPtr.Zero;
      private static ReaderWriterLock messageSetLock;
      private static Dictionary<int, int> messageSet;

      private static void EnsureMonitorWindowCreated()
      {
        lock (syncObject)
        {
          if (messageSetLock == null)
            messageSetLock = new ReaderWriterLock();

          if (messageSet == null)
            messageSet = new Dictionary<int, int>();

          // Get the SynchronizationContext associated with the calling thread. This will be used to post-back
          //  the MessageReceived event.
          // SynchronizationContext.Current is not used because it can return null. AsyncOperationManager.SynchronizationContext
          //  creates a default context if one does not yet exist on the calling thread.
          if (syncContext == null)
            syncContext = AsyncOperationManager.SynchronizationContext;

          if (monitorWindowHandle == IntPtr.Zero)
          {
            int lastWin32Error = 0;

            // This wait event is used to wait for the thread to create the monitoring window.
            using (ManualResetEvent threadCreateSignal = new ManualResetEvent(false))
            {
              Thread thread = new Thread((ThreadStart)delegate
              {
                // Create the window on our background thread so that messages to it are 'seen' by our message pump.
                if ((monitorWindowHandle = CreateWindow()) == IntPtr.Zero)
                  // Access to lastWin32Error, a stack variable outside our scope, is made safe by the reset event.
                  lastWin32Error = Marshal.GetLastWin32Error();

                // Signal our creator that we have (or have not) created the message window.
                threadCreateSignal.Set();

                // Enter message loop only if we successfully created the message window.
                if (monitorWindowHandle != IntPtr.Zero)
                {
                  NativeMethods.MSG msg = new NativeMethods.MSG();
                  while (UnsafeNativeMethods.GetMessage(ref msg, IntPtr.Zero, 0, 0))
                    UnsafeNativeMethods.DispatchMessage(ref msg);
                }
              });
              thread.Name = "MessageMonitorThread";
              thread.IsBackground = true;
              thread.Start();
              threadCreateSignal.WaitOne();
            }

            if (lastWin32Error != 0)
              throw new Win32Exception(lastWin32Error);
          }
        }
      }

      private static IntPtr CreateWindow()
      {
        IntPtr hWnd = IntPtr.Zero;
        string className = RegisterWndClass();
        if (className != null)
          // Note that we do not use a "message only window" on purpose. Broadcast messages are never
          //  sent to them and so we just use a regular window to ensure that they too can be monitored.
          return UnsafeNativeMethods.CreateWindowEx(0, className, className, 0, 0, 0, 0, 0, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, null);
        return hWnd;
      }

      private static string RegisterWndClass()
      {
        NativeMethods.WNDCLASS wc = new NativeMethods.WNDCLASS();
        wc.lpfnWndProc = WndProc;

        // This will keep trying if it has to, varying the class name until it gets one. This
        //  assures that we will get our own window class object. Overkill, I know, but I like
        //  to leave no loose ends.
        for (int n = 1; n < int.MaxValue; n++)
        {
          wc.lpszClassName = String.Format(CultureInfo.InvariantCulture, "MessageMonitorWindow:{0}", n);
          short ret = UnsafeNativeMethods.RegisterClass(wc);
          if (ret != 0)
            return wc.lpszClassName;
          else if (Marshal.GetLastWin32Error() != NativeMethods.ERROR_CLASS_ALREADY_EXISTS)
            return null;
          // ret == 0 && ERROR_CLASS_ALREADY_EXISTS, try again
        }
        return null;
      }

      public  static IntPtr WndProc(IntPtr hwnd, int message, IntPtr wParam, IntPtr lParam)
      {
        messageSetLock.AcquireReaderLock(Timeout.Infinite);
        bool watchingThisMessage = messageSet.ContainsKey(message);
        messageSetLock.ReleaseReaderLock();

        if (watchingThisMessage)
        {
          // We have to package these values to a struct for the Post call, NativeMethods.MSG is
          //  just covenient. The handler doesn't use this structure because I don't want to 
          //  expose it, and since I don't want to create yet another message structure for the
          //  handler, I package them here, and unpack them when invoking the handler.
          NativeMethods.MSG msg = new NativeMethods.MSG();
          msg.hwnd = hwnd;
          msg.message = message;
          msg.wParam = wParam;
          msg.lParam = lParam;

          // Post the invocation of the event handler to the thread that is interested in the event.
          syncContext.Post(delegate(object state)
          {
            MessageMonitorEventHandler handler = MessageReceived;
            if (handler != null)
            {
              NativeMethods.MSG msgCopy = (NativeMethods.MSG)state;
              handler(msgCopy.hwnd, msgCopy.message, msgCopy.wParam, msgCopy.lParam);
            }
          }, msg);
        }

        return UnsafeNativeMethods.DefWindowProc(hwnd, message, wParam, lParam);
      }

      #region PInvoke

      private static class NativeMethods
      {
        public const int ERROR_CLASS_ALREADY_EXISTS = 0x582;

        public delegate IntPtr WndProc(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
        public class WNDCLASS
        {
          public int style;
          public WndProc lpfnWndProc;
          public int cbClsExtra;
          public int cbWndExtra;
          public IntPtr hInstance = IntPtr.Zero;
          public IntPtr hIcon = IntPtr.Zero;
          public IntPtr hCursor = IntPtr.Zero;
          public IntPtr hbrBackground = IntPtr.Zero;
          public string lpszMenuName;
          public string lpszClassName;
        }

        [Serializable, StructLayout(LayoutKind.Sequential)]
        public struct MSG
        {
          public IntPtr hwnd;
          public int message;
          public IntPtr wParam;
          public IntPtr lParam;
          public int time;
          public int pt_x;
          public int pt_y;
        }
      }

      [SuppressUnmanagedCodeSecurity]
      private static class UnsafeNativeMethods
      {
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern IntPtr CreateWindowEx(int dwExStyle, string lpszClassName, string lpszWindowName, int style, int x, int y, int width, int height, IntPtr hWndParent, IntPtr hMenu, IntPtr hInst, [MarshalAs(UnmanagedType.AsAny)] object pvParam);

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr DefWindowProc(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr DispatchMessage([In] ref NativeMethods.MSG msg);

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool GetMessage([In, Out] ref NativeMethods.MSG msg, IntPtr hWnd, int uMsgFilterMin, int uMsgFilterMax);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern short RegisterClass(NativeMethods.WNDCLASS wc);
      }

      #endregion
    }

Now this is my app code ,all this is part of one app

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

            [DllImport("PaymentManager.dll")]
            static extern int openpaymentmanager();

            [DllImport("PaymentManager.dll")]
            static extern int closepaymentmanager();

            [DllImport("PaymentManager.dll")]
            static extern int startpaymentmanager(IntPtr handle,int messageaddress,int devices,int protocol,int messageconfig);

            [DllImport("PaymentManager.dll")]
            static extern int stoppaymentmanager();

            [DllImport("PaymentManager.dll")]
            static extern int setpaymentmanager(int command, int selection, int info1, int info2);


            private void Form1_Load(object sender, EventArgs e)
            {
                int closepaymentmng = closepaymentmanager();

                const int WM_USER = 0x0400;
                MessageMonitor.MessageReceived += new MessageMonitorEventHandler(MessageMonitor_MessageReceived);
                MessageMonitor.WatchMessage(0x3B9); // MM_MCINOTIFY
                int openpaymentmng = openpaymentmanager();
                int startpaymentmnh = startpaymentmanager(MessageMonitor.WindowHandle , 0x3B9, 0, 0, 0);
                long setpaymentmng = setpaymentmanager(0, 0, 0, 0);
                textBoxprice.Text = "0";
                textBoxpaid.Text = "0";
            }



            private void MessageMonitor_MessageReceived(IntPtr hwnd, int message, IntPtr wParam, IntPtr lParam)
            {

                Console.WriteLine(string.Format ("message:{0} , wparam= {1} ,lparam = {2}", message,wParam,lParam));
                if (wParam.ToString() == "17")
                {
                    textBoxpaid.Text = (Convert.ToDecimal( textBoxpaid.Text)+ Convert.ToDecimal( lParam.ToString())/100).ToString();
                }
                if (wParam.ToString() == "18")
                {
                    textBoxpaid.Text = (Convert.ToDecimal(textBoxpaid.Text) + Convert.ToDecimal(lParam.ToString()) / 100).ToString();
                }
                if (wParam.ToString() == "33")
                {
                    textBoxpaid.Text = (Convert.ToDecimal(textBoxpaid.Text) - Convert.ToDecimal(lParam.ToString()) / 100).ToString();
                }
            }
     ect.....

i have tried the following but is not working

     public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
            private const string crashDllName = @"C:\Users\Chantelle\Documents\CashRecyclerTestapp\CashRecyclerTestapp\bin\Debug\PaymentManager.dll";

            [DllImport(crashDllName)]
            static extern int openpaymentmanager();

            [DllImport(crashDllName)]
            static extern int closepaymentmanager();

            [DllImport(crashDllName)]
            static extern int startpaymentmanager(IntPtr handle,int messageaddress,int devices,int protocol,int messageconfig);

            [DllImport(crashDllName)]
            static extern int stoppaymentmanager();

            [DllImport(crashDllName)]
            static extern int setpaymentmanager(int command, int selection, int info1, int info2);


            private static  IntPtr hndle;
            private static MessageMonitorEventHandler msgmntr;

            private void Form1_Load(object sender, EventArgs e)
            {
                int closepaymentmng = closepaymentmanager();

                const int WM_USER = 0x0400;
                msgmntr = new MessageMonitorEventHandler(MessageMonitor_MessageReceived);
                MessageMonitor.MessageReceived +=  msgmntr;
                MessageMonitor.WatchMessage(0x3B9); // MM_MCINOTIFY
                hndle = MessageMonitor.WindowHandle;

                int openpaymentmng = openpaymentmanager();
                int startpaymentmnh = startpaymentmanager(hndle, 0x3B9, 0, 0, 0);
                long setpaymentmng = setpaymentmanager(0, 0, 0, 0);
                textBoxprice.Text = "0";
                textBoxpaid.Text = "0";
            }



            public  void MessageMonitor_MessageReceived(IntPtr hwnd, int message, IntPtr wParam, IntPtr lParam)
            {

                Console.WriteLine(string.Format ("message:{0} , wparam= {1} ,lparam = {2}", message,wParam,lParam));
                if (wParam.ToString() == "17")
                {
                    textBoxpaid.Text = (Convert.ToDecimal( textBoxpaid.Text)+ Convert.ToDecimal( lParam.ToString())/100).ToString();
                }
                if (wParam.ToString() == "18")
                {
                    textBoxpaid.Text = (Convert.ToDecimal(textBoxpaid.Text) + Convert.ToDecimal(lParam.ToString()) / 100).ToString();
                }
                if (wParam.ToString() == "33")
                {
                    textBoxpaid.Text = (Convert.ToDecimal(textBoxpaid.Text) - Convert.ToDecimal(lParam.ToString()) / 100).ToString();
                }
            }

have tried other ways no sucess. So i really need any help even if its to catch the messages another way but im beyond fustrated and would appreciate any help

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

ι不睡觉的鱼゛ 2024-12-12 00:30:18

RegisterWndClass 中,您正在创建一个本地 WNDCLASS 实例 - wclpfnWndProc 字段包含一个委托,该委托是用于回调您的代码。由于这是一个局部变量,因此一旦该方法完成,wc 就可以进行垃圾回收,用于回调代码的委托也是如此。

您必须确保作为回调传递的委托不会被垃圾回收。这可以通过向 MessageMonitor 类添加静态字段来实现:

private static readonly NativeMethods.WndProc StaticWndProcDelegate = WndProc;

在当前拥有的 RegisterWndClass 中:

wc.lpfnWndProc = WndProc;

将其替换为:

wc.lpfnWndProc = StaticWndProcDelegate;

In RegisterWndClass, you're creating a local WNDCLASS instance - wc, the lpfnWndProc field holds a delegate which is used to call back into your code. As this is a local variable, as soon as that method completes, wc is eligible for garbage collection, as is the delegate that is being used to call back into your code.

You must ensure that the delegate you're passing as a callback is not garbage collected. This can be achieved by adding a static field to the MessageMonitor class:

private static readonly NativeMethods.WndProc StaticWndProcDelegate = WndProc;

And in RegisterWndClass where you currently have:

wc.lpfnWndProc = WndProc;

Replace it with:

wc.lpfnWndProc = StaticWndProcDelegate;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文