Laden...
J
Jelly myCSharp.de - Member
Burden (Luxemburg) Dabei seit 09.09.2007 1.114 Beiträge
Benutzerbeschreibung

Forenbeiträge von Jelly Ingesamt 1.114 Beiträge

24.09.2009 - 17:22 Uhr

Du bist auch nicht gezwungen, den WCF Dienst überhaupt im IIS zu hosten, sondern kannst das Ganze auch z.B. als normalen Windows Dienst oder Konsolenanwendung laufen lassen. So mach ich das persönlich eigentlich immer.

24.09.2009 - 13:57 Uhr

Ermittele doch einfach in einer getrenntren Abfrage erst dein Max(Datum1) und Min(Datum2) und nehme diese Werte als Vergleichswerte in der eigentlich Abfrage

select kw, max(datum1), min(datum2) from x group by kw where datum1 < @madDatum1 and datum2 > @minDatum2

o.ä.

Kann sein, dass ich noch nicht so richtig dein Problem verstanden habe.

24.09.2009 - 13:49 Uhr

Schon folgendes probiert?

select kw, max(datum1), min(datum2) from x group by kw having max(datum1) < min(datum2)
24.09.2009 - 12:11 Uhr

Und unter WCF scheint dies auch noch nicht umgesetzt zu sein.

Natürlich geht das dort. Kuck dir mal die DuplexChannels an, die es da so gibt... Diese funktionieren allerdings nicht mit jedem Binding, sondern eigentlich nur mit NetTcp und WsHttp. Das wiederum ist keine standardmässige Unterstützung mehr von einem Webservice, und kann somit nur von einem .NET Client konsumiert werden.

Einen interessanten Artikel zu diesen Callbackgeschichten findest du hier bei CodeProject.

24.09.2009 - 10:22 Uhr

dass geschieht allerdings in einem Temp-Ordner - vllt läuft da aber auch etwas schief.

In welchem denn, dann kann ich das überprüfen!

23.09.2009 - 15:55 Uhr

Also erst einmal freut es mich zu hören, dass du die Property "AllowCancellation" einbauen wirst, damit der Anwender den update Prozess nicht abbrechen kann.

Unter Verdacht, dass ich vielleicht immer wieder die gleichen Themen ausgrabe: Zum Thema "Impersonifikation" ist mir aber, wie es scheint, ein gravierender Bug aufgefallen. Zum Scenario:
Ich habe in einem Ordner die Schreibrechte für den User geknippst, so dass beim Versuch, durchs Updaten in den Ordner zu schreiben, schön brav wie gewollt eine Fehlermeldung kommt, bei der ich dann auswähle, das Update unter einem anderem Benutzer auszuführen. Dort gebe ich dann die korrekten Daten an, und der Benutzer wird auch korrekt impersonifiziert. Es handelt sich dabei um einen Benutzer aus einer Domäne.. Beim Updatevorgang passiert dann aber folgendes:

  1. Es werden alle zu updatenden Dateien erstmal glöscht (die Rechte des Users stimmen also).
  2. Danach bricht das Ganze ab, d.h. die neuen Dateien werden nicht geschrieben.

Das hat zur Folge, dass die Exe im Verzeichnis nicht mal mehr existiert. Irgendwelche Backupfiles gibt es auch nicht. Ein weiterer Updateversuch kann nicht mehr ausgeführt werden, da die Echse nicht mehr existiert.

17.09.2009 - 07:54 Uhr

Benutze seit Dezember ein HTC Touch HD. Eigentlich ein ganz nettes Teil, ist mir zeitweise nur ein bischen gross, was bei gewissen Aktivitäten stört (z.B. beim Radfahren, wo ich immer gern ein Handy dabei hab). Für solche Sachen nutz ich dann aber einfach mein altes, da tuts dann auch nicht so weh wenn kaputt geht.

Der Funktionsumfang vom HTC steht dem vom iPhone in nichts nach. Der Touchscreen funktioniert tadellos, wenn auch mit etwas mehr Druck als beim iPhone. Dafür funktioniert es aber auch mit Stift, beim iPhone nur mit dem Finger.

Ich hatte mich aber letztlich für das HTC entschieden aus folgenden Gründen:*Will meine Termine schön synchron halten mit meinem Outlook zuhause. Der eigentliche Terminplaner im Windows Mobile finde ich zwar schrottig, und habe mir dafür für 25$ eine Zusatzsoftware gekauft, die wirklich gut funktioniert. *Als Entwickler und vor allem C# Entwickler möchte ich auch mal Applikationen fürs Handy schreiben (naja, dachte ich damals zumindest, bislang ist noch ausser einer Testapplikation nix passiert 😃 *Bessers und hochauflösenderes Display als das iPhone *Recht lange Akkulaufzeit von +/- 3 Tagen (sofern nicht permanent gesurft wird, oder das Teil im Auto (=Faradaykäfig) rumliegt und wie verrückt strahlt. *Meine Abneigung zu Apple. Hatte das Glück, im Vorfeld mal mit dem berüchtigten iTunes zu arbeiten. Und nachdem das Ding meinen Rechner quasi bei jedem Start lahmlegte, wollte ich mit sowas nichts mehr am Hut haben. Ausserdem konnten damals (muss Mitte letzten Jahres gewesen sein), die iPhone weder PDF aufmachen, noch Worddokumente, noch MMS verschicken. Und über Bluetooth konnten auch nur Headsets und dergleichen angeschlossen werden. Aber z.B. Kontaktdaten zu einem anderem Telefon über Bluetooth verschicken ging nicht. Soviel zum Thema Standards. Hat sich aber mittlerweilen ja zum Glück geändert (zu der Bluetooth Geschichte weiss ich nicht, ob das mit einem neuen Modell klappt), aber damals war das ein nogo. *Ich folge nicht jedem Hype in der Werbung. Mittlerweilen besitzt jeder 2. meiner Freunde ein iPhone, und ich bin froh drüber, dass ich keins hab.

16.09.2009 - 10:04 Uhr

Du hast den Beitrag hier sicherlich übersehen. Gibts dazu schon was zu sagen?

11.09.2009 - 13:38 Uhr

Auch Quick and Dirty wäre das aufrufende Fenster bei einem Fehler einfach zu disablen, und das topMost Flag des Dialogs auf true zu setzen 😃

11.09.2009 - 08:51 Uhr

Ich messe etwas und möchte diese Daten in die Tabelle hinzufügen.

Du kannst doch einfach, ganz ohne DataSet oder sonstige .NET Monster, dein "Insert into..." Befehl an die DB schicken. Warum alles vorher noch in einem DataSet zwischenspeichern, und sich so einen unnötigen Overhead einhandeln.

11.09.2009 - 08:48 Uhr

Kannst du nicht einfach die gemeinsamen Eigenschaften in deiner Basisklasse "MeineListe" unterbringen?

10.09.2009 - 15:35 Uhr

Setze doch mal vor dem Printjob die PrintController Eigenschaft der PrintDocument Klasse auf einen StandardPrinterController... Bei mir wird der Dialog dann gar nicht mehr angezeigt:

private void PrintMe()
{
            System.Drawing.Printing.PrintDocument print = new System.Drawing.Printing.PrintDocument();
            print.PrintController = new System.Drawing.Printing.StandardPrintController();

            print.PrinterSettings.PrinterName = "HP Officejet Pro 8500 A909a Series";
            print.PrintPage += new System.Drawing.Printing.PrintPageEventHandler(print_PrintPage);
            print.Print();
}

private void print_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
    e.Graphics.DrawString("Test\r\nSecond Line", new Font(this.Font, FontStyle.Bold), new SolidBrush(Color.Red), new PointF(100, 100));
    e.Graphics.DrawEllipse(new Pen(new SolidBrush(Color.Blue), 10), 100, 300, 500, 500);
}

Interessanterweise hast du das ja schon hier angedeutet. Habe dazu kein Code von dir, aber das von mir gepostete Beispiel funktioniert auf meinem Rechner mit meinem Drucker wie gewünscht, ganz ohne PrintDialog.

10.09.2009 - 07:59 Uhr

Zeig doch mal ein bischen Code, wie du den Drucktauftrag startest, und an welcher Stelle du versuchst, dein Fenster wieder hervorzubringen. Aussagen wie

Funktioniert bei mir leider nicht.

sind nicht aussagekröftig genug, um näheres zu deinem Problem zu sagen.

09.09.2009 - 15:11 Uhr

Das heisst genau das, ja! Deshalb musst du invoken. Und weil Herbivore sowieso auch hierher verlinken würde, nehm ich's ihm mal vorweg: Warum blockiert mein GUI?
Wenn dir diese ganze Invoke Geschichte zu kompliziert erscheint, so kannst du immer noch die BackgroundWorker Klasse nehmen, und dort das ProgressChanged Event auswerten, und in der Methode dein Gui updaten.

09.09.2009 - 14:34 Uhr

Wie lange dauert denn dein gesamter DB Update. Wenn es auch nur einige Sekunden sind, so ist während dieser Zeit dein Fenster blockiert, und du kriegst z.B. unschöne Artefakte, wenn du ein anderes Fenster einer anderen Anwendung darüber bewegst.

Um das zu vermeiden, sollte man längere Operationen in eigene Threads auslagern. Und wenn dir das Thema Threading noch eventuell ein Dorn im Auge ist, so schau dir doch mal die BackgroundWorker Klasse an. In deinem konkreten Problemfall des DB Updatens würde ich sogar fast sagen wäre das die optimale Denkrichtung.

09.09.2009 - 08:13 Uhr

Ja, danke... Wär ich nie drauf gekommen. Ich finde solche Antworten immer sehr hilfreich. F1 drücke ich ca alle 30 Sekunden.

Also ich darf doch sehr bitten. Wenn du F1 drückst, und dann vielleicht noch nach DllImport suchst, dann stolperst du doch von selbst über die DllImport Klasse. Alle 30 Sekunden F1 drücken ist nicht die geeignete Taktik: man sollte die gefundenen Seiten dann auch ruhig mal durchlesen. Und weil aus der Fehlermeldung doch mehr als klar hervorgeht, woran es liegen kann, nämlich an einer fehlenden referenzierten Assembly oder einer fehlenden using-Direktive, ist das doch dann sicher nicht zuviel verlangt, die Hilfe Seite einfach mal zu lesen. Aber ehrlich :evil:

08.09.2009 - 16:08 Uhr

Mach mal ein

lbl_Status.Refresh();
08.09.2009 - 14:09 Uhr

Ok, lag tatsächlich am Blockieren, nur komisch, dass sich dann bei der Progressbar was geregt hat.

Was womöglich daran liegt, dass beim Aufruf der Increment Methode der ProgrssBar ein neuzeichnen der Komponente erzwungen wird (Refresh z.B.)

08.09.2009 - 11:41 Uhr

@Jelly: Bei mir wirft er Fehler:
Fehler 3 Der Typ- oder Namespacename "DllImport" konnte nicht gefunden werden. (Fehlt eine Using-Direktive oder ein Assemblyverweis?)

Dann würd ich vorschlagen, die Fehlermeldung mal zu lesen und zu verstehen. Soll heissen sowohl schauen, dass die Assembly referenziert ist (sollt eigentlich standardmässig in einem VS Projekt sein), und kontrollieren, ob du den Namespace, der DLLImport behrbergt, auch in deinen using-Direktiven steht. Welcher Namespace das im Detail ist, dafür ist z.B. einmal F1 sehr hilfreich.

08.09.2009 - 08:50 Uhr

SetForeGroundWindow bringt das Fenster ab Windows XP nicht mehr in den Vordergrund, sondern nur die Taskleisten-Schaltfläche zum Blinken.

Meine BasisForm Klasse besitzt eigentlich immer folgende Methode.

[DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool SetForegroundWindow(IntPtr hWnd);

        public bool ForceBringToFront()
        {
            bool ok = SetForegroundWindow(this.Handle);
            BringToFront();
            return ok;
        }

Ein ForceBringToFront() legt das Fenster eigentlich bei mir ausnahmslos immer schön in den Vordergrund. Auch bei XP.

04.09.2009 - 17:58 Uhr

Grad habich die Idee für einen bösen Workaround:
Application.Openforms durchlaufen, und per Reflection alle components auspuhlen, und vergleichen, obs mit Site.Components übereinstimmt.

Ui... Das ist die ganz dreiste Methode... Und die wird sogar funktionieren, wenn ich das richtig verstanden habe. Aber den Aufwand wollte ich meiden. Wenn ein Component Objekt diese Funktionalität nicht von Haus aus bietet, dann möchte ich da auch nur ganz ungern was drumrumstricken. Ich hab dem Ganzen jetzt eine Eigenschaft Owner vom Typ Object spendiert, die der Aufrufer dann halt setzen muss.

03.09.2009 - 13:48 Uhr

Ich hab jetzt eine viel einfachere und obendrauf auch noch gemanagte Lösung gewählt:

private Image CaptureForm()
{
    Rectangle r = this.RectangleToScreen(this.ClientRectangle);
    Image img = new Bitmap(r.Width, r.Height);
    using (Graphics gfx = Graphics.FromImage(img))
    {
        gfx.CopyFromScreen(r.Left, r.Top, 0, 0, img.Size);
    }
    return img;
}
03.09.2009 - 10:53 Uhr

Ich hab das mal übersetzt in

private Image CaptureClientAres()
{
    IntPtr hwnd = this.Handle; ;

    IntPtr hdcSrc = User32.GetWindowDC(hwnd);
    IntPtr hdcDest = GDI32.CreateCompatibleDC(hdcSrc);
    User32.RECT r = new User32.RECT();
    User32.GetWindowRect(hwnd, ref r);
    int w = r.right - r.left;
    int h = r.bottom - r.top;
    IntPtr hBitmap = GDI32.CreateCompatibleBitmap(hdcSrc, w, h);
    IntPtr hOld = GDI32.SelectObject(hdcDest, hBitmap);
    User32.PrintWindow(hwnd, hdcDest, 0x00000001);
    GDI32.SelectObject(hdcDest, hOld);
    GDI32.DeleteDC(hdcDest);
    User32.ReleaseDC(hwnd, hdcSrc);
    Image img = Image.FromHbitmap(hBitmap);
    GDI32.DeleteObject(hBitmap);
    return img;
}

Als Flag in PrintWindow habe ich nun 1 gesetzt, das eigentlich bedeuten sollte dass nur der ClientArea genommenr wird... dem ist aber trotzdem nicht so?

03.09.2009 - 09:53 Uhr

bist du dir sicher, dass du nicht bei IComponent.Site.Component geguckt hast?

Ich habe folgende Eigenschaft in meiner Komponente:

public Form ParentForm
{
    get
    {
        if (Site.Container is Form)
            return (Form)Site.Container;
        else
            return null;
    }
}

und die liefert mir null, da Site.Container keine Form ist, sondern die Komponente selbst.

Eine Component muss ja nicht zwangsweise auf einem Form eingebunden sein.

Das ist mir schon klar, deshalb prüfe ich ja.

03.09.2009 - 09:34 Uhr

Ich habe folgende Capture() Methode in einer Form, die mir ein Image (Screenshot) des Fensters liefert. Das funktioniert auch, jedoch möchte ich nur den aktiven Fensterinhalt ohne Titelleiste und Rahmen... Ich finde aber über die GetWindowRect Methode keine Möglichkeit, dies einzugrenzen.

Wie werd ich also den Rahmen los?


        private Image Capture()
        {
            if (Left < 0)
                Left = 0;
            if (Top < 0)
                Top = 0;

            IntPtr handle = this.Handle;

            // get te hDC of the target window
            IntPtr hdcSrc = User32.GetWindowDC(handle);
            // get the size
            User32.RECT windowRect = new User32.RECT();
            User32.GetWindowRect(handle, ref windowRect);
            int width = windowRect.right - windowRect.left;
            int height = windowRect.bottom - windowRect.top;
            // create a device context we can copy to
            IntPtr hdcDest = GDI32.CreateCompatibleDC(hdcSrc);
            // create a bitmap we can copy it to,
            // using GetDeviceCaps to get the width/height
            IntPtr hBitmap = GDI32.CreateCompatibleBitmap(hdcSrc, width, height);
            // select the bitmap object
            IntPtr hOld = GDI32.SelectObject(hdcDest, hBitmap);
            // bitblt over
            GDI32.BitBlt(hdcDest, 0, 0, width, height, hdcSrc, 0, 0, GDI32.SRCCOPY);
            // restore selection
            GDI32.SelectObject(hdcDest, hOld);
            // clean up 
            GDI32.DeleteDC(hdcDest);
            User32.ReleaseDC(handle, hdcSrc);
            // get a .NET image object for it
            Image img = Image.FromHbitmap(hBitmap);
            // free up the Bitmap object
            GDI32.DeleteObject(hBitmap);
            return img;
        }

        private class User32
        {
            [StructLayout(LayoutKind.Sequential)]
            public struct RECT
            {
                public int left;
                public int top;
                public int right;
                public int bottom;
            }
            [DllImport("user32.dll")]
            public static extern IntPtr GetDesktopWindow();
            [DllImport("user32.dll")]
            public static extern IntPtr GetWindowDC(IntPtr hWnd);
            [DllImport("user32.dll")]
            public static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDC);
            [DllImport("user32.dll")]
            public static extern IntPtr GetWindowRect(IntPtr hWnd, ref RECT rect);
        }

        private class GDI32
        {

            public const int SRCCOPY = 0x00CC0020; // BitBlt dwRop parameter
            [DllImport("gdi32.dll")]
            public static extern bool BitBlt(IntPtr hObject, int nXDest, int nYDest,
                int nWidth, int nHeight, IntPtr hObjectSource,
                int nXSrc, int nYSrc, int dwRop);
            [DllImport("gdi32.dll")]
            public static extern IntPtr CreateCompatibleBitmap(IntPtr hDC, int nWidth,
                int nHeight);
            [DllImport("gdi32.dll")]
            public static extern IntPtr CreateCompatibleDC(IntPtr hDC);
            [DllImport("gdi32.dll")]
            public static extern bool DeleteDC(IntPtr hDC);
            [DllImport("gdi32.dll")]
            public static extern bool DeleteObject(IntPtr hObject);
            [DllImport("gdi32.dll")]
            public static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject);
        }

03.09.2009 - 09:30 Uhr

Ein Site.Container gibt mir lediglich die Komponenteninstanz zurück, nicht aber die Form auf der die Komponente eingebunden ist. 🤔

03.09.2009 - 08:18 Uhr

Wenn ich mir ein eigenes Component ableite, so kann ich dieses ja problemlos auf eine Form ziehen (ähnlich wie NotifyIcon, OpenFileDialog usw.).

Gibt es eine Möglichkeit innerhalb meiner abgeleiteten Component Klasse dessen Beherberger heruaszufinden. Unter Delphi gabs die Eigenschaft Owner, die in diesem Fall auf meine Form verweisen würde. Unter C# finde ich aber nichts Vergleichbares?

02.09.2009 - 08:24 Uhr

Du kannst die Exception selbst im Catch-Block nochmal schmeissen, nachdem du sie weggelogt hast.


        private void pictureBox_Click(object sender, EventArgs e)
        {
            try
            {
                PictureBox pictureBox = (PictureBox)sender;
                string filename = pictureBox.Name;

                MessageBox.Show(filename);
            }
            catch (Exception ex)
            {
                // Logge die Exception ex weg (EventLog, EMail, usw.)
                throw;   // Exception nochmals schmeissen, damit sie dem User angezeigt wird und der Vorgang abgebrochen werden kann
            }
        } 
01.09.2009 - 10:25 Uhr

Hehe, der Link ist genial... Werd ich mir merken

01.09.2009 - 10:22 Uhr

Du kannst bequem über GSPrint.exe drucken (Google mal nach GhostScript und GhostView).

01.09.2009 - 10:05 Uhr

In WCF kannst du meines Wissens keine Diskriminierung machen, welches Programm sich mit dem Service verbindet. Du kannst dich zwar als Host und User authentifizieren, aber das geht dann von jedem Client (=Programm) aus, für die der Service erreichbar sein soll.

Ich weiss nicht wie sicher das Ganze werden muss, aber du könntest deinem Service z.B. eine Methode Connect offrieren, die ein Client aufrufen muss, bevor er loslegen kann andere Service Methoden aufzurufen. Der Connect Methode muss z.B. ein Passwort übergeben werden, das dann wiederum nur dein Clientprogramm kennen darf.

01.09.2009 - 09:20 Uhr

bin vor Kurzem mit meinem Lizenzgenerator fertig geworden und wollte einfach mal nachfragen was ihr davon haltet...

Ich halte von Lizenzgeneratoren allgemein rein gar nichst, und von machinengebundenen Lizenzschlüsseln noch weniger. Ich geh sogar soweit, dass wenn ich an eine machinengebundene Lizenz gezwungen bin, ich die Software gar nicht erst kaufe. Ich hab damit soviel Negativerfahrung gemacht, dass ich solchen Problemen aus dem Weg gehe. Es gibt genug Alternativsoftware, gerade im Sharewarebereich, dass ich mich sicherlich kaum gezwungen fühlen, unbedingt auf eine spezielle Applikation zu binden. Und ich hab meine Gründe: Was mach ich, wenn ich mir einen neuen Rechner zulege. Wo krieg ich einen neuen Lizenzschlüssel her, wenn es den Entwickler z.B. nicht mehr gibt. Ich weiss nicht wie professionell du deine Software vertreibst, oder ob es nur ein Hobby ist für dich. Aber wenn ich als Anwender keine neue Lizenz mehr von dir erhalten kann weil du vielleicht mittlerweilen Surflehrer auf Hawai geworden bist und die Softwareentwicklung komplett an den Nagel gehängt hast? Dann zieh ich als Anwender die A****-Karte wenn ich mir einen neuen Rechner zulege.

Was hast du von deiner Lizenz. Sie schreckt nur ab. Und wenn du wirklich eine so tolle Applikation entwickelt hast, die viele tausend User ansprechen (was ich dir ja wirklich auch wünsche), dann taucht in kurzer Zeit im Internet der erste Crack auf. Es bleibt dir also nichts anderes übrig, als auf deine ehrlichen Anwender zu setzen, die Geld für deine Anwendung ausgeben. Und dann ist es egal, ob du eine machinegebundene Lizenz hast, oder einfach z.B. nur eine Seriennummer.

Edit: DonMaxo war etwas schneller, hat aber die gleichen Grundgedanken aufgeschrieben wie ich

01.09.2009 - 08:30 Uhr

Also ich hab eine kleine Anwendung geschrieben, die je User(aus der Datenbank)einen Ordner anlegt und dann aus einem Temp Ordner (12Files) die benötigten Files in den User Ordner kopiert.

hat jemand eine idee oder ein beispiel wie ich das selbe file in einem thread in 2000 ordner kopieren kann?

Das hört sich doch an, dass du für 2000 User jeweils die gleichen 12 Files ins Userverzeichnis des jeweiligen Users kopieren musst?

Dann denke ich, ist der Ansatz über File.Copy verkehrt, weil dadurch allein die 12 Filese auch für jeden der 2000 User neu gelesen wird (12*2000=24000 Leseoperationen). Auch wenn die HD und das OS den IO cached, ist das doch ziemlich verschwenderisch. Warum also nicht einfach die 12 Files in z.B. 12 Bytearrays einlesen und diese dann einfach in deine Zielordner wegschreiben, z.B. über FileStream o.ä. Sollte erheblich performanter sein.

31.08.2009 - 11:51 Uhr

Ein timeStamp = 01.01.2009 kann natürlich nicht funktionieren.

Du könntest mit den Datumfunktionen aus T-SQL hantieren (DatePart usw.), aber bei Vergleichen mit Funktionswerten greift dein Index auf der timeStamp Spalte nicht mehr (falls du denn einen gesetzt hast). Deshalbt ist deine andere genannte Variante vorzuziehen... Alternativ, und vielleicht besser lesbar, geht auch:

where timestamp between '2009-01-01' and '2009-01-02'

28.08.2009 - 13:06 Uhr

Und das Betriebssystem, auf dem SQL Server Express läuft, kostet ja zum Glück auch nichts 😉?

Guter Einwand 😉 Frag mich jetzt natürlich wazu ich für mein XP bezahlt hab 🤔

28.08.2009 - 11:00 Uhr

Ich wäre sowieso vorsichtig, überhaupt Daten online zu speichern, und von aussen via SqlConnection drauf zugreifen. Ich weiss ja nicht, wie sensibel deine Daten sind, die du abspeichern willst, aber auf jeden Fall solltest du beachten, wo du deine Daten hostest. Selbst wenn du jetzt einen freien Hoster findest, so weisst du noch immer nicht, wie sicher das Ganze ist. Zumal du ja wohl ein Login und Passwort übermittelst, kann dies relativ leicht gesniffet werden.

Wenn du hingegen irgendwo ein virtuelles System mietest, hast du selbst den Finger drauf, und weisst, wie der Server aus Datensicherheitssicht, konfiguriert ist.

Aber trotzdem mal so als Einstieg: Wenn du über einen DSL Anschluss verfügst, kannst du auch z.B. über dyndns.org deinen Rechner über einen Internet DNS Namen versehen, an den du auch von aussen rankommst, sofern dein Router korrekt konfiguriert ist (DMZ, Firewall usw.). Einige Router erlauben sogar direkt einen dyddns.org Account... Performant wird das Ganze aber wohl nicht unbedingt werden, da deine DSL Uploadrate stark begrenzt ist.

28.08.2009 - 09:57 Uhr

Da wirst du wenig Erfolg haben, denn MSSQL verursacht beim Hoster Lizenzkosten und die muss schließlich jemand bezahlen.

Für die Express Varianten fallen auch für Hoster keine Lizenzkosten an. Aber bedingt durch die Performanceminderung der Express Versionen ist diese nicht wirklich geeignet, um zahlreiche User und Datenbanken mit grossem Traffic zu hosten.

28.08.2009 - 09:13 Uhr

Der Reader installiert automatisch ein ActiveX-Steuerelement.

Wobei aber peinlichst auf die Acrobatversion zu achten ist. Wenn der Zielrechner eine andere Acrobat Version installiert hat wie dein Entwicklungsrechner, schlägts fehl.

Eine Alternative zu Acrobat ist GPrint.exe, die in Ghostscript und Ghostview enthalten ist. Ist, finde ich, wesentlich schlanker als ein Acrobat Reader, und auch schneller beim Drucken. Über verschiedene Commandline Parameter können noch unterschiedliche Druckoptionen definiert werden: Druckername, Anzahl Kopien usw.

24.08.2009 - 16:24 Uhr

es geht mir hier um das prinzip eine anwendung von vorne bis hinten gesichert publizieren zu können ohne mir vorher ein bein abzunagen ..

Um ein gewisses Maß an Sicherheit zu erlangen kommst du kaum um eine Middleware rum: WCF, Remoting, Webservices usw. Dann kannst du bequem die Sicherheit in den Applikationsserver verlagern, d.h. deine Anwender sehen die Datenbank an sich überhaupt nicht. Authentifizierung gegen den Applikationsserver geht in Windowsdomains von Haus aus über die integrierte Windowsauthentifizierung. Soll der Server übers Internet erreichbar sein, kannst du mit Zertifikaten arbeiten. In beiden Fällen ist die Verbindung asymetrisch verschlüsselt.

24.08.2009 - 11:28 Uhr

ist die URL einmal einem potentiellen angreifer bekannt, so kann dieser die software ohne probleme installieren & zur ausführung bringen, ohne das vorher eine authentifizierung notwendig wäre! natürlich kann man beim programmstart nach einem passwort fragen etc, aber das hindert einen angreifer nicht daran sich den code zu disassemblieren und darin nach daten etc zu suchen.

Ich denke, wenn du eine Anwendung der breiten Masse zur Verfügung stellst, und in deiner Anwendung einen hardcoded ConnectionString verwendest, wirst du keine Lösung zu deinem Problem finden. Als einfache Lösung würde ich z.B. sehen, dass der Anwender beim Start seinen Login und Passwort selbst eingibt (und dann für später z.B. lokal speichert). Ohne Login und Passwort kommt so also keiner in deine DB rein.

Zum Thema Disassemblieren: Google mal nach Obfuscator. Persönlich verwende ich den Phoenix Protector. Ich habe allerdings keine Ahnung, wie man den in Verbindung mit ClickOnce verwenden kann. Aber persönlich bin ich eh kein Freund von ClickOnce und distribuiere meine Anwendungen in der Regel selbst über ein Setup. Dein Updates kannst du z.B. mit dem KUpdater erzielen.

14.08.2009 - 18:41 Uhr

Ausgangssituation:
TabelleA (ID, Number, Language, weitere Spalten) --> enthält tausende Datensätze
TabelleB (ID, Number, Text, weitere Spalten) --> ist leer

In Tabelle A gibt es die Spalte Number welche Nummern von 1 bis 8 enthält. Nun möchte ich Datensätze in Tabelle B einfügen ALLERDINGS soll hier eine Number nur einmal auftauchen.
Es dürfen also am Ende maximal 8 Datensätze existieren (1 bis 8).

Wie ist diese Aussage zu verstehen? Du hast in Tabelle A tausende von Datensätzen, alle mit einer Number zwischen 1 und 8? Was wäre dann dein auswahlkriterium, um den Datensatz herauszupicken, der letzlich in Tabelle B wandern soll?

Die Struktur von Tabelle A ist, wie es scheint, anders als die aus Tabelle B. Welchen Wert soll denn z.B. die Spalte Text in B erhalten, wenn diese Spalte so nicht in A existiert.

n.b. Der Spaltenname "Text" ist etwas ungeschickt gewählt, da es im SQL Server auch den Datentyp "Text" gibt. Um verwechslungen auszuschliessen, sollte man solche Dubletten wenn möglich vermeiden. Gleiches gilt für Spaltennamen mit Leerzeichen oder Sonderzeichen drin.

13.08.2009 - 10:02 Uhr

nun möchte ich das ganze mit einer batch datei zum laufen bekommen d.h ich will in der batch datei die .exe datei starten und in der batch datei schon feste drei parameter übergeben das problem ist ich glaub ich hab das schon hinbekommen nur er schliesst die cmd obwohl er mir noch drei werte zurück geben muss ??!?!? muss ich in c# noch etwas reinschreiben damit er das weiss oder hat das was mit der batch datei zutuhn ??

Kennst du Taste , und . und Shift schon? Ich denke wenn du willst, dass dir hier jemand hilft, dann gib dir wenigstens die Mühe, deine Frage mal ordentlich zu formulieren...

muss ich in c# noch etwas reinschreiben damit er das weiss oder hat das was mit der batch datei zutuhn ??

Wer ist er?

13.08.2009 - 09:58 Uhr

Wie sieht deine View aus... Wenn du dort ein Select * drin hast, also nicht die Kolonnen aus der Tabelle namentlich angibst, kann es zu Problemen mit solchen Views führen, wenn sich die zugrunde liegende Tabellenstruktur ändert. Dann verrutschen dir Spalten, was natürlich nachher bei der Ausführung zu Problemen führt.

13.08.2009 - 09:50 Uhr

Nein, es wird sich wohl am Sachverhalt nichts gross ändern bei uns, da wir den SQL Server nicht neu starten dürfen, nur um mal eben ein Setting auszuprobieren. Wir haben das Problem der CLR TV Funktion jetzt deswegen anders lösen müssen. Statt einer Tabelle gebe ich nun ein Commaseparated String zurück. Das kann ich deshalb machen, da es sich im Regelfall eh nur um einen Wert handelt, und in den seltensten Fällen mal um 2 oder maximal 3.

Ich hätte auch gerne mehr zu der Thematik geschrieben. Wenn wir mal Zeit haben, können wir eventuell das SQL System auf einen identischen Server clonen und dann an dem rumspielen. Dafür fehlen uns aber z.Z. die Zeit und Resourcen.

10.08.2009 - 13:16 Uhr

Derzeit ist die Logik die, dass der Updater versucht die Dateien auszutauschen und erst wenn eine Aktion (Löschen oder Kopieren) fehlschlägt es nochmals mit dem angegebenen Benutzerkonto versucht.

Ok, das war ein Denkfehler meinerseits. Ich ging davon aus, dass er immer die impersonifizierten User heranzieht. Starte ich das Programm mit RunAs unter normalen User, so wird das Update dann korrekterweise unter dem angegebenem impersonifizierten konto durchgefphrt. Soweit also alles im Lot.

Ein kleiner Designfehler hat das Ganze jedoch in meinen Augen noch. Wenn eine Aktion nicht durchgeführt werden kann, krieg ich die Wahl, das Ganze zu Wiederholen (das natürlich nochmals fehlschlägt), das Konto zu wechseln (das klappt, wenn ich denn die Logindaten eines befugten Users kenne), oder die Aktion abzubrechen. Letzteres bringt das Problem hervor, dass dadurch zwar der Updatevorgang abgebrochen wird, jedoch weil ich unter "Starten" meines Updatepakets angegeben habe, meine EXE wieder nach Update aufzurufen, erscheint der Dialog kurze Zeit später erneut. Ich bewege mich also im Kreis. 😃

Dazu noch die Frage. Wie brichst du unter diesen Umständen das Update ab. Werden erfolgreiche Updateaktionen damit auch wiederrufen, oder brichst du den Updatevorgang einfach nur ab. Es kann ja sein, dass der normale User eine Datei kopieren konnte, für eine 2. jedoch Adminrechte nötig sind. Wenn er diese nicht kennt, und das Update abbricht, wird dann die ursprüngliche Datei, die bereits durch eine neue überschrieben wurde, wieder hergestellt?

Eins noch möchte ich kurz erwähnen: Der Benutzer kriegt immer die Möglichkeit, ein Update per Klick abzubrechen. Kann man das eventuell irgendwie unterbinden. Ich möchte unter Umständen nicht, das der User überhaupt in den Updateprozess eingreifen darf. (siehe Anhang).

PS: Den Kosmetikfehler in der Anzeige aus ein paar Posts weiter oben, dass ein Update erfolgreich durchgeführt wurde, hab ich auch.

08.08.2009 - 18:47 Uhr

So, ich habe die Beta nun auch endlich testen können, und möchte natürlich auch was dazu schreiben.

  1. Ich habe mal testweise das Versionformat auf 4 Stellen gesetzt. beim updater.CurrentReleaseInfo.VersionNumber steht dann auch korrekterweise z.B. 2.0.0.0 drin. Wenn jetzt jedoch ein updater.Check() durchgeführt wird, ändert sich der Wert von updater.CurrentReleaseInfo.VersionNumber auf 2.0 Ich denke, das sollte doch auf 4 Stellen bleiben.

  2. Ich kriege die Sache mit der Impersonifikation nicht hin. Egalwas ich angebe scheint mir das Update immer unter dem eingeloggten User zu laufen. Muss da am Client nocht was übergeben werden oder wie läuft das Update ab.

  3. Ein kleiner Tippteufel hat sich noch eingeschlichen: Im Versions-Updates Tab steht statt Beschreibung (English) ein Beschriebung.

Naja... ist mal das was mir als erstes aufgefallen ist.


SelfUpdate updater = new SelfUpdate();


updater.ServerAuthentication.Mode = DataTypes.ServerAuthenticationMode.None;
updater.CurrentReleaseInfo.VersionNumber = Assembly.GetExecutingAssembly().GetName().Version.ToString();
updater.GuiLanguage = DataTypes.Language.German;
updater.UpdatePath = "http://www.tp-soft.de/appdater/test";


DataTypes.UpdateCheckResult check = updater.Check();

if (check.Result == DataTypes.ResultType.UpdateAvailable)
{
    updater.HideOkMessage = true;
    updater.DoUpdate();
}

31.07.2009 - 16:10 Uhr

Kenne mich überhaupt nicht mit installern aus

Installer gibts zu genüge auf dem Markt.

Wenns kommerziell sein darf: InstallShield, InstallAware
Wenns für umme sein soll: WiX

Alle bisher genannten basieren auf MSI, das aber in meinen Augen nicht immer notwendig ist, wenn es um kleinere Setups geht ohne grosse Abhängigkeiten zu anderen Paketen. Füpr solche Zwecke nutze ich privat den Astrum Installwizard. Ist zwar schon ein paar Monate her seit ich zuletzt damit was erstellt habe, war aber immer wirklich damit zufrieden.

Es gibt aber noch weitere wie InnoSetup um nur noch einen zu nennen.

31.07.2009 - 11:31 Uhr

Steht sogar in Einsteigerbüchern:

>

Was ich noch vergessen hab... Gerade in dem genannte Buch steht auch (Absatz vor 31.2.1):

Das Ziel von ClickOnce ist, die Verteilung von Anwendungen zentral zu verwalten und zu vereinfachen. Aber es gibt auch Einschränkungen, die schon in der Planungsphase zu berücksichtigen sind. Während der Einrichtung einer ClickOnce-Anwendung sind keine Operationen erlaubt, die administrative Rechte voraussetzen. Dazu gehören der Zugriff auf das Dateisystem und der Zugriff auf die Registrierungsdatenbank. Genauso wenig können Assemblys in den Global Assembly Cache (GAC) eingetragen oder Windows-Dienste eingerichtet werden.

Was ich ja auch schon oben erwähnte. Und wenn keine administrative Aufgaben erledigt werden können, dann reicht ein simples xcopy auch aus, und ClickOnce wird damit überflüssig und müllt beim Client nicht das Profil voll

31.07.2009 - 10:11 Uhr

Anschließend wird die vollständige aktualisierte Anwendung von einem neuen parallelen Ordner aus neu installiert.

Dass es so ist, wissen wir ja. Und nur weil es so designt ist, heisst das für mich noch lange nicht, dass ich es auch für gut empfinde.

31.07.2009 - 10:03 Uhr

anderseits wird der veröffentlichte Key vermutlich fast ausschließlich den Raubkopieren und nicht den ehrlichen Benutzern nützen, so dass ich die Veröffentlichung nicht gutheißte

Dem stimm ich 100% zu. Ehrliche Kunden werden genervt und müssen dafür zahlen (diese ganz Aktivierungspolitik muss ja auch entwickelt werden), weil Raubkopierer sich einen Sch*** drum kümmern. Das ist aber ein Phenomen unserer Gesellschaft geworden, eben zu meinen, man müsste immer alles wie ein Fort Knox sichern (Alarmanlagen überall wo man hinsieht, Überwachungskameras usw.)

Eine kleine Anekdote, weils irgendwie doch zum Thema passt:

Ich war mal in Schottland in einer kleinen 30000 Seelenstadt, da war der Alltag in einer ganz unbekannten Ausprägung. Die Leute, die dort wohnen, scheinen so ehrlich miteinander umgehen zu können, dass es dort keine einzigen Supermarkt mit RFID Detektoren gibt, dass 50% der Leute ihre Wagen mitten in der Stadt nicht abschliessen, und dass selbst Haustüren nicht abgeschlossen werden. Mein Bekannter von dort erklärte mir, dass das eben hier so sei. Bislang hat noch keiner schlechte Erfahrungen gemacht, also warum einen immensen Aufwand betreiben, um sich vor Übeltätern zu schützen, die es dort gar nicht gibt. Hätt ich's nicht liver miterlebt, würd ich's nicht glauben. Und glaubt mir, der Alltag war dort sowas von entspannt und geprägt mit einem unzwanghaften und lockeren Umgang mit den anderen, dass es ein wahrer Genuss war.