Geh am besten mal das Tutorial von Cheat Engine durch (Das ist bei der Installation dabei). Darin wird das alles ganz genau erklärt.
Der Trick ist, dass es eine feste Adresse gibt, die einen Pointer auf die Variable darstellt. Das bedeutet du hast eine Adresse an der die Adresse von der Variable steht. Das lässt sich mit beliebig vielen Pointern verketten:
Obwohl das nach einer seltsamen "Technik" aussieht ist der eigentliche Fehler nicht, das die Variablen statisch sind, da die Klasse genauso wie das Objekt heißt (und somit auch die statischen Variablen angesprochen werden).
Der Grund warum es erst bei zweitem Aufruf funktioniert ist, dass bei der Objekterzeugung von convert_files die aktuellen Werte der statischen Variable benutzt/kopiert werden. Diese Strings werden erst im Nachhinein geändert. Das bedeutet beim zweiten Aufruf haben sie die Werte, die im ersten Aufruf in den Textboxen stehen.
Du müsstest also die strings auf die richtigen Werte setzen, bevor du deine Form instanzierst.
Allerdings schaut das so aus, als würde da irgendwas falsch laufen. Die statischen Variablen scheinen keinen Sinn zu machen, wie Programmierhans schon gesagt hat ;)
Zumindest als ich das letzte Mal mit XNA gearbeitet habe (XNA 3.1) musste die Runtime noch auf den Rechnern installiert sein, auf denen kein XNA GameStudio läuft.
Verwende doch einfache eine Klasse IP und ein paar Helfer-Methoden.
Da möchte ich noch anmerken, dass es bereits eine IPAddress Klasse im .NET Framework gibt: IPAddress
Diese hat sowohl die Methoden IPAddress.TryParse zur Validierung/Konvertierung eines Strings, als auch ToString (wie jedes object ;) ) um die IPAdresse formatiert(x.x.x.x bzw ipv6) auszugeben.
Ausserdem wird zusätzlich IPv6 unterstützt.
Damit lässt sich der Code des Threaderstellers vermutlich auf das folgende kürzen:
static void Main(string[] args)
{
IPAddress ip = null;
string input = "";
while (!IPAddress.TryParse(input, out ip))
{
Console.Clear();
Console.Write("Please enter your ip: ");
input = Console.ReadLine();
}
Console.WriteLine("Your IP address is: " + ip.ToString());
Console.ReadKey();
}
int.TryParse(textBox1.Text, out num1);
if (int.TryParse(textBox1.Text, out num1))
{ ... }
Hier rufst du die Methode zweimal auf, einmal innerhalb der If-Bedingung reicht aus.
2. Zu deinem eigentlichen Problem
binary(num1);
Wie du schon richtig gemacht hast gibst du in deiner Methode den veränderten String zurück. Allerdings machst du nichts mit dem Rückgabe Wert.
Also z.B.
string s = binary(num1);
Zahlen haben keine dezimale, hexadezimale, binäre Darstellung. Im physikalischen Speicher sind am Ende alles "nullen und einsen". Deswegen kannst du aus einem int auch keinen "binär int" machen. Nur Anzeigen kannst du diese Zahlen in verschiedenen Formaten(binär, dezimal, ...).
Das Problem ist, es gibt keinen Datentyp der aus 9 bit besteht. Und selbst wenn könnte er nicht so verarbeitet/gespeichert werden, da alle Datentypen Vielfache von 1 byte sind (short=2*byte, int=4*byte, ...).
Ich kenne auch keine Assemblerbefehle, die mit Werten kleiner als einem byte rechnen. Du musst also mindestens 2 byte schicken.
Auch bool's sind ein byte groß und nicht 1 bit.
Und wenn du 2 bytes sendest musst du einfach vor jedem Element in deinem byte Array ein neues byte mit dem Wert: 1000 0000(bin.) einfügen.
Du wirst wohl die Variante mit den 2 Bytes nehmen müssen, da der kleinste Datentyp ein byte(8 bit) ist.
So reicht es dann auch aus, wenn du vor jedem byte in dem Array ein neues byte einfügst, mit dem Wert -128 (signed, dez. = 1000 0000b). Dadurch wird dein Array natürlich doppelt so groß.
Also bei Opera 10.53 kann ich das Verhalten nicht nachvollziehen. Wenn ich Text markiere und auf den Code Tag Button drücke springt die Textbox nicht nach oben sondern bleibt da wo sie ist.
Im GUI Designer von VS findest du im "Eigenschaften" Fenster auch noch den "Tab" Events. Dort werden dir auch die Events von dem aktuell ausgewähltem Control angezeigt.
Im angehaengten Bild hab ich dir den Button markiert.
Du kannst eine Klasse erstellen, die diesen Filter implementiert und dann in der Methode PreFilterMessage die einzelnen Window Messages filtern. Diesen Filter kannst du anwenden indem du deiner Application-Klasse mit der Methode AddMessageFilter deine Filter-Klasse übergibst.
Hier ein kleines Beispiel:
public class MyInputFilter : IMessageFilter
{
private const int WM_LBUTTONDOWN = 0x201;
private const int WM_LBUTTONUP = 0x202;
public bool PreFilterMessage(ref Message m)
{
return m.Msg == WM_LBUTTONUP || m.Msg == WM_LBUTTONDOWN;
}
}
Allerdings müsstest du bei dem Beispiel auch noch einen Doppelklick abfangen. Das hat sehr seltsame Effekte, wenn man so einen Doppelklick auf einen Button macht ;)
Thunderbird kann also Text Dateien einlesen und als Signatur(Text der unter der E-Mail steht) benutzen. Und du übergibst Thunderbird jetzt ein PE File statt einem Textfile? Wie machst du das, also wie erwartest du, dass Thunderbird die richtige Signatur aus der exe bekommt?
So wie das aussieht ist deine "Fehlermeldung" einfach die ASCII Darstellung deines Programms. Also die einzelnen Bytes aus denen dein Programm besteht in ASCII-Code angezeigt.
So wie ich das sehe, interpretiert Thunderbird deine .exe einfach als Textdokument ;)
Die "Fehlermeldung": "This program can only be run in DOS mode." wird bei .NET Anwendungen immer im .text Segment der exe gespeichert. Das heißt aber nicht, dass die Meldung auch angezeigt wird.
[offtopic]
Im Multiplayer wird sowas meistens sowieso nicht funktionieren, weil Informationen wie Lebenspunkte, Munition, ... auf dem Server gespeichert werden.
[/offtopic]
Das ist eigentlich sogar relativ einfach unter Windows zu erreichen mit der WriteProcessMemory Methode
Hilfreich dabei ist auch die ReadProcessMemory Methode und pinvoke ist bei sowas sowieso immer hilfreich ;). Ausserdem ist es sinvoll den Prozess mit den richtigen Access-Privilegien zu öffnen: OpenProcess
Du musst nur aufpassen, da bei den meisten Spielen die Speicheradressen nicht konstant bleiben. Das heisst bei jedem Neustart, oder Levelwechsel, etc. ändert sich die Adresse. Bei sowas brauchst du dann Multilevel Pointer. Das heisst einen Pointer auf einen Pointer auf einen Pointer...
Pseudo Code:
//Prozess ID suchen
//ProcessAccessFlags.AllAccess -> siehe pinvoke.net
IntPtr hProc = OpenProcess(ProcessAccessFlags.AllAccess, false, proc.Id);
//Richtige Adresse einsetzen
int address = 0xFFFFFFFF
int buffer;
//bytesToWrite ist ein byte[], und bytesToWrite.Length ist die Anzahl an bytes, die geschrieben werden soll
WriteProcessMemory(hProc, (IntPtr)address, bytesToWrite, bytesToWrite.Length, out buffer);
a) InitiateSystemShutdown oder InitiateSystemShutdownEx
Das ist die WinAPI Methode um den Rechner herunterzufahren. Ist nicht ganz einfach, aber Hilfe findest du bei www.pinvoke.net
b) shutdown.exe
Die einfachere, wenn auch nicht ganz so schoene Methode (hat bei mir nicht immer funktioniert, evtl gehts unter Vista/Win7 ohne Admin Rechte nicht)
Hierbei einfach mit Hilfe der System.Diagnostics.Process Klasse die shutdown.exe starten. Die richtigen Parameter nicht vergessen (siehe shutdown /?)
Hast du denn meine erste Antwort bereits getestet (keybd_event)? Ist zwar nicht garantiert, dass das funktioniert hat aber bei mir schon oefter funktioniert.
Ich finde es ist einen Versuch wert ;)
Du koenntest vll auch mal schreiben, von was fuer einem Spiel du redest.
EDIT:
Das \\ ist sowieso nicht ganz geschickt, besser wäre das Path.DirectorySeparatorChar Feld zu benutzen. Und noch besser wäre es in Kombination mit der Path.Combine Methode.
Also ich habe mit dem Buch "C# von Kopf bis Fuß" (siehe hier: "C# von Kopf bis Fuß" empfehlenswert?) angefangen. Ich kann es empfehlen, auch wenn es etwas "anders" ist als die anderen Bücher . Du kannst hier mal ein Probekapitel lesen: http://www.oreilly.de/catalog/hfcsharpger/chapter/
Wobei ich sagen muss, das das Probekapitel etwas unglücklich gewählt ist, weil es das erste Kapitel ist, was eine Art Motivation ist. Es wird also nicht viel erklärt, sondern nur gezeigt, was möglich ist. Allerdings ist es danach wirklich gut erklärt und den "Stil" von dem Buch kann man auch an dem Probekapitel erkennen.
Zum Galileo Openbook:
Ich finde, es ist für Anfänger nur bedingt geeignet, da alles nur sehr "kompakt" beschrieben wird (nicht unvollständig nur "kompakt" ). Ich glaube, dass es für den Anfang einfach zu schwer zum Verstehen ist, bzw nur mit viel Aufwand, was das ganze nicht gerade spaßig macht. Allerdings kannst du dir das ja selber mal anschauen (kostet ja nix).
Zum Schluss bleibt noch zu sagen, dass es hier im Forum noch etliche Vorschläge für Bücher für Anfänger gibt. Da kannst du dir auch noch Tipps und Meinungen durchlesen.
Auf die Hinweise unten achten, weil soweit ich mich erinnere nur dem aktiven Fenster der Tastendruck geschickt wird.
Alternativ gibts noch die PostMessage-Methode der Win32-API. Wenn du im Forum nach PostMessage oder SendKeys suchst wirst du einiges finden.
So in der Main(...) Methode wird an DoSth(...) eine Referenz auf a übergeben. Das heißt wenn in der Methode DoSth(...) s = "B" aufgerufen wird, wird nicht der String im Speicher geändert, sondern die Referenz a. Deswegen funktioniert das so.
Aber sobald du einem anderen String s zuweist, wird der String wieder kopiert.
Wenn du als Parameter eine Referenz auf ein Objekt übergibst geschieht dies per call by reference. Das bedeutet der Methode wird eine Kopie der Referenz auf ein bestimmtes Objekt übergeben. Deshalb funktioniert es mit deiner Listname-Klasse, da dort nur ein Objekt im Speicher ist, das verändert wird.
Bei String geht es nicht, da wenn du NewLine = nl; folgendes passiert:
-Eine Kopie von nl wird im Speicher erstellt
-NewList wird dieses Objekt zugewiesen.
Allerdings funktioniert folgendes:
static void Main()
{
string s = "Hallo";
DoSth(ref s);
//s hat jetzt hier den Wert "Welt"
}
static void DoSth(ref string s)
{
s = "Welt";
}
Da aber das dxdiag auf nem 32-Bit-System den "/64bit"-Schalter nicht kennt, musst du wohl in deinem c# programm unterscheiden, ob du mit 64 oder 32 Bit läufst.
Aber das sollte mit IntPtr.Size möglich sein.
Noch ne kleine Anmerkung wie das geht:
Wenn IntPtr.Size == 4 ist es ein 32-Bit OS ( 4 Byte = 32 Bit )
Und falls IntPtr.Size == 8 ist es ein 64 Bit OS ( 8 Byte = 64 Bit )
Also einfach abfragen, ob IntPtr.Size == 8 und dann mit dem /64bit Parameter starten.
Fehler 3 Die beste Übereinstimmung für die überladene Promille_Rechner.Rechnung.AlkoholAufgenommenAusrechnen(double[], double[])-Methode hat einige ungültige Argumente.
Das heißt du übergibst deiner Methode beim Aufrufen 2 doubles statt 2 double-Arrays.
Also z.B.
double a = 0;
double b = 0;
AlkoholAufgenommenAusrechnen(a, b);
Richtig wäre:
double[] a = new double[6];
double[] b = new double[6];
AlkoholAufgenommenAusrechnen(a, b);
EDIT:
Zitat von Skillllord
Wo muss ich denn eine Instanz von den Arrays erstellen?
Auf jeden Fall bevor du die Methode AlkoholAufgenommenAusrechnen(...) aufrufst.