Laden...

Zentrales Verzeichnis für DLLs erstellen, aus dem jedes Programm lesen kann

Erstellt von Hummakavula vor 7 Jahren Letzter Beitrag vor 7 Jahren 3.765 Views
H
Hummakavula Themenstarter:in
7 Beiträge seit 2016
vor 7 Jahren
Zentrales Verzeichnis für DLLs erstellen, aus dem jedes Programm lesen kann

Hallo Allerseits,

ich möchte gerne ein Verzeichnis erstellen z.B. "C:\C#_DLLs" in dem alle meine Standardbibliotheken liegen (DruckDLL, EMailDLL usw.). Alle "Released"-Programme sollen die benötigten Bibliotheken in diesem Verzeichnis suchen und natürlich auch finden.
Die System-Path - Variable habe ich schon gesetzt.

Wenn ich jetzt mit VS2015 die Release-Version erstelle z.B. in C:\MeinProgramm\ liegt dort die EXE und auch meine Referenz-DLLs. Die DLLs sollen aber im obigen Verzeichnis liegen. Wenn ich manuell die DLLs umkopiere/verschiebe, startet das Programm nicht mehr.

Leider finde ich dazu keine rechte Anleitung. Es ist bestimmt ganz einfach.

Danke schonmal für evtl. Hilfe

3.170 Beiträge seit 2006
vor 7 Jahren

Hallo,

mehrere Möglichkeiten:

  1. GAC
    Du kannst Deine DLLs statt in einen eigenen Ordner, in den GAC installieren. Dann werden sie von jeder .NET-Anwendung gefunden.

  2. Referenzen anpassen
    Stell Deine DLL-Projekte so ein, dass sie direkt in Deinen Zielpfad bauen, oder kopiere diese von Hand dahin. Passe dann in dem Projekt, das die DLLs verwenden soll, die Referenzen (im Eigenschaftenfenster) so an, dass nicht mehr die Projekte, sondern die DLLs direkt verwiesen werden, und dass "Copy local" auf false steht. Dann müsste die DLL immer in diesem Verzeichnis gesucht werden.

  3. AppDomain.AssemblyResolve
    Du kannst mit den Anwendungen, die die DLLs nutzen sollen, das AppDomain.AssemblyResolve-Ereignis abonnieren und dort den gewünschten Pfad selbst auflösen.

Bei all diesen Möglichkeiten bedenke aber Folgendes:
Wenn Du die DLLs an einem zentralen Ort ablegst, bekommst Du ein Problem, wenn Du in einer der gemeinsam genutzten DLLs einen "Breaking Change" machst, müssen ggf. alle Anwendungen aktualisiert werden. Wenn Du wie bisher mit lokalen Kopien der DLLs arbeiuest, bekommst Du dieses Problem nicht.

Gruß, MarsStein

Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca

1.040 Beiträge seit 2007
vor 7 Jahren

Kannst du kurz erläutern, was dein Ziel ist? 🤔

H
Hummakavula Themenstarter:in
7 Beiträge seit 2016
vor 7 Jahren

@MarsStein:

Schritt 2 werde ich mal probieren. Das klingt nach dem was ich suche.

@p!lle:

Mein Ziel: Ich habe einen Haufen kleine Progrämmchen, die Prozesse vereinfachen sollen. Jedes Programm nutzt dabei immer meine DruckDLL oder meine AdressDLL usw. Diese DLLs werden eigentlich nie geändert und wenn, bin ich mir bewusst, das alle Programme neu kompiliert werden müssen.

a) aus Platzgründen muss nicht in jedem Programmverzeichnis die DLL stehen, die sowieso jedes Programm benutzt.
b) der Übersicht halber. Ziel ist es in den jeweiligen Verzeichnissen wenn möglich nur die EXE und jeweiligen Daten liegen zu haben.
c) so kann ich theoretisch die EXE irgendwohin kopieren und dann dort ausführen.

16.806 Beiträge seit 2008
vor 7 Jahren

Ganz so funktioniert .NET bzw. allgemein der Umgang mit DLLs nicht.
Siehe: How the Runtime Locates Assemblies

Assemblies im GAC müssen einen Strong Name besitzen.

Aber um ehrlich zu sein: das, was Du da vor hast ist genau das, was man heute nicht mehr will 😉
Wenn das für Dich persönlich so ist; dann mach das, was Dich weiter bringt. Ich rate aber massiv davon ab, das für größere Dinge oder Dritte zu nutzen.

P
1.090 Beiträge seit 2011
vor 7 Jahren

zu a) Platz sollte wirklich keine Rolle spielen.

zu b) Wenn du nur 1 Exe haben willst schau dir mal ILMerge an.

zu c) Die Exe mal eben auf einen anderen Rechner kopieren und Ausführen geht so nicht. Und lokal die Exe hin und her zu Kopieren machen jetzt die wenigsten.

Ich würde dir auch davon abraten, im Endeffekt macht es mehr Probleme als es Vorteile hat.

Sollte man mal gelesen haben:

Clean Code Developer
Entwurfsmuster
Anti-Pattern

H
Hummakavula Themenstarter:in
7 Beiträge seit 2016
vor 7 Jahren

fast alle Programme, die ich schreibe sind kleine Tools, manchmal sogar nur für eine einmalige Verwendung (Datenaufbereitung, kleine Werteerfassung, Importtools, usw.). Diese werden mal auf diesem und mal auf jenem Rechner benötigt.
Diese Programme sind auch nicht für andere gedacht und werden auch nicht weiter gegeben. Ich habe gerade mal durchgesehen, es sind inzwischen über 100 Tools und Progrämmchen ...

Deshalb diese Vereinfachung.

Danke trotzdem für Eure Tipps. Bei großen Programmen sehe ich das ja genau so.

16.806 Beiträge seit 2008
vor 7 Jahren

Dann mach Dir nen lokales NuGet Repository und arbeite mit ILMerge.
Mach ich auch und kann das Vorgehen nur empfehlen. Zehn mal weniger Stress als sich da irgendein unstabiles Konstrukt zu basteln, das auch noch mehr Zeit kostet 😉

1.040 Beiträge seit 2007
vor 7 Jahren

Halte es persönlich für keine gute Idee.

Sofern du einen Bugfix in einer der zentralen DLLs vornimmst, könnte es sein, dass deine 100 Programme nicht mehr laufen, da die Version der zentralen DLL nicht mehr stimmt.

Dann lieber mit ILMerge arbeiten oder es eben in Kauf nehmen, dass im Output-Verzeichnis 2, 3 kleine DLLs mehr liegen.

R
228 Beiträge seit 2013
vor 7 Jahren

Als alternative zu ILMerge wäre noch Costura.Fody zu empfehlen. Du installierst das Nuget-Package und bist fertig. Die kompilierte exe enthält sämtliche Abhängigkeiten und du brauchst die dll's nicht daneben liegen haben.

Wenn du deine Projekt-Datei anpasst:

<Target 
    AfterTargets="AfterBuild;NonWinFodyTarget"
    Name="CleanReferenceCopyLocalPaths" >
     <Delete Files="@(ReferenceCopyLocalPaths->'$(OutDir)%(DestinationSubDirectory)%(Filename)%(Extension)')" />
</Target>

Bekommst du auch noch ein sauberes Output-Directory.

A
764 Beiträge seit 2007
vor 7 Jahren

Als alternative zu ILMerge wäre noch Costura.Fody zu empfehlen. Du installierst das Nuget-Package und bist fertig. Die kompilierte exe enthält sämtliche Abhängigkeiten und du brauchst die dll's nicht daneben liegen haben.

Gleich mal ausprobiert. Das ist wirklich genial einfach. 👍 😁

2.078 Beiträge seit 2012
vor 7 Jahren

Ich schließ mich da mal an:

Danke für den Tipp, der ist super! 😄

Hab's einfach installiert und es lief, genial einfach.

2.298 Beiträge seit 2010
vor 7 Jahren

Naja, wiederspricht das Zusammenpacken von DLL's zur Exe nicht ein wenig dem Konzept, dass einzelne Module leicht austauschbar sein sollten?

Ich habe es lieben gelernt, dass ich nicht immer das ganze Programm ersetzen muss sondern nur die erweiterte Assembly. Wird diese nun in das Programm fest eingebunden, ist das nicht mehr möglich und je nach Projekt hat man dann eine mords Dateigröße.

Wissen ist nicht alles. Man muss es auch anwenden können.

PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |

2.078 Beiträge seit 2012
vor 7 Jahren

Stimmt schon, es kann aber dennoch mal sinnvoll sein, ilmerge wird ja auch genutzt.
Ich finde einfach nur die extreme Einfachheit dieser Variante klasse, da hier alles automatisch passiert.

16.806 Beiträge seit 2008
vor 7 Jahren

Für so kleine Tools ist das Merging schon praktisch.

2.078 Beiträge seit 2012
vor 7 Jahren

Noch was zu Costura.Fody:

Ich hatte das in meiner aktuellen Solution in einem Dummy-Projekt installiert.
Der Test hat wunderbar funktioniert, aber scheinbar wird es nicht richtig deinstalliert.

Ich habe es über den NugetManager deinstalliert, der Hacken zum Entfernen der Abhängigkeiten war drin.
Nun habe ich das Problem, dass ich ein anderes Projekt, was mit dem Test-Projekt nichts zu tun hat, nicht mehr builden kann, weil jedes mal ein Fehler von Costura.Fody kommt, der besagt, dass es seine config, die eigentlich im Projekt liegen sollte, nicht findet.

Eine Lösung habe ich noch nicht gefunden, daher die Info an Alle: Lieber eine eigene Solution zum Rumspielen erstellen 😃

PS:

Ich hab in der csproj-Datei ganz unten folgenden Abschnitt gefunden:

<UsingTask TaskName="CosturaCleanup" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll" TaskFactory="CodeTaskFactory">
  <ParameterGroup>
    <Config Output="false" Required="true" ParameterType="Microsoft.Build.Framework.ITaskItem" />
    <Files Output="false" Required="true" ParameterType="Microsoft.Build.Framework.ITaskItem[]" />
  </ParameterGroup>
  <Task Evaluate="true">
    <Reference xmlns="http://schemas.microsoft.com/developer/msbuild/2003" Include="System.Xml" />
    <Reference xmlns="http://schemas.microsoft.com/developer/msbuild/2003" Include="System.Xml.Linq" />
    <Using xmlns="http://schemas.microsoft.com/developer/msbuild/2003" Namespace="System" />
    <Using xmlns="http://schemas.microsoft.com/developer/msbuild/2003" Namespace="System.IO" />
    <Using xmlns="http://schemas.microsoft.com/developer/msbuild/2003" Namespace="System.Xml.Linq" />
    <Code xmlns="http://schemas.microsoft.com/developer/msbuild/2003" Type="Fragment" Language="cs"><![CDATA[
var config = XElement.Load(Config.ItemSpec).Elements("Costura").FirstOrDefault();

if (config == null) return true;

var excludedAssemblies = new List<string>();
var attribute = config.Attribute("ExcludeAssemblies");
if (attribute != null)
  foreach (var item in attribute.Value.Split('|').Select(x => x.Trim()).Where(x => x != string.Empty))
      excludedAssemblies.Add(item);
var element = config.Element("ExcludeAssemblies");
if (element != null)
  foreach (var item in element.Value.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim()).Where(x => x != string.Empty))
      excludedAssemblies.Add(item);

var filesToCleanup = Files.Select(f => f.ItemSpec).Where(f => !excludedAssemblies.Contains(Path.GetFileNameWithoutExtension(f), StringComparer.InvariantCultureIgnoreCase));

foreach (var item in filesToCleanup)
File.Delete(item);
]]></Code>
  </Task>
</UsingTask>
<Target Name="CleanReferenceCopyLocalPaths" AfterTargets="AfterBuild;NonWinFodyTarget">
  <CosturaCleanup Config="FodyWeavers.xml" Files="@(ReferenceCopyLocalPaths->'$(OutDir)%(DestinationSubDirectory)%(Filename)%(Extension)')" />
</Target>

Wie der da rein kommt, weiß ich nicht, aber der muss raus, dann läuft's wieder.

16.806 Beiträge seit 2008
vor 7 Jahren

Rein kommt er via PowerShell-Script. Ist oft so, dass NuGet Pakete nur ein Install.ps1 haben aber kein Uninstall-Script.