Laden...

Forenbeiträge von BhaaL Ingesamt 656 Beiträge

10.07.2009 - 22:19 Uhr

Hm, mag sein, dass ich irgendwas überlesen habe, aber wo / wie genau bindest du deinen PlainTextEncoder ein?

Ist das an der Stelle übehaupt relevant? Aufgerufen wird ja alles korrekt...

HttpTransportBindingElement transport = new HttpTransportBindingElement() { ManualAddressing = true };
PlainTextEncoderBindingElement encoder = new PlainTextEncoderBindingElement();
CustomBinding binding = new CustomBinding(encoder, transport);

var asClient = new WebChannelFactory<IAudioscrobbler>(binding, new Uri("http://post.audioscrobbler.com")).CreateChannel();
var handshake = asClient.Handshake("WCF", "v1", userName, unixTime, auth); //hier zerlegts den Serializer mit "unable to deserialize"

Ich bin mir nicht ganz sicher, ob deine Herangehensweise wirklich auf dein Problem passt (wie gesagt, möglich, dass ich dein Problem falsch verstanden habe). Ich an deiner Stelle hätte eher so etwas wie
>
(letztes Drittel der Seite) gemacht.

Die Seite hab ich auch schon unlängst gefunden, und vor meinen Tests mit dem Encoder probiert, aber irgendwie ist mir nicht so ganz klar, ob ich hier wirklich auch einen eigenen Contract Serializer schreiben muss...sind ja letztendlich nur stinknormale POCOs (oder anderweitig serialisierbare Objekte). Das sollte doch eigentlich der DataContractSerializer für mich erledigen können?
Abgesehen davon, selbst wenn ich nur den Contract Serializer austausche, hatte ich bisher das Problem, dass der Request gar nicht erst bis zum Serializer durchkam - vorzeitig wurde mit "expected xml, got text/plain" abgebrochen, weil der Server ja kein XML liefert, sondern nur Text.
Kann aber auch durchaus sein, dass ich hier am Konzept des Serializers was missverstanden oder falsch gemacht habe, bin das erste mal so tief unten im WCF-Kaninchenbau...

> ](http://de.wikipedia.org/wiki/Representational_State_Transfer) ansiehst...){gray}

Hm, möglicherweise der übliche Fall von Begriffsverwirrung. REST heißt ja unter anderem, dass man verschiedene Funktionalitäten über eigene Urls und je nachdem Request Methods bereitstellt. Is in dem Fall vielleicht übertrieben, es als REST zu bezeichnen...

10.07.2009 - 14:45 Uhr

Mahlzeit!

Ich bastle grade an einer kleinen Test-App, die am Beispiel last.fm/Audioscrobbler die bereitgestellten REST-Services anspricht. Wie gesagt, REST, und dort kommt Plain-text zurück, kein XML (auch kein JSON).
WebClient, DownloadString/UploadString, alles schön und gut...aber is nich grade the-WCF-Way.
Bin dann unlängst über den Blog von Nicholas Allen gestolpert und habs mit Hilfe seiner Artikel soweit gebracht, dass den Response bis in meinen Encoder reinbekomme und dort in ReadMessage theoretisch was damit tun könnte.
Mit Strings funktioniert das ganze, mit Objekten nicht.

Grob umrissen sieht das ganze so aus:

[ServiceContract]
public interface IAudioscrobbler 
{
   //nur ein test auf meinem lokalen Server, funktioniert soweit
   [OperationContract(ReplyAction = "*")]
   [WebGet(BodyStyle = WebMessageBodyStyle.Bare, UriTemplate = "{test}")]
   string PlainTextTest(string test);

   //der "echte" Request, will nicht so richtig
   [OperationContract(ReplyAction = "*")]
   [WebGet(BodyStyle = WebMessageBodyStyle.Bare, UriTemplate = "?hs=true&p=1.2&c={clientId}&v={clientVer}&u={user}&t={timestamp}&a={auth}")]
   HandshakeReply Handshake(string clientId, string clientVer, string user, int timestamp, string auth);
}

[Serializable]
public class HandshakeReply
{
   public string SessionId { get; set; }
   public string NowPlayingUrl { get; set; }
   public string SubmissionUrl { get; set; }
}

PlainTextTest habe ich mal testhalber auf meinem lokalen Server versucht, indem ich innerhalb des Message Encoders einfach einen String aus dem Buffer ziehe, und diesen über die Return Message weitergebe.
Versuche ich das ganze aber mit einem HandshakeReply, der innerhalb ReadMessage erzeugt wird, gibts nur diesen Fehler:

An unhandled exception of type 'System.Runtime.Serialization.SerializationException' occurred in mscorlib.dll

Additional information: Unable to deserialize XML body with root name 'string' and root namespace 'http://schemas.microsoft.com/2003/10/Serialization/' (for operation 'Handshake' and contract ('IAudioscrobbler', 'http://tempuri.org/')) using DataContractSerializer. Ensure that the type corresponding to the XML is added to the known types collection of the service.

Der Fehler tritt aber nicht mehr im Encoder auf (der Aufruf zu ReadMessage läuft ohne Probleme durch), sondern beim Aufruf selbst, wo die Message ausgelesen wird:

  mscorlib.dll!System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(System.Runtime.Remoting.Messaging.IMessage reqMsg = {System.Runtime.Remoting.Messaging.Message}, System.Runtime.Remoting.Messaging.IMessage retMsg) + 0xc1 bytes	
  mscorlib.dll!System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(ref System.Runtime.Remoting.Proxies.MessageData msgData, int type) + 0x114 bytes	
> WcfHttpTest.exe!WcfHttpTest.Program.Main(string[] args = {string[0x00000000]}) Line 25 + 0x9 bytes	C#

Im Encoder sieht das ganze so aus (gekürzt):

public class PlainTextEncoder : MessageEncoder
{
   //...
   public override Message ReadMessage(ArraySegment<byte> buffer, BufferManager bufferManager, string contentType)
   {
      string response = Encoding.UTF8.GetString(buffer.Array, buffer.Offset, buffer.Count);

      if (!response.StartsWith("OK"))
         throw new Exception("something went wrong"); //TODO

      object ret = response;
      string[] spl = response.Split('\n');
      if (spl.Length == 4)
      {
         ret = new HandshakeReply()
         {
             SessionId = spl[1],
             NowPlayingUrl = spl[2],
             SubmissionUrl = spl[3]
         };
      }

      return Message.CreateMessage(MessageVersion.None, "*", response);
   }
}

Muss mir keiner sagen, das parsen da drin ist nicht grade gut strukturiert, vor allem weils noch weitere Fälle berücksichtigen muss - aber für einen Test reichts. (Ideen und Tipps hierzu sind erwünscht, wie man das am sinnvollsten auslagern kann - siehe Anmerkung zu Action* unten).

Wie unschwer zu erkennen ist, wird im "OK" Fall der String zerlegt; und wenns 4 Teile sind (OK inklusive) dann wird das ganze in meinen Reply umgefüllt.
Warum muss ich das so machen? Basierend auf dem Content habe ich keine Möglichkeit herauszufinden, welche Methode aufgerufen wurde, und dementsprechend wie der Content aussehen sollte und wohin ich ihn umfüllen muss.
* Aus diesem Grund setze ich auch die Action der Message sowie die ReplyAction im Contract auf "*", damit es nicht zum Fehler

Additional information: A reply message was received for operation 'Handshake' with action '<was auch immer ich bei CreateMessage mitgebe>'. However, your client code requires action 'http://tempuri.org/IAudioscrobbler/Handshake'.

kommen kann - das Problem hätte ich vermutlich auch nicht, wenn ich über den Encoder mitbekommen könnte, in welchem Context (sprich: welche Methode wurde aufgerufen/welche Action wird erwartet/usw.) das ganze passiert.
Auch hierzu sind Ideen und Tipps herzlich willkommen.

Das Ziel in hoffentlich nicht allzu weiter Ferne ist, dass ich über einen Aufruf

HandshakeReply reply = asClient.Handshake(...);
//do stuff with reply

einfach an meine Sachen komme, ohne mich an dieser Stelle um das Parsing kümmern zu müssen - damit soll sich der Encoder rumschlagen.

In erster Linie ist jetzt mal die Frage: wie bekomme ich mein eigenes Objekt (oder auch andere POCOs; KeyValuePair hat z.b. auch nicht funktioniert) aus dem Encoder.ReadMessage zurück zu client.CallService?
Wäre das einigermaßen geklärt, stehen noch die Fragen zu Auslagerung des Parsings und die Ermittlung der grade ausgeführten Action im Raum - letzteres könnte ersteres vereinfachen, indem ich einfach am Encoder mehrere Handler registriere, die sich je nach Action darum kümmern, was gebaut wird.

Gruß und Danke im Vorraus,
BhaaL

26.06.2009 - 08:04 Uhr

Morgen!

Schau dir mal DataTable.Select an.

10.06.2009 - 08:14 Uhr

Sollte eigentlich schon so hinhauen. Hast du die C# Keybindings aktiviert, oder verwendest du möglicherweise die VB Bindings?
Wenn nicht, kannst du dir über Tool > Customize, Keyboard die Commands View.NavigateBackward und View.NavigateForward belegen.
Dort gibts übrigens unter Commands auch eine Kategorie View, wo es die beiden Commands als Button gibt - Standardmäßig sind die in der "Standard"-Toolbar, gleich neben Undo und Redo

Gruß, BhaaL

08.06.2009 - 12:39 Uhr

Du könntest mal die Funktion SOUNDEX ausprobieren.
MySQL bietet zudem auch noch andere Vergleichsfunktionen ala Levensthein; die scheint der SQL Server aber nicht zu kennen.

Gruß, BhaaL

14.05.2009 - 16:03 Uhr

Gleich mal vorab, solche Catch-Alls (catch (Exception)) sind grundsätzlich schlecht, weil du möglicherweise bestimmte Exceptions fängst (und unter umständen sogar ignorierst), die du eigentlich nicht ignorieren solltest.
Das ganze ist unter anderem auch eine Microsoft-Guideline, eine Applikation sollte und darf sogar nicht jede einzelne Exception fangen (Teil des Certified for Xxx Programms, die Applikation muss abstürzen können).
Mit .Net 4.0 wirds dann sogar un-catchable Exceptions geben, aber das ist eine andere Sache.

Zum Thema Logging würde ich dir AppDomain.UnhandledException bzw. Application.ThreadException ans Herz legen; dort solltest du immer mitloggen was Sache ist (damit kannst du zwar keine Behandlung machen, aber ein Log schreiben bevor die Applikation absemmelt).
In diesem Zusammenhang ist natürlich auch das throw; Schlüsselwort sinnvoll, weil du im Gegensatz zu throw ex; den Stacktrace beibehältst, sprich du siehst auch direkt wo die Exception aufgetreten ist. Kannst/willst du das nicht tun, solltest du die InnerException Kapazitäten aller Exception-Klassen bemühen.

Bei uns gibts für Exceptions, die irgendwann dem Benutzer präsentiert werden sollen, eine eigene Basis-Exception.
Die hat eine generische Message für uns Entwickler und eine Art Message Code. Über diesen Code wird dann je nach eingestellter Programmsprache eine lokalisierte Meldung ausgegeben; e.Message sieht der Benutzer im normalfall nicht.

Gruß, BhaaL

05.05.2009 - 08:19 Uhr

Auf die schnelle würde ich hier auch sagen, dass du vermutlich per Tool am schnellsten sein wirst.
Ein fertiges Tool ist mir nicht bekannt (falls jemand eins findet, nur her damit!), aber theoretisch kann mans ja einfach selber schreiben:

Schnapp dir über
a)

var resourceManager = new ComponentResourceManager(typeof(MyForm));

eine Instanz des Resource files und verwende dessen Methoden, um an die Einträge zu kommen.
b) XmlReader/XmlDocument die jeweiligen Resources files und geh alle Einträge mit einem "name"-Attribut durch.

Per Reflection holst du dir dann
a) alle Felder des Formulars (auch private usw.) und vergleichst deren Name bzw. ">>" + Name mit dem Anfang des jeweiligen Resource Strings (z.b. _myButton.Text und >>_myButton.Size)
b) den IL Code der InitializeComponent Methode und suchst dort nach Object creations.

a) geht vermutlich schneller, kann unter umständen aber Controls "übersehen" (wenn du GenerateMember auf false setzt).
b) hingegen ist ein wenig aufwändiger, kann aber auch diese Controls erwischen.

Gruß, BhaaL

29.04.2009 - 10:53 Uhr

Bin zwar nicht der über-drüber Schema-Experte, aber soweit ich hier weiß wirst du das nicht über (nur) Schema abbilden können.
Spricht etwas dagegen, die beiden einfach als Alternativen zu definieren? So ala choice(ArticleID | Articles(ArticleID+)).

Wenn du keine Mischformen erlauben willst/kannst/sollst, wird dir nur eine externe Validierung weiterhelfen können (wie zum Beispiel Schematron).

Gruß, BhaaL

23.04.2009 - 09:14 Uhr

...oder alternativ Func<TIn1, ..., TResult> verwenden.
Was du in dem Fall suchst wäre ein Func<ClassA, ClassA> - rein kommt "ClassA" (der erste Typparameter), raus kommt "ClassA" (der letzte Typparameter).

Gruß, BhaaL

15.04.2009 - 08:20 Uhr

Wenn es sich um eine Ziffer (ein Zeichen, [0-9]) handelt, ist

char.IsDigit(meinText[ziffernIndex])

vermutlich die beste Alternative, bevor man hier großartig mit Regex auffährt.
Wenns eine Zahl (ein bis n Zeichen, [0-9]+) sein kann, kommts wieder drauf an was du damit machen willst. Brauchst du das ganze als Integer, versuch int.TryParse (wie bereits vorgeschlagen). Willst du nur nachsehen, ob auch wirklich eine Zahl da ist, tuts ein Regex genauso.

Gruß, BhaaL

14.04.2009 - 12:46 Uhr

Verwende die englischen Begriffe für das CategoryAttribute. Z.B. "Appearance" für "Darstellung". VS setzt das dann automatisch in die jeweilige Sprache um. Also wäre es dann "Design" für "Entwurf".

Dem kann ich nicht ganz beipflichten. Falls die IDE das selbst macht, meinetwegen.
Aber Framework-intern gibt es dafür abgeleitet von DescriptionAttribute und CategoryAttribute die Klassen SRDescriptionAttribute und SRCategoryAttribute, die über die SR Klasse eine Lokalisierung durchführen - diese sind aber internal und kann man nicht direkt verwenden.

14.04.2009 - 08:11 Uhr

Je nachdem ist es sicher auch sinnig, die jeweiligen Attribute zu vergeben:

public class Foo
{
  [Browsable(true)]
  [Description("You can see this property")]
  [Category("My Custom Properties")]
  public string YouCanSeeMe { get; set; }
  [Browsable(false)]
  public string YouCantSeeMe { get; set; }
}

YouCanSeeMe wird im Designer angezeigt (weil Browsable = true), und ist in einer eigenen Kategorie mit dem angegebenen Hilfetext zu sehen.
YouCantSeeMe wird nicht angezeigt - sowas ist sinnvoll, wenn du bestimmte Properties nicht über den Designer setzen lassen willst, oder auf andere Weise public Properties hast, die nicht im Designer aufscheinen sollen.

08.04.2009 - 14:46 Uhr

Du kannst dir einen benutzerdefinierten Config Section Handler schreiben wo du ein Array wegsicherst.
Mehr dazu siehe MSDN zum Thema ConfigurationSection (Ist zwar unter ASP.Net drin, funktioniert unter WinForms aber genauso).

Gruß, BhaaL

07.04.2009 - 12:41 Uhr

Natürlich bekommst du die Sachen übergeben.
Stehen alle im Request drin, die dein Server empfängt. Und das passiert ja wohl bevor du php-cgi.exe aufrufst.
Schau dir einfach mal an, was dein Socket empfängt - da ist alles drin was du brauchst (und möglicherweise sogar im richtigen Format, um es 1:1 an PHP weiterzureichen).

Gruß, BhaaL

06.04.2009 - 17:22 Uhr

Kurz:

Bei GET schreibst du das ganze in die Umgebungsvariable, sprich

p.StartInfo.EnvironmentVariables["QUERY_STRING"] = "?my=query&string=as&environment=variable";

Bei POST schreibst du das ganze über StandardInput rein:

string postRequest = yourPostRequest;
p.StandardInput.WriteLine(@"Content-type: application/x-www-form-urlencoded
Content-length: " + postRequest.Length + "

" + postRequest);

(Nicht getestet, könnte der ein oder andere Header fehlen; aber grundsätzlich sollte das reichen, um dich in die richtige Richtung zu bekommen)
Mehr dazu in der HTTP RFC zu Requests, Request Headern und POST Requests.

Gruß, BhaaL

06.04.2009 - 15:45 Uhr

Eventuell wäre hier auch zu überlegen, ob du nicht einfach im OnPaint des Formulars/Panels/PictureBox dein Dreieck zeichnest; ein Thread/ThreadPool/BackgroundWorker allerdings die Berechnung dessen Eckpunkte durchführt.

Könnte dann so aussehen:

private Point _pendel1;
private Point _pendel2;
private Point _nullPunkt;

public override void OnPaint(PaintEventArgs e)
{
  //checks usw.
  e.Graphics.DrawXxx(_pendel1, _pendel2, _nullPunkt);
}

private void backgroundWorker1_DoWork(object sender, EventArgs e)
{
  foreach (var step in calculation) //pseudo
  {
    _pendel1 = new Point(step.X1, step.Y1);
    _pendel2 = new Point(step.X2, step.Y2);
    Invalidate();
    //könnte optimiert werden, indem du nur den Bereich der Pendelbewegung "invalidatest", 
    //und im OnPaint entsprechend nur diesen Teil neuzeichnest.
  }
}

Gruß, BhaaL

06.04.2009 - 14:27 Uhr

Wenn es well-formed XML ist, würde ich dir ein XmlDocument mit xmlDocument.SelectNodes() über XPath bzw. XDocument und xDocument.Elements() vorschlagen.

Ein string.Split würde nur dann Sinn machen, wenn es sich nicht um Tags handeln würde, sprich anstelle von <text></text> nur ein <text> zwischendrin wäre (<br/>, eventuell?)

03.04.2009 - 09:38 Uhr

Weil der Text leider variabel ist und ich keine lust habe selber eine OCR zu schreiben.

FZelle meinte, dass du direkt per WinAPI (z.b. SendMessage mit WM_GETTEXT) den Button nach seinem Text befragen sollst; und nicht erst einen Screenshot machen, den du nachher per OCR zerpflückst.
Oder hast du an der Stelle keinen Zugriff auf die Applikation?

03.04.2009 - 08:09 Uhr

Schau dir mal die Commit/Rollback (nach erfolgter/abgebrochener Installation) sowie die Uninstall-Methode an.
:rtfm:

02.04.2009 - 12:19 Uhr

Ein bisschen Google liefert das hier:

Besonders bei neueren XP-Installationen wird der Key nicht korrekt entschlüsselt.
Der Grund hierfür liegt darin begründet das Microsoft eine Version XP inklusive Servicepack2 ( genauer SP2c) wegen Keymangels released hat welches den Schlüssel erweitert. Damit sind nun mehr Buchstaben möglich was das vorliegende Programm nicht berücksichtigt, die Art der Generierung hingegen hat sich nicht geändert wie auch zumindest unter Vista inkl. Servicepack1 Beta bisher nicht.

Möglicherweise hast du den "alten" Algorithmus erwischt, wo die PossibleChars noch nicht komplett sind. Auf die schnelle hab ich aber auch nichts gefunden, wo die kompletter gewesen wären.

Gruß, BhaaL

01.04.2009 - 15:23 Uhr

Servus SeeQuark!

Das markieren an sich sollte ja kein Problem darstellen.
Eig. besteht das nur aus dem Cursor setzen, den Bereichn blau übermalen und ev. noch Funktionalitäten wie Copy/Paste/Cut zur Verfügung zu stellen.

Ich hätte eigentlich gedacht/gehofft, dass es da einen anderen Trick für gibt. Wenns nicht anders geht, meinetwegen.

Das einfachste wäre zum Beispiel, ein komplett neues Control zu entwickeln.
Die Überlegungen siehst du schön in
>

Hatte ich auch vor, und danke für den Link!
An SharpDevelop hatte ich jetzt gar nicht gedacht, was das Control angeht.
Und wenn man sieht, was dr4g0n da schönes gezaubert hat, dürfts auch bei nem Browsercontrol nicht allzu schwierig werden.

Andererseits, wenn dir das Browser-Control nicht passt, könntest du auch die (für managed gemachte) Variante des FF (
>
) nehmen oder das
>
managed machen, etc.

Sicher könnte ich das. Ich könnte auch das vorhandene WebBrowser Control verwenden. 😃
Ich erfind gerne Räder neu, und wer will nicht gern seinen eigenen Browser schreiben? 😉

Ich werd mir bezeiten mal den SharpDevelop Code zu gemüte führen, und eventuell bei dr4g0n anklopfen, ob der ein paar Schnipsel parat hätte.
Bisher schon mal besten Dank für die Links/Vorschläge!

Gruß, BhaaL

Edit:
So, mal ein wenig in SharpDevelop rumgegraben, und meine Befürchtungen wurden bestätigt - alles per Hand gezeichnet.
In jedem Fall, Danke an alle beteiligten, vielleicht hört ihr dann ja bald von einem managed Browser Control 😉

01.04.2009 - 13:23 Uhr

Hallo herbivore,

am Ende soll sowas wie ein Browser-Control rausschauen; nur eben in Managed Code, nicht über ActiveX (und vor allem nicht mit dem Internet Explorer unten drunter).
CodeProject machts vor, nur mit dem Problem, dass man Text nicht markieren kann.

Und ich halte es für recht unsinnig, für jeden Block (der möglicherweise auch noch andere Blöcke in sich tragen könnte, oder sich gar anderes verhalten soll, wie z.b. Formularfelder) eine eigene Textbox zu erstellen.
Außerdem könnte man da unter Umständen schnell an die Grenzen der verfügbaren Window-Handles geraten, zumindest wenn man nebenbei noch genug aufhat, so wie ich hier grade mit meinen 4 Visual Studios :evil:

Vor allem stelle ich mir das aus Sicht des Users recht unschön vor, wenn man beispielsweise alles markieren will; sogesehen würde sich dann doch nur eine der Textboxen angesprochen fühlen...

Andererseits kann ich mir aber auch schwer vorstellen, mein Control dann von einer Textbox (RichTextBox, TextBoxBase, etc) abzuleiten; weil das sicher auch seine Nachteile hat.
Oder sieht das jemand anders?

Gruß, BhaaL

01.04.2009 - 08:57 Uhr

Morgen liebe CSharp-Gemeinde!

Ich werfe vorab gleich mal was zum Denken in die Runde:
Was ist der Unterschied zwischen einem Label und einer read-only Textbox ohne Border?

Antwort: Die Textbox bietet nach wie vor die Möglichkeit, den Text zu markieren und ggf. auch rauszukopieren.

Nun bin ich auf der Suche nach genau dieser Funktionalität.
Allgemein habe ich eine Oberfläche (Panel, Label, Graphics, ...) und will darauf Text darstellen (zeichnen, einbetten, was-auch-immer) - dieser Text soll sich analog zu einer Textbox auch markieren lassen.
Um das ganze auch noch ein wenig zu erschweren: Ich hätte hier gerne eine 100% managed Möglichkeit um das zu erreichen. P/Invoke will ich an dieser Stelle nur ungern verwenden, werde ich aber tun wenn es keine managed Alternative gibt.

Ich hab bisher schon ein wenig per Reflector in TextBox und TextBoxBase rumgegraben, auch in den referenzierten TextBoxRenderer und TextRenderer Klassen.
Nur leider ist der M$ Code immer kryptisch genug um ein einfaches Copy&Paste der relevanten Teile zu verhindern. 😄

Durfte sich schon mal jemand mit einem ähnlichen Problem herumschlagen, kennt eine Lösung, oder kann mir zumindest den richtigen Trampelpfad im großen Framework-Dschungel weisen?

Gruß, und Dank im Vorraus,
BhaaL

30.03.2009 - 14:44 Uhr

Sein Problem ist wohl genau das umgekehrte.
Wie ich das verstanden habe, ist zur Laufzeit alles in Ordnung, aber im Designer nicht.

Kontrollier möglicherweise mal, ob deine Methode (wo sämtliche Controls erzeugt werden) auch tatsächlich InitializeComponent heißt - der Designer parst diese Methode und zeigt entsprechend die Controls an.

Edit: Oh, fast übersehen, sind die beiden Klassen als partial markiert? Sowohl im Hauptfile als auch im Designer File muss partial dabei stehen, sonst wird die Klasse nicht korrekt übernommen.
Das mit der Anzeige kannst du mittels Texteditor im Project-File händisch ändern, sollte aber auf die Funktionalität keinen Einfluss haben.

30.03.2009 - 09:39 Uhr

Passiert mir inzwischen auch immer häufiger, sprich ich wäre auch für ein solches Plugin zu begeistern!

Ich hoffe nur, dass es sowas gibt. Die Auswahl der Exceptions (und auch Benutzerdefinierte!) wird in der suo gespeichert; dh. diese Auswahl ist pro Benutzer und pro Projekt separat gespeichert.

26.03.2009 - 17:58 Uhr

Vielleicht ist ein DateTime erstellen da auch schon zu viel overhead?

Im Hintergrund passiert da nämlich mehr, als man denken würde; so werden unter anderem TimeSpan.TimeToTicks, DateToTicks und diverse andere Checks ausgeführt.

Wie wärs damit?

string[] timeOrMs = timeString.Split(':', ',');
long time = (long)(int.Parse(timeOrMs[0]) * 3600 + int.Parse(timeOrMs[1]) * 60 + int.Parse(timeOrMs[2])) * 1000 + int.Parse(timeOrMs[3]);
times.Add(time);

Eventuell machts auch Sinn, hier statt einem int.Parse gleich direkt auf die Zahlenwerte zu gehen:

int Parse(string value)
{
  if (string.IsNullOrEmpty(value))
    return 0;
  int ret = 0;
  for (int i = 0; i < value.Length; i++) 
    ret += (int)('0' - value[i]) * ((value.Length - i - 1) * 10);
  return ret;
}

Nicht getestet, aber ich denke du erkennt die Intention dahinter.

Ist halt immer so ne Sache mit Performance unter Managed Umgebungen, auch wenn diese schon recht nah an native Code sind.

Gruß, BhaaL

23.03.2009 - 12:06 Uhr

Für sowas bietet sich der SgmlReader an. HTML ist ja nur eine weitere Ausprägung von SGML (auch XML, nur ist dieses "logischer", mit zwingenden Ende-Tags usw).

Das ganze in ein XmlDocument (oder XDocument) rein, und schon kannst du per XPath oder Linq drüberfahren.

18.03.2009 - 09:07 Uhr

Beim Installer musst du aber auch immer aufpassen!
Es gibt ein Web-Setup (üblicherweise im Bereich 20-30 MB), welches im Laufe des Setup die benötigten Dateien runterlädt.
Dazu gibts aber auch noch ein redistributable Setup, wo gleich alles drin ist (200 MB und mehr).

Rein von der Größe des Setups solltest du deshalb nicht gehen.

Bezüglich Service Pack kann ich bestätigen, dass es zumindest auf XP SP2 und SP3 funktioniert, SP1 haben wir hier nicht mehr rumfliegen.

Gruß, BhaaL

18.03.2009 - 08:00 Uhr

Abgesehen davon, dass es keine schöne Lösung ist, vergisst du damit auch das normale Visual Studio - sprich wenn du mal ein Update auf eine "echte" Visual Studio Version machst, wird das Schnipsel nicht mehr funktionieren.

Sinnvoller wäre es, deine Initialisierung aus dem Konstruktor weg in eine Load Methode zu packen. Bei Formularen wäre hierfür oft OnLoad geeignet, bei UserControls eventuell OnHandleCreated. Im Gegensatz zum Konstruktor funktioniert dort auch die Property DesignMode.

Gruß, BhaaL

17.03.2009 - 17:17 Uhr

Nur zur Info:

Anschließend packst du die XML-Dokumentation in das gleiche Verzeichnis wie die dll, dann sollte alles klappen.

Der Teil ist wichtig.
Generiert wird dir die Xml ja scheinbar schon, sie muss nur auch mit der DLL weitergegeben werden damit Intellisense sie auch finden kann.

Gruß, BhaaL

12.03.2009 - 13:30 Uhr

Falls ich gemein war: Was spricht dagegen und tut weh? 😃

12.03.2009 - 12:50 Uhr

Dort gebe ich Controls übrigens auch nen Prefix. Das hat den Vorteil, dass Controls die logisch zusammen gehören (z.B. Ein Lable + eine TextBox) den selben Namen haben können (Beispiel: myTbName, myLblName).

Ein ähnliches Argument habe ich auch grade im anderen Thread hier drüben angebracht:
Ungarische Notation in GUIs

Membervariablen bekommen bei mir immer einen Underscore davor, je nach Art könnte hier auch noch ein Typ-Präfix ala "lbl" oder "txt" dazukommen.

Guidelines sind schön und gut, aber wenn man sich damit nicht zurechtfindet, sollte man sie einfach nicht in dieser Form anwenden bzw. abändern.
Ich kann mir sehr gut vorstellen, dass unsere Produkte oft und viel gegen Microsoft Guidelines verstoßen, aber im Vergleich zu diversen anderen Sachen, die nicht von uns sind, finde ich (und auch meine Kollegen) mich hier eher zurecht als in 3rd-Party Sources die anderen Guidelines entsprechen.

Gruß, BhaaL

12.03.2009 - 12:44 Uhr

Hm, ungarische Notation, das Wort hab ich schon lange nicht mehr gehört.

Ich hab mir über die Zeit folgende Schreibweisen angewöhnt, und diese decken sich auch großteils mit unseren gängigen/festgehaltenen internen Codierungsrichlinien:

class SomeForm : Form 
{
  private int _clickCount;
  private int _btnClickMe;

  public int ClickCount { get { return _clickCount; } }
  private void ClickMe_Clicked(object sender, EventArgs e) 
  {
    int clickCount = ClickCount;
    clickCount++;
    _clickCount = clickCount;
  }
}

Mag ein wenig konfus aussehen auf den ersten Blick, aber alles hat seine daseinsberechtigung.*Member-Variablen mit Underscore, damit man sie von lokalen Variablen unterscheiden kann (_clickCount vs. clickCount) *Member-Namen nach dem Underscore in Camel-Case. *Member für Controls mit Präfix, damit ua. auch im Intellisense z.b. sämtliche Buttons unter "btn" gelistet sind (erleichtert die Suche nach einem Button, wenn man nicht selbst der Ersteller des Formulars ist). *Properties in Pascal-Case, ohne Präfix. Würde man Member nach JAck30lena's Beispiel benennen, könnte "Name" sowohl eine Property als auch ein Member sein - das ist IMO nicht allzu gut so. Auf den ersten Blick wäre auch nicht ersichtlich, ob es sich z.b um einen string handelt, oder um eine TextBox (im Gegensatz zu _txtName) wenn man onlinegurke's Beitrag noch weiter treibt und auch das "Box" weglässt. *Lokale Variablen per Camel-Case, ohne Präfix.

onlinegurke hat zwar ein gutes Argument gegen die Präfixe genannt, das müsste mMn. dann aber auch für die Suffixe gelten.
Benennt ein Entwickler das Control zum zumachen des Formulars "CloseButton", der nächste "OkButton", der dritte "SchliessenButton" und der vierte "CancelButton", kann man schon mal durch die ganze Liste scrollen um was zu finden. Die Tatsache, dass es ein Button ist, hilft mir bei der Suche nicht.
Dem würden aber zumindest die Underscores als Präfix für Member zugute kommen.

Ich werd mir bezeiten mal die anderen Links hier ansehen, aber ich bezweifle stark dass ich irgendwas an meinen Gewohnheiten ändern werde; sind immerhin (abgesehen von unseren internen Richtlinien) schon lange in dieser Form in Verwendung und helfen mir auch dabei, mich in eigenen/fremden Codes zurechtzufinden (ich suche einen Button, weil ich das Image im Code setzen will; tippe "_b" und bin dann meist schon in der Liste aller Buttons).

Am ehesten kann ich mir nur vorstellen, dass ich Konzepte finden werde, die "gar nicht so blöd" sind, und diese in meine Gewohnheiten einfließen lasse bzw. Kompromisse eingehe. Alles umwerfen und umgewöhnen, nein nein!

Gruß, BhaaL

10.03.2009 - 17:50 Uhr

Unter aller Sau oder nicht, es sind so oder so Implementierungen von Standardisierten Algorithmen. Sprich da kann weder Microsoft noch das Framework was dafür, dass die Dinger so tun wie sie tun 😃

10.03.2009 - 16:39 Uhr

Wenns dir nur um Kompression geht, würd ich mal einen Blick auf System.IO.Compression werfen.
Dort gibts zwar nur DeflateStream und GZipStream, die dürften aber für deine Vorhaben ausreichen; wenn du bisher auch nur BZip2 hattest.
Wenn du selber eine Art Fehlerkorrektur implementiert hast, kannst du den DeflateStream verwenden, ansonsten ist der GZipStream möglicherweise besser (der hat einen CRC Check eingebaut).

Gruß, BhaaL

09.03.2009 - 13:58 Uhr

Wozu willst du das so machen? Starte doch deine Anwendung einfach mittels runas.

Hi zommi,

wir haben in der firma ein tool dass sich notebookuser adminrechte geben können wenn diese unterwegs sind. sie müssen dann auch eine reason eingeben und da wird auch ein logfile erstellt und und und.

Wenn jeder Benutzer so oder so das Passwort für den lokalen Administrator kennt, was hindert ihn dann daran, Regedit selbst per runas oder einem anderen Mechanismus zu starten und somit dein Logging zu umgehen?

Ich würde bei einigermaßen kritischen Sachen eher (zusätzlich?) hergehen, und per AuditRule (hier am Beispiel Registry mit einer RegistryAuditRule) einen Eintrag im Security EventLog erstellen zu lassen - automatisch vom Betriebssystem.
Das wird einmal durch euren SysAdmin ausgeführt, wenn die Notebooks ausgegeben/aufgesetzt werden; alles andere kann wenn dann nur ein versierter Benutzer mit Kenntnissen in dem Bereich (und ggf. auch Kenntnissen in einer .Net Sprache) ändern.

06.03.2009 - 13:01 Uhr

Ich kenne leider auch nur Komponenten, mit denen man PDFs erstellen kann; kaum welche von denen unterstützen lesen geschweigedenn modifizieren von bestehenden Dokumenten.
Hast du eventuell die Möglichkeit, das Ausgangsdokument herzubekommen, bevor daraus ein PDF wird?

06.03.2009 - 12:49 Uhr

Konvertiere dir das HTML in XHTML und mache XPath abfragen. IMHO das einfachste und evtl. sogar schneller als mit Regex.

Wenn das nicht geht, versuchs mit dem SgmlReader. Kannst du auch in ein XmlDocument/XDocument laden, parst aber gemäß SGML-Regeln (XML und HTML sind eine Form von SGML, after all).

Gruß, BhaaL

04.03.2009 - 15:06 Uhr

Typeof übergibt nur den Typ der Klasse, keine spezifischen Informationen über welchen Konstruktor das ganze verwenden soll, oder welche Parameter dort reinkommen.

Nachdem dein Programm sowiso nur aus einer (statischen) Main-Methode besteht, könntest du auch die Variable statisch machen (sofern diese auch in dem Kontext verwendet wird; wenn du wieder Instanzen davon anlegst weiß dein Service ja nicht mehr, welche Instanz davon zu nehmen ist).
Wie LaTino schon angemerkt hatte, ein Singleton ist möglicherweise das, was du willst, wenn das ganze aus diversen Gründen nicht statisch sein kann.

26.02.2009 - 14:52 Uhr

Visual Studio kann sehr wohl C (zumindest behauptet es das).
Bei einem C++ Projekt kannst du einstellen, dass der Code als C-Code kompiliert werden soll (irgendwo in den Projekteigenschaften beim Compiler, "Treat Source as: C/C++" oder so).

25.02.2009 - 11:25 Uhr

Also ich bin sehr mit CodeRushX zufrieden (vor allem weils gratis ist).
Ein paar Sachen hab ich deaktiviert, ein paar umkonfiguriert, aber alles in allem ist das Ding sehr mächtig: Properties konvertieren (auto-implemented, backing store, Dependency Properties per Plugin), Methoden extrahieren, Anonyme Klassen konkret ausprägen, Move Type to File, und und und.
Ich fand das ganze unter anderem bei einem kleinen Projekt praktisch, wo ich erst sämtliche Unittests geschrieben habe (TDD), und dabei per CodeRush Klassen und Methoden generieren ließ. Diese wurden nachher mit Code befüllt, und alles tut wie es soll.

Ich will den ReSharper aber auch nicht schlecht machen, ein Kollege verwendet den, und der hat doch ein paar nette Sachen drin. Was mir persönlich an dem aber nicht gefällt, er ist eher schwerfällig und überladen wenn man den mal installiert...und bei größeren Solutions ist das Studio auch so schon schweinelangsam 😃

Gruß, BhaaL

20.02.2009 - 10:39 Uhr

Deswegen: Kein CAS, keine Friends, sondern Architektur plugintauglich machen. Sinnvollerweise das in .NET 3.5 enthaltene Addin-Framework verwenden.

....wobei die Plugin-Pipeline schon leicht umständlich ist 😃
Ich kann da nur zu MEF raten. Noch CTP, aber in C# 4.0 mit dabei (vielleicht auch schon früher). Keine 7 Projekte usw. 😉

20.02.2009 - 10:24 Uhr

Die Lösung mit internal ist auch nicht so toll, weil es sich um Plugins handelt. Wenn jeder Plugins schreiben können soll, sperrst du denen über internal sämtliche Zugriffsrechte.

Man kann auch Friend-Assemblies verwenden. In diesem Fall muß nur die Hauptanwendung via Strongname dem PlugIn bekannt sein.

Hab ich auch angemerkt, und ist so nicht ganz korrekt.
Das Plugin ist friend der Applikation, nicht die Applikation ist friend des Plugins. In der Applikation muss das InternalsVisibleTo definiert werden, weshalb im vorraus die Plugins (inklusive Strong Name!) bekannt sein müssen. Erweiterbarkeit gibts so dann nicht, ohne die Applikation selbst auszutauschen.

Gruß, BhaaL

19.02.2009 - 15:10 Uhr

Ich denke, der DeflateStream wird dir da nicht weiterhelfen.
Eine Zip-Datei ist ein (nicht komprimierter) Container, der neben Metadaten und Datei/Ordnerstruktur (möglicherweise) komprimierte Daten beinhält.
Mit dem DeflateStream könntest du die Daten entpacken (sofern diese per Deflate gespeichert wurden), aber an die Dateistruktur selbst kommst du auch ohne ran.

Ist halt die Frage, ob du gerne Räder neu erfindest oder nicht. Je nachdem würde ich dir zu www.wotsit.org und der Zip File Format Specification oder SharpZipLib bzw. DotNetZip raten.
Ich habe außer SharpZipLib schon mal alle alternativen durchprobiert, in mehreren verschiedenen Sprachen, und es liegt an dir, je nach Interesse an der Technik/Verfügbarer Zeit/Faulheit? eine auszuwählen.

Gruß, BhaaL

18.02.2009 - 08:15 Uhr

Die Lösung mit internal ist auch nicht so toll, weil es sich um Plugins handelt. Wenn jeder Plugins schreiben können soll, sperrst du denen über internal sämtliche Zugriffsrechte.
Schreibst nur du die Plugins, kannst du in der Basisapplikation per InternalsVisibleTo eine Ausnahme hinzufügen. Problem: Neues Plugin -> Basisapplikation austauschen. Und außerdem ist InternalsVisibleTo nicht die sauberste Lösung (würde ich höchstens für Unittests und ähnliches verwenden).

Eventuell könntest du das auch über das Security-Konzept des Frameworks machen.

Eine eigene Permission-Klasse schreiben (z.b. PluginPermission) und diese an die Methoden dranhängen bzw. per .Demand() überprüfen. Schlägt das fehl, fliegt eine Exception.
Deine Plugins müssen dann lediglich diese Permission verwenden und bezeugen, dass sie diese auch haben (unter anderem per .Assert() möglich).

Ist aber auch nur eine Schein-Sicherheit, sowohl Host als auch Plugin müssen diese Klasse kennen. Und jemand, der die Exception bekommt, könnte einfach per Reflector nachsehen, warum das so ist, und seinen Code entsprechend abändern.

Gruß, BhaaL

11.02.2009 - 16:17 Uhr

Wenn du über die Project Settings eine Settings-Datei einfügst, kannst du erstens per Properties.Settings.settingName drauf zugreifen, und diese zweitens per Properties.Settings.Save() in der user.config (bzw. im Isolated Storage, pro Benutzer pro Applikation) abspeichern.
Die Arbeit macht das Framework für dich, du musst nur drauf achten dass du das Setting auf UserSetting stellst (ApplicationSettings sind für alle Benutzer, und können zudem nicht geändert werden).

Gruß, BhaaL

04.02.2009 - 15:26 Uhr

Per parameter.Arg4? Ist doch nur eine Klasse, die an mehrere Methoden weitergereicht wird...im Grunde ähnlich einer EventArgs Klasse.

04.02.2009 - 12:52 Uhr

Ich würde zum einen mal überprüfen, ob array (bei der Verwendung als array[0]) eventuell null ist.
Zum anderen, hast du einen statischen Konstruktor (static Balise() { ... }) bzw. statische Member (static SomeClass _staticObject = new SomeClass()) , die initialisiert werden?

03.02.2009 - 09:20 Uhr

Klingt für mich nach Dynamic Invocation über Typ/Methodennamen...

Meinst du sowas?

class Test { public void DoSomething() { Console.WriteLine("doing something"); } }
//...
string method = "DoSomething";
Test test = new Test();
Type t = test.GetType();
MethodInfo m = t.GetMethod(method);
m.Invoke(test, null); //ruft DoSomething auf und gibt "doing something" aus

Das andere klingt danach, als ob du dynamisch Properties "erzeugen" willst.
Geht direkt nicht, kann man aber über ein Dictionary und/oder einen Indexer abbilden:

class Test 
{
   private Dictionary<string, object> _myValues = new Dictionary<string, object>();
   public object this[string key] 
   {
      get { return _myValues[key]; }
      set { _myValues[key] = value; }
   }
}
//...
Test test = new Test();
test["abc"] = randomObject;

Sollte keins der beiden zutreffen, versuch mal genauer zu beschreiben, was du eigentlich vorhast - mit entsprechendem Pseudocode, wie du es dir vorstellst; und wenn möglich ohne object.[replaceMe] 😉

Gruß, BhaaL

02.02.2009 - 09:04 Uhr

Einer der großen Vorteile von Mono ist die Modularität.
Vorausgesetzt, du befasst dich genügend damit, und hast auch keine Angst davor, mal selber Hand anzulegen, dann kannst du dir das Framework selber customizen, und wirklich nur Funktionalität reinpacken, die du auch wirklich brauchst.
Miguel de Icaza hat damals auf der PDC08 im Vortrag erwähnt, dass das kleinstmögliche Mono-Image irgendwo bei 2 MB ist.