Laden...
P
parsifal myCSharp.de - Member
Dipl.-Wirt.Inform., Softwareentwickler Siegen Dabei seit 11.11.2006 66 Beiträge
Benutzerbeschreibung

Forenbeiträge von parsifal Ingesamt 66 Beiträge

26.02.2009 - 13:48 Uhr

Ein Konstruktor sollte ein Objekt nur initialisieren und die notwendigen Eigenschaften des Objektes setzen. Ob es richtig initialisiert ist sollte durch die Methoden überprüft werden und ggf. eine InvalidOperation geworfen werden.

Ich würde für den von dir genannten Konstruktor eine Überladung erstellen, dem ich den Pfad zu der Konfigurationsdatei übergebe.

19.02.2009 - 10:53 Uhr

Ich könnte dafür NDepend (http://www.ndepend.com/) empfehlen.

Ist zwar nicht direkt in Visual Studio integriert. Aber damit kannst du Assemblyübergreifend jeden nicht benutzen Code und vieles mehr rausfinden.

18.12.2008 - 09:04 Uhr

Beschreibung:

Der folgende Codeauszug soll verdeutlichen wie der Einsatz der Klasse AsyncOperation genutzt werden kann, um Controls im UI-Thread, durch ein Ereignis das in einem anderen Thread ausgelöst wurde, zu aktualisieren ohne auf delegates und die Abfrage der Eigenschaft InvokeRequired zurückzugreifen.

Ausgangsbasis ist eine Klasse 'EventService' die Ereignisse anbietet um über Änderungen an Daten zu informieren. Diese ist durch die Schnittstelle 'IEventService' definiert ist. Eine Instanz der Klasse 'EventService' befindet sich in einem anderen Thread (oder Prozess), als dem UI-Thread und bietet Ereignisse an, die z. B. dazu verwendet werden Controls im UI-Thread zu aktualisieren.


public interface IEventService {
  event EventHandler Changed;
}

public class EventService : IEventService {
  #region IEventService Members

  public event EventHandler Changed;

  #endregion

  public void ChangeSomething() {
    // Ändert irgendetwas und feuert dann das Ereignis Changed.
    ThrowChangedEvent( EventArgs.Empty );
  }

  protected virtual void ThrowChangedEvent( EventArgs e ) {
    EventHandler changed = Changed;
    if ( changed != null ) {
      changed( this, e );
    }
  }
}

Im o. g. Szenario würde man eine InvalidOperationException mit dem u. g. Text erhalten, wenn man z. B. versuchen würde in der EventHandler-Methode eine Textbox mit Text zu füllen.


Ungültiger threadübergreifender Vorgang: Der Zugriff auf das Steuerelement Form1
erfolgte von einem anderen Thread als dem Thread, für den es erstellt wurde.

Um diese threadübergreifenden Vorgänge zu umgehen, ist in der EventHandler-Methode die Eigenschaft InvokeRequired von Controls zu prüfen,
ob ein direkter oder ein indirekter Zugriff (mittels delegate und Invoke) erfolgen kann/muss.


private void OnEventServiceChanged( object sender, EventArgs e ) {
  if ( this.InvokeRequired ) {
    this.Invoke( new MethodInvoker( DisplayText ) );
  }
  else {
    DisplayText();
  }
}

private void DisplayText() {
  textBox1.AppendText( "Es hat sich was getan" );
  textBox1.AppendText( Environment.NewLine );
}

Eine andere Möglichkeit, diese threadübergreifenden Vorgänge zu ermöglichen ohne die Eigenschaft InvokeRequired zu prüfen und der Definition/Implementierung von Delegates, die für den Invoke benötigt werden, besteht darin eine Wrapper für die Klasse 'EventService' zu implementieren, der ebenfalls die Schnittstelle 'IEventService' implementiert.

Der Wrapper erhält eine Referenz auf den echten 'EventService' und registriert beim diesem alle angebotenen Ereignisse. Intern erstellt der Wrapper im Konstruktor eine AsyncOperation über den AsyncOperationManager, die er zum Auslösen der eigenen Ereignisse benötigt. Löst nun der echte 'EventService' ein Ereignis aus, wird die EventHandler-Methode des Wrappers aufgerufen. In dieser löst der Wrapper über den Aufruf Post(System.Threading.SendOrPostCallback, object) das entsprechende eigene Ereignis aus.

Dabei wird das Ereignisse des Wrappers in dem Thread ausgelöst, in dem er erstellt wurde. Wenn also der Wrapper im UI-Thread erzeugt wird. z. B innerhalb einer Form, dann werden die Ereignisse des Wrappers im UI-Thread ausgeführt und es kann ein direkter Zugriff auf die Controls erfolgen.

Nachfolgend ist die Implementierung der Wrapper-Klasse für den oben angegebenen 'EventService' dargestellt.


public class WrappedEventService : IEventService {

  private IEventService _realEventService;
  private AsyncOperation _operation;

  public WrappedEventService() {
    _operation = AsyncOperationManager.CreateOperation( Guid.NewGuid() );
  }

  public WrappedEventService( IEventService realEventService ) : this() {
	RealEventService = realEventService;
  }

  public IEventService RealEventService {
    get { return _realEventService; }
    set {
      if ( _realEventService != null ) {
        _realEventService.Changed -= OnChanged;
      }
      _realEventService = value;
      if ( _realEventService != null ) {
        _realEventService.Changed += OnChanged;
      }
    }
  }

  private void OnChanged( object sender, EventArgs e ) {
    _operation.Post( ThrowChangedEvent, e );
  }

  protected virtual void ThrowChangedEvent( object e ) {
    EventHandler changed = Changed;
    if ( changed != null ) {
      changed( this, ( EventArgs ) e );
    }
  }

  #region IEventService Members

  public event EventHandler Changed;

  #endregion
}

In der angehängten Zip habe ich ein Beispielprogramm (Visual Studio 2008 Solution) hinterlegt, um den Sachverhalt praktisch zu verdeutlichen. Der wesentliche Code ist im Konstruktor der Klasse Form1 enthalten. Die wesentlichen Stellen sind mit Kommentaren versehen.

Events, InvokeRequired, AsyncOperation, UI-Thread, Threadübergreifend

03.12.2008 - 07:54 Uhr

Patric Smacchia (Entwickler von NDepend) hat sich schonmal mit der selben Fragestellung beschäftigt.

Den Artikel dazu findest du unter

http://codebetter.com/blogs/patricksmacchia/archive/2008/11/19/an-easy-and-efficient-way-to-improve-net-code-performances.aspx

26.11.2008 - 13:36 Uhr

Bei Microsoft wird ein Bootstrapper Package angeboten, dass u. a. das .NET Framework 2.0 SP2 enthält.

Das ganze Paket kann unter http://msdn.microsoft.com/en-us/vs2008/bb898654.aspx
heruntergeladen werden.

Im Installationsverzeichnis des Pakets (z. B. C:\Programme\Microsoft SDKs\Windows\v6.0A\Bootstrapper\Packages) sind die ganzen Redistributables, u. a. auch vom .NET Framework 2.0 SP2 enthalten.

Gefunden unter : http://stackoverflow.com/questions/192100/net-framework-20-sp2

14.11.2008 - 07:37 Uhr

Die Process-Klasse hat eine Eigenschaft MainModule vom Typ ProcessModule.

Die Klasse ProcessModule hat eine Eigenschaft Filename. Über den kannst du ggf. den StartUpPath deiner Anwendung herausfinden.

Sieht ungefährt so aus.


System.Diagnostics.Process[] outlookProcesses = System.Diagnostics.Process.GetProcessesByName( "Outlook" );

string filename = outlookProcesses[0].MainModule.FileName;

Console.WriteLine(filename) => Ausgabe "C:\progra~1\micros~3\office12\outlook.exe"

Vielleicht kommt dieser Wert dem StartUpPath am nächsten.

10.11.2008 - 08:24 Uhr

Kann das Buch von Juval Lövy nur empfehlen.

Zur Komponentenorientieren Programmierung fallen mir noch die Artikel von Ralf Westphal in der dotnetpro ein. In seinen Blogs schreibt er auch häufig über KOP.

06.10.2008 - 08:32 Uhr

Mono 2.0 wurde released und die Homepage des Mono-Project zeigt sich in einem neuem Gewand.

Hier gehts zum Download:
http://www.go-mono.com/mono-downloads/download.html

Hier die Release Notes:
http://www.mono-project.com/Release_Notes_Mono_2.0

Hier der Mono Migration Analyzer:
http://mono-project.com/MoMA

19.09.2008 - 11:11 Uhr

Zum Team Foundation Server kann ich leider nichts sagen, aber wir setzen hier auf der Arbeit Subversion 1.5 ein und haben bisher gute Erfahrung gesammelt.

Als Clients nutzen wird TortoiseSvn ein, was sich wunderbar in den Explorer integriert.

Seit neuestem (etwa 2 Wochen) habe ich mir AnkhSvn 2.0 (http://ankhsvn.open.collab.net/) installiert, das sich als Source Control Provider in Visual Studio integriert.

Ich muss sagen, dass man mit AnkhSvn mittlerweile gut arbeiten kann, da es sich als SCP und nicht als Add-in in VS integriert. Ob es zuverlässig wird sich in nächster Zeit zeigen. Bisher gabs keine Probleme.

15.09.2008 - 08:33 Uhr

Soweit ich mich erinnere hat das nichts damit zu tun ob das .NET Framework NICHT installiert ist, sondern eher damit wenn mehrere Verisonen des .NET Framework installiert sind.

Ich glaube man kann das ungefähr so erklären:

In einem Prozess (also dem Explorer), kann immer nur eine CLR laufen. Läuft z. B. die 2.0 CLR bereits schon in dem Prozess und du führt deine Shell Extension aus, die eine andere Version der CLR benötigt, dann schmiert der ganze Prozess (Rechner) ab.

Kommerziell würde ich keine Shell Extension mit .NET entwickeln. Privat für sich selbst kann man das bestimmt machen, man sollte sich halt nur nicht wundern warum der Rechner auf einmal abstürzt.

Hier gibt ein paar Gründe, warum man keine Shell Extension mit .NET entwickeln sollte.
http://www.mastropaolo.com/2006/11/08/shell-extensions-in-c-andor-vbnet/

02.09.2008 - 09:03 Uhr

Nutz du .NET Events in deinem Observer Pattern.

Ich hatte mal ein vergleichbares Problem mit dem deregistrieren von nicht mehr erreichbaren EventHandlern.

In meiner Serverklasse, habe ich eine Methode definiert, die zum Feuern des jeweiligen Events (hier Changed) genutzt wird. Clients melden sich an diesem Event an.

In der Methode ThrowChangedEvent rufe ich jeden registrieren EventHandler einzeln auf und fange eine WebException ab. Anhand dieser Exception kann davon ausgegangen werden das der Client nicht mehr erreichbar ist, und dieser somit vom Event deregistriert werden kann.

Innerhalb des catch-Blocks rufe ich die Methode HandleError(sieh unten) auf, die das deregistrieren des EventHandlers vornimmt.


private void ThrowChangedEvent( EventArgs e ) {
  EventHandler changed = Changed;
  if ( changed != null ) {
    foreach ( EventHandler handler in changed.GetInvocationList() ) {
      try {
        handler( this, e );
      }
      catch ( System.Net.WebException webexce ) {						  
        HandleError( handler );
        Console.WriteLine( "Client not reachable." );
        Console.WriteLine( webexce.Message );
      }
    }
  }
}

In der Klasse habe ich ein Dictionary (_handlerWithError) definiert, in dem ich die EventHandler speicher, die eine WebException verursacht haben. Zu jedem EventHandler wird ein Integer gespeichert, der die Anzahl angibt, wie oft dieser EventHandler die WebException verursacht hat.

Die Methode HandleError prüft ob der EventHandler bereits 3x die WebException verursacht hat. Falls ja, wird der EventHandler beim Event (hier Changed) deregistriert. Ansonsten wird der Integer um eins hochgezählt und im Dictionary gespeichert.



private Dictionary<EventHandler, int> _handlerWithError;

private void HandleError( EventHandler handler ) {
  if ( _handlerWithError == null ) {
    _handlerWithError = new Dictionary<EventHandler, int>();
  }
  if ( _handlerWithError.ContainsKey( handler ) ) {
    int count = _handlerWithError[handler];
    count++;
    _handlerWithError[handler] = count;
    if ( count > 3 ) {
      _handlerWithError.Remove( handler );
      Changed -= handler;
      Console.WriteLine( "ClientHandler removed, cause its 3times not reachable." ); 
    }
  }
  else {
    _handlerWithError.Add( handler, 1 );
  }
}

Vielleicht hilft dir das bei deiner Problemstellung etwas weiter.

28.08.2008 - 12:20 Uhr

Machst du Unittest mit NUnit oder verwendet du das eingebaut Unittest-Framework von Microsoft?

Wenn du das von Microsoft verwendest, dann gibt es in jeder Solution eine Datei die "LocalTestRun.testrunconfig" heist. Wenn du diese öffnest erscheint ein Dialog in dem du deine Testläufe konfigurieren kannst.

Im Bereich "Deployment" kannst du Dateien angegeben, die bei jedem Testlauf in das jeweilige "Out"-Verzeichnis kopiert werden. (Setz voraus das du Deployment aktivierst)

Innerhalb deiner Unittest kannst du per Environment.CurrentDirectory auf das jeweilige Out-Verzeichnis zugreifen und dir über Path.Combine die Pfade zu den benötigten Datein zusammenbauen.

22.08.2008 - 08:51 Uhr

Du musst der MEthode Open des Exce.Application-Objektes den absoluten Pfad zur xls-Datei übergeben und nicht einen relativen.

13.08.2008 - 10:32 Uhr

Hallo zusammen,

gibt es in Visual Studio 2008 ein Window/Ansicht für die Debugsitzung, in der ich die aktuellen AppDomains angezeigt bekomme und ggf. die Assemblies die in die jeweilige AppDomain geladen sind?

Es gibt Sichten für Threads, Processes, Modules, usw. nur eine für AppDomains finde ich nicht.

23.07.2008 - 09:44 Uhr

Setz die Methode ServiceController.WaitForStatus() (http://msdn.microsoft.com/en-us/library/w52kaf2y.aspx) ein um solange zu warten bis der Service wirklich beendet, bzw. gestartet wurde.

05.06.2008 - 12:44 Uhr

Ich habe vor kurzem ein ähnliches Testprogramm geschrieben, mit dem ich Updates über den WebClient herunterladen. Ich hänge den Code mal an.


public partial class Form1 : Form {
		private WebClient client;

		public Form1() {
			InitializeComponent();

			client = new WebClient();
			client.DownloadFileCompleted += new AsyncCompletedEventHandler( client_DownloadFileCompleted );
			client.DownloadProgressChanged += new DownloadProgressChangedEventHandler( client_DownloadProgressChanged );
            client.DownloadFileAsync( "http://www.update.de/update.exe", @"C:\temp\update.exe" );
		}

		void client_DownloadProgressChanged( object sender, DownloadProgressChangedEventArgs e ) {
			progressBar1.Value = e.ProgressPercentage;
			label1.Text = e.BytesReceived + " / " + e.TotalBytesToReceive;
			label2.Text = e.ProgressPercentage + "%";
		}

		void client_DownloadFileCompleted( object sender, AsyncCompletedEventArgs e ) {
			DialogResult result = MessageBox.Show( "Update installieren?", "Update installieren", MessageBoxButtons.YesNo );

			if ( result == DialogResult.Yes ) {
				Process p = new Process();
				p.StartInfo = new ProcessStartInfo( @"C:\temp\update.exe" );
				p.Start();
			}
		}
}

Da der WebClient das Asynchronous-Pattern (vgl. dotnetpro 12/2007 oder http://msdn.microsoft.com/de-de/library/wewwczdw(VS.80).aspx) implementiert, vgl. BackgroundWorker, musst du keine Invoke-Aufrufe machen um die Progressbar anzusprechen. Dies wird direkt im GUI-Thread ausgeführt, wenn die WebClient-Instanz im GUI-Thread erstellt wurde.

In deinem Fall, so wie ich das sehe, musst du nur für jeden Download eine WebClient-Instanz und eine zugehörige Progressbar erstellen und die Progressbar über die Ereignisse des WebClient aktualisieren.

Vielleicht hilft dir das etwas weiter.

20.05.2008 - 08:38 Uhr

Hallo sprinter252,

ob du Schreib- oder Leserechte auf ein Verzeichnis oder Datei hast kannst du wirklich erst prüfen, wenn du auf die Ressource, z. B. mit dem Aufruf


DirectoryInfo dinfThis = new DirectoryInfo("D:\\Test\\Disallow\\");
int intCount = dinfThis.GetFiles().Length;

zugreifst. Soweit ich die CAS verstehe hat die erstmal nichts mit den Rechten zu tun die auf einem Betriebssystem eingestellt sind.

Mit Permissions kannst du nur deinen eigenen Code oder Komponenten von 3ten, den Zugriff auf bestimmte Ressourcen gewähren, verhindern oder beschränkt zulassen.

Hab mal versucht das an einem Beispiel deutlich zu machen.


class Program {
  static void Main( string[] args ) {
    string path = @"c:\temp";
    FileIOPermission permThis = new FileIOPermission(FileIOPermissionAccess.AllAccess, path );

    // Hier wird der Zugriff auf das Verzeichnis c:\Temp gewährt
    permThis.Demand();
    DirectoryInfo dinfThis = new DirectoryInfo( path );
    int intCount = dinfThis.GetFiles().Length;

    // Hier wird der Zugriff auf das Verzeichnis c:\Temp verhindert.
    permThis.Deny();
    try {
      dinfThis = new DirectoryInfo( path );
      intCount = dinfThis.GetFiles().Length;
    }
    catch ( SecurityException secexce ) {
        Console.WriteLine( secexce.Message );
	Console.WriteLine( secexce.StackTrace );
    }

    // Hier wird nur der lesende Zugrifff aus das Verzeichnis c:\Temp gewährt
    permThis = new FileIOPermission( FileIOPermissionAccess.Read, path );

    permThis.Demand();

    try {
      // Exception da versucht wird auf das Verzeichnis c:\temp schreibend zugegriffen wird.
      File.Create( Path.Combine( dinfThis.FullName,"test.temp" ));
    }
    catch ( SecurityException secexce ) {
	Console.WriteLine( secexce.Message );
	Console.WriteLine( secexce.StackTrace );
    }
  }
}

19.05.2008 - 07:27 Uhr

Ein gutes Programm dafür, was ich gerade selbst am ausprobieren bin, ist NDepend (http://www.ndepend.com).

Damit kann man wirklich hervorragend Abhängigkeiten von Assemblies und Typen untersuchen und eigent sich gut zur Code Analyse und Review. NDepend kostet zwar etwas Geld, aber man kann es auch in einer abgespeckten Studentenversion nutzen.

15.05.2008 - 15:00 Uhr

Also zur Dokumentation von Namespaces nutze ich den Sandcastle Helpfile Builder (http://www.codeplex.com/SHFB). Dieser bietet die Möglichkeit die Namespaces der Assemblies mit einem Text zu dokumentieren.

Direkt in der IDE ist das glaube ich nicht möglich. Zumindest wird keine Unterstützung bei "///" vor einem Namespace geboten.

14.05.2008 - 08:14 Uhr

Das Windows bietet eine Schnittstelle IFilter mit der du Texte aus Dateien (z. B. Pdf) extrahieren kannst (Google -> IFilter).

Von Adobe wird eine Implementierung der Schnittstelle für PDF-Dokumente angeboten (Adobe PDF IFilter v6.0, www.adobe.com/support/downloads/detail.jsp?ftpID=2611).

U. a. wird diese Schnittstelle von Lucene.NET (Volltextsuchmaschine) genutzt.

Damit kannst du die Texte aus Pdf Dokumenten auslesen und dann vergleichen.

08.04.2008 - 08:04 Uhr

Hallo honkman16,

vor einem ähnlichen Problem habe ich auch schon mal gestanden.
Das hatte aber mehr mit einem 64-Bit Windows Vista zu tun.

Soweit ich mich da erinnere, musst du die .NET-Anwendung als 32-Bit (x86) kompilieren. Das kannst du in den Projekteigenschaften->Build->Platform target einstellen.

Nach dem ich meine Anwendung so kompiliert hatte, konnte ich ohne Probleme auf die Registry zugreifen (Mit den gleichen Pfaden, ohne weitere Änderungen vorzunehmen). Das mappen in den Registry-Zweig übernimmt das Betriebssystem/CLR.

Vielleicht hilft die das etwas weiter.

21.03.2008 - 10:03 Uhr

Bin mir nicht ganz sicher, aber ich meine wenn du


info.CreateNoWindow = true;

setzt, dann musst du auch


info.UseShellExecute = true;

setzen, oder UseShellExecute gar nicht zu weisen (Standardwert ist true). Dann sollte das Fenster nich erscheinen.

20.03.2008 - 08:30 Uhr

Vielleicht ist auch Ranorex etwas für dich. Das ist ein Automatisierungswerkzeug für UI-Tests.

http://www.ranorex.com/

Hab das Programm selbst noch nicht ausprobiert. Bin durch Herrn Westphal (http://ralfw.blogspot.com/2008/03/mehr-warum-statt-wie-vom-wert-der.html) auf das Programm gestoßen.

22.02.2008 - 15:51 Uhr

Du must die Zuweisung in den Rumpf einer Methode oder des Konstruktors packen, sonst funktioniert das nicht.


public class Test {
  int[][] arr = new int[2][];
  
  // Konstruktor
  public Test() {
    arr[0] = new int[] {5,10,15,20,25,30};
    arr[1] = new int[] {1,2,3,4};
  }

}

11.01.2008 - 12:11 Uhr

Dll haben eigentlich selbst keine .config Datei. (Im Forum wurde das auch schon öfters diskutiert. ggf. findest du über die Suche entsprechende Beiträge, wo eine Lösung geboten wird.)

Da du ja selbst nur die DLLs erstellt muss es doch irgendwo eine .exe geben, die deine DLLs benutzt. Dort muss du dann in der .exe.config, die entsprechenden Einträge vornehmen.

10.01.2008 - 13:58 Uhr

Hallo Kentarion,

du kannst in der Konfigurationsdatei der Anwendung eine Versionsumleitung für eingebundene Assemblies angeben.

BEISPIEL AUS MSDN:


<configuration>
   <runtime>
      <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
         <dependentAssembly>
            <assemblyIdentity name="myAssembly"
                              publicKeyToken="32ab4ba45e0a69a1"
                              culture="neutral" />
            <bindingRedirect oldVersion="1.0.0.0"
                             newVersion="2.0.0.0"/>
            <codeBase version="2.0.0.0"
                      href="http://www.litwareinc.com/myAssembly.dll"/>
         </dependentAssembly>
      </assemblyBinding>
   </runtime>
</configuration>

Der Eintrag codebase ist nicht so wichtig. In der MSDN findest du genauere Informationen, wie du die Versionsumleitung einrichtest

05.12.2007 - 13:12 Uhr

Hallo,

mir ist gerade ein Problem über den Weg gelaufen, das bei der Verwendung der TreeView-Klasse des .NET Framework 2.0 auftritt.

Ich habe einen TreeView in dem sich ein paar Elemente befinden und ich das BeforeSelect-Ereignis des TreeView konsumieren. Innerhalb des BeforeSelect-EventHandlers lasse ich eine MessageBox mit einem beliebigen Text ausgeben.

Wenn ich das Programm starte (aus der Entwicklungsumgebung im Debug-Modus) und keine Node des TreeView selektiert (SelectedNode = null) ist und ich dann eine Node auswähle, so landet das Programm in einer Endlosschleife und die MessageBox, bzw. das BeforeSelect-Ereignis, wird immer wieder angezeigt/ausgelöst.


TreeView treeView1 = new TreeView();
treeView1.Nodes.Add("Test");
treeView.BeforeSelect += new EventHandler(treeView1_BeforeSelect);

private void treeView1_BeforeSelect( object sender, TreeViewCancelEventArgs e ) {
  DialogResult result = MessageBox.Show( "test" );
}

Wird die Eigenschaft SelectedNode des TreeView beim Programmstart auf eine Node festgelegt, so wird das BeforeSelect-Ereignis nur einmal ausgelöst.

Um das o. g. zu umgehen stellt jetzt für mich kein Problem dar. Mir ist nur daran gelegen zu erfahren

  • ob hier einen Bug im .NET Framework vorliegt,
  • das Verhalten der TreeView-Klasse so korrekt ist,
  • oder ich die TreeView-Klasse falsch anwende??

Ich hab im Forum gesucht und keine entsprechendes Thema gefunden. Als Entwicklungsumgebung setze ich Visual Studio 2008 Professional auf Windows Vista Enterprise ein.

Vielleicht hat jemand eine passende Antwort parat oder eine Quelle wo ich was zu diesem Thema nachlesen kann.

02.12.2007 - 19:42 Uhr

Ich rate mal so ins Blaue und denke das currentfile bei dir null ist und der Aufruf

fiExt = fiExt.ToUpper();

zu der NullReferenceException führt.

27.08.2007 - 15:45 Uhr

Hallo zusammen,

ich hab ne Frage zu ILMerge.

Ich hab zwei kleine Assemblies, die nicht viel enthalten (Größe 16 KB) und mittels ILMerge zu einer einzelnen Assembly gemergt. (.pdb gemergt und signiert)

Soweit alles kein Problem. Jetzt ist mir nur aufgefallen dass die neue Assembly nur noch 6 KB groß ist.

Ich hatte eigentlich gedacht das die mindestens auch 16 KB oder max. 32 KB groß wird.

Filtert IL-Merge Daten raus? Ist das normal das die gemergte Assembly relativ kleiner ist?

Vielleicht kann mir da jemand eine Antwort geben.

Grüße Jens

30.07.2007 - 09:34 Uhr

Tach zusammen,
hab mal ein kurze Frage
Unter Windows Vista wird im Explorer, wenn ich mir die Eigenschaften einer DLL oder Exe (.NET) anzeigen lasse, keine Assembly Version unter Details angezeigt.

Muss ich das irgendwo explizit einstellen, dass diese angezeigt wird?
Muss ich beim kompilieren der DLL/EXE spezielle Parameter setzen, damit diese unter Eigenschaften angezeigt wird?

Windows XP ist das ja kein Problem, dort wird ja unter den Eigenschaften unter Version die Assembly Version angezeigt!!

Vielleicht hat ja jemand eine Antwort parat.

Gruß

Jens

05.07.2007 - 09:17 Uhr

Ruf mal in der Commadozeile

devenv /installvstemplates

auf. Das installiert die ganzen Vorlagen für Projekte und Dateien.

Für den Aufruf musst du ins VisualStudio-Verzeichnis wechseln, bei mir ist das "C:\Programme\Microsoft Visual Studio 8\Common7\IDE", oder den Pfad in den Umgebungsvariablen setzen

05.07.2007 - 09:06 Uhr

Hallo Dwaynor,

hast du schon eine Lösung für dein Problem gefunden? Vielleicht kannst du etwas Code spendieren um deine Lösung zu zeigen oder eine zu finden Bin daran interessiert, wie du das gelöst hast.

Mir fällt da momentan auch keine bessere Lösung ein.
Außer dass man vielleicht eine eigene Permission (IPermission) implementiert, welche die Überprüfung durchführt.

Lädst du eigentlich das Addin in eine eigene AppDomain?
Ich denke, dass wenn du in einer anderen AppDomain, außer der DefaultAppDomain, also der in der das Programm gestartet wurde, GetEntryAssembly() aufrufst immer null zurück liefert wird, da diese AppDomain keine EntryAssembly hat!

Steckt die Funktionalität der Überprüfung in einer eigenen Assembly(DLL)?

Die ganzen GetxxxAssembly() finde ich etwas verwirrend vom Namen her, deshalb hiermal ein kleines Szenario um zu bestimmen, welche Methode welche Assembly liefert und wie ich das ganze verstanden habe.

Wir haben 3 Assemblies (A, B, C). Mit Assembly A wird das Programm gestartet. Assembly B enthält etwas Programmlogik und Assembly C
enthält die Überprüfung des PublicKeys und ruft auch die GetxxxAssemby()-Methoden auf.

Dann liefert der Aufruf in C der Methode

  • GetEntryAssembly() --> die Assembly A, wegen Startpunkt der Anwendung (Main-Methode)
  • GetCallingAssembly() --> die direkte vorgänger Assembly, d. h. wenn Assembly B, die Methode in Assembly C aufruft, dann wird Assembly B zurück gegeben. Ruft Assembly A die Methode in Assembly C auf, dann wird Assembly A zurückgegeben.
  • GetExecutingAssembly() --> die Assembly C, weil dort die Methode zur Überprüfung deklariert ist und dort ausgeführt wird.

Vielleicht hilft dir das ganze etwas weiter.

Gruß

parsifal

04.07.2007 - 13:52 Uhr

Hallo Fabian,

soweit ich mich erinnere müssen Typen die du in eine andere AppDomain lädst und dann verwendet möchstet von MarshalByRefObject erben. Da bin ich mir aber nicht ganz sicher.

Ansonsten musst du


domain.CreateInstanceFromAndUnwrap();

aufrufen und dann in deinen entsprechenden Typ casten.

Bei


domain.CreateInstance()

bekommst du nur einen ObjectHandle geliefert. Über diesen kannst du dann aber UnWrap aufrufen und dann in den entsprechenden Typ casten.

04.07.2007 - 12:59 Uhr

Hallo Dwaynor,


Assembly ass = Assembly.GetEntryAssembly();

gibt dir die Assembly zurück, die in dem Prozess als erstes geladen wurde. Im Grunde ist das bei einer .exe (.NET-Anwendung), die Assembly in der die Main-Methode steht.

Jetzt ist die Frage, in was für einem Programm dein Add-in läuft??
Ich nehme jetzt einfach mal an, das wenn das Programm keine .NET-Anwendung ist, GetEntryAssembly() null zurück gibt.

Ich denke in deinem Fall musst du


Assembly ass = Assembly.GetCallingAssembly();

aufrufen. Dann solltest du die Assembly erhalten, die das Add-in enthält.

Ich verstehe allerdings noch nicht so ganz, wofür du die Überprüfung mit dem StrongName und dem PublicKeyToken brauchst?

29.06.2007 - 08:48 Uhr

Hallo ganymedes,

laut Doku des FileSystemWatcher (FSW) reicht das Setzen von


myWatcher.EnableRaisingEvents = false;

um dem FSW zu stoppen und das Auslösen der Events zu unterbinden.

Was zu noch machen kannst ist, zu einem die EventHandler die zu registriert hast, wieder zu deregistrieren, und zum anderen


myWatcher.Dispose();

aufzurufen.

Hier noch etwas Text den ich in der Doku gefunden habe.

Die Komponente löst keine Ereignisse aus, solange EnableRaisingEvents nicht auf **true **festgelegt wird.

Hinweis
Die Komponente überwacht das angegebene Verzeichnis erst, wenn die Path-Eigenschaft festgelegt wurde und EnableRaisingEvents den Wert **true **hat.

Auch wenn diese Eigenschaft auf **false **festgelegt ist, können mithilfe der WaitForChanged-Methode Ereignishandler aufgerufen werden, die auf Dateiänderungen reagieren.

21.06.2007 - 23:23 Uhr

Hallo kingBob,

in die Anwendungsschicht kommt die Logik rein, welche die Verzeichnisse nach Assemblies durchsucht. Die gefundenen Assemblies, bzw. die Typen stellt die Anwendungsschicht über eine Property (Eigenschaft) oder Methode zur Verfügung.


public Assembly[] FoundAssemblies{
    get{
        return _foundAssemblies;
    }
}

Die Gui ruft die Anwendungsschicht auf und über die Property die gefundenen Assemblies, bzw. Typen ab. Die Gui baut die Items für die Toolbar zusammen.

Wenn du das so trennst, dann braucht die Anwendungsschicht nichts von der GUI zu wissen, sondern nur die GUI kennt die Anwendungsschicht.

25.05.2007 - 13:11 Uhr

Hallo JAck30lena,

ich hab mal einen Artikel in der dotnetpro gelesen, wie mann Flash in eigenen WindowsForms Anwendung verwenden kann. Vielleicht hiflt dir das weiter.

Dazu musst du das COM-Steuerelement Shockwave Flash Object in die Toolbox von VisualStudio hinzufügen.

Mit diesem kannst du dann ein WebControl Shockwave-Flash auf deiner Form ablegen.

Um eine Flash-Animation abzuspielen musst du


string movie = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
movie += @”\flashmovie.swf”; //Dateiname der Flashanimation
axShockwaveFlash1.LoadMovie(0, movie);
axShockwaveFlash1.Play();

einfügen. axShockwaveFlash1 ist dabei der Name des Controls.

Das Control bietet einige Ereignisse (FSCommand) an, über das du die Flash-Animation steuern kannst.

16.05.2007 - 12:24 Uhr

Hallo Thask,

ich persönlich kenne keine Programme die das machen. Aber du kannst dir
selbst solch ein Programm schreiben, indem du über die Images der ImageList iterierst und diese dann abspeicherst.


foreach(Image img in MyImageList.Images)
{
    img.Save(<<Hier Pfad + Name eintragen unter dem das Image gespeichert werden soll>>);
}

Vielleicht hilft dir diese Lösung etwas weiter.

10.05.2007 - 12:11 Uhr

Hallo Bitworm,

ja sowas gibt es auch in C#.

Schlagworte dazu sind zum einen Statische Klassen (static) und das Entwurfsmuster (Design Pattern) Singleton.

10.05.2007 - 11:58 Uhr

Hallo SecondSun,

eine kleine Empfehlung um dir die ganzen Try-Catch-Blöcke zu sparen. Verwende die Methode bool Decimal.TryParse (String, out Decimal).

Der Rückgabewert sagt dir ob das parsen funktioniert hat und über den out-Parameter erhälst du den geparsten Decimalwert, wenn das parsen erfolgreich war.

09.05.2007 - 12:15 Uhr

Hallo Esher,

Oder muss ich die Implementierung fpr den Client noch anders kenntlich machen?

Nein einen Verweis auf die Assembly zu legen, in der die Exception enthalten ist reicht aus.

Zweite Frage, wie gehe ich nun mit der Methode ISerializable.GetObjectData ...

evtl. kannst du die ISerializable-Schnittstelle weglassen, da ApplicationException von Exception abgeleitet ist, und diese sowieso die ISerializable-Schnittstelle implementiert.

Ansonsten kann du die Methode ISerializable.GetObjectData an die base weiterleiten


void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
{            
    base.GetObjectData(info,context);
}

oder aber die ISerializable.GetObjectData-Methode komplett weglassen (dann wird eh die base-Methode aufgerufen.

Was ich vorher auch noch vergessen hatte zu erwähnen: Die Klasse greift auch auf ein Enum zu, welches sich in der selben Datei befindet wie die Klasse. Hat das noch Auswirkungen?

Solang der Client die Enum kennt, stellt das kein Problem beim Serialisieren dar.

09.05.2007 - 11:49 Uhr

Hallo Esher,

zunächst solltest du eigene Exceptions nicht von System.Exception sondern von ApplicationException.

Desweiteren muss die Exception mit dem Attribut [Serializable()] gekennzeichnet sein und das Interface ISerializable implementieren.

Zusätzlich muss der Client die Implementierung der eigenen Exception kennen, sonst kann er diese nich deserialisieren.

Hier etwas Beispiel-Code wie die Exception aussehen kann.


[Serializable()]
public class ServerException : ApplicationException, ISerializable {

    public ServerException ( string message ) : base(message){}

    public ServerException ( string message, Exception innerException )
        : base( message, innerException ) {
    }

    protected ServerException ( SerializationInfo info, StreamingContext context )
        : base( info, context ) {
    }
}

Hoffe ich konnte dir etwas helfen.

08.05.2007 - 11:52 Uhr

hallo decay,

du musst bei dem Objekt, welches du per Remoting (von MarshalByRefObject) nutzt, die Methode InitializeLifetimeService überschreiben


public override object InitializeLifetimeService () {
    return null;
}

Return null hat den Effekt, dass das Objekt während der gesamten Lebenszeit des Servers aktiv (am leben) bleibt.

04.05.2007 - 11:32 Uhr

Hallo DevHB,

Doch wenn ich nun mit dem DBAdapter auf die Datenbank (SqlExpress) zugreifen will,
dann scheitert es an dem Auslesen der App.Config in der "ConnectionString Section".
Auslesen sieht folgendermaßen aus:

Hast du die "ConnectionString Section" in der .Config der Host-Applikation stehen? Oder in der von dir erwähnten "DBAdapter.config" die du im Testprojekt verwendest.

Da du in deinem Code den "ConfigurationManager" verwendest, müssen die Einstellungen in der .config der Host-Applikation (z. B. MeineApplikation.exe.config) stehen.


ConnectionStringSettings setting = ConfigurationManager.ConnectionStrings["ConnectionString"];

Der ConfigurationManager greift auf Einstellungen der aktuellen Anwendung zu, d. h. die Anwendung, bzw. .exe die gestartet wurde.

Ich weis ja nicht wo du die Einstellungen für das Mapping des Microkernel ablegst. (Extra XML-Datei oder app.config der Host-Anwendung). Normalerweise werden diese in der app.config der Host-Anwendung abgelegt und der Microkernel liest diese per eigenem ConfigSectionHandler aus. Genauso müsste das eigentlich mit den Einstellungen für die "ConnectionStrings" auch geschehen, nur das du keinen eigenen SectionHandler benötigst.

BTW:
Hier noch ein Link zu dem Microkernel von Ralf Westphal http://weblogs.asp.net/ralfw/archive/2006/08/02/Dynamic-component-binding-made-easier-2D00-An-easy-to-use-Microkernel-to-help-reap-Contract_2D00_First_2D00_Design-benefits-in-.NET-programs.aspx

Dort gibt es nochmal einen guten Überblick über Microkernel und CFD. Desweiteren kannst du dir den Quellcode zu Ralfs Microkernel runterladen.

30.04.2007 - 17:16 Uhr

Hallo tequila slammer,

Die Klassen die du verwenden möchtest, sind wahrscheinlich nicht als public deklariert.


public class MeineKlasse

30.04.2007 - 11:30 Uhr

Hallo AtzeX,
hast du die externe Komponente selbst entwickelt?? Oder ist das eine 3rd Party Komponente?

Ansonsten, solltest du die beiden Typen "EkTyp1" und "EkTyp2" aus der "EK.dll" mit in die Interface-Assembly packen. Dann sparst du dir das einbinden der "EK.dll".

30.04.2007 - 08:28 Uhr

Hallo cow_weasel

du musst bei der Initialisierung deiner Backgroundworker angeben, das diese einen "ReportProgress" melden. Dazu musst du


ServerTesten.WorkerReportsProgress = true;

setzen.

Möchtest du die Worker abbrechen können, musst du


ServerTesten.WorkerSupportsCancellation = true;

Prinzipiell kannst du mehrere BackgroundWorker verwenden, die Beschränkung wieviele gleichzeitig arbeiten wird durch den ThreadPool bestimmt (müssten so 25 sein).

Diese können auch die gleichen Event-Methoden nutzen.

26.04.2007 - 15:11 Uhr

Danke Rainbird für deine Antwort

Die hat mich auf die richtige Spur gebracht. Allerdings wollte ich auf Serverseite ungern den Namespace System.Drawing (bzw. die Dll einbinden) öffnen um ein Icon-Objekt zu verwenden, da ich den Namespace dort nicht benötige.

Auf Serverseite lese ich die Icon-Datei mit einem BinaryReader in ein byte[] ein und übertrage dieses an den Client.
Der Client erstellt mit dem byte[] einen MemoryStream und übergibt diesen an den Kontruktor des Icon-Objekts.

Das wars. Somit gelöst/erledigt.

Anbei noch der Code:

Server-Code


public byte[] GetIconFile ( string iconfile ) {
    lock(getIconLock) {
        System.IO.Stream ic = System.IO.File.OpenRead( iconfile )

        BinaryReader reader = new BinaryReader( ic );
        byte[] b = reader.ReadBytes( Convert.ToInt32( ic.Length ) );
        reader.Close();
    }
    return b;
}

Client-Code


private void GetIconFiles () {
    string[] iconFiles = Server.GetIconFiles();
    ImageList icons = new ImageList();

    for (int i = 0; i < iconFiles.Length; i++) {
        try {
            byte[] iconBytes = Server.GetIconFile(  iconFiles[i] );
            System.IO.MemoryStream( iconBytes );
            Icon ico = new Icon( memStream );
            icons.Images.Add( format.Extension, ico );
        }
        catch (Exception exce) {
            Console.WriteLine(exce.Message);
        }
    }
}

20.04.2007 - 10:15 Uhr

Hallo,
ich arbeite zur Zeit an einer Client-/Server-Anwendung mit .NET-Remoting. In Zuge der Entwicklung ist es notwendig das auf Serverseite mehrere Icon-Dateien verwaltet werden und diese für alle Clients zur Verfügung gestellt werden.
Die Clients fordern die Icon-Dateien beim Server über die Methode GetIconFile an und bekommen einen Stream zurück, mit dem sie das Icon-Objekt erstellen können und in einer ImageList ablegen. Die ImageList wird an ListViews und TreeViews gebunden.

Hier erstmal der notwendige Code dazu:

Server-Code


public System.IO.Stream GetIconFile ( string iconFile ) {
    if (string.IsNullOrEmpty( iconFile )) { throw new ArgumentNullException( "iconFile", "May not be null or empty" ); }
    if (string.IsNullOrEmpty( _iconFolder )) { throw new InvalidOperationException( "IconFolder not set" ); }

    string fullFile = Path.Combine( _iconFolder, iconFile );
    if (File.Exists( fullFile )) {
        return System.IO.File.OpenRead( fullFile );
    }
    else {
        throw new InvalidOperationException("Icon-File not found");
    }
}

_iconFolder ist eine Klassenvariable die den Pfad zu dem Verzeichnis speichert, in dem die Icon-Datien liegen.

Client-Code


private void GetIconFiles () {
    string[] iconFiles = Server.GetIconFiles();
    ImageList icons = new ImageList();

    for (int i = 0; i < iconFiles.Length; i++) {
        try {
            System.IO.Stream sr = Server.GetIconFile( format.IconFile );
            Icon icon = new Icon( sr );
            icons.Images.Add( iconFiles[i], icon );
            sr.Dispose();
        }
        catch (Exception exce) {
            Console.WriteLine(exce.Message);
        }
    }
}

Die Methode Server.GetIconFiles() liefert ein string[] zurück, mit den Dateinamen der verfügbaren Icon-Dateien.

Die ganze Vorgehensweise klappt bisher wunderbar. Nur meine Frage in diesem Fall ist, ob dass die richtige Vorgehensweise ist, um die Icon-Dateien zu übertragen.

  • Evtl. könnte der Stream durch den Client nicht geschlossen werden!!
  • Zwei Clients fordern die gleiche Icon-Datei zur selben Zeit an!! (Was passiert dann??)

Hat jemand schonmal etwas vergleichbares programmiert, und wenn ja, wie gelöst?

Vielen Dank schonmal im Voraus.

Entwicklungsumgebung : VisualStudio 2005 Prof.
Framework-Version : 2.0