<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="pl-pl">
<link rel="self" type="application/atom+xml" href="https://forum.atnel.pl/feed.php?f=59&amp;t=4372&amp;mode" />

<title>ATNEL tech-forum</title>
<link href="https://forum.atnel.pl/index.php" />
<updated>2013-10-04T16:57:32+01:00</updated>

<author><name><![CDATA[ATNEL tech-forum]]></name></author>
<id>https://forum.atnel.pl/feed.php?f=59&amp;t=4372&amp;mode</id>
<entry>
<author><name><![CDATA[SunRiver]]></name></author>
<updated>2013-10-04T16:57:32+01:00</updated>
<published>2013-10-04T16:57:32+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=4372&amp;p=51903#p51903</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=4372&amp;p=51903#p51903"/>
<title type="html"><![CDATA[Re: Visual C# -- Wbudowujmy elementy]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=4372&amp;p=51903#p51903"><![CDATA[
E tam nic wielkiego przecież ....<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=58">SunRiver</a> — 4 paź 2013, o 16:57</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[mirekk36]]></name></author>
<updated>2013-10-04T14:58:21+01:00</updated>
<published>2013-10-04T14:58:21+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=4372&amp;p=51899#p51899</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=4372&amp;p=51899#p51899"/>
<title type="html"><![CDATA[Re: Visual C# -- Wbudowujmy elementy]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=4372&amp;p=51899#p51899"><![CDATA[
Kurczę kiedy ja będę miał czas .... przeorać te wszystkie ŚWIETNE poradniki <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" /> ... kolejne cacuszko do kolekcji <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" /> DZIĘKI SUN !<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=54">mirekk36</a> — 4 paź 2013, o 14:58</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[Malutki_27]]></name></author>
<updated>2013-10-04T14:54:16+01:00</updated>
<published>2013-10-04T14:54:16+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=4372&amp;p=51898#p51898</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=4372&amp;p=51898#p51898"/>
<title type="html"><![CDATA[Re: Visual C# -- Wbudowujmy elementy]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=4372&amp;p=51898#p51898"><![CDATA[
Hehee no to teraz już wiem czemu tak cicho siedziałeś <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" /><p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=225">Malutki_27</a> — 4 paź 2013, o 14:54</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[SunRiver]]></name></author>
<updated>2013-10-04T13:13:47+01:00</updated>
<published>2013-10-04T13:13:47+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=4372&amp;p=51888#p51888</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=4372&amp;p=51888#p51888"/>
<title type="html"><![CDATA[Visual C# -- Wbudowujmy elementy]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=4372&amp;p=51888#p51888"><![CDATA[
Często w naszym programie zachodzi konieczność zastosowania zewnętrznych bibliotek<br />do różnych celów np do obsługi czegoś tam ... <img src="https://forum.atnel.pl/images/smilies/icon_e_smile.gif" alt=":)" title="Szczęśliwy" /> tak tak wiem zacząłem z dziwnej strony ...<br />niemniej zaraz wszystko stanie się jasne ....<br /><br /><br />W zasadzie mamy w przypadku używania zewnętrznych bibliotek x.dll  dwie możliwości:<br /><br />1.  Dodajemy w projekcie Odwołanie do biblioteki i we właściwościach odwołania (reference) <br />     zaznaczamy żeby była wykonana kopia lokalna <br /><br />  - spowoduje to że po kompilacji do folderu zostanie zapisany plik dll i będzie można tak jej <br />     używać z pliku dll z folderu programu .<br /><br />Rozwiązanie jest dobre i często się takie stosuje. Niemniej czasem jest mało wygodne , czasem chcemy też by nasz program nie zawierał zbyt wielu plików .... <br /><br />Co możemy więc z tym zrobić ??  <br />-- ano całkiem sporo  <img src="https://forum.atnel.pl/images/smilies/icon_e_smile.gif" alt=":)" title="Szczęśliwy" /><br /><br />W tym poradniku zajmiemy się osadzaniem bibliotek dll w pliku exe. <br /><br />Powiecie pewnie jaki ma to cel i sens ....<br />No spory - zwłaszcza gdy chcemy by nasz program był przenośny zobaczmy więc co tak naprawdę nam daje ....<br /><br /><strong>-------- ZALETY </strong><br /><br />- ułatwia dystrybucję programu wśród użytkowników jeden plik - zamiast wielu<br />- wymagane pliki dll nie zostaną przypadkiem pominięte przez użytkownika , <br />- w przypadku niektórych bibliotek może się pojawić nowa wersja - użytkownik będzie <br />  wolał pobrać jeden plik niż np ręcznie zmieniać pliki dll.<br />   <br /><br />Jak widać to dużo , ale metoda ma też wadę może w  dobie dzisiejszych komputerów nie aż tak <br />istotną , ale jednak...<br /><br />- wymaga więcej pracy od programisty i wymusza podjęcie dodatkowych kroków w celu scalenia plików, a keżde nowe wydanie dla danego dll jeśli jest to konieczne w aplikacji wymaga jej przepakowanie ...<br /><br />----------------------------------------------------------------------------------------------<br /><br />Osadzanie plików *.dll jest używane przez programy instalatorów  powiecie , przecież też są w jednym pliku.  Tak to prawda , ale nasza aplikacja nie wymaga instalacji jest za mała , po za tym<br />przecież nie robimy tradycyjnego śmietnika na dysku rozrzucając pliki po całym dysku i rejestrze. <br /><br />Zróbmy to tak jak powinno się to robić i jak to było wykonywane w porządnych systemach ...<br /><br /><br />Dobrze .... zatem stwórzmy nowy projekt i nazwijmy go ... wbudowana_biblioteka<br />następnie jakieś biblioteki :<br /><br />a niech to będzie np System.Windows.Forms.Ribbon35.DLL  z <!-- m --><a class="postlink" href="http://officeribbon.codeplex.com" >http://officeribbon.codeplex.com</a><!-- m --> <br />oraz System.Data.SQLite.DLL z <!-- m --><a class="postlink" href="http://system.data.sqlite.org" >http://system.data.sqlite.org</a><!-- m --> <br /><br />to dobra okazja bowiem pierwsza zawiera pakiet komponentów, a druga obsługę bazy danych <br />i sie różnią  - pierwsza jest zarządzalna , a druga nie <img src="https://forum.atnel.pl/images/smilies/icon_e_smile.gif" alt=":)" title="Szczęśliwy" /><br /><br />oznacza to że do pierwszej poza wywołaniem funkcji przekazujemy parametry , a z drugiej tylko<br />wywołujemy funkcje. Dobra mamy już nasz projekt i biblioteki. i Co teraz  ??<br /><br />A no nic ... <br /><br />gdy już mamy nasz projekt dodajemy odwołanie do naszych bibliotek. <br />jest to banalnie proste , klikamy RMB  na Odwołania i z meny wybieramy Dodaj odwołanie <br />pojawi się nam okienko:<br /><br /><a href="http://forum.atnel.pl/_obrazki/o/58/d74168d7f1315d03f7784d883d36e521.JPG"  class="postlink"><img src="http://forum.atnel.pl/_obrazki/o/thumb/58/d74168d7f1315d03f7784d883d36e521.JPG" alt="Obrazek" /></a><br /><br />gdzie w zakładce przeglądaj wybieramy nasze biblioteki po kolei i klikamy OK ....<br /><br />Odwołania mamy z głowy ... pojawiły się ...<br /><br /><a href="http://forum.atnel.pl/_obrazki/o/58/9a4bd4f656aa299eeaf4942f56f0461a.JPG"  class="postlink"><img src="http://forum.atnel.pl/_obrazki/o/thumb/58/9a4bd4f656aa299eeaf4942f56f0461a.JPG" alt="Obrazek" /></a><br /><br />W zasadzie od teraz możemy już używać w naszym programie już bibliotek o czym wspomniałem na początku<br />wymaga to tylko dodania bibliotek do pliku wykonywalnego ... (do ProgDira) co możemy ja wspominałem <br />zrobić we właściwościach odwołania :<br /> <br /><a href="http://forum.atnel.pl/_obrazki/o/58/73cd731d0d8df9adcf6697e918bb798d.JPG"  class="postlink"><img src="http://forum.atnel.pl/_obrazki/o/thumb/58/73cd731d0d8df9adcf6697e918bb798d.JPG" alt="Obrazek" /></a><br /><br />zmieniając wartość pola Kopia lokalna na true  -- co spowoduje skopiowanie pliku dll do folderu kompilacji  (dołączenie do programu).<br />Ale nas to nie interesuje ....mu chcemy nasze biblioteki zaszyć w pliku exe....<br /><br />Zatem teraz musimy nasze pliki dll dodać do projektu...<br />Możemy to zrobić na 2 sposoby...<br /><br />1. kliknąć RMB na nazwie projektu i wybrać dodaj - istniejący element lub Shift-Alt-A  i wybrać nasze pliki dll<br />2. Przeciągnąć je na projekt np z pulpitu lub lokalizacji projektu i upuścić (drag&amp;drop)<br /><br />ma to wyglądać tak:<br /><br /><a href="http://forum.atnel.pl/_obrazki/o/58/d28eb18e16a69c4552e57849c3c6da8b.JPG"  class="postlink"><img src="http://forum.atnel.pl/_obrazki/o/thumb/58/d28eb18e16a69c4552e57849c3c6da8b.JPG" alt="Obrazek" /></a><br /><br />Teraz będzie trudniej .... <br /><br />Przede wszystkim w odwołaniu do biblioteki  kopia lokalna ma być false  -- co widać wyżej .... (nie będziemy kopiować bibliotek)<br />Teraz klikamy na naszych plikach DLL w eksploratorze projektu i w ich właściwościach .....<br /><br /><a href="http://forum.atnel.pl/_obrazki/o/58/405b971337afc53886db9bf0a22a6f83.JPG"  class="postlink"><img src="http://forum.atnel.pl/_obrazki/o/thumb/58/405b971337afc53886db9bf0a22a6f83.JPG" alt="Obrazek" /></a><br /><br />Dla obu plików .dll zmieniamy wartość pola Akcja Kompilacji  na  Zasób osadzony .....<img src="https://forum.atnel.pl/images/smilies/icon_e_smile.gif" alt=":)" title="Szczęśliwy" /><br />ma to wyglądać dokładnie jak widzicie wyżej...<br /><br />Uffff ... to tyle ....  <br /><br /><br />no nie żartowałem ...   fakt po kompilacji nasze biblioteki zostaną dołączone do pliku exe, ale nie będą używane i nie zadziała nasz program na kompie bez tych bibliotek ....<br /><br />Zróbmy więc cokolwiek co zawierają nasze libsy na formie1.<br /><br /><a href="http://forum.atnel.pl/_obrazki/o/58/ed2db99eb7032ad063413d5c75ce8823.JPG"  class="postlink"><img src="http://forum.atnel.pl/_obrazki/o/thumb/58/ed2db99eb7032ad063413d5c75ce8823.JPG" alt="Obrazek" /></a><br /><br />np tak ....  dodamy panel z biblioteki Ribon <br /><br />i sami sprawdźcie ... po kompilacji  że bez bibliotek wasz program nie działa .... no bo niby jak co ..<br />przecież poza tym ze dodaliśmy je do pliku program nie wie gdzie są i jak je użyć ....<br /><br />no to do roboty.....<br /><br />Nasze zadanie jest proste ... musimy podczas uruchomienia programu wypakować biblioteki i załadować do programu ...<br /><br />Szukamy w projekcie pliku  Program.cs  (zawiera on podstawową klase naszego programu) i otwieramy go:<br /><br />tam znajdujemy funkcję main() <br /><br />[syntax=c]static  class Program<br />{<br />    / / /  &lt; summary &gt;<br />     / / / Główny punkt wejścia dla aplikacji.<br />     / / /  &lt; / summary &gt;<br />     &#91;STAThread&#93;<br />     static  void Main ()<br />    {<br />        Application.EnableVisualStyles ();<br />        Application.SetCompatibleTextRenderingDefault ( false );<br />        Application.Run ( new Form1 ());<br />    }<br />}[/syntax]<br /><br />jak widać całość jest jasna  ... <br />i dopisujemy ładowanie naszych dll do ram....<br /><br />co powinno wyglądać tak <img src="https://forum.atnel.pl/images/smilies/icon_e_smile.gif" alt=":)" title="Szczęśliwy" /><br /><br />[syntax=c]static class Program<br />    {<br />        /// &lt;summary&gt;<br />        /// Główny punkt wejścia dla aplikacji.<br />        /// &lt;/summary&gt;<br />        &#91;STAThread&#93;<br />        static void Main()<br />        {<br />            PaczkaDll.Load(&quot;Wbudowana_biblioteka.System.Data.SQLite.dll&quot;, &quot;System.Data.SQLite.dll&quot;);<br />            PaczkaDll.Load(&quot;Wbudowana_biblioteka.System.Windows.Forms.Ribbon35.dll&quot;, &quot;System.Windows.Forms.Ribbon35.dll&quot;);<br /><br />            AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);<br /><br />            Application.EnableVisualStyles();<br />            Application.SetCompatibleTextRenderingDefault(false);<br />            Application.Run(new Form1());<br />        }[/syntax]<br /><br />Używamy jak widać metody PaczkaDll.Load by załadować nasze wbudowane biblioteki do pamięci RAM. Zwróćcie też uwagę na format ciągu zasobów:<br /><br /><strong>Wbudowana_biblioteka.System.Data.SQLite.dll</strong><br /><br />Ciąg ten to jakby adres naszego zasobu.  Zawiera nazwę naszego projektu i pliku DLL. trzeba na to uważać gdyż jeśli chcemy np dodać biblioteki w folderze np DLLe to ta nazwa folderu musi byc też uwzględniona w adresie. Ale tu dodajemy tylko czyste pliki dll... niemniej jeśli trzeba to powinno to wyglądać tak:<br /><br /><strong>nazwa_aplikacji.nazwa_folderu.System.Data.SQLite.dll</strong> <br /><br />zdarzenie  AppDomain.CurrentDomain.AssemblyResolve.. jest przydatne w wypadku gdy biblioteki nie mogą być zlokalizowane przez aplikację do dystrybucji. AssemblyResolve wywołuję żądanie plików DLL <br />których brakuje. Musimy więc jej powiedzieć że nasze biblioteki są w pamięci RAM, w tym celu użyjemy metody PaczkaDll.Get by pobrać biblioteki z pamięci i przekazać je do AssemblyResolve, który obsłuży całą resztę ...<br /><br />a więc dopiszmy jeszcze kawałek kodu pod funkcją main() <br /><br />[syntax=c]static System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)<br />        {<br />            return PaczkaDll.Get(args.Name);<br />        }[/syntax]<br /><br />a cały nasz plik Program.cs powinien wyglądać np tak:<br /><br /><br /><br />[syntax=c]using System;<br />using System.Collections.Generic;<br />using System.Linq;<br />using System.Windows.Forms;<br /><br />namespace Wbudowana_biblioteka<br />{<br />    static class Program<br />    {<br />        /// &lt;summary&gt;<br />        /// The main entry point for the application.<br />        /// &lt;/summary&gt;<br />        &#91;STAThread&#93;<br />        static void Main()<br />        {<br />            PaczkaDll.Load(&quot;Wbudowana_biblioteka.System.Data.SQLite.dll&quot;, &quot;System.Data.SQLite.dll&quot;);<br />            PaczkaDll.Load(&quot;Wbudowana_biblioteka.System.Windows.Forms.Ribbon35.dll&quot;, &quot;System.Windows.Forms.Ribbon35.dll&quot;);<br /><br />            AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);<br /><br />            Application.EnableVisualStyles();<br />            Application.SetCompatibleTextRenderingDefault(false);<br />            Application.Run(new Form1());<br />        }<br /><br />        static System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)<br />        {<br />            return PaczkaDll.Get(args.Name);<br />        }<br />    }[/syntax]<br /><br />I to by było na tyle ?? - <br /><br /><br />tak i nie ...  gdyż potrzeba nam jeszcze stworzyć klasę PaczkaDll.<br /><br />w tym celu do naszego projektu dodajemy nową klasę  (Shift-Alt-C) i nazywamy ją PaczkaDll.cs<br />otwieramy plik i w nim umieszczamy kod:<br /><br />[syntax=c]// ------------------------------------------------------------------<br />// Sunriver <br />// Klasa importu wbudowanych plików dll<br />//-------------------------------------------------------------------<br /><br /><br /><br />using System;<br />using System.Collections.Generic;<br />using System.Text;<br />using System.IO;<br />using System.Reflection;<br />using System.Security.Cryptography;<br /><br /><br />/// Klasa ładowania bibliotek wbudowanych <br /><br />public class PaczkaDll<br />{<br />    <br /><br />    static Dictionary&lt;string, Assembly&gt; dic = null;<br /><br />    <br />    // Wypakowanie i załądowanie wbudowanych bibliotek do ram.<br />    <br />    public static void Load(string embeddedResource, string fileName)<br />    {<br />        if (dic == null)<br />            dic = new Dictionary&lt;string, Assembly&gt;();<br /><br />        byte&#91;&#93; ba = null;<br />        Assembly asm = null;<br />        Assembly curAsm = Assembly.GetExecutingAssembly();<br /><br />        using (Stream stm = curAsm.GetManifestResourceStream(embeddedResource))<br />        {<br />            // Sprawdzenie czy sa jakieś pliki wbudowane<br />            if (stm == null)<br />                throw new Exception(embeddedResource + &quot; nie znalazłem żanych wbudowanych bibliotek.&quot;);<br /><br />            // Pobranie byte&#91;&#93; z wbudowanych dlli <br />            ba = new byte&#91;(int)stm.Length&#93;;<br />            stm.Read(ba, 0, (int)stm.Length);<br />            try<br />            {<br />                asm = Assembly.Load(ba);<br /><br />                // Dodanie do słowników danych z plików<br />                dic.Add(asm.FullName, asm);<br />                return;<br />            }<br />            catch<br />            {<br />                // Tu narazie nic nie ma , ale .... moze byc konieczne<br />                // dopisanie kodu pobierania danych do byte&#91;&#93; w przypadku bibliotek niezarządzalnych<br />                <br />            }<br />        }<br /><br />        bool fileOk = false;<br />        string tempFile = &quot;&quot;;<br /><br />        using (SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider())<br />        {<br />            // Pobranie danych z plików wbudowanych<br />            string fileHash = BitConverter.ToString(sha1.ComputeHash(ba)).Replace(&quot;-&quot;, string.Empty);<br /><br />            // Wyszukanie folderu tymczasowego na zapisanie biblioteki<br />            tempFile = Path.GetTempPath() + fileName;<br /><br />            // Sprawdzenie czy jest w temp<br />            if (File.Exists(tempFile))<br />            {<br />                // Pobranie hasza istniejącego pliku<br />                byte&#91;&#93; bb = File.ReadAllBytes(tempFile);<br />                string fileHash2 = BitConverter.ToString(sha1.ComputeHash(bb)).Replace(&quot;-&quot;, string.Empty);<br /><br />                // Sprawdzenie czy plik dll istnieje czy nie <br />                if (fileHash == fileHash2)<br />                {<br />                    // Jest Plik !<br />                    fileOk = true;<br />                }<br />                else<br />                {<br />                    // Niema pliku ??<br />                    fileOk = false;<br />                }<br />            }<br />            else<br />            {<br />                // Sprawdzenie czy plik istnieje<br />                fileOk = false;<br />            }<br />        }<br /><br />        // Utworzenie pliku na dysku<br />        if (!fileOk)<br />        {<br />            System.IO.File.WriteAllBytes(tempFile, ba);<br />        }<br /><br />        // Wczytanie do pamięci RAM<br />        asm = Assembly.LoadFile(tempFile);<br /><br />        // Dodanie załadowanej biblioteki do słowników przestrzeni nazw i odwołań<br />        dic.Add(asm.FullName, asm);<br />    }<br /><br />   <br />    // Pobranie i załadowanie wyspecyfikowanych plików bibliotek do ram.<br />    <br />    public static Assembly Get(string assemblyFullName)<br />    {<br />        if (dic == null || dic.Count == 0)<br />            return null;<br /><br />        if (dic.ContainsKey(assemblyFullName))<br />            return dic&#91;assemblyFullName&#93;;<br /><br />        return null;<br /><br />    }<br />}[/syntax]<br /><br />Powyższy kod zawiera metody ładowania plików DLL które będą używane z .Net<br />A musimy wiedzieć że mamy dwa typy plików Dll<br /><br />- Zarządzane DLL<br />- Niezarządzalne DLL lub Mixed Code DLL  <br /><br />dlatego też procedury ładowania sa odmienne ...<br /><br /><br />W przypadku zarządzalnych DLL   procedura ładowania jest prosta i można ją zrealizować np tak:<br /><br />[syntax=c]public static Assembly Load()<br />{<br />    byte&#91;&#93; ba = null;<br />    string resource = &quot;wbudowana_biblioteka.System.Windows.Forms.Ribbon35.dll&quot;;<br />    Assembly curAsm = Assembly.GetExecutingAssembly();<br />    using (Stream stm = curAsm.GetManifestResourceStream(resource))<br />    {<br />        ba = new byte&#91;(int)stm.Length&#93;;<br />        stm.Read(ba, 0, (int)stm.Length);<br /> <br />        return Assembly.Load(ba);<br />    }<br />}[/syntax]<br /><br />Ale biblioteki niezarządzalnej nie możemy załadować bezpośrednio do tablicy byte[] tak jak zarządzalnej<br />tu musimy:<br /><br />1. najpierw załadować osadzoną bibliotekę do tablicy byte[]<br />2. zapisać zawartość tablicy byte[] do fizycznego pliku i przechować w folderze temp<br />3. użyć metody loadFile() by załadować plik do pamieci<br /><br />co opisałem w komentarzach w kodzie PaczkaDLL.. która to będzie wstępnie ładować wymagane biblioteki DLL i przechowywać je wewnątrz &quot;Słownika&quot;, a gdy nastąpi ewent AssembyResolve metoda PaczkaDll.Get()<br />zwróci żądaną bibliotekę.<br /><br />Miłej zabawy z osadzaniem plików....<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=58">SunRiver</a> — 4 paź 2013, o 13:13</p><hr />
]]></content>
</entry>
</feed>