Announcement

Collapse
No announcement yet.

.NET Anwendung von einem Server starten

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • .NET Anwendung von einem Server starten

    Hallo zusammen,
    also irgendwie verstehe ich es nicht. Ich habe eine kleine Anwendung geschrieben, die von einem ApplicationServer aus gestertet werden soll. Jetzt habe ich das Programm mit allen nötigen Dateien auf den Server kopiert, und mir das Laufwerk per Mapping zugeordnet. Jetzt kommt eine Fehlermeldung. dass ich nicht genug Berechtigungen habe. Dann habe ich für jeden Benutzer volle Zugriffsrechte gesetzt (Ordner der Dateien). Aber die Medlung kommt nach wie vor. Was mache ich denn jetzt schon wieder falsch?

    Gruß

    Sascha

  • #2
    Hallo,
    wenn eine .NET-Anwendung nicht vom lokalen Laufwerk aus gestartet wird, führt die CLR die Anwendung automatisch in einem Sandkasten aus, der nur eingeschränkte Rechte hat. Beim Start über ein gemapptes Netzlaufwerk sind die Rechte der Zone <b>Intranet</b> aktiv. In diesem Fall greift das strenge Regelwert der <i>Code Access Security</i> (CAS), wobei für CAS die Rechte des Benutzerkontos keine Rolle spielen (d.h. auch ein Administrator des Active Directory erhält das gleiche Veto, unabhängig von seinen NTFS-Zugriffsrechten auf dem Server). Für CAS entscheidend ist die Frage, von wo aus ein ausführbares .NET-Modul geladen wurde. Bei jedem Verstoß würgt eine <i>System.Security.Permissions.SecurityPermissio n</i> den unerlaubten Zugriff ab. Es stehen mindestens 4 Alternativen zur Verfügung, um dieses Verhalten zu ändern:
    <br>
    1.) In einem Firmennetzwerk kann der Administrator die einmalig von Hand zusammengestellte Richtlinienstruktur über den Weitergabepaket-Assistenten der .NET Framework-Konfiguration als MSI-Setup zusammenpacken. Diese Setup überschreibt dann bei den zu konfigurierenden Rechnern die Standard-Einstellung durch die definierte Richtlinienstruktur des Unternehmens. <br>
    2. Während der Weitergabepaket-Assistent der .NET Framework-Konfiguration eine „Alles-oder-Nichts“-Lösung ist, erlaubt das Kommandozeilen-Tool <b>caspol.exe</b> einen chirurgischen Eingriff, indem ein Script die Konfiguration einer zusätzlichen Codegruppe übernimmt. <br>
    3. Das Installationsprogramm der .NET-Anwendung (MSI-Setup) wird um eine Installer-Klasse erweitert, die die benötigte Codegruppe während des Setups anlegt. Allerdings gilt auch hier, dass zur Änderung der Computer-Berechtigungsgruppen für das Setup die Administrator-Rechte benötigt werden. <br>
    4. Der CodeGroup-Eintrag wird über die <b>.NET Framework Configuration</b> von Hand angelegt.

    <br>
    In dem Artikel <i>Gesprengte Fesseln</i> (Auswirkungen der Code Access Security auf das Setup der Anwendung) des <b>dot.net magazin 1/2.06</b> habe ich ein Setup-Programm vorgestellt, dass die Sandkasten-Rechte für die eigenen Anwendungen automatisch erweitert. Der folgende Auszug beschreibt das Verfahren:

    "<i>Von den verfügbaren Optionen erfüllt das MSI-Setup der Beispielanwendung die Anforderungen am Besten - denn im Normalfall soll die Anwendung ja auch lokal installiert werden. Nur für den Fall, dass eine Unternehmensrichtlinie den lokalen Aufruf nicht vorsieht, wird die Codegruppe für FullTrust-Berechtigung angelegt, so dass die Anwendung auch dann noch problemlos aufgerufen werden kann, wenn diese nur von einem Netzlaufwerk aus gestartet werden soll.

    Nachdem das Grundgerüst des Setup-Projekts steht, wird der Projektmappe ein weiteres Projekt für eine Klassenbibliothek hinzugefügt. Damit das MSI-Setup die neue Klasse einbindet, muss diese von <b>System.Configuration.Install.Installer</b> abstammen und mit dem Attribut <b>[RunInstaller(true)]</B> gekennzeichnet werden. Der einfachste Weg, eine derartige Klasse zu erhalten, führt über die Vorlage Installer Class – so dass nur noch die geerbten Methoden Install, Commit und Uninstall überschrieben werden müssen. Einen Anhaltspunkt über die notwendigen Schritte findet sich in [3], so dass die Checkliste für eigene Anpassungen sehr kurz ist:<br>
    a) Es wird ein sprechender, eindeutiger Name für die neue Codegruppe festgelegt. <br>
    b) Da der Strong Name für die Zuordnung herangezogen werden soll, muss auf StrongNameMembershipCondition zurückgegriffen werden. Über die StrongNamePublicKeyBlob-Klasse werden die öffentlichen Schlüsselinformationen des Strong Name aufbereitet, wobei die Rohdaten vom Kommandozeilen-Tool secutil.exe stammen. Mit dem Aufruf »secutil -c -s VBWinApp.exe > output.txt« schreibt dieses Tool die gesuchte Information in eine Datei, wobei dann die Public Key-Zeichenkette über die Zwischenablage in das Klassenbibliotheks-Projekt kopiert wird. <br>
    c) Die Klassenbibliothek wird mit in das Setup-Projekt aufgenommen.<br>
    d) Im Setup-Projekt wird der Custom Actions-Editor aufgerufen, um jeweils in den Ordnern Install, Commit und Uninstall einen Verweis auf die Klassenbibliothek mit der Installer-Klasse hinzuzufügen (Abbildung 3).

    Damit sind alle Zutaten fertig. Wenn die Anwendung über das Setup auf einem Rechner installiert wird, richtet das Setup dabei die eigene Codegruppe dotnetMagazin ein. Falls nun der Anwender die Programmdateien auf einem Netzlauf ablegt, kann er die Anwendung trotzdem uneingeschränkt nutzen. <br>
    Wird das Programm später über die SYSTEMSTEUERUNG | SOFTWARE wieder deinstalliert, räumt die eigene Installer-Klasse auch die Codegruppe dotnetMagazin wieder ab.</I>" (Zitat Ende)
    <br>
    Der eigene <b>Installer</b>-Nachfolger sieht wie folgt aus:
    <code>
    <font color="#0000FF">using</font> System;
    <font color="#0000FF">using</font> System.Collections;
    <font color="#0000FF">using</font> System.ComponentModel;
    <font color="#0000FF">using</font> System.Configuration.Install;
    <font color="#008000">//</font>
    <font color="#0000FF">using</font> System.Security;
    <font color="#0000FF">using</font> System.Security.Permissions;
    <font color="#0000FF">using</font> System.Security.<font color="#008080">Policy</font>;

    <font color="#0000FF">namespace</font> CodeGroupInstaller
    {
    <font color="#008000">/// &lt;summary&gt;</font>
    <font color="#008000">/// Richtet die CodeGroup dotnetMagazin mit FullTrust für die mit einem bestimmten</font>
    <font color="#008000">/// Strong Name signierten Assemblies ein.</font>
    <font color="#008000">/// Gerüst aus dem Microsoft Dev Days 2004 Source Project IssueVision </font>
    <font color="#008000">/// (http://www.windowsforms.net/Applications/application.aspx?PageID=40&tabindex=8)</font>
    <font color="#008000">/// &lt;/summary&gt;</font>
    [RunInstaller(<font color="#0000FF">true</font>)]
    <font color="#0000FF">public</font> <font color="#0000FF">class</font> InstallerCodeGroup : System.Configuration.Install.Installer
    {
    <font color="#008000">/// &lt;summary&gt;</font>
    <font color="#008000">/// Required designer variable.</font>
    <font color="#008000">/// &lt;/summary&gt;</font>
    <font color="#0000FF">private</font> System.ComponentModel.<font color="#008080">Container</font> components = <font color="#0000FF">null</font>;

    <font color="#0000FF">public</font> InstallerCodeGroup()
    {
    <font color="#008000">// This call is required by the Designer.</font>
    InitializeComponent();
    <font color="#008000">// Add any initialization after the InitializeComponent call</font>
    }

    <font color="#008000">/// &lt;summary&gt; </font>
    <font color="#008000">/// Clean up any resources being used.</font>
    <font color="#008000">/// &lt;/summary&gt;</font>
    <font color="#0000FF">protected</font> <font color="#0000FF">override</font> <font color="#0000FF">void</font> Dispose( <font color="#0000FF">bool</font> disposing )
    {
    <font color="#0000FF">if</font>( disposing )
    {
    <font color="#0000FF">if</font>(components != <font color="#0000FF">null</font>)
    {
    components.Dispose();
    }
    }
    <font color="#0000FF">base</font>.Dispose( disposing );
    }

    #<font color="#0000FF">region</font> <font color="#008080">Component</font> Designer generated code
    <font color="#008000">/// &lt;summary&gt;</font>
    <font color="#008000">/// Required method for Designer support - do not modify</font>
    <font color="#008000">/// the contents of this method with the code editor.</font>
    <font color="#008000">/// &lt;/summary&gt;</font>
    <font color="#0000FF">private</font> <font color="#0000FF">void</font> InitializeComponent()
    {
    components = <font color="#0000FF">new</font> System.ComponentModel.<font color="#008080">Container</font>();
    }
    #<font color="#0000FF">endregion</font>

    <font color="#0000FF">private</font> <font color="#0000FF">string</font> LevelName = "Machine";
    <font color="#0000FF">private</font> <font color="#0000FF">string</font> CodeGroupName = "dotnetMagazin";

    <font color="#008000">/// &lt;summary&gt;</font>
    <font color="#008000">/// Codegruppe beim Installieren anlegen</font>
    <font color="#008000">/// &lt;/summary&gt;</font>
    <font color="#008000">/// &lt;param name="stateSaver"&gt;&lt;/param&gt;</font>
    <font color="#0000FF">public</font> <font color="#0000FF">override</font> <font color="#0000FF">void</font> Install(System.Collections.IDictionary stateSaver)
    {
    <font color="#0000FF">base</font>.Install(stateSaver);
    <font color="#0000FF">try</font>
    {
    <font color="#008000">// Erzeugt mit "secutil -c -s VBWinApp.exe"</font>
    <font color="#0000FF">byte</font>[] AppStrongNamePublicKey = { 0, 36, 0, 0, 4, 128, 0, 0, 148, 0, 0, 0, 6, 2, 0, 0, 0, 36, 0, 0, 82, 83, 65, 49, 0, 4, 0, 0, 1, 0, 1, 0, 133, 193, 96, 5, 82, 44, 240, 22, 106, 196, 254, 134, 122, 61, 98, 143, 109, 236, 227, 247, 235, 58, 193, 74, 181, 47, 152, 117, 1, 143, 171, 196, 51, 0, 168, 250, 198, 22, 120, 165, 55, 20, 197, 217, 173, 106, 149, 149, 113, 172, 39, 3, 28, 229, 168, 102, 27, 202, 197, 200, 22, 148, 177, 71, 242, 95, 107, 40, 141, 165, 116, 87, 78, 146, 16, 103, 133, 235, 37, 103, 249, 55, 30, 111, 24, 42, 109, 105, 232, 208, 122, 45, 37, 247, 139, 24, 141, 67, 8, 90, 149, 188, 212, 170, 233, 149, 127, 183, 9, 241, 243, 83, 183, 183, 94, 219, 126, 133, 219, 55, 24, 36, 28, 224, 57, 87, 73, 162 };
    <font color="#008080">StrongNamePublicKeyBlob</font> aSNPKB = <font color="#0000FF">new</font> <font color="#008080">StrongNamePublicKeyBlob</font>(AppStrongNamePublicKey);
    <font color="#008000">// Nur Strong Name, kein Dateiname und keine Version berücksichtigen</font>
    <font color="#008080">StrongNameMembershipCondition</font> aSNMC = <font color="#0000FF">new</font> <font color="#008080">StrongNameMembershipCondition</font>(aSNPKB, <font color="#0000FF">null</font>, <font color="#0000FF">null</font>);
    <font color="#008000">// Code Access Security konfigurieren</font>
    CreateRootCodeGroup(LevelName, CodeGroupName,
    "FullTrust für Strong Name »DotNetMagNetzwerk.snk« ",
    aSNMC, <font color="#0000FF">new</font> <font color="#008080">NamedPermissionSet</font>("FullTrust"));
    }
    <font color="#0000FF">catch</font>
    {
    }
    }

    <font color="#0000FF">public</font> <font color="#0000FF">override</font> <font color="#0000FF">void</font> Commit(System.Collections.IDictionary stateSaver)
    {
    <font color="#0000FF">base</font>.Commit(stateSaver);
    <font color="#008080">SecurityManager</font>.SavePolicy();
    }

    <font color="#008000">/// &lt;summary&gt;</font>
    <font color="#008000">/// Codegruppe beim Deinstallieren wieder entfernen</font>
    <font color="#008000">/// &lt;/summary&gt;</font>
    <font color="#008000">/// &lt;param name="stateSaver"&gt;&lt;/param&gt;</font>
    <font color="#0000FF">public</font> <font color="#0000FF">override</font> <font color="#0000FF">void</font> Uninstall(System.Collections.IDictionary stateSaver)
    {
    <font color="#0000FF">base</font>.Uninstall(stateSaver);
    <font color="#0000FF">try</font>
    {
    RemoveRootCodeGroup(LevelName, CodeGroupName);
    <font color="#008080">SecurityManager</font>.SavePolicy();
    }
    <font color="#0000FF">catch</font>
    {
    }
    }

    #<font color="#0000FF">region</font> PrivateMethoden

    <font color="#008000">/// &lt;summary&gt;</font>
    <font color="#008000">/// Neue CodeGroup unterhalb von All_Code anlegen</font>
    <font color="#008000">/// &lt;/summary&gt;</font>
    <font color="#008000">/// &lt;param name="level"&gt;Machine&lt;/param&gt;</font>
    <font color="#008000">/// &lt;param name="name"&gt;CodeGroup-Name&lt;/param&gt;</font>
    <font color="#008000">/// &lt;param name="description"&gt;Beschreibung&lt;/param&gt;</font>
    <font color="#008000">/// &lt;param name="membership"&gt;StrongNameMembershipCondition &lt;/param&gt;</font>
    <font color="#008000">/// &lt;param name="permissions"&gt;NamedPermissionSet("FullTrus t")&lt;/param&gt;</font>
    <font color="#0000FF">private</font> <font color="#0000FF">static</font> <font color="#0000FF">void</font> CreateRootCodeGroup(<font color="#0000FF">string</font> level, <font color="#0000FF">string</font> name, <font color="#0000FF">string</font> description, IMembershipCondition membership, <font color="#008080">PermissionSet</font> permissions)
    {
    <font color="#008080">CodeGroup</font> aUCG = <font color="#0000FF">new</font> <font color="#008080">UnionCodeGroup</font>(membership, <font color="#0000FF">new</font> <font color="#008080">PolicyStatement</font>(permissions));
    aUCG.Name = name;
    aUCG.Description = description;
    <font color="#008080">CodeGroup</font> aRootGroup = FindPolicyLevel(level).RootCodeGroup;
    aRootGroup.AddChild(aUCG);
    }

    <font color="#008000">/// &lt;summary&gt;</font>
    <font color="#008000">/// CodeGroup entfernen</font>
    <font color="#008000">/// &lt;/summary&gt;</font>
    <font color="#008000">/// &lt;param name="level"&gt;Machine&lt;/param&gt;</font>
    <font color="#008000">/// &lt;param name="name"&gt;CodeGroup-Name&lt;/param&gt;</font>
    <font color="#0000FF">private</font> <font color="#0000FF">static</font> <font color="#0000FF">void</font> RemoveRootCodeGroup(<font color="#0000FF">string</font> level, <font color="#0000FF">string</font> name)
    {
    <font color="#008080">CodeGroup</font> aRootGroup = FindPolicyLevel(level).RootCodeGroup;
    <font color="#008080">CodeGroup</font> aCustomGroup = FindCodeGroup(aRootGroup, name);
    aRootGroup.RemoveChild(aCustomGroup);
    }

    <font color="#0000FF">private</font> <font color="#0000FF">static</font> <font color="#008080">PolicyLevel</font> FindPolicyLevel(<font color="#0000FF">string</font> label)
    {
    IEnumerator levels = <font color="#008080">SecurityManager</font>.PolicyHierarchy();
    <font color="#0000FF">while</font> (levels.MoveNext())
    {
    <font color="#008080">PolicyLevel</font> level = (<font color="#008080">PolicyLevel</font>)levels.Current;
    <font color="#0000FF">if</font> (level.<font color="#008080"><font color="#008080">Label</font></font> == label)
    {
    <font color="#0000FF">return</font> level;
    }
    }
    <font color="#0000FF">return</font> <font color="#0000FF">null</font>;
    }

    <font color="#0000FF">private</font> <font color="#0000FF">static</font> <font color="#008080">CodeGroup</font> FindCodeGroup(<font color="#008080">CodeGroup</font> parent, <font color="#0000FF">string</font> name)
    {
    IList children = parent.Children;
    <font color="#0000FF">foreach</font> (<font color="#008080">CodeGroup</font> child <font color="#0000FF">in</font> children)
    {
    <font color="#0000FF">if</font> (child.Name == name)
    {
    <font color="#0000FF">return</font> child;
    }
    }
    <font color="#0000FF">return</font> <font color="#0000FF">null</font>;
    }

    #<font color="#0000FF">endregion</font>
    }
    }
    </code&gt

    Comment

    Working...
    X