Für eine Autostart Anwendung trifft das jetzt nicht zu, aber wenn du einen Dienst (also windows-Service) implementierst, kannst du Abhängigkeiten für den Start definieren, in deinem Fall also TFSService und der Netzwerklaufwerke-Client-Dienst (sofern es den gibt ;-))
Wenn du keinen Service willst, würde ich aber auch einfach auf die Preconditions checken.
Das ist nicht so einfach. Unsere Anwendung besteht nur zum Teil aus .Net-Programmen. Der überwiegende Teil sind zurzeit unmanaged COBOL-Dlls (ca. 2.000 Stück). Das macht wohl keinen Sinn, die jedes Mal alles in jedes Projekt zu kopieren.
Du musst sie nicht jedes mal kopieren ein Repository zeichnet sich ja grade dadurch aus, dass es nur geänderte Dateien überträgt. Und den Rest schafft man wie winsharp93 schon gesagt hat mit ein paar Post-Build-Events und Robocopy ...
Zitat von xdaniel
Mein beschriebenes Problem kenne ich aus anderen Entwicklungsumgebungen nicht, dort spielt es keine Rolle, welchen Stand die DLL im Anwendungsordner hat. Es wird immer die aktuelle aus dem Projektverzeichnis verwendet.
Daher hätte ich gehofft, dass ich diese Möglichkeit in Visual Studio bislang nur einfach noch nicht gefunden habe.
Wie willst du ordentlich debuggen, wenn es nicht die gleichen sind?
Für mich klingt das nach einem Fall in dem ein Repository wahre Wunder wirken könnte: zum Beispiel GIT oder Mercurial.
Damit könnte jeder eine Lokale Kopie der zentralen Anwendung haben und diese auf seinem PC starten. Dann hat man keine Probleme mit Locks, unstabilen Versionen auf dem Share oder ähnlichem.
Gute Idee, aber würde dann nicht eine Meldung beim Boot-Vorgang erscheinen?
Das wäre dann vielleicht noch verwirrender für die Leute
Nein - dann würde dich ja jeder Windows-(nicht-unbedingt-von-MS)-Dienst fragen, der als System läuft, ob er starten darf - ich vermute so etwas hast du bisher noch nicht gesehen. Das wird bereits bei der Installation vom Dienst festgelegt und dort kommt dann die Abfrage nach erhöhten Rechten.
Ich hab mir keine direkten Notitzen gemacht, aber es ist eine LSA-Fehlermeldung, dass GroupPrincipals nicht aufgelöst werden können (in diesem Fall), die undefiniert auftritt. Ich hab 4 Server in einer kleinen Farm, davon waren 2 ständig betroffen und einer zeitweise betroffen.
Ich habe dann GetAuthorizationGroups über das underlyingObject und die tokenGroups-Property nachgebaut - nur löse ich die Gruppen dann von Hand auf und nicht wie der LSA das tut auf einen Schlag.
Andere Unzulänglichkeiten hab ich selbst noch nicht bemerkt, aber in StackOverflow gabs einige Hinweise zu offenen Bugs (mit Connect-Link).
Mehr kann ich aber auch nicht sagen.
Fall 1) Windows-Authentifizierung (Kerberos)
Der Benutzer bekommt bei der Anmeldung ein Kerberos-TGT (Ticket-Granting-Ticket), das heißt er darf sich selbst Tickets für bestimmte Ressourcen (DB, Files, Webseiten, etc.) ausstellen. In diesem TGT ist auch der Gruppenvektor des Benutzers enthalten. Selbiger wird beim Login aktualisiert.
Fall 2) Die Anwendung sucht den Benutzer im AD und fragt seine Rollen ab
Die Anwendung kennt nur den Benutzernamen und holt sich die Gruppen im AD. Das führt dazu, dass (sofern nicht gecacht wird) der Gruppenvektor immer aktuell ist - nutzt man NTLM oder AccountManagement (.NET) werden dabei die APIs von LSA benutzt. Ob selbiger einen Cache hat oder nicht kann ich nicht sagen.
Man sollte beachten, dass der AccountManagement Namespace und die von Abt angesprochenen Principals (User und Computer) GetGroups() und GetAuthorizationGroups() anbieten. Ersteres liefert alle DIREKTEN Gruppen und DistributionGroups, letzteres leifert alle Sicherheitsgruppen (auch rekursive). Um die rekursiven Gruppen zu lesen, muss der lesende Account Mitglied in "Windows Authorization Access" sein (das ist eine Well-Known-Group im AD).
GetGroups() ruft im übrigen "MemberOf" des Benutzers ab und GetAuthorizationGroups() ruft "tokenGroups" auf.
Der AccountManagement-Namespace hat aber einige Bugs, die dazu führen können, das GetAuthorizationGroups() nicht funktioniert, weshalb sich ein eigener Rekursiver aufruf von GetGroups als alternative lohnen kann - natürlich nur, wenn vorher GetAuthorizationGroups() gescheitert ist, das ist nämlich deutlich performanter.
Der WebServer steht unter meiner Kontrolle und ich habe somit kein Partial-Trust o.Ä. Der Pool-Benutzer ist ein Domänen-Account.
Folgendes passiert nun:
Applikation als AppPoolUser --> Proxy wird verwendet
Applikation als Domänen-Account --> Proxy wird nicht verwendet
Domänen-Account in (lokaler) Administrator-Gruppe --> Proxy wird verwendet.
Via netsh winhttp ist der Proxy eingetragen und auch für den Benutzer-Account in IE eingetragen.
Die Applikation kann aber auf Dauer nicht als AppPoolUser laufen und Admin-Rechte soll sie natürlich auch nicht haben.
Hat jemand damit Erfahrung, warum so etwas auftritt?
//Ergänzung:
Ich habe den Domänen-Benutzer auch schon in anderen Gruppen untergebracht, wie z.B. IUSRS, Domain Users, Lokaler Benutzer, etc. pp. und auch jedes mal neu gestartet - aber nix hilft ...
was häufig klappt um dinge zu verarbeiten, die eigentlich nicht automatisiert werden "wollen" ist das Ausführen der Anwendung per ProcessInfo.Start().
Im schlimmsten Fall musst du dann die Ergebnisse dieses Programms in eine Datei schreiben lassen und sie von dort wieder laden.
Das mag zwar nicht elegant sein, funktioniert aber fast immer.
Entweder konstruierst du deinen SQL Befehl einfach selbst (auf jeden Fall parameterisiertes SQL benutzen!) oder du schaust dir mal das Entity-Framework an - letzteres kann auch mit zusammengesetzen Schlüsseln arbeiten.
Ich wollte nicht sagen, dass dein Vorschlag blödsinn ist - was aber mein Problem angeht, so liefert es keine Lösung.
Ich nun auch die ViewBags entfernt. Aber es bleibt dabei - model.DisplayName im DropDownListFor führt zum falschen markierten Eintrag.
Die Änderung der Selektion passiert beim Aufruf von DropDownListFor - vorher ist die Selektion ja korrekt. Und wie gesagt - ein anderer Name umgeht das Problem - das ist nicht optimal, aber reicht mir für den Moment.
Ich hätte gerne mit dem Debugger reingeschaut, aber weder der MS Symbol-Server noch Reflector erlauben mir das - und zum eindinden der MVC3 Quellen war ich .. nicht motiviert genug.
Ich habe es mal genauer betrachtet - ein Umbenennen von DisplayName > DisplayedName bringt den gewünschten Erfolg.
Lieber wäre es mir allerdings, wenn ich wüßte, warum das nicht mit "DisplayName" funktioniert.
Das auswählen und generieren einer SelectList aus einer anderen Liste kann man im Übrigen durchaus als "View-Logik" bewerten, weshalb es in der View stehen darf - zumindest hier bei uns.
ist aber leider der erste Eintrag markiert. Kurz vor der Ausführung, ist die SelectList noch in Ordnung (geprüft mit dem Debugger).
Ein weiteres Feld mit dem Namen "DisplayName" existiert nicht und es wird auch im QueryString kein solcher Name übergeben.
Ein Label, dass den gleichen Inhalt wie die DropDown-Box hat, zeigt den erwarteten Text an.
also deine Verschlüsselung kannst du dir (wenn sie Synchron ist) getrost sparen - synchrone verschlüsselung mit öffentlichen Schlüsseln bringt in etwa .... nichts. (Deshalb war auch dieses Xpire-Bild-selbst-lösch-System nichts wert)
Viel wichtiger wäre es das ganze in HTTPS (oder ein anderes asynchrones Verschlüsselungsverfahren) zu kapseln, aber das nur am Rande.
Du könntest anstatt diese Antwort zu senden auch ein Cookie senden, wo du genau den String reinschreibst.
Egal wie - da REST ja eher JSON und XML spricht anstatt von Klassen kannst du sicherlich (hab's nicht geprüft - ich vermute nur grade) auch einfach einen String zurückgeben.
Für eine Session-Basierte authentifizierung, würdest du klassischerweise wohl ein Session-Cookie erzeugen, das eine genügend Randomisierte generierte Zahl enthält, die du dann mitsendest.
Auf Serverseite speicherst du das entweder in HTTPContext.Session (das ist allerdings wohl nicht "REST-Konform" (sofern es letzteres überhaupt gibt) oder du speicherst es in eine Datenbank (macht auch ne Serverseitige Session).
Du kannst aber auch sowas wie NTLM oder die Basic-Authentifizierung benutzen, dabei wird jedesmal die Authentifizierung mitgesendet (was im Kontext von REST wohl der "richtige" Weg wäre).
Zwei Dinge:
1) REST als solches sollte Zustandslos sein (so sagt es zumindest Wiki)
2) Da du offensichtlich HTTP verwendest, solltest du auch HTTP-Standard-Mechanismen zur Authentifizierung verwenden.