Die header der response angucken und prüfen ob "Content-Disposition" vorhanden ist.
Wenn vorhanden: Dateinamen aus dem wert des headers auslesen: Z.B. sollte die zweite gruppe des matches von folgendem regex den dateinamen enthalten (ignorecase setzen): "(^|;) *filename *=([^;]+)"
Wenn so kein dateiname gefunden wurde, dann ist der dateiname der teil von HttpWebResponse.ResponseUri.AbsolutePath, der nach dem letzten schrägstrich kommt.
Bei mir geht es auch mit den dlls.
Allerdings führe ich den shadowrunner auch nicht im anwendungsverzeichnis aus, daran ligt es wahrscheinlich. Ich gucks mir später genauer an.
Man kann direkte Verbindungen über das Internet herstellen, wenn auf beiden Computern gleichzeitig ein geeignetes Programm läuft und
- entweder einer der Computer keine Firewall hat und nicht hinter einem Nat-Router ist (esseiedenn es wurden entsprechende Regeln definiert, dass es dennoch geht) und der andere die Addresse kennt (also quasi ein Server)
- oder beide Computer gleichzeitig von beiden Enden aus auf vorher festgelegten Ports eine Verbindung aufbauen (erfordert einen Vermittler).
Du musst also in jedem Falle einen Weg haben, wie der eine Computer die Addresse des anderen bekommt.
Wenn kein Router/Firewall im Weg ist:
Das einfachste aber für den Benutzer unfreundlichste ist es, den Benutzer die IPs herausfinden zu lassen. Ansonsten kann man soetwas wie dyndns einsetzen. Alternativ kann man irgendwo auf einem Webspace eine Datei oder ein Script platzieren.
Ich bin zwar kein profi in sowas, aber so würde ich an die sache rangehen:
1.) Seite mittels browser komplett auf der platte speichern
3.) http://jsbeautifier.org/
2 ) Texteditor mit syntax-highlighting nehmen und variablennamen erraten+ersetzen
4.) Firebug und bei bedarf evl noch Wireshark
5.) Geduld
Hab das für n kleines Projekt mit etlichen Dateien, die ins Ausgabeverzeichnis kopiert werden gemacht. So nach dem Motto: Mal eben schnell Erstellen drücken (um die Dateien neu zu kopieren), aktualisieren und gucken, wies aussieht, wenn der Knopf unten rechts 5 Pixel schmaler ist. Problem is blolß, dass das normalerweise fehlschlägt, solange das Programm läuft.
Zitat
man muss also das Programmm schon vorher anders starten, falls mans evtl. überschreiben mag?
Ja, es wird das Ladeprogramm gelockt, anstatt des eigendlichen Programms.
Wer kennt das nicht: Man will mal schnell ne Exe überschreiben oder löschen, ohne gleich das dazugehörige Programm zu beenden.
Desahlb habe ich mal ein kleines Programm zusammengehackt, welches eine Exe samt Dlls mittels Assembly.Load(byte[]) lädt und dann ausführt. Der erste Parameter ist die zu ladende Exe-datei, danach folgen die zu übergebenden Parameter. MIT-Lizenz
Mit WPF-Anwendungen gibts anscheinend Probleme beim Laden von Resourcen.
Vielleicht kanns ja trotzdem jemand gebrauchen^^ Wer das Konsolenfenster loswerden will, der kann einfach in den Projekteigenschaften auf Windows-Anwendung umstellen.
Wenn die Daten an einem stück liegen ist das sicherleich die beste möglichkeit, aber wenn (wovon ich ausgegangen bin) die daten in mehreren häppchen fragmentiert sind, dann wird das sehr schnell sehr unhandlich.
Beide methoden benutzen "Reflection" (wenn auch in der nativen=schnelleren Variante), um zu prüfen, ob die Operation gültig ist.
Ich denke RtlMoveMemory könnte schneller sein, weil die ganzen Abfragen zur Laufzeit wegfallen.
Ansonsten gibts an platformunabängigen sachen noch cpblk, welches aber äußerst umständlich zu benutzen ist, oder man kann was eigenes mit unsafe schreiben, was dann aber tendenziell eher langsamer ist.
Fazit: Buffer.BlockCopy ist bequem und relativ schnell, ansonsten probier mal RtlMoveMemory.
Dennoch interressiert es mich, ob es nicht einen besseren weg gäbe dein Ziel zu erreichen, als massenweise Bytearrays umzokopieren. Dazu musst du aber mal den Anwendungsfall nennen!
Nein, eine für jeden lichttyp (ambient, punktlicht, paralleles licht und spotlight sind üblich)
Ambient kann man getrost seperat betrachten, ist einfach nur ein farbwert, der dem shader übergeben und überall hinzugefügt wird.
Paralleles licht wird meißt nur von der Sonne ausgestrahlt. Wenn dies der fall ist, dann kann man es getrennt betrachten.
Bleiben noch die sonst verstreuten lichter:
Definier mal ein struct, das alle eigenschaften einer dynamischen lichtquelle (also punktlicht und spotlight) enthält, inclusive dem typ. Eine instanz pro lichtquelle wird zur laufzeit vom hauptprogramm erzeugt und dem shader übergeben.
Wenn man realistische schatten will, muss man shadowmapping einsetzen.
Zitat
Wassereffekte
Dafür rendert man die szene mit manipulierter viewmatrix (so dass die spiegelung passt) zuerst auf eine textur und die textur übergibt man dem sahder, der das wasser rendert.
Hmm, nette idee.
Zur deiner konkreten umsetzung: Irgendwie habe ich das gefühl, dass du vorher mit c/c++ gearbeitet hast^^
Schau dir mal folgendes an: BinaryWriter, Encoding.ASCII
Außerdem kann man von der klasse Stream erben, anstatt einen memorystream zu nehmen.
Ich hab einfach mal den code leicht modifiziert, den ich hier schon gepostet hatte im programmier-spiel. Man kann die in dem blog angegebenen formeln 1:1 übernehmen.
class Program
{
const int samplerate = 8000;//8 khz
private static byte Function(int t)
{
return (byte)(t * (((t >> 12) | (t >> 8)) & (63 & (t >> 4))));
}
static void Main(string[] args)
{
int t=0;
//Setup OpenAl:
IntPtr device = ALC.OpenDevice(null);
IntPtr ctx = ALC.CreateContext(device, null);
ALC.MakeContextCurrent(ctx);
uint source = AL.GenSource();
byte[] samples = new byte[1024];
uint[] buffers = AL.GenBuffers(10);
int iCurrentBuffer = 0;
//Status of sine wave:
double rotangle = 0, rotangle2 = 0;
while (true)
{
//Get information:
int numQueued = AL.GetSourcei(source, AlSourceInts.Buffers_Queued);
int numProcessed = AL.GetSourcei(source, AlSourceInts.Buffers_Processed);
int numRemaining = numQueued - numProcessed;
//Take the processed buffers from the queue:
if (numProcessed > 0) AL.SourceUnqueueBuffers(source, numProcessed);
if (numRemaining ≥ buffers.Length)//Nothing to do?
{
System.Threading.Thread.Sleep(5);//Then wait a bit
continue;//and try again
}
//Calculate the new samples:
for (int i = 0; i < samples.Length; i++)
{
samples[i] = Function(t++);
}
//queue the samples
AL.BufferData(buffers[iCurrentBuffer], AlAudioFormat.Mono8Bit, samples, sizeof(byte) * samples.Length, samplerate);
AL.SourceQueueBuffer(source, buffers[iCurrentBuffer]);
if (++iCurrentBuffer ≥ buffers.Length) iCurrentBuffer = 0;//increment iBuffer
//play if the source is not already playing
if ((AlSourceState)AL.GetSourcei(source, AlSourceInts.Source_State) != AlSourceState.Playing)
AL.SourcePlay(source);
}
}
}
Die bindings für openal (welches übrigends installiert sein muss) hatte ich hier gepostet.
Ich habe zwar nur wenig erfahrung mit glsl, aber ich antworte einfach trotzdem mal:
Ersteinmal möchte ich euch zum shaderentwickeln in glsl das kostenlose programm rendermonkey von ati ans herz legen. Von nvidea gibts noch fxcomposer, welcher zwar besser zu bedienen ist, aber eher auf directx/hlsl ausgelegt ist.
Dann schreibt am besten ersteinmal nen shader, der für genau eine lichtquelle funktioniert.
Wenn es für eine lichtquelle klappt, kann man etweder aus den uniform-variablen statische arrays machen oder die parameter als textur übergeben. Letzteres ist zwar ein bisschen flexibler, aber auch ziemlicher frickelkram.
Beim rendern immer die lichtquellen nach bedeutung für das aktuelle objekt sortieren und dem shader nur die wichtigste(n) übergeben.
Es wäre vielleicht hilfreich, wenn du uns den namen des chatclients, sowie das verwendete chatprotokoll (irc,icq,skype,etc) und dein eigendliches vorhaben (einzelne nachrichten lesen oder ein kompletter bot oder was? ) nennen würdest. Für viele protokolle gibt es bibliotheken (z.B. für irc) und für viele clients gibt es addins (z.B. skype ermöglicht addins)
2.) char* in c++ ist immer Ansi und CharSet.Auto wird standardmäßig unicode. Unicodestrings werden mit 2 nullbytes beendet. Ansi-strings haben aber nur 1 nullbyte. Deshalb wird über das Ende hinaus gelesen und du kiregst ne Access Violation.
3.) Wenn du kein memoryleak haben willst musst du das mashalling eh selber machen.
[DllImport(@"Pfad zu C++ dll", CallingConvention = CallingConvention.StdCall)]
public static extern IntPtr StringReturnAPI01();
[DllImport(@"Pfad zu C++ dll", CallingConvention = CallingConvention.StdCall)]
public static extern void FreeString(IntPtr ptr);
Ich kann deine erkenntnisse nur bestätigen. Allerdings weist m$ dieser sorte von bugs gerne ein won'tfix zu, da es sonst zu kompatibilitätsproblemen kommt. Workaround ist halt, dass man überall GetHashCode so implementiert, wie mans grade braucht.
Es gibt auch extra hash-suchmaschinen (z.B. Md5 Suchmaschine, LM / NTLM Decrypter tool)
Ntlm-passwörter (für die windows-anmeldung) kann man übrigends unmöglich sicher bekommen ganz egal wie lang man sie macht. Das passwort wird erst in teile von 7 zeichen länge zerstückelt und dann jeder teil einzeln gehasht. (siehe ophcrack, cain&abel, etc ...)
Zudem stellt ein GCHandle auch sicher, dass der GC das Objekt nicht umkopiert sprich der Pointer ungültig wird.
Das problem stellt sich garnicht erst, da code (marshalling-stub) und daten (mit dem pointer auf den code) in seperaten heaps liegen. Der stub bleibt also so oder so wo er is...
GC.KeepAlive kann man getrost übersetzen als: Mach absolut garnichts, aber tu dabei so, alsob du den parameter verwenden würdest => Keinerlei effekt hier
hhook = SetWindowsHookEx(WH_KEYBOARD_LL, new globalKeyboardHook.keyboardHookProc(this.hookProc), hInstance, 0);
Man beachte das new.
Du musst nichts weiter tun, als den delegaten zu speichern und das genau so lange, bis du den hook wieder mit UnhookWindowsHookEx entfernst:
Es ist zwar eigendlich unnötig, aber wenn du lustig bist kannst nach der zeile mit UnhookWindowsHookEx noch GC.KeepAlive(this.gepeicherterDeleagte); einfügen.
Genauer gesagt wird für den parameter hookProc implizit ein delegate erstellt und dieser wird dann vom gc eingesackt...
Erstell den delegaten explizit und speicher ihn in nem member.
Wirklich glücklich bin ich nicht:
Mein PC mag es irgendwie nicht, dass du die bufferlängen auswürfelst und spielt deshalb keinen ton ab.
Deine Schleifenlogik ist auch recht ulkig:
Wenn mehr als 0 buffer verarbeitet wurden, dann:
1. Nimm 0 (=keine) buffer aus der queue
2. Befülle genau einen buffer mit daten (ganz egal wieviele buffer gespielt wurden)
3. Packe den nachfolger dieses buffers in die warteschlange
Außerdem lastest du einen kern zu 100% aus.
Ich poste hier einfach mal meine lösung und wer will kann eine neue aufgabe stellen.
using System;
using OpenAL;
namespace ALSynthesizer
{
class Program
{
const int samplerate = 44100;
const double frequency = 1000;
const double frequency2 = 0.5;
static void Main(string[] args)
{
//Setup OpenAl:
IntPtr device = ALC.OpenDevice(null);
IntPtr ctx = ALC.CreateContext(device, null);
ALC.MakeContextCurrent(ctx);
uint source = AL.GenSource();
short[] samples = new short[1024];
uint[] buffers = AL.GenBuffers(10);
int iCurrentBuffer = 0;
//Status of sine wave:
double rotangle = 0, rotangle2 = 0;
while (true)
{
//Get information:
int numQueued = AL.GetSourcei(source, AlSourceInts.Buffers_Queued);
int numProcessed = AL.GetSourcei(source, AlSourceInts.Buffers_Processed);
int numRemaining = numQueued - numProcessed;
//Take the processed buffers from the queue:
if (numProcessed > 0) AL.SourceUnqueueBuffers(source, numProcessed);
if (numRemaining ≥ buffers.Length)//Nothing to do?
{
System.Threading.Thread.Sleep(5);//Then wait a bit
continue;//and try again
}
//Calculate the new samples:
for (int i = 0; i < samples.Length; i++)
{
rotangle += frequency * ((Math.PI * 2) / samplerate);
if (rotangle > Math.PI * 2) rotangle -= Math.PI * 2;
rotangle2 += frequency2 * ((Math.PI * 2) / samplerate);
if (rotangle2 > Math.PI * 2) rotangle2 -= Math.PI * 2;
samples[i] = (short)(Math.Sin(rotangle) * Math.Sin(rotangle2) * short.MaxValue);
}
//Queue the samples
AL.BufferData(buffers[iCurrentBuffer], AlAudioFormat.Mono16Bit, samples, sizeof(short) * samples.Length, samplerate);
AL.SourceQueueBuffer(source, buffers[iCurrentBuffer]);
if (++iCurrentBuffer ≥ buffers.Length) iCurrentBuffer = 0;//Increment iBuffer
//Play if the source is not already playing
if ((AlSourceState)AL.GetSourcei(source, AlSourceInts.Source_State) != AlSourceState.Playing)
AL.SourcePlay(source);
}
}
}
}
Ich weiß ned so recht: Die lösung spielt zwar einen ton mit 125 hz** ab, aber man hört ein regelmäßiges ploppen, da das abspielen erst kurz nach dem ende wieder angestoßen wird.
Der trick es unterbrechungsfrei hinzubekommen liegt eigendlich darin, mehr als einen buffer zu verwenden und diese nacheinander einzureihen, sodass SourcePlay eigendlich nur einmal aufgerufen werden muss! Mit on the fly meinte ich, dass man die buffer neu befüllt, bevor man sie wieder verwendet. Wenn man das nicht macht, hat man ein problem wenn man zwei oder mehr frequenzen gleichzeitig spielen will.
Buffers_Processed gibt an, wieviele buffer vollständig abgespielt wurden und entfernt werden können. Buffers_Queued gibt an, wieviele buffer insgesamt in der schlange sind.
**125hz und nicht 1000 hz, weil der letzte parameter von BufferData die sampelrate ist, aber daran solls ned scheitern^^
Konkret: Ein ton soll on the fly generiert und mittels OpenAL ausgegeben werden.
Das kann z.B. eine sinus- oder sägezahnwelle sein, eine schwebung oder sogar eine melodie wäre auch nett, bei ner einfachen sinusschwingunggilt die aufgabe aber auch schon als gelöst.
Um auf OpenAL zuzugreifen habe ich unten die nötigen dllimports angefügt, aber wer unbedingt will kann auch OpenTK verwenden.
Ich hatte an eine konsolenanwendung gedacht, die einfach solange spielt, bis man das fenster schließt, aber die oberfläche ist jedem selbst überlassen!
Noch ein paar regeln:
-Es ist nicht erlaubt, eine sounddatei auf der platte zu erstellen. Der ton muss die ganze zeit on the fly generiert werden.
-Die tonhöhe muss durch konstanten im quelltext oder sonstige parameter/eingaben frei wählbar sein.
Aufwand: Je nachdem, wie man sich anstellt, sollte es zwischen 55 und 110 zeilen liegen. (Meine lösung hat 55 zeilen)
Ich hoffe, dass ihr es nicht bei einem sinuston belasst, sondern auch ein bisschen damit rumspielt und verschiedene klänge und effekte ausprobiert, denn das war die eigendliche grundidee!
Wer sich nicht so auskennt: Hier sind die benötigten apis:
alcOpenDevice, alcCreateContext, alcMakeContextCurrent, alGenSources, alGenBuffers, alGetSourcei, alSourceUnqueueBuffers, alBufferData, alSourceQueueBuffers, alSourcePlay (lieber zu oft als zu selten), Thread.Sleep