Gå til innhold

Anbefalte innlegg

Hei. For et par dager siden bestemte jeg meg for a lage en bot, og satte meg som mål at den skulle kunne

motta taster uten å være i fokus, samt at den skulle kunne sende taster til prosesser som ikke har fokus.

Jeg kom til første kriterie av mitt program før jeg støtte på dette:

 

CallBackonDetectedDelegate was detected:

Et tilbakekall ble utført til en datasanert representant av typen key preview!Utilities.globalKeyboardHook+keyboardHookProc::Invoke. Dette kan forårsake programkrasj, ødelagte data og datatap. Når representanter sendes til uforvaltet kode, må de vedlikeholdes av det forvaltede programmet til det er sikkert at de aldri vil bli kalt.

 

Siden jeg er ganske ustødig på C# (noe som kanskje kommer av at jeg er ganske utålmodig), er jeg usikker på hva jeg kan gjøre for å fikse problemet. Derfor er jeg kommet hit, i håp om at noen kan si meg hva feilmeldingen kommer

av, og hva jeg kan gjøre for å komme videre i mitt lille prosjekt. Takk på forhånd :) .

Lenke til kommentar
Videoannonse
Annonse

1) Det kan være lurt å poste koden som du mener har feil.

2) Windows på norsk når man programmerer er håpløst. Feilmeldingene gir sjeldent fornuftig mening, og det er håpløst å søke etter hjelp på nettet. Anbefaler deg å bruke engelsk Windows.

Lenke til kommentar

Her er koden i programmet mitt:

globalKeyboardHook gkh = new globalKeyboardHook();
	//Declaring variables

	//ints used to store mouse coords 
	int X;
	int Y;
	//used as switches to determine wether an action is running or not
	bool onoff1 = true;
	bool onoff2 = true;
	bool onoff3 = true;
	//bools used when checking if the input the user gave is a number, back space, or other key
	bool NonNumber1 = false;
	bool NonNumber2 = false;
	bool NonNumber3 = false;
	//ints used to store the intervals the user gives through the textboxes
	int anInterval1;
	int anInterval2;
	int anInterval3;

	//variables declared


	public Form1() 
	{
		InitializeComponent();
	}
	[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
	public static extern void mouse_event(long dwFlags, long dx, long dy, long cButtons, long dwExtraInfo);

	private const int MOUSEEVENTF_LEFTDOWN = 0x02;
	private const int MOUSEEVENTF_LEFTUP = 0x04;
	private const int MOUSEEVENTF_RIGHTDOWN = 0x08;
	private const int MOUSEEVENTF_RIGHTUP = 0x10;

	public void DoMouseClick()
	{
		//Call the imported function with the cursor's current position
		X = Cursor.Position.X;
		Y = Cursor.Position.Y;
		mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, X, Y, 0, 0);
	}


	private void Form1_Load(object sender, EventArgs e) {
		gkh.HookedKeys.Add(Keys.F2);
		gkh.HookedKeys.Add(Keys.F4);
		gkh.HookedKeys.Add(Keys.F9);
		gkh.KeyDown += new KeyEventHandler(gkh_KeyDown);
		gkh.KeyUp += new KeyEventHandler(gkh_KeyUp);
	}

	void gkh_KeyUp(object sender, KeyEventArgs e)
	{
	   if (e.KeyCode == Keys.F4)
		{
		  //  lstLog.Items.Add("Up\t" + e.KeyCode.ToString());
			e.Handled = true;
			if (onoff1 == true)
			{
				if (textBox1.Text == "")
				{
				}
				else
				{
					anInterval1 = int.Parse(textBox1.Text.ToString());
					timer1.Interval = anInterval1;
					timer1.Enabled = true;
					onoff1 = false;
				}
			}
			else
			{
				timer1.Enabled = false;
				onoff1 = true;
			}
		}
		else if (e.KeyCode == Keys.F9)
		{
			if (onoff2 == true)
			{
				if (textBox2.Text == "")
				{
				}
				else
				{
					anInterval2 = int.Parse(textBox2.Text.ToString());
					timer2.Interval = anInterval2;
					timer2.Enabled = true;
					onoff2 = false;
				}
			}
			else
			{
				timer2.Enabled = false;
				onoff2 = true;
			}
		}
		else if (e.KeyCode == Keys.F2)
		{
			if (onoff3 == true)
			{
				if (textBox3.Text == "")
				{

				}
				else
				{
					anInterval3 = int.Parse(textBox3.Text.ToString());
					timer3.Interval = anInterval3;
					timer3.Enabled = true;
					onoff3 = false;
				}
			}
			else
			{
				timer3.Enabled = false;
				onoff3 = true;
			}

		}
	}

	void gkh_KeyDown(object sender, KeyEventArgs e)
	{
		//lstLog.Items.Add("Down\t" + e.KeyCode.ToString());
		e.Handled = true;
	}

	private void timer1_Tick(object sender, EventArgs e)
	{
		mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, X, Y, 0, 0);
	}

	private void timer2_Tick(object sender, EventArgs e)
	{
		SendKeys.Send("z");
	}

	private void timer3_Tick(object sender, EventArgs e)
	{
		SendKeys.Send("x");
	}

	private void textBox1_KeyDown(object sender, KeyEventArgs e)
	{

		NonNumber1 = false;
		if (e.KeyCode < Keys.D0 || e.KeyCode > Keys.D9)
		{
			if (e.KeyCode < Keys.NumPad0 || e.KeyCode > Keys.NumPad9)
			{
				if (e.KeyCode != Keys.Back)
				{

						if (e.KeyCode == Keys.F2 ||e.KeyCode==Keys.F9 || e.KeyCode==Keys.F4 )
						{
							//let it run
						}
						else 
						{
							NonNumber1 = true;
							// if it isnt any number, backspace or assigned button, stop it.
						}
					}
				}
			}
		}


	private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
	{
		if (NonNumber1 == true)
		{
			e.Handled = true;
		}
	}

	private void textBox2_KeyDown(object sender, KeyEventArgs e)
	{
		NonNumber2 = false;
		if (e.KeyCode < Keys.D0 || e.KeyCode > Keys.D9)
		{
			if (e.KeyCode < Keys.NumPad0 || e.KeyCode > Keys.NumPad9)
			{
				if (e.KeyCode != Keys.Back)
				{

					if (e.KeyCode == Keys.F2 || e.KeyCode == Keys.F9 || e.KeyCode == Keys.F4)
					{
						//let it run
					}
					else
					{
						NonNumber2 = true;
						// if it isnt any number, backspace or assigned button, stop it.
					}
				}
			}
		}
	}

	private void textBox2_KeyPress(object sender, KeyPressEventArgs e)
	{
		if (NonNumber2 == true)
		{
			e.Handled = true;
		}
	}

	private void textBox3_KeyDown(object sender, KeyEventArgs e)
	{
		NonNumber3 = false;
		if (e.KeyCode < Keys.D0 || e.KeyCode > Keys.D9)
		{
			if (e.KeyCode < Keys.NumPad0 || e.KeyCode > Keys.NumPad9)
			{
				if (e.KeyCode != Keys.Back)
				{

					if (e.KeyCode == Keys.F2 || e.KeyCode == Keys.F9 || e.KeyCode == Keys.F4)
					{
						//let it run
					}
					else
					{
						NonNumber3 = true;
						// if it isnt any number, backspace or assigned button, stop it.
					}
				}
			}
		}
	}

	private void textBox3_KeyPress(object sender, KeyPressEventArgs e)
	{
		if (NonNumber3 == true)
		{
			e.Handled = true;
		}
	}


}
}

 

Søkte etter måter å simulere museklikk og fant DomouseClick som jeg bruker i koden over, har testet det og det virker greit nok, men

gir av og til en lignende feilmelding som den jeg postet tidligere. Bruker også Stormy Spikes globalkeyboardHook.cs

til å "overvåke" tastaturet, her er en link til hele prosjektet hans :http://www.codeproject.com/KB/cs/CSLLKeyboardHook/key_preview.zip

som sagt bruker jeg bare en av filene du finner i linken, så resten av dem kan dere se bort ifra.

Resten av koden i programmet har jeg skrevet selv, og tviler sterkt på at det har noe med feilen å gjøre,

men hvis det har det må dere bare si ifra.

Endret av Velena
Lenke til kommentar

GeirGrusom: Her er koden som omhandler globalKeyboardHook:

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace Utilities {
/// <summary>
/// A class that manages a global low level keyboard hook
/// </summary>
class globalKeyboardHook {
	#region Constant, Structure and Delegate Definitions
	/// <summary>
	/// defines the callback type for the hook
	/// </summary>

	public delegate int keyboardHookProc(int code, int wParam, ref keyboardHookStruct lParam);

	public struct keyboardHookStruct {
		public int vkCode;
		public int scanCode;
		public int flags;
		public int time;
		public int dwExtraInfo;
	}

	const int WH_KEYBOARD_LL = 13;
	const int WM_KEYDOWN = 0x100;
	const int WM_KEYUP = 0x101;
	const int WM_SYSKEYDOWN = 0x104;
	const int WM_SYSKEYUP = 0x105;
	#endregion

	#region Instance Variables
	/// <summary>
	/// The collections of keys to watch for
	/// </summary>
	public List<Keys> HookedKeys = new List<Keys>();
	/// <summary>
	/// Handle to the hook, need this to unhook and call the next hook
	/// </summary>
	IntPtr hhook = IntPtr.Zero;
	#endregion

	#region Events
	/// <summary>
	/// Occurs when one of the hooked keys is pressed
	/// </summary>
	public event KeyEventHandler KeyDown;
	/// <summary>
	/// Occurs when one of the hooked keys is released
	/// </summary>
	public event KeyEventHandler KeyUp;
	#endregion

	#region Constructors and Destructors
	/// <summary>
	/// Initializes a new instance of the <see cref="globalKeyboardHook"/> class and installs the keyboard hook.
	/// </summary>
	public globalKeyboardHook() {
		hook();
	}

	/// <summary>
	/// Releases unmanaged resources and performs other cleanup operations before the
	/// <see cref="globalKeyboardHook"/> is reclaimed by garbage collection and uninstalls the keyboard hook.
	/// </summary>
	~globalKeyboardHook() {
		unhook();
	}
	#endregion

	#region Public Methods
	/// <summary>
	/// Installs the global hook
	/// </summary>
	public void hook() {
		IntPtr hInstance = LoadLibrary("User32");
		hhook = SetWindowsHookEx(WH_KEYBOARD_LL, hookProc, hInstance, 0);
	}

	/// <summary>
	/// Uninstalls the global hook
	/// </summary>
	public void unhook() {
		UnhookWindowsHookEx(hhook);
	}

	/// <summary>
	/// The callback for the keyboard hook
	/// </summary>
	/// <param name="code">The hook code, if it isn't >= 0, the function shouldn't do anyting</param>
	/// <param name="wParam">The event type</param>
	/// <param name="lParam">The keyhook event information</param>
	/// <returns></returns>
	public int hookProc(int code, int wParam, ref keyboardHookStruct lParam) {
		if (code >= 0) {
			Keys key = (Keys)lParam.vkCode;
			if (HookedKeys.Contains(key)) {
				KeyEventArgs kea = new KeyEventArgs(key);
				if ((wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN) && (KeyDown != null)) {
					KeyDown(this, kea);
				} else if ((wParam == WM_KEYUP || wParam == WM_SYSKEYUP) && (KeyUp != null)) {
					KeyUp(this, kea);
				}
				if (kea.Handled)
					return 1;
			}
		}
		return CallNextHookEx(hhook, code, wParam, ref lParam);
	}
	#endregion

	#region DLL imports
	/// <summary>
	/// Sets the windows hook, do the desired event, one of hInstance or threadId must be non-null
	/// </summary>
	/// <param name="idHook">The id of the event you want to hook</param>
	/// <param name="callback">The callback.</param>
	/// <param name="hInstance">The handle you want to attach the event to, can be null</param>
	/// <param name="threadId">The thread you want to attach the event to, can be null</param>
	/// <returns>a handle to the desired hook</returns>
	[DllImport("user32.dll")]
	static extern IntPtr SetWindowsHookEx(int idHook, keyboardHookProc callback, IntPtr hInstance, uint threadId);

	/// <summary>
	/// Unhooks the windows hook.
	/// </summary>
	/// <param name="hInstance">The hook handle that was returned from SetWindowsHookEx</param>
	/// <returns>True if successful, false otherwise</returns>
	[DllImport("user32.dll")]
	static extern bool UnhookWindowsHookEx(IntPtr hInstance);

	/// <summary>
	/// Calls the next hook.
	/// </summary>
	/// <param name="idHook">The hook id</param>
	/// <param name="nCode">The hook code</param>
	/// <param name="wParam">The wparam.</param>
	/// <param name="lParam">The lparam.</param>
	/// <returns></returns>
	[DllImport("user32.dll")]
	static extern int CallNextHookEx(IntPtr idHook, int nCode, int wParam, ref keyboardHookStruct lParam);

	/// <summary>
	/// Loads the library.
	/// </summary>
	/// <param name="lpFileName">Name of the library</param>
	/// <returns>A handle to the library</returns>
	[DllImport("kernel32.dll")]
	static extern IntPtr LoadLibrary(string lpFileName);
	#endregion
}
}

Når det gjelder det du sa om å "sette opsettet", mente du da å flytte denne koden

gkh.HookedKeys.Add(Keys.F2);
gkh.HookedKeys.Add(Keys.F4);
gkh.HookedKeys.Add(Keys.F9);
gkh.KeyDown += new KeyEventHandler(gkh_KeyDown);
gkh.KeyUp += new KeyEventHandler(gkh_KeyUp);

fra Form_load eventen til der klassen globalKeyboardHook blir deklarert? Er litt forvirret anngående hva du mente med "constructoren".

Endret av Velena
Lenke til kommentar

Constructoren til en klasse er den funksjonen som blir kalt når objektet blir skapt.

I Visual basic heter den Sub New()

 

Hvis du skriver "Public Sub New()" Så vil Visual Studio lage en ny funksjon som inneholder "InitializeComponents()"

Før InitComponents kan du initialisere alle variabler.

Grunnen til at dette kan være kjekt, er at det du skriver før InitializeComponents skjer før kontroller og slikt blir laget.

Grunnen til at dette igjen er tryggere, er fordi da er du helt sikker på at ingen events eller noe blir kalt som er avhengig av at objektene dine er initialisert.

Lenke til kommentar

La meg se om jeg har forstått det rett:

public partial class Form1 : Form <------- dette er klassen


	bool bool1;
	int integer1;
	string aMsg;


public Form1() <------dette er constructoren til klassen over
	{
		InitializeComponent(); 
						<----jeg burde plassere opsettet her
}
}

Er dette riktig?

Edit: Det gjorde koden min litt mindre, men feilmeldingen kommer fortsatt opp når jeg trykker på

F4, F2, F9, og når jeg gir textboxene mine input.

Endret av Velena
Lenke til kommentar

Har søkt litt rundt på nettet etter en løsning, og fant noen med omtrent samme problem som meg. Her er forresten

en engelsk oversettelse av feilmeldingen hvis det hjelper:

CallbackOnCollectedDelegate was detected

Message: A callback was made on a garbage collected delegate of type key preview!Utilities.globalKeyboardHook+keyboardHookProc::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 tråden var det noen som foreslo :

...A common tecnique is to use a static(shared) variable for the calllback method intead of a local variable to

avoid the delegate from being collected....

På norsk: En vanlig metode er å bruke en statisk(delt) variabel til tilbakekalls metoden istedet for en lokal variabel

for a unngå at delegatet blir oppsamlet.

Refererer posteren til dette:

public int hookProc(int code, int wParam, ref keyboardHookStruct lParam) {
		if (code >= 0) {
			Keys key = (Keys)lParam.vkCode;
			if (HookedKeys.Contains(key)) {
				KeyEventArgs kea = new KeyEventArgs(key);
				if ((wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN) && (KeyDown != null)) {
					KeyDown(this, kea) ;
				} else if ((wParam == WM_KEYUP || wParam == WM_SYSKEYUP) && (KeyUp != null)) {
					KeyUp(this, kea);
				}
				if (kea.Handled)
					return 1;
			}
		}
		return CallNextHookEx(hhook, code, wParam, ref lParam);
	}

når han nevner "the callback method"? I så fall er jeg usikker på hvilke variabler han mener jeg burde definere som

"static".

Endret av Velena
Lenke til kommentar

Er det ingen som vet hva jeg kan gjøre for å bli kvitt problemet? Jeg føler at ingen har gitt meg et direkte svar enda.

 

 

Jeg har også et nytt spørsmål jeg gjerne vil ha svar på:

Jeg har bestemt meg for å sende tastetrykk ved hjelp av SendMessage, og har kommet frem til denne koden:

(.....)
[DllImport("User32.dll")]
	public static extern Int32 SendMessage( 
		int hWnd,              
		int Msg,                
		int wParam,             
		[MarshalAs(UnmanagedType.LPStr)] string lParam); 

private System.Int32 iHandle;
Keys key = Keys.A;
(....)
private void timer1_Tick(object sender, EventArgs e)
       {
           Win32.SendMessage(iHandle, Win32.WM_KEYDOWN, (int)key, 0x00000000);
       }

Dessverre virker ikke dette av en eller annen grunn. Jeg vet at programmet finner vinduet, da notepad har reagert

på en litt alterert kode. Jeg tror det har noe med at å typecaste key ikke virker som jeg vil, kan dette være problemet?

Endret av Velena
Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
  • Hvem er aktive   0 medlemmer

    • Ingen innloggede medlemmer aktive
×
×
  • Opprett ny...