Hallo obi111,
ja grundsätzlich schon. Das UserControl im anderen Prozess würde dann via CoreRemoting ferngesteuert.
Der ferngesteuerte Prozess (in dem das UserControl eigentlich lebt) wäre der Server, der andere Prozess der Client.
CoreRemoting kommuniziert standardmäßig über Websockets.
Das heißt, dass der Server-Prozess einen festen TCP-Port belegt.
Auf einem normalen Windows PC sollte das kein Problem sein.
Auf einer Remotedesktopserver (RDS) sieht das allerdings anders aus.
Da würden ja dann mehrere Instanzen der Prozesse laufen (1 pro User, der die Anwendung geöffnet hat). Jeder Instanz des Servers brauchte einen eigenen TCP-Port.
Auf einem RDS Server würde es deshalb nicht funktionieren.
Es sei denn, man implementiert einen CoreRemoting-Kommunikationskanal, der keine TCP-Ports braucht.
Also eine zusätzliche Implementierung für IServerChannel und IClientChannel schreiben. Z.B. mit dem Named Pipes-Protokoll.
Bei CoreRemoting bestimmt nicht die Abstammung einer Klasse, ob sie aus der Ferne aufrufbar ist.
Stattdessen werden Klassen serverseitig als Services registriert.
Einzige Voraussetzung dafür ist, dass sie eine Schnittstelle implementieren, welche in einer gemeinsamen Assembly definiert ist, welche sowohl dem Server als auch dem Client bekannt ist.
**.NET Remoting **ist leider nicht mehr in .NET Core bzw. .NET 5 enthalten.
Microsoft verweist auf gRPC und WebAPI als Alternative.
Wer eine größere Codebasis hat, die auf .NET Remoting aufgebaut ist, für den bedeutet das trotzdem große Teile der Applikation komplett neu zu schreiben,
wenn die Anwendung auf .NET 5 zum Laufen gebracht werden soll.
Für solche Migrationsszenarien und auch für alle, die vom Solgan "Embrace HTTP" nicht ganz so begeistert sind, möchte ich mit dem neuen Projekt CoreRemoting eine Alternative anbieten. CoreRemoting ist kein 1:1 .NET Remoting-Nachbau und auch vom Netzwerkprotokoll her nicht binär-kompatibel, aber die API ist so ähnlich, dass sich Client/Server-Anwendung mit geringem Aufwand migrieren lassen.
Da CoreRemoting mit moderner Technologie und nach modernen Entwurfsmustern gebaut ist, eignet es sich natürlich auch für neue Projekte und nicht nur für Migrationsszenarien. Allerdings nur in reinen .NET-Anwendungen. CoreRemoting ist für möglichst komfortable entfernte Methodenaufrufe von .NET zu .NET. Man kann damit keine REST-Server für Javascript-Clients bauen. Wer das möchte, sollte lieber WebAPI verwenden. In Blazor Server-Anwendungen funktioniert CoreRemoting aber auch (falls man doch einmal einen Webclient braucht).
CoreRemoting wird als .NET Standard 2.0 Assembly kompiliert und lässt sich deshalb sowohl in .NET Framework 4.x als auch in .NET Core / .NET 5 Umgebungen gleichermaßen nutzen. Es läuft auf jeden Fall unter Windows und Linux. Mac sollte auch gehen, aber da ich selbst keinen Mac habe, konnte ich es da leider noch nicht testen.
Die Netzwerkkommunikation läuft über Websockets.
Für die nötige Sicherheit der Netzwerkaufrufe sorgt die integrierte Verschlüsselung und Nachrichtensignierung mit RSA und AES.
Eine Authentifizierungsschrittstelle ist ebenfalls eingebaut.
Für Authentifizierung mit Benutzername und Passwort gegen lokale Betriebssystembenutzer (Windows / Linux wird automatisch erkannt) gibt es bereits einen fertigen Authentifizierungsanbieter: https://www.nuget.org/packages/CoreRemoting.Authentication.GenericOsAuthProvider/
Zur Serialisierung der Aufrufe kommt standardmäßig BSON (Binary JSON) zum Einsatz. Alternativ kann auch der klassische BinaryFormatter verwendet werden, um die größt mögliche Kompatibilität zum klassischen .NET Remoting zu erreichen.
Netzwerktransportschicht, Serialisierer und Authentifizierung sind austauschbar (auch gegen Eigenkreationen).
Der Quellcode steht unter MIT Lizenz und ist auf GitHub verfügbar: https://github.com/theRainbird/CoreRemoting
Ein NuGet-Paket gibt es natürlich auch: https://www.nuget.org/packages/CoreRemoting/
Quellcode für eine einfache Hello World-Client/Server-Anwendung findet ihr hier: https://github.com/theRainbird/CoreRemoting/tree/master/Examples/HelloWorld
Eine Dokumentation und einen Migrations-Guide für .NET Remoting bin ich gerade am schreiben: theRainbird/CoreRemoting
Die Migration kann man sich aber bereits jetzt in Form einer kleinen Beispielanwendung ansehen, welche im Original mit .NET Remoting implementiert ist und in einer zweiten Version auf CoreRemoting migriert wurde: theRainbird/CoreRemoting
Ich hoffe das Projekt ist für den einen oder anderen nützlich und beschert vielleicht einem altgedienten .NET Remoting Projekt ein zweites Leben unter .NET 5.
Falls ihr Bugs findet, meldet diese bitte über die GitHUb-Projektseite direkt: theRainbird/CoreRemoting
Viel Spaß mit CoreRemoting.
@Abt
Das Egoismus-Argument ist - finde ich - eine Killerphrase, weil man dagegen praktisch nichts mehr einwenden kann.
Das Egoismus-Argument kommt auch beim Klimaschutz. Ich muss mir z.B. von manchen anhören, dass ich egoistisch bin, weil ich Fleisch esse, ein Auto mit Benzin-Motor fahre und unnötigerweise einen Hund halte, der eine schlechte CO²-Bilanz hat. Ich würde mit meinem Egoismus den zukünftigen Generationen die Lebensgrundlage entziehen.
Beim Rassismus ist es genauso. Es wird unterstellt, dass Menschen, die nicht weiss sind, leiden müssen und benachteiligt werden, weil ich so egoistisch bin.
Wenn wir diese Debatte führen, kommen wir irgendwann an den Punkt, wo man verbindlich festlegen muss, was noch okay ist und ab wann es widerlich egoistisch wird. Und dann ist die Frage, wer darüber entscheidet.
Ich habe intensiv darüber nachgedacht, warum es auch mir persönlich so schwer fällt, eine Umbenennung von master/slave einfach so zu akzeptieren.
Für mich fühlt sich das irgendwie erzwungen an.
Ich weiss, dass es gut gemeint und eigentlich auch richtig ist, aber dieses "Gute" wird irgendwie von außen "verordnet".
Bei anderen Themen habe ich das selbe Gefühl. Z.B. beim Essen, also die Fleisch / kein Fleisch Geschichte, beim Gendering oder bei allem was mit dem Thema Klima zu tun hat. Dieses "Aufgezwungene" erzeugt bei mir den Widerstand (oder ist es Trotz?) dagegen.
Es fühlt sich für mich teilweise an, wie im Film "Demolition Man".
Hallo Stefan,
im DuplexChannel, der unter der Haube verwendet wird, ist leider kein Timeout definiert. Deshalb bietet auch das entsprechende ProtocolSetup keine Property dafür an.
Man müsste in die Zyan.Communication.Protocols.Tcp.DuplexChannel.Connection-Klasse einen einstellbaren Timeout einbauen. In dieser Klasse wird der Socket erzeugt, über den die Netzwerkkommunikation läuft. Die Socket-Klasse hat die Eigenschaften SendTimeout und ReceiveTimeout. Die müssen praktisch nur "durchgeschleift" werden.
Ich kann das gerne einbauen. Kann aber ein paar Tage dauern, bis ich dazu komme.
Beste Grüße
Rainbird
Hallo Stefan,
welches Protocol Binding verwendest Du?
Beste Grüße
Rainbird
Hallo GigaMann,
das geht auch mit Katana. Das ist die Microsoft-Implementierung der OWIN-Schnittstelle.
Damit kann man sich einen eigenen Webserver basteln.
schau mal hier:
ASP.NET self hosting mit Katana
Gruß
Rainbird
Hallo nickname8,
Dokumentation zu Zyan findest Du hier: Zyan Dokumentation (deutsch)
Code-Beispiele findest Du hier: Codeplex: Zyan Code-Beispiele (Examples)
Nun zu Deinem Probelm. Sowohl Tasse als auch Schrank sind auf einem Zyan-Server veröffentlichte Remote-Komponenten. Du versuchst, einen clientseitigen Verweis auf die entfernte Komponente Tasse an die entfernte Komponente Schrank zu übergeben. Das wird so nicht unterstützt.
Zyan trennt strikt zwischen Client und Server. Der Server bietet Funktionalität an, der Client konsumiert sie. Wenn Client und Server Daten austauschen, dann muss dies über Typen gemacht werden, die serialisierbar sind (Also alle Typen, die ISerializable implementieren oder mit [Serializable] gekennzeichnet sind, und primitive Typen wie int, string, byte, etc.)
Es gibt deshalb grundsätzlich zwei Kategorien von Klassen:*Komponenten, die Funktionalität anbieten *Datenklassen, welche zum verseden von Daten übers Netzwerk eingesetzt werden
Damit Dein Beispiel funktioniert, müsste Tasse eine serialisierbare Datenklasse sein und NICHT als Remote-Komponente am Zyan-Server veröffentlicht werden. Es könnte z.B. eine Komponente "TassenFabrik" geben, welche Tassen produziert und die fertigen Tassen als Datenklassen zurückgibt. Die kann man dann mit proxySchrank.StelleRein(datenTasse) auch an den entfernten Schrank schicken.
Hallo Stefan,
klingt so, als würde ein asynchroner Callback vom Zyan Server versuchen auf GUI Objekte zuzugreifen. Zugriffe auf GUI Objekte dürfen nur im GUI Thread erfolgen. Du musst im Callback auf den GUI Thread umleiten. Unter Windows.Forms ist dafür Invoke/InvokeRequired das Stichwort. In WPF gibt es auch etwas Vergleichbares, weiss es nur gerade nicht auswendig.
Gruß Rainbird
Hallo Zusammen,
Zyan 2.6 ist da!
Die neue Version bringt folgende Neuerungen mit:
*Unterstützung für Android (in Verbindung mit Xamarin Mono for Android!); Bereits ab Zyan 2.5
*Automatische Ermittlung laufender ZyanComponentHost-Instanzen im LAN (#2085)
*Registrieren und Deregistrieren von Ereignishandlern erfolgt nun standardmäßig nebenläufig (#2308):
*Unterstützung für Synchronisierungskontext für Callbacks und Ereignisse (#1827):
*Wiederverbinden von entfernten Ereignissen wird nun mittels schneller Stapelverarbeitung durchgeführt (statt durch Einzelaufrufe in einer Schleife) (#2309) *Neues Ereignis: ZyanComponentHost.ClientLogonCanceled (bei Anmeldungsabbruch) (#2318) *Neue Eigenschaft: AuthRequestMessage.ClientAddress (enthält die IP-Adresse des Clients) *Unterstützung für AuthorizedGroup und ExclusiveAddressUse Einstellungen für IPC Protokoll-Setups (#2345) *Unterstützung für .NET Framework v4.5/4.5.1 (#2295) *Neues Beispiel Projekt: Zyan Drench, ein Spiel für Android, 50K+ Downloads bei Google Play
Detaillierte Liste der behobenen Bugs: https://zyan.codeplex.com/releases/view/110163
Auf diesen Wegen könnt ihr die neue Version 2.6 ziehen:*Zyan Homepage *Zyan NuGet Paket *Zyan 2.6 Binary Download Seite *Zyan Source Code Seite *Zyan SVN Repository
Bugs könnt ihr wie immer auf CodePlex im Issue Tracker melden.
Hallo elTorito,
Wie implementiere ich das mit dem Zyan?
Es gibt folgende Möglichkeiten:*Gepufferte Übertragung von Dateien komplett als byte[] *Gepufferte Übetragung von Dateien in Segmenten als byte[] *Streaming mit herkömmlichen .NET Streams
Für große Dateien (mehrere Megabyte) sind Streams zu empfehlen. Für kleine Dateien gepufferte Übertragung als byte[].
Die Stream-Lösung hat allerdings den Nachteil, dass der Server statuswahrend implementiert sein muss. Außerdem steuert der Client dabei eine serverseitige Stream-Instanz fern, was dem Server ein Stück weit die Kontrolle entzieht. Wenn das nicht gewünscht ist, ist die gepufferte segmentierte Variante eine Alternative. Aber auch die verlangt statuswahrende Implementierung, da die einzelnen Segmente über mehrere Methodenaufrufe hinweg übertragen werden.
Schau Dir folgenden Testcode am, um zu verstehen, wie Streams mittels Zyan übertragen werden können: Streaming mit Zyan
Die Varianten mit byte[] werden so implementiert:*Datei mittels Stream in ein byte[] einlesen *byte[] ganz normal als Methodenparameter oder Property an den Server senden *Dateiname ebenfalls als Methodenparameter mitgeben *Serverseitig das byte[] in einen FileStream auf die Serverplatte schreiben, oder in eine DB, oder sonst wohin.
Bei der segmentierten Variante wird einfach nicht die komplette Datei auf einen Rutsch übertragen, sondern kleinere Batzen (auch Chunks genannt). So kann der Server bereits bei Erhalt des ersten Bytehaufenbatzen mit dem schreiben auf Platte beginnen (ganz ähnlich wie bei der Strwam-Lösung), was bei großen Dateien, wie z.B. Videos, ein großer Zeitvorteill ist.
Hab da was gelesen von
> ist das der richtige Ansatz?
Nein, NegotiateStream würdest Du verwenden, wenn Du Dich auf Socketebene bewegst.
Gruß
Rainbird
Hallo alanblack,
meine Antwort kommt zwar spät, aber vielleicht ist sie ja trotzdem noch für Dich nützlich. Ich habe eine Beispiel-Applikation geschrieben, wie man einzelne Clients mit Hilfe von Zyan benachrichtigen kann.
Du findest es im aktuellen Zyan Code Repository auf zyan.codeplex.com.
Es liet im Ordner examples und heißt Zyan.Examples.WhisperChat.
Hier hatte jemand ein ähnliches Problem: http://zyan.codeplex.com/discussions/430015
Gruß
Rainbird
Hallo TheBrainiac,
der Bug ist nun ab ChangeSet 27989 behoben. Ab Zyan Version 2.4 wurde das Event Handling standardmäßig auf asynchrone Verarbeitung umgestellt. Bis Zyan 2.3 wurden Ereignisse synchron verarbeitet und verhielten sich damit wie lokale Ereignisse. Im Enterprise-Umfeld ist das aber nicht die bevorzugte Methode. Das MiniChat Beispiel wurde aber mit der urspsprünglichen synchronen Ereignisverarbeitung entwickelt.
Bei Verwendung von Zyan 2.4 oder höher muss die synchrone Ereignisverarbeitung explizit eingeschaltet werden. Dies wurde im MiniChat Beispielcode einfach vergessen.
Die synchrone Verarbeitung muss serverseitig mit folgender Zeile eingeschaltet werden:
ZyanComponentHost.LegacyBlockingEvents = true;
Damit läuft das MiniChat Beispiel wieder einwandfrei.
Hallo TheBrainiac,
ich konnte Dein Problem reproduzieren. Es handelt sich offensichtlich um einen Bug in Zyan 2.4. Ich habe den Bug im Issue Tracking System erfasst. Hier kannst Du den Status dieses Bugs verfolgen: http://zyan.codeplex.com/workitem/1852
Bitte entschuldige die Unannehmlichkeiten.
Danke dass Du das Problem gleich im Forum gemeldet hast.
Gruß
Rainbird
Hallo malignate,
das sind ganz spezifische Anforderungen. Die wird in dieser Zusammenstellung wohl außer Dir niemand genau so haben. Wenn Du eine fertige Library einsetzt, musst Du Dich an deren Funktionalität anpassen.
Wenn das nicht geht, wirst Du wohl selber einen passenden XSD Code Generator schreiben müssen, der genau das kann. Mit CodeDOM ist das reine Fleißarbeit.
Gruß
Rainbird
Hallo WiglWagl,
ich glaube, was Du suchst, findest Du hier: MSDN: Gewusst wie: Sicherstellen, dass benutzerdefinierte Elementeigenschaften in Abfragen auf Ordnerebene unterstützt werden
Gruß
Rainbird
Hallo astra,
das NetOffice-Projekt könnte für Dich interessant sein: http://netoffice.codeplex.com/
Gruß
Rainbird
Hallo Andreas,
Du schreibst ein Add-In für Excel. Warum verwendest Du nicht einfach die in Excel bereits vorhandenen Diagramm-Features?
Die kann man standardmäßig in Word als OLE-Objekt einfügen.
Wenn Du das selbst implementieren willst, wirst Du vermutlich Monate dafür brauchen. Du musst dazu einen eigenen COM-Server schreiben und dort entsprechende OLE-Schnittstellen implementieren. Wenn Du das nicht schon früher mit C++ gemacht hast, ist das unter Umständen harter Tobak.
Hier findest Du ein Beispiel mit Quellcode: http://blocko.blogspot.de/2008/05/ole-in-process-server-in-c.html
Das lohnt sich nach meiner Einschätzung nicht, vor allem weil Office das ja alles schon kann. Warum etwas nachbauen, was schon da ist? Da Du es eh als Excel Add-In implementieren willst, ist Excel auf jeden Fall verfügbar. Was spricht dagegen, den Werkzeugkasten einzusetzen, den Excel fix und fertig mitbringt?
Gruß
Rainbird
Hallo realProg,
das Webservice-Protokoll speziell zum Drucken heißt WS-Print. Hier findest Du die Spezifikationen: MSDN: Implementing Web Services on devices for printing and scanning
Diese Seite richtet sich zwar Hauptsächlich an Hersteller von Geräten, die dieses Protokoll implementieren möchten, aber enthält natürlich auch Informationen, die für den Client-Entwickler nützlich sind.
Folgende Präsentation könnte Dir auch weiterhelfen: TheArchitect: Web Services for Printers - Step by Step
Hallo csharp-user,
der folgende Artikel könnte für Dich interessant sein: Remote Desktop using C#.NET
Ansonsten solltest Du die Dokumentation der Remote Desktop Services API anschauen: Remote Desktop Services API (Windows)
Gruß
Rainbird
Hallo Zusammen,
Zuerst möchte ich mich für die über 650 Downloads bei NuGet und über 3400 Downloads auf Codeplex seit der Veröffentlichung von Zyan bedanken.
Viele der Features, die Zyan inzwischen mitbringt, sind durch das rege Feedback der Community angeregt worden.
Ich hoffe, dass auch die neue Version 2.4 so regen Zuspruch findet.
Neben zahlreichen Bugfixes bietet Zyan 2.4 folgende neue Features:*Komprimierung des Datenverkehrs (besonders nützlich bei langsamen Intrnetverbindungen) *Verbesserungen beim Handling von verteilten Ereignissen
*Verbesserungen bei der Clientverbindung (ZyanConnection)
*Verbesserungen beim TCP-Duplex-Transportkanal
*Neuer Null-Transportkanal für Test- und Monitoringzwecke *Verbesserte Kompatibilität zum Mono Framework
Eine Liste mit allen Neuerungen und Bugfixes findet ihr unter: http://zyan.codeplex.com/releases/view/84528.
Eine detaillierte Beschreibung der neuen Features steht auf folgender Seite: What´s new in Zyan 2.4?
Die Binaries könnt ihr hier runterladen: Zyan 2.4 Download
Zyan 2.4 kann auch bequem über NuGet gezogen werden: NuGet Gallery | Zyan 2.4
Liste mit Referenzen: Projects using Zyan Framework
Wenn ihr Bugs findet, meldet sie bitte im Issue Tracking System: Zyan Issue Tracking
Fragen, Anregungen und Diskussionen gerne hier auf mycsharp.de oder direkt im Zyan Diskussionsbereich
Gruß
Rainbird
Hallo felix,
mono liefert eine Runtime für Windows-Dienste unter Linux. Damit sollte es möglich sein, Deinen Server als Linux-Dämon im Hintergrund laufen zu lassen.
Schau mal: Mono Documentation: mono-service
Gruß
Rainbird
Hallo felix,
die einfachste Variante wären ganz herkömmlich Events. Wenn Du Zyan verwendest, kannst Du Events ganz intuitiv verwenden, genau so wie bei ein Click-Ereignis eines Buttons auf einem Windows-Formular.
In der Zyan-Doku gibt es dafür ein Beispiel: Ereignisse einsetzen
Solche verteilten Ereignisse verhalten sich dabei genauso wie herkömmliche lokale Ereignisse. Die Abonnenten des Ereignisses werden nacheinander aufgerufen. Das ist aber nicht immer das, was man erreichen will. Manchmal möchte man, dass der Server alle registrierten Clients möglichst gleichzeitig informiert. Dann kann man statt Events mit Delegaten arbeiten. Ein einfacher serverseitiger Benachrichtigungsdienst mit Delegaten könnte z.B. so aussehen:
public class SomeServerComponent : ISomeServerComponent
{
private ConcurrentDictionary<Guid, Action<string>> _subscribers = new ConcurrentDictionary<Guid, Action<string>>();
public Guid Subscribe(Action<string> clientCallback)
{
if (clientCallback == null)
throw new ArgumentNullException("clientCallback");
Guid subscriptionID = Guid.NewGuid();
_subscribers.TryAdd(subscriptionID, clientCallback);
return subscriptionID;
}
public void Unsubscribe(Guid subscriptionID)
{
Action<string> clientCallback;
_subscribers.TryRemove(subscriptionID, out clientCallback);
}
public void NotifyClients(string message)
{
Parallel.ForEach(_subscribers.Values, callback =>
{
try
{
callback(message);
}
catch (SocketException)
{
//TODO: Ausnahme loggen
}
catch (RemotingException)
{
//TODO: Ausnahme loggen
}
});
}
}
Der Client kann sich ganz einfach für Benachrichtigungen registrieren.
ISomeServerComponent proxy = _connection.CreateProxy<ISomeServerComponent>();
proxy.Subscribe(OnServerNotification);
Wenn auf dem Server NotifyClients aufgerufen wird, führt das dann dazu, dass auf dem Client OnServerComponent aufgerufen wird.
private void OnServerNotification(string message)
{
Console.WriteLine(message);
}
Hallo felix,
das ist ganz einfach möglich. Allerdings wird das binden an eine bestimmte IP-Adresse nicht von allen Kanaltypen unterstützt.
Wenn Du keine Events oder Callbacks durch Client-Firewalls hindurch übertragen musst, kannst Du ein TcpCustomServerProtocolSetup wie folgt verwenden:
// TCP-Protokoll mit unverschlüsselter binärer Datenübetragung
var protocol = new TcpCustomServerProtocolSetup
(
8080, // TCP-Port
new BasicWindowsAuthProvider(), // Authentifizierung mit Windows-Benutzername und Passwort
true // Verschlüsselung eingeschaltet
);
// TCP-Kanal an bestimmte IP-Adresse binden
//TODO: Statt 192.168.0.10 die gewünschte eigene IP-Adresse einsetzen
protocol.ChannelSettings.Add("bindTo", "192.168.0.10");
protocol.ChannelSettings.Add("machineName", "192.168.0.10"); // Nur setzen, wenn Server eine öffentliche statische IP hat! Bei DynDNS etc. nicht setzen!
protocol.ChannelSettings.Add("useIpAddress", true); // Nur setzen, wenn Server eine öffentliche statische IP hat! Bei DynDNS etc. nicht setzen!
Über die ChannelSettings kann man direkt Einstellungen des Kommunikationskanals einstellen. Das TcpCustomServerProtocolSetup verwendet einen TcpChannel. Dessen Konfigurationseinstellungen kannst Du hier nachlesen: MSDN Libraray: Channel und Formatter Configuration
Gruß
Rainbird
Hallo KroaX,
ich glaube was Du suchst ist InterLinq.
Damit kannst Du Linq-Abfragen über WCF oder .NET Remoting serialisieren.
Als Autor der Kommunikationskomponente Zyan möchte ich an der Stelle auch ein bischen Eigenwerbung machen. Zyan serialisiert LINQ-Abfragen out-of-the-box.
Beispiel:
// Service-Schnittstelle
interface ISampleService
{
IEnumerable<T> GetList<T>() where T : class;
IQueryable<T> Query<T>() where T : class;
}
// Vom Client aus Verbindung zum Applikationsserver herstellen herstellen
using (var connection = new ZyanConnection("tcpex://localhost/myappserver"))
{
// Verbindung zum Service herstellen
var proxy = connection.CreateProxy<ISampleService>();
// LINQ-Abfrage direkt auf den Service machen
var query =
from c in proxy.Query<Customer>()
where c.BirthDate > DateTime.Today.AddYears(-18)
select c;
...
}
Die Customer-Klasse im Beispiel muss natürlich serialisierbar sein.
Wenn Du interoperabel sein musst, also Dein Client kein .NET Client (min. .NET Client Profile wird benötigt) ist, dann ist Zyan leider nicht geeignet. Zyan macht innerhalb der schönen .NET-Welt alles in Sachen RPC sehr einfach, kann aber nicht Kaffeebohnen, Telefonen, Toastern, etc. reden. Wenn Letztere auf Deiner Client-Liste stehen, nimm WCF und probier mal InterLinq aus.
Gruß
Rainbird
Hallo LukasS,
jede Instanz Deiner Applikation ist ein eigener Windows-Prozess. ChannelServices.GetChannel kann nur Channels über den Namen abrufen, die im aktuellen Prozess existieren. Dein Ansatz, einen Channel, der in Prozess A erzeugt wurde und in dessen Speicherbereich existiert von Prozess B aus abrufen zu wollen, kann nicht funktionieren.
Du kannst das Probelm aber umgehen, indem Du in jeder Instanz Deiner Anwendung einen eindeutigen Kanalnamen verwendest. Häng einfach einen GUID hinter den Namen.
Beispiel:
// Eindeutigen Kanalnamen erzeugen
string channelName = "MyTestChannel" + Guid.NewGuid().ToString();
IDictionary properties = new Hashtable();
properties.Add("name", channelName);
properties.Add("portName", "PortXYZ");
So kommen sich Deine Anwendungsinstanzen nicht in die Quere.
Gruß
Rainbird
Hallo lexi,
die Schnittstelle IVestasComponent hast Du doppelt. Einmal im Server und einmal im Client. Auch wenn sie beide gleich heißen, sind es zwei verschiedene Typen für die .NET Laufzeitumgebung.
Damit es funktioniert, musst Du die Schnittstelle in eine separate Assembly (also auch separates Visual Studio Projekt vom Typ Klassenbibliothek) auslagern. Diese Schnittstellen-Assembly musst Du ja im Server und im Client als Verweis einbinden. Deshalb wird eine solche Assembly auch Shared Assembly (also gemeinsame Assembly) genannt. Client und Server kommunizieren über eine gemeinsame Schnittstelle (nämlich IVestasComponent). Damit das funktioniert muss es auch wirklich die selbe Schnittstelle sein.
Du kannst das auch noch mal hier nachlesen: http://zyan.codeplex.com/wikipage?title=Erste%20Schritte&referringTitle=Deutsche%20Dokumentation
Gruß
Rainbird
Hallo elTorito,
Werde nunmal schauen wie das mit der Berechtigung geht.
Du kannst Dir auch einen eigenen Authentifizierungsanbieter schreiben. In folgendem Diskussionsbeitrag findest Du ein einfaches Beispiel, wie das geht:
http://zyan.codeplex.com/discussions/267636
Hallo elTorito,
ich vermute dass es daran liegt, dass die drei Windows 7 PCs nicht Teil der selben Active Directory-Domäne sind. Das n-Tier-Architekturbeispiel verwendet Windows-Authentifizierung über Kerberos oder alternativ auch das NTLM-Protokoll. Das funktioniert nur in einem Domänennetzwerk sinnvoll. Ohne einen zentralen Domänencontroller kann die Authentifizierung nicht richtig funktionieren, da jeder alleinstehende Windows 7-PC (also einer der nicht Mitglied einer Domäne ist) nur seine eigenen Benutzer und Gruppen kennt und auch nur diese authentifizieren kann.
Angenommen der Clientcomputer heißt PC1 und der Benutzer Peter, dann würde er sich mit PC1\Peter versuchen beim Server anzumelden. Wenn der Server PC2 heißt und auch einen Benutzer Peter hat, klappt zwar die Authentifiziere, wenn auf beiden PCs für den Benutzer Peter das selbe Passwort gesetzt ist, aber PC2 kann nicht prüfen, in welchen Gruppen PC1\Peter Mitglied ist. Für die Prüfung der Gruppenmitgliedschaft, müsste PC2 auf die SAM-Datenbank von PC1 zugreifen. Das geht aber in einem Peer-To-Peer Netzwerk nicht. Bei einem Domänennetzwerk sieht die Sache anders aus. Da gibt es eine zentrale SAM-Datenbank auf dem Domänencontroller. Alle Gruppenmitgliedschaftsprüfungen laufen dabei über den Domänencontroller.
Mein Beispiel wurde für den Einsatz in einem Domänennetzwerk geschrieben. Ohne Domänennetzwerk wird es nicht sinnvoll funktionieren. Es ist eben nur ein Beispiel.
Zyan bietet aber eine Lösung für das Problem an. Mit dem BasicWindowsAuthProvider Authentifizierungsanbieter kannst Du Windows-Authentifizierung haben, die nur serverseitig abläuft. Dabei spielt es keine Rolle, ob Client und Server in einer Domäne sind, oder nicht.
Auf folgende Doku-Seiten erfährst Du mehr über Zyan und welche Konfigurationsmöglichkeiten es gibt:
Architektur einer Zyan-Anwendung
ProtocolSetups
Wenn Dir Zyan nicht gefällt, kannst Du auch im Standard .NET Remoting eine eigene Authentifizierung implementieren. Dazu musst Du eigene Kanalsenken schreiben. Schau mal hier: MSDN: Sinks and Sink Chains
Das schreiben von Remoting-Kanalsenken an sich ist nicht schwer. Du brauchst aber tiefgreifende Kenntnisse über die .NET Remoting Infrastruktur.
Gruß
Rainbird
Hallo lmdf,
danke fürs positive Feedback. Freut mich, dass Dir meine Komponente nützlich ist.
Gruß
Rainbird
Hallo Heinz,
sorry, dass die Antwort erst so spät kommt, aber ich habe momentan sehr viel zu tun, was sich leider negativ auf meine Antwortzeiten auswirkt.
Woran kann es liegen, dass ich keinen anonymen Typparameter als Funktionsparameter benutzen kann?
Anonyme Typen werden von Zyan nicht unterstützt. Das liegt daran, dass sie zur Laufzeit erstellt werden und deshalb in einer entfernten Anwendungsdomäne nicht verfügbar sind.
Zyan erkennt die aufzurufende Methode an ihrer Signatur. Dabei sind Methodenname, Typ des Rückgabewerts und die Typen der Parameter relevant. Der Dispatcher (das ist die interne Komponente, welche Remoting-Nachrichten parst und sie in reale Methodenaufrufe auf dem Server verwandelt) überprüft dabei die Typ-Kompatiblität der übergebenen Parameterwerte mit der Methodensignatur. Er kann aber nur dann ermitteln, ob ein Typ mit einem anderen kompatibel ist, wenn er beide kennt.
Anonyme Typen, die zur Laufzeit auf dem Client erzeugt werden, kann der Server nicht kennen. Der Server versucht unbekannte Typen aus den entsprechenden Assemblies nachzuladen. Da anonyme Typen aber flüchtig sind und nicht als Assembly vorliegen, klappt das natürlich nicht. Zyan kann den Typ nicht laden und so auch nicht ermitteln, ob er mit dem entsprechenden Parameter aus der Signatur der aufzurufenden entfernten Methode kompatibel ist. Als Folge davon geht Zyan davon aus, dass für den Aufruf keine passende Überladung vorhanden ist.
So kommt der Fehler "Methode nicht gefunden" zustande.
Es ist theoretisch möglich auch anonyme Typen automatisch auf den Server zu bringen. Dazu müssten aber die Rohdaten des dynamischen Kompilats serialisiert und automatisch mit der Remoting-Nachricht mitgeschickt werden. Derzeit ist so ein Mechanismus nicht in Zyan vorhanden.
Ich sehe das auch kritisch wegen der Performance. Die Rohdaten des anonymen Typs müssten auf dem Server auch wieder in eine ladbare Form gebracht werden. Da würde sich dann die Frage stellen, ob man diese übertragenen anonymen Typen sinvoll cachen kann, also ob man erkennen kann, wann es sich um den selben anonymen Typ handelt.
Für entfernte Methodenaufrufe musst Du derzeit also leider noch auf anonyme Typen verzichten.
Es gibt aber schon ein erfasstes Feature im Zyan Issue Tracker: http://zyan.codeplex.com/workitem/626
Du bist nicht der Erste, der sich anonyme Typen für entfernte Methodenaufrufe wünscht.
Gruß
Rainbird
Hallo Folkz,
wenn ich Dich richtig verstanden habe, brauchst Du einen Server, der Daten über HTTP von einem Smartphone entgegen nimmt und weiterverarbeitet.
Meistens macht man das mit einem Webserver. Dieser muss über einen DNS-Namen vom Internet aus erreichbar sein. Für ein kleines Berufschulprojekt willst Du vermutlich keinen kostenpflichtigten Webserver bei einem Provider anmieten.
Du kannst aber einen eigenen Server auf einem normalen PC aufsetzen. Dazu musst Du zuerst dafür sorgen, dass dieser PC übers Internet erreichbar ist. Die meisten Internetzugänge im privaten Bereich (z.B. DSL) arbeiten mit dynamischer IP-Adressvergabe, was für den Betrieb eines Servers denkbar schlecht ist, da sich die IP-Adresse immer wieder ändert und die Clients den Server dann plötzlich nicht mehr erreichen.
Die Lösung dafür sind kostenlose dynamische DNS-Dienste (auch DDNS genannt), welche Änderungen an der IP-Adresse sofort auch auf einen öffentlichen DNS-Namen übertragen (z.B. http://www.no-ip.com/services/managed_dns/free_dynamic_dns.html).
Wenn Du DDNS eingerichtet hast, kannst Du Deinen Server in C# schreiben. Das geht z.B. mit der HttpListener-Klasse.
Natürlich könntest Du auch einen IIS aufsetzen oder einen WCF-Service schreiben.
Die neue Zyan Version 2.3 ist fertig.
Folgende Neuerungen stecken drin:*Sitzungsgebundene Ereignisse (session-bound events) *Serverseitige Ereignisfilter *Ereignis-Abos werden beim wiederverbinden automatisch wiederhergestellt *Call Interception wurde verbessert (Pausierbar + Erweiterungen für leichteres Erstellen von Abfangregeln) *HttpCustomClientProtocolSetup unterstützt nun Proxy Server (auch mit Authentifizierung) *Remote Streaming funktioniert und wurde durch Unit Tests getestet *Zahlreiche Bugs wurden behoben
Weitere Informationen, die aktuellen Binaries und den vollständigen Quellcode gibts auf der Zyan Codeplex-Seite.
Das Zyan Communication Framework ist nun auch auf Ohloh zu finden: http://www.ohloh.net/p/zyan
Setzt ihr Zyan in Real-World-Projekten ein?
Falls ja, würde ich mich über eine kurze Rückmeldung im Zyan-Diskussionsbereich Projects using Zyan Framework (Thread ist allerdings in Englisch!) sehr freuen.
Hallo jump.sonic,
So ähnlich habe ich das umgesetzt, nur dass ich den Clients immer das geänderte DataSet mit dem Event schicke. Das macht mir etwas Kopfzerbrechen, da hier doch viele Daten verschickt werden auch wenn das DataSet sehr klein ist.
Wie viele bytes werden denn da verschickt, dass Du Dir da solche Sorgen machst?
Eine generelle Fausregel bei verteilten Anwendungen heißt: Klotzen, nicht kleckern. Will heißen, dass man möglichst große Brocken am Stück überträgt und dafür die Anzahl der Aufrufe auf ein Minimum reduziert. Schnittstellen vom Server-Komponenten sollten also chunky und nicht chatty sein.
Generell solltest Du anstreben, dass die Serverkomponenten möglichst statuslos sind. Das skaliert am besten. Hohe Skalierbarkeit bedeutet, dass die Anwendung mehr gleichzeige Clients verkraften kann. Wenn irgend möglich sollten die meisten Deiner Server-Komponenten SingleCall aktiviert sein und nicht Singleton aktiviert werden.
Ich würde die Benachrichtigung (Events) in eine separate Komponente auslagern, damit die Geschäftslogik-Komponenten statuslos (SingleCall) sein können. Events haben außerdem das Problem dass sie nur synchron arbeiten. Stell Dir vor, Du hast 100 gleichzeitig angemeldete Clients. Jetzt ändert sich irgend ein Datensatz und Deine Events benachrichtigen die anderen Clients darüber. Dann wird ein Client nach dem anderen benachrichtigt. Und der Server wartet auch jedesaml auf die Antwort eines Clients, bis er mit dem nächsten weitermacht. In Zyan 2.3 wird dieses Problem gelöst werden, indem asynchrone Events (mittels Multithreading) eingeführt werden. Derzeit sind Events aber nur bedingt in ganz kleinen Szenarien einsetzbar. Du solltest statt Events besser selbstverwaltete Callback-Delegaten einsetzen. Damit kannst Du den selben Komfort in Deiner API beiten wie mit Events, aber hast die volle Kontrolle darüber, wie die Benachrictigung der Clients abgewickelt wird. Du kannst den Status des async. Event-Features hier nachverfolgen: http://zyan.codeplex.com/workitem/1348
Ein Client der ein Datensatz hinzufügt bekommt den Primärschlüssel 0, da dieser von der Datenbank vergeben werden soll. Das macht mir Sorgen, wenn ich nur die IDs mitteile die geändert wurden, da zwischenzeitlich ja vielleicht 2 Clients etwas ändern wollten und ich somit nicht die 0 ersetzen kann. Muss ich das so machen und damit eine Logik implementieren, die entweder bei hinzufügen den Datensatz anhängt oder beim Ersteller den Datensatz mit 0 ändert?
Mit getChanges() und Merge() kann ich ja leider nicht arbeiten, weil damit der Primärschlüssel 0 bestehen bleibt.
Du kannst dieses Problem komplett umgehen, indem Du Guids (im SQL Server heißt der Datentyp uniqueidentifier) als Primärschlüssel verwendest. Das hat den Vorteil, dass bereits offline ein gültiger eindeutiger Schlüssel erzeugt werden kann.
Wie wird bei dem Zyan (Remoting) Server die Clientzugriffe abgearbeitet? Wenn 2 Clients gleichzeitig speichern wird das in unterschiedlichen Threads gemacht oder nacheinander?
Jede Client-Anfrage wird vom Server in einem eigenen Thread verarbeitet. Zyan nutzt dafür den .NET Thread Pool. Ein weiterer Grund, warum man möglichst mit SingleCall statt mit Singleton arbeiten sollte. Bei Singleton greifen mehrere Threads gleichzeitig auf die Komponente zu. Du musst also threadsicher programmieren. Bei SingleCall bekommt jeder Aufruf eine eigene Instanz, die anschließend wieder entsorgt wird. Da jeder Thread seine eigene Instanz bekommt, musst Du bei SingleCall nicht threadsicher programmieren.
Hallo jump.sonic,
Das heisst aber, dass nur der Client, der die Daten speichert auch die aktuellen Daten wieder zurück bekommt oder?
Ich möchte ja, dass alle Clients die angemeldet sind die aktuelle Daten zurück bekommen.
Habe ich da etwas falsch verstanden?
Das hast Du richtig verstanden. Es kommt auf die Aufgabenstellung an, ob das ausreicht. Für das Auftragserfassungs-Beispiel ist das völlig ausreichend, da nicht mehrere Sachbearbeiter den selben Auftrag bearbeiten. Für ein Flugbuchungssystem wäre es z.B. nicht ausreichend.
Du kannst die anderen Clients schon per Event benachrichtigen, dass ein Datensatz geändert/erstellt/gelöscht wurde. Allerdings sollte das - meiner Meinung nach - zusätzlich zur normalen Speicherlogik erfolgen.
Beispiel:
public OrderDataSet SaveOrders(OrderDataSet dataSet)
{
using(TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
{
// Validieren
ValidateOrders(dataSet);
if (!dataSet.HasErrors)
{
// Kopfdatensatz speichern
new OrderHeadTableAdapter().Update(dataSet.OrderHead);
// Positionen speichern
new OrderDetailTableAdapter().Update(dataSet.OrderDetail);
// Transaktion abschließen
scope.Complete();
// Andere Clients benachrichtigen
OnOrdersChanged(null);
}
}
return dataSet;
}
Die anderen Clients bekommen praktisch nur ein Signal, dass sich was geändert hat (und bei Bedarf vielleicht noch die IDs des geänderten Datensatzes).
Denke bitte auch daran, dass das Event in den Clients in einem eigenen Thread gefeuert wird. Bei Zugriffen auf Steuerelemente muss deshalb mit Invoke gearbeitet werden.
Hallo jump.sonic,
- Wie verschicke ich die Änderungen an die Clients am klügsten? Ist es hier sinnvoll ganze DataSets zu verschicken oder sollte ich lieber DataRowArrays schicken, die die Clients dann in ihr eigenens DataSet einpflegen?
Je nach Bedarf ganze DataSets oder DataTables verschicken. DataSets dann verwenden, wenn Änderungen an mehreren Datensätzen verschiedener Tabellen innerhalb einer Transaktion gespeichert werden sollen.
Angenommen Du schreibst ein System zur Auftragserfassung. Ein Auftrag besteht immer aus einem Kopfdatensatz und Positionen. Du erfasst den kompletten Auftrag im Client in einem DataSet mit zwei DataTables. Dann schickst Du das DataSet zum Speichern an den Applikationsserver. Dieser überprüft die Daten auf Korrektheit und Konsistenz und speichert das DataSet (z.B. mit Hilfe von TableAdaptern), wenn alle Prüfungen erfolgreich waren. Falls die Daten Fehler (falsche Eingaben, ungültige Werte, etc.) enthalten, sollten entsprechende ColumnErrors in den DataTables gesetzt werden. In beiden Fällen (also egal ob erfolgreich gespeichert oder Fehler gefunden) wird das DataSet bzw. die DataTable zurück zum Client gesendet. Der Client aktualisiert sein lokales DataSet mittels Clear und Merge. Dann kann er ggf. gesetzte ColumnErrors auswerten.
Das ist die Standardvorgehensweise mit DataSets.
- Wie verhält es sich mit Beziehungen? Im Moment kommt es mir so vor als wäre es einfacher keine Datenbankbeziehungen zu erstellen, die Spalten aber dennoch zu behalten. Somit könnte ich im Code zum Beispiel einfach die Daten filtern, je nachdem welche Auswahl in der Mastertabelle zu Grunde liegt.
Beziehungen in typisierten DataSets erleichtern die Navigation zwischen verknüpften Datensätzen. Der DataSet-Designer erzeugt automatisch Properties, um z.B. von einem Auftragspositionsdatensatz zum passenden Kopfdatensatz zu navigieren und umgekehrt. Außerdem kannst Du - ähnlich wie z.B. im SQL-Server - Löschweitergabe und Aktualisierungsweitergabe bei Schlüsseländerungen und Löschungen aktivieren. Dann werden z.B. alle Positionen eines Auftrags automatisch gelöscht, wenn der Kopfdatensatz gelöscht wird.
- Clients bekommen bei der Anmeldung mehrere DataSets (für jede Form gibt es ein DataSet, das reduziert etwas die zu übertragende Datenmenge später). Sollte ein Client eine Änderung vornehmen sendet er über DataSet.getChanges() ein kleines DataSet an den Server. Der Server trägt die Daten in die Datenbank ein und fragt sie erneut ab. Jenachdem welches DataSet geändert wurde wirft der Server ein Event, dass das geänderte (aber komplette) DataSet an die Clients, die ihre DataSource damit aktualisieren.
Ich würde an der Stelle nicht mit Events arbeiten. Der Server kann das gespeicherte/aktualisierte DataSet doch einfach wieder als Rückgabewert an den Client zurückgeben. Das könnte so aussehen:
public OrderDataSet SaveOrders(OrderDataSet dataSet)
{
using(TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
{
// Validieren
ValidateOrders(dataSet);
if (!dataSet.HasErrors)
{
// Kopfdatensatz speichern
new OrderHeadTableAdapter().Update(dataSet.OrderHead);
// Positionen speichern
new OrderDetailTableAdapter().Update(dataSet.OrderDetail);
// Transaktion abschließen
scope.Complete();
}
}
return dataSet;
}
- Clients bekommen bei der Anmeldung mehrere DataSets (wie bei Punkt 1.). Wird nun eine Änderung oder Inser durchgeführt wird nur die geänderte DataRow oder ein DataRowArray mit dem DataSetNamen an den Server geschickt, der diese dann in die Datenbank einpflegt. Per Event verschickt der Server dann wieder die geänderten Rows an die Clients, die wiederum die Rows in ihr DataSet einpflegen.
Das wird so nicht klappen. DataRows sind nämlich nicht serialisierbar. Du kannst eine DataRow nicht alleine übers Netzwerk schicken. Du musst schon eine DataTable senden.
@Abt: DataSets sind viel besser als ihr Ruf. In verteilten Anwendungen ist EF nicht unbedingt die beste Wahl. DataSets haben da sogar eher die Nase vorn (Aber darüber kann man sicherlich streiten). Ich habe vor einiger Zeiten einen Blog-Eintrag zu dem Thema verfasst: http://yellow-rainbird.de/blogs/rainbird/archive/2009/01/09/habe-sehnsucht-nach-dem-rowstate.aspx
Hallo mstoll,
schön Dir mein Office-Wrapper gefällt.
Dann könnte aber auch das folgende Open Source-Projekt für Dich interessant sein:
http://netoffice.codeplex.com/
Das ist ein versionsunabhängiger (bezogen auf die Office-Version) Wrapper für Office und bringt noch eine Menge Zusatztools mit. Damit wird es noch viel einfacher verschiedene Office-Versionen mit einer einzigen Codebasis zu unterstützen.
Hallo zusammen,
für das Kommunikationsframework Zyan wurde soeben die neue Version 2.2 veröffentlicht. Neben jeder Menge Bugfixes bringt die neue Version folgende Neuerungen mit:*Weite Teile des Zyan-Kerns wurden refaktorisiert *Clientseitige MEF (Managed Extensibility Framework) Integration *Einfachere Integration von eigenen Remoting-Senken möglich *Vordefinierte Protocol Setups sind nun individuell erweiterbar *Abonnieren von entfernten Delegaten und Ereignissen ist nun wesentlich schneller *Zyan kann nun unerwartete Verbindungsabbrüche erkennen *Die neue Basisklasse SessionManagerBase vereinfacht die Implementierung einer eigenen Sitzungsverwaltung *Zyan.Communication.dll hat nun einen Starken Namen (ist mit SNK-Datei signiert) *Strikte Versionierung bei Serialisierung kann nun abgeschaltet werden
Auf folgender Webseite (in Englischer Sprache) gibts eine detaillierte Übersicht über die Änderungen: What's new in Zyan 2.2?
Die neuen Binaries gibts entweder direkt bei Codeplex oder als NuGet-Paket.
Zyan 2.2 unterstüzt .NET Framework 3.5, .NET Framwork 4.0 und Mono 2.8 (oder höher).
Offene Fragen beantworte ich gerne hier auf mycsharp.de oder im Zyan-Diskussionsbereich.
Hallo ..Heinz..,
ich habe den Fehler - hoffentlich - behoben. Problemursache war, dass der Client-Remotingkanal bei Aufruf von Dispose nicht richtig deregistriert wurde.
Du kannst den aktualisierten Zyan-Quellcode hier runterladen: http://zyan.codeplex.com/SourceControl/changeset/changes/13345
Hallo ..Heinz..,
damit ich den Fehler reproduzieren kann, brauche ich noch ein paar Informationen:*Welche Zyan -Version hast Du eingesetzt? *Auf welchen Betriebssystemen laufen Client und Server? *Welches ProtocolSetup hast Du verwendet? *Welche Sicherheitsfeatures hast Du aktiviert? *Wie viele Verbindungen hast Du aufgebaut?
Am besten wäre ein Codeschnipsel, wie Du vorgegangen bist.
Hallo diego2k,
die neuste VSTO-Version unterstüzt nur Office 2007 und Office 2010. Für Office 2003 müsstest Du auf die Vorgängerversion zurückgreifen, die auch nicht mit Visual Studio 2010, sondern nur mit Visual Studio 2008 läuft.
Für Office 2003 stehen einige neue Features auch gar nicht zur Verfügung.
Alternative wäre ein klassisches Shared-Add-In. Das basiert auf COM-Interop und geht für alle Office-Versionen (2000 oder neuer).
Folgender Artikel könnte Dir da weiterhelfen: Developing COM Add-ins for Microsoft Office in VB.NET
Hallo ..Heinz..,
Danke für den Hinweis. Ich habe einen Starken Namen für Zyan 2.2 eben auf die TODO-Liste gesetzt. Hier kannst Du den Status der Entwickleraufgabe verfolgen: http://zyan.codeplex.com/workitem/1231
Bis zum release von Zyan 2.2 kannst Du Dir behlfen indem Du die Quellen von Zyan herunterlädst und zum Projekt Zyan.Communication selber einen SNK-Schlüssel zufügst und das Projekt anschließend neu kompilierst.
Für .NET 4.0, .NET 3.5 und mono gibt es getrennte SLN Dateien im Ordner \source.
Hallo diego2k,
Excel-Anbindung ist sehr wichtig, da die Kunden damit flexibel sind und selber mit den Zahlen "spielen" können. Trotzdem sollten statische Reports (z.B. via ReportViewer) zusätzlich vorhanden sein, um die Standardfälle per Knopfdruck abdecken zu können.
Für die Excel-Anbindung eignet sich ein VSTO-Excel-AddIn (auf Anwendungsebene) hervorragend. Das AddIn kann Excel um neue Menüs bzw. Ribbons und .NET Dialoge erweitern, die es dem Kunden z.B. ermöglichen parametrisierte Abfragen über den WCF-Dienst direkt in Excel auszuführen und diese Abfrageergbnisse bereits vorab aufbereitet aufs Tabellenblatt zu bringen.
Du kannst mit VSTO auch eigene Arbeitsbereiche (die seitlich gedockten Panels, die es seit Office 2003 gibt) und Smarttags schreiben.
Der Vorteil eines zentral installieren AddIns ist, dass der Kunde die Funktionalität in jeder Excel-Mappe zur Verfügung hat und nicht nur in einer bestimmten Vorlage. Oft muss man Daten aus einer Anwendung mit vorhandenen anderen Daten kombinieren. Das geht sehr leicht, wenn man einfach die Excel-Mappe mit den vorhandenen Daten öffnet und sich per AddIn-Funktionalität die gewünschten Daten aus der Anwendung dazulädt.
Der Team Foundation Server von Microsoft (Tool zur Quellcode- und Projektverwaltung) macht dies ganz ähnlich.
Sowas ist auch nicht schwierig zu programmieren.
Welche Excel-Versionen musst Du denn unterstützen?
Hallo Wupper,
am besten gar nicht mit Acrobat.
Es gibt eine kostenlose Alternative: iTextSharp
Hier ist ein Beispiel, wie die Bibliothek eingesetzt wird: Where can I find good examples/tutorials for iText using .NET?
iTextSharp ist im Prinzip ein XmlTextWriter nur nicht für XML, sondern für PDF.
Hier noch ein Link, der zeigt, wie man im PDF-Dokument Tabellen mit iTextSharp generiert: iTextSharp - Introducing Tables
Du brauchst für iTextSharp weder den Adobe Reader noch den Adobe Acrobat.
Natürlich kannst Du auch die COM-Schnittstellen des Acrobat nutzen. Dafür musst Du das Acrobat SDK runterladen und installieren. Das SDK sowie die Dokumentation dazu findest Du unter: http://www.adobe.com/devnet/acrobat/downloads.html
Hallo Campy,
muss es denn zwingend WCF sein?
Muss die Kommunikation bestimmten Standards (z.B. SOAP) genügen?
Must Du Silverlight Clients bedienen können?
Falls nicht, gibt es Alternativen zu WCF, die können, was Du willst.
WCF folgt dem Dogma der Serviceorientierung. Dies beinhaltet auch die Regel, dass Dienste explizite Schnittstellen haben müssen. Das hat zwar in heterogenen System absolut seine Berechtigung, ist aber in reinen .NET-Anwendungen absolut unnötig.
Wie es aussieht stört Dich diese Regel (wie mich übrigens auch). Du versuchst das irgendwie "aufzuweichen". Falls WCF als Kommunikationsframework für Dein Projekt nicht in Stein gehauen feststeht, könnte ich Dir Alternativen vorstellen.
Gruß
Rainbird
Hallo zusammen,
Das ist nicht schön und deshalb würde ich das Problem von Grund auf anders betrachten: gar nix auf dem Client machen und alles an den Server delegieren, denn der kann dann mit einem lokalen Context arbeiten. Beim WCF-Service ev. mit Sessions arbeiten und dann ist es gut.
Ich würde eher sagen, dass das ganz böse ist. Das würde bedeuten, dass der Server statusbehaftet sein muss. Das ist Gift für die Skalierbarkeit der Anwendung. Der Status sollte beim Client liegen. Der Server sollte auf keinen Fall pro Clientsitzung einen EF-Kontext offen halten. Wie viele Benutzer verkraftet der Server gleichzeitig, wenn er für jeden dessen EF-Kontext verwalten muss?
Selbst wenn das mit der jetzigen Userzahl kein Problem ist, könnte es vielleicht in zwei Jahren ein Problem werden, wenn die Firma gewachsen ist (gesunde Unternehmen wachsen und die Software muss mitwachsen). Statusbehaftete Server verschwenden jede Menge Ressourcen.
EF verträgt sich mit verteilten Architekturen eben nur mäßig bis schlecht. Auch wenn es noch so schön abstrakt ist.
Mit etwas Verspätung auch hier die Ankündigung der neusten Zyan-Version 2.1.
Neu in Zyan 2.1
*Unterstützung für Generische Methoden
*Unterstützung für deterministische Ressourcenfreigabe
Binaries gibt`s hier: http://zyan.codeplex.com/releases/view/68252
NuGet-Paket gibt´s hier: http://nuget.org/List/Packages/Zyan
Hallo Gandulf,
um Verfälschung Deiner Prognose durch Ausreißer in Deinen Zahlenreihen zu eleminieren, hilft Dir vielleicht eher die Normalverteilung weiter:
Wikipedia: Normalverteilung
Diese Ausreißer treten ja zufällig auf. Es steckt keine Logik dahinter, die ein Neuronales Netz "lernen" könnte.
Kann dann z.B. unter dem IIS (oder mit Linux unter XSP) laufen, und Du brauchst keinen eigenen Server zu schreiben.
Naja, bei Zyan ist ein Server mit gerade mal drei Zeilen Code geschrieben. Bei WCF und klassischem Remoting sieht´s ähnlich aus. Den Server schreiben ist vermutlich das kleinste Problem.
Natürlich können IIS gehostete SOAP-Webdienste trotzdem eine gute Lösung sein. Vor allem, wenn Interoperabilität ein Thema ist.