Edytor formy głównej

0

Otóż mam dwie formy, Form1 i formę Edytor. Forma Edytor zawiera 5 textboxów, z których pobieram treść i przekazuje do zmiennych Form1. Wszystko ładnie działa. Tylko teraz nie wiem jak rozwiązać mój problem, ponieważ forma Edytuj służy do wczytywania danych dla Form1 i jest uruchamiana buttonem z głównej. Po wczytaniu danych, można zamknąć formę edytuj i pracować na form1 ale to miało działać tak, że włączam program wpisuje dane do formy edytuj, zamykam ją i przy ponownym uruchomieniu programu już nie ma formy edytuj a tylko główna zawierająca zmienne, w których są zawarte dane przekazane z formy edytuj.
Może się wygłupiłem z tym pytaniem ale proszę o jakąś rade i z góry dzięki.
Myślałem o rozłożeniu tego na 2 programy, ale nie wiem jak w tedy przekazywać dane z jednego programu do drugiego.

0

Po odczytaniu danych od użytkownika, zapisz je np. do pliku (utwórz katalog w %appdata% i tam umieść swój plik).

0

Pliki textowe to ostateczność. Chciałbym żeby ten program był łatwy przenoszeniu, bez zbędnych plików tylko sam .exe

0

jeżeli samo .exe, to chyba musialby ściągać te dane przez np. FTP, ja bym tak kombinował.

0

Program podczas działania nie może zmieniać swojego pliku exe - jedynie po zakończeniu, poza tym na tym poziomie na którym jesteś takie coś jest niewykonalne. Pozostaje jeszcze rejestr windows, ale musiał byś zadbać jeszcze o jakiś deinstalator który posprząta po sobie gdy user zapragnie wywalić twoją apke

0

mathiuf mówiąc o przenoszeniu, chyba miał na myśli przenoszenie pomiędzy różnymi maszynami, więc rejestr tutaj nie zda egzaminu.

0

evensense właśnie o to mi chodzi, żeby mój program był łatwy w przenoszeniu między komputerami. Może macie jakiś pomysł jak to rozwiązać z tym edytorem, ponieważ ta aplikacja ma być elastyczna dla rożnych danych( robię taki mały quiz) .

0

tak jak wyżej napisane - pliku .exe nie można zmieniać w czasie działania programu.
ja to widzę tak : zrobić tą aplikacje na zasadzie klient-serwer, przy włączaniu sprawdza, czy opcje zostały ustawione, jeżeli tak to je ściąga, jeżeli nie to wprowadzasz nowe.

Poza tym co masz na myśli mówiąc 'elastyczna dla różnych danych' ?

0

Chodzi o to, że tak jak mówiłem to taki mały quiz, gdzie np ja wprowadzam pytania z programowania i mogę go używać i skopiować na wiele stanowisk, a znowu Jan Kowalski wprowadzi pytania z geografii i skopiuje program na wiele stanowisk.

0

No to zrób program wczytujący quiz.
A do edytowania / tworzenia jakiś poboczny.
I zrobisz powiedzmy rozszerzenie .qui i otworzysz w programie 1.

Nie wiem co masz przeciwko dodatkowemu plikowi, przenosisz wtedy plik z programem + plik z quizem.
Ja robiłem takie coś ze słownikiem - tylko tam jest 1 program do edycji i otwierania. W sumie też ma funkcje quizu (link jest w moim podpisie).
Tyle że ktoś może sobie edytować. Ale oczywiście możesz zrobić opcje ze jak się wczyta plik to nie można edytować.

0

Podoba mi się twój pomysł z tym programem pobocznym, tylko mógłbyś mi jeszcze podać jakieś linki albo napisać jak mam się za to zabrać. Pliki są problemem, bo na tym programie mają pracować rożni ludzie i jeden usunie sobie plik txt i klapa program się wyłoży.

0

Jak usunie, to użytkownik jest dupa i tyle.
Nawet jeśli bedziesz miał dwa programy, jeden do edycji a drugi do obsługi, to i tak musisz skądś pobrać te dane.
Najprościej było by z osobnego pliku. Nie musi mieć rozszerzenia txt. Możesz wymyślić jakiekolwiek inne. Natomiast większość programów nie składa się z jednego pliku. I jeżeli dasz ten program w folderze, to niezaawansowany użytkownik komputera raczej Ci go nie usunie, bo będzie się bał.
Ewentualnie mógłbyś spróbować wsadzić te pytania w ten program (w plik .exe) do otwarcia quizu, ale to już inni eksperci forumowi Ci powiedzą, czy się tak da.

Edit. albo postaw se stronkę, i program do edycji będzie na nią ładował przez FTP (to nie jest trudne, bo w System.Net jest wbudowana obsługa http i ftp) według szablonu pytania powiedzmy do pliku o nazwie "geografia" na serwerze, a plik do obsługi quizu będzie się łączył z Twoją stroną (WebClient) i pobierał z niej pytania. Nawet możesz zrobić tak, że program nazywa się "geografia.exe" -> pobiera dane z pliku o nazwie geografia.txt na serwerze. Nazywa się "dupa.exe" pobiera z dupa.txt

0

Nawet przypadkowe usuniecie spowodowało by ponowne kopiowanie, a ten program wyglądałby prosto bo byłby plik .exe i txt.Nie tak jak zaawansowane aplikacje albo gra która chcą zainstalować i się boją :)
Czyli pliki są nieuniknione ale warto było próbować.
To z tym plikiem w .exe było by świetnym rozwiązaniem, ale chyba on najpierw musi się gdzieś utworzyć na dysku żeby go potem dodać do programu(to tylko moje przypuszczenia więc jeśli się mylę proszę o sprostowanie). Fajnie by było gdyby się tworzył gdzieś w jakieś uniwersalnej lokalizacji dla windows xp,vista,7

0

Ok quiz to będą dwa programy: edytor i quiz.
Dane z edytora zapisze do pliku w folderze temp(uniwersalny dla xp i 7)

            StreamWriter strumien1 = new StreamWriter(Path.GetTempPath() + "plik.txt");
            strumien1.Write("opis");
            strumien1.Close();

Ale i tak pojawia się właśnie teraz główny problem z dołączeniem tego powstałego pliku do .exe quizu, bo przecież ten plik będzie raz utworzony na komputerze "matka", a quiz skopiowany na wiele stanowisk.

0

do modyfikacji exe najlepiej posłużyć się zasobami poniższy temat powinien cie nakierować
http://4programmers.net/Forum/Delphi_Pascal/114333-edycja_zasobow_w_exe_-_jak_to_zrobic
a jak to za wiele istnieją różnego rodzaju bindery, ale antywirusy często źle reagują na aplikacje potraktowane takim programem.

//ups pisałem tego posta w kontekście delphi, nie mam pojęcia czy takie możliwości daje .NET

0

szopenfx dzięki za naprowadzenie na temat, choć nie z c# to i tak coś mi to dało.

Jak dołączyć plik .txt do projektu, który później jest w .exe napisane jest tutaj:

http://support.microsoft.com/kb/319292

0
matihuf napisał(a)

Dane z edytora zapisze do pliku w folderze temp(uniwersalny dla xp i 7)

Super rozwiązanie, ktoś sobie wyczyści tempa i program nie działa. ;]

matihuf napisał(a)

Jak dołączyć plik .txt do projektu, który później jest w .exe napisane jest tutaj:

http://support.microsoft.com/kb/319292

Czy pytania w Twoim quizie nigdy się nie zmienią?

0

Teraz mam tak, że program Edytor tworzy plik textowy na dysku c, z którego później program quiz odczytuje dane, ale jak raz dodam ten plik do zasobów to później jego zwartość się nie zmienia, a przecież on miał się zmieniać zależnie od tego z jakiego działu użytkownik wpisze pytania w Edytorze.

Masz może jakiś pomysł jak to zrobić żeby potem był tylko gotowy quiz.exe bez innych plików

0

Ja bym zrobił tak...Dodałbym Quiz.exe do zasobów projektu Edytor. Następnie wsadzał w ten exek z poziomu aplikacji Edytor pytania i odpowiedzi do quizu.
A Quiz.exe byłby napisany tak, że odczytywałby te dane. Tzn standardowo były by powiedzmy to
"Pytanie 1" - "Odpowiedź 1" "Odpowiedź 2"
Które były zamieniane przez Edytor na
"Najdłuższa rzeka w Ameryce północnej" "Missisipi" "Missouri"
To jest pomysł ale wymaga weryfikacji przez kogoś na tym forum, co się zna - bo ja osobiście nie modyfikowałem jeszcze plików exe z poziomu aplikacji.

PS. że też chce ci się tak męczyć. Osobny plik byłby naprawde najlepszym , bezawaryjnym rozwiązaniem.

0

Wiem, że osobny plik txt przy .exe jest prostym rozwiązaniem, ale jeśli jest możliwość rozwiązania tego w inny sposób to czemu nie dążyć do poznania tej metody. To jest moje wyzwanie, w którym proszę o Waszą pomoc :)

0

Dobra.. nudziło mi się.

Rozwiązaniem może być program, który trzyma dane w swoich zasobach i potrafi je sam (z małą pomocą) zmienić. Z małą pomocą dlatego, że jednak te dane trzeba w pliku wykonywalnym przechowywać, a podczas działania programu zmienić się go nie da. Dlatego trzeba napisać dwa programy. Ten drugi oczywiście można umieścić.. gdzie? W zasobach tego pierwszego oczywiście ;). Sam program modyfikujący zasoby będziemy trzymać w zasobach .NET, a dane w zasobach natywnych (bo istnieje do tego kilka prostych, gotowych funkcji, gdzie w przeciwieństwie do zasobów .NET trzeba użyć.. linkera).

Najpierw program modyfikujący zasoby.

Importy z Windows API:

internal class Win32
{
    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern IntPtr BeginUpdateResource(string pFileName, [MarshalAs(UnmanagedType.Bool)] bool bDeleteExistingResources);

    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern bool UpdateResource(IntPtr hUpdate, string lpType, string lpName, ushort wLanguage, IntPtr lpData, uint cbData);

    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern bool EndUpdateResource(IntPtr hUpdate, bool fDiscard);
}

Klasa i metoda do aktualizacji danego zasobu z pliku w podanym pliku wykonywalnym:

public class Win32Resources
{
    public static void UpdateResource(string executablePath, string name, string type, byte[] data)
    {
        var handle = Win32.BeginUpdateResource(executablePath, false);
        if (handle == IntPtr.Zero) throw new Win32Exception();

        var dataPtr = Marshal.AllocHGlobal(data.Length);

        Marshal.Copy(data, 0, dataPtr, data.Length);
        try
        {
            if (!Win32.UpdateResource(handle, type, name, 0x007F, dataPtr, (uint)data.Length))
                throw new Win32Exception();
        }
        catch (Exception)
        {
            throw;
        }
        finally
        {
            Marshal.FreeHGlobal(dataPtr);
        }

        if (!Win32.EndUpdateResource(handle, false))
            throw new Win32Exception();
    }
}

I sam program:

using System;
using System.Linq;
using System.IO;
using System.Diagnostics;
using System.Windows.Forms;

namespace ResourcesEmbedder
{
    static class Program
    {
        [STAThread]
        static void Main()
        {
            // todo: jakieś ambitniejsza obsługa błędów czy przekazanie rezultatu aplikacji-host

            var arguments = Environment.GetCommandLineArgs();

            if (arguments.Length != 6)
                Environment.Exit(1);

            int hostProcessId;
            if (!int.TryParse(arguments[1], out hostProcessId))
                Environment.Exit(2);

            var hostExecutablePath = arguments[2];
            var targetResourceFile = arguments[3];
            var targetResourceName = arguments[4];
            var targetResourceType = arguments[5];

            var hostProcess = Process.GetProcesses().Where(p => p.Id == hostProcessId).FirstOrDefault();
                // jest Process.GetProcessById, ale rzuta wyjątkiem, gdy proces nie jest działa,
                // a dla nas to żadna wyjątkowa sytuacja nie jest

            if (hostProcess != null && !hostProcess.HasExited)
                hostProcess.WaitForExit();

            byte[] data = null;

            try
            {
                data = File.ReadAllBytes(targetResourceFile);
            }
            catch (Exception)
            {
                Environment.Exit(3);
            }

            try
            {
                Win32Resources.UpdateResource(hostExecutablePath, targetResourceName, targetResourceType, data);
            }
            catch (Exception ex)
            {
                MessageBox.Show("nie udalo sie zaktualizowac zasobow " + ex.Message);
                Environment.Exit(4);
            }

            try
            {
                File.Delete(targetResourceFile);
            }
            catch (Exception)
            {
                // nie udało się z jakiegoś powodu usunąć pliku, ale udało się go umieścić w pliku wykonywalnym
                // nie róbcie pustych bloków catch (komentarze się nie liczą ;P)
            }

            try
            {
                Process.Start(hostExecutablePath);
            }
            catch (Exception)
            {
                Environment.Exit(5);
            }
        }
    }
}

Taki gotowy program wrzucamy do zasobów naszego głównego programu.

Importy:

internal class Win32
{
    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern IntPtr FindResource(IntPtr hModule, string lpName, string lpType);

    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern IntPtr LoadResource(IntPtr hModule, IntPtr hResInfo);

    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern IntPtr LockResource(IntPtr hResData);

    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern uint SizeofResource(IntPtr hModule, IntPtr hResInfo);
}

Klasa i metoda do odczytania zasobu:

public class Win32Resources
{
    public static byte[] GetResource(string name, string type)
    {
        var resourceInfoHandle = Win32.FindResource(IntPtr.Zero, name, type);
        if (resourceInfoHandle == IntPtr.Zero) throw new Win32Exception();

        int resourceSize = (int)Win32.SizeofResource(IntPtr.Zero, resourceInfoHandle);
        if (resourceSize == 0) throw new Win32Exception();

        var resourceDataHandle = Win32.LoadResource(IntPtr.Zero, resourceInfoHandle);
        if (resourceDataHandle == IntPtr.Zero) throw new Win32Exception();

        var dataPtr = Win32.LockResource(resourceDataHandle);
        if (dataPtr == IntPtr.Zero) throw new Win32Exception();

        var data = new byte[resourceSize];

        Marshal.Copy(dataPtr, data, 0, resourceSize);

        return data;
    }
}

Odczytanie zasobu:

var data = Win32Resources.GetResource("TestData", "TestType");
textBoxData.Text = Encoding.Unicode.GetString(data);

I zapisanie zasobu:

try
{
    var data = Encoding.Unicode.GetBytes(textBoxData.Text);

    var tempFilePath = Path.GetTempFileName();

    File.WriteAllBytes(tempFilePath, data);

    var process = Process.GetCurrentProcess();

    var arguments = process.Id + " \"" + process.MainModule.FileName + "\" \"" + tempFilePath + "\" TestData TestType";

    var tempResourceEmbedderPath = Path.Combine(Path.GetTempPath(), "ResourcesEmbedder.exe");
    File.WriteAllBytes(tempResourceEmbedderPath, Resources.ResourcesEmbedder);

    Process.Start(tempResourceEmbedderPath, arguments);

    Application.Exit();
}
catch (Exception ex)
{
    MessageBox.Show(ex.Message);
}

Powinno działać.

0

Dzięki ale trochę to skomplikowane, ciężko mi to dopasować pod siebie.
To jest rozwiązanie pod Windows Form? Bo wiele poleceń mi podkreśla, że ich nie zna.

0

Niektóre rzeczy z winapi, wkleiłeś importy dll'i?

0

Dałem ci gotowy kod, dałem ci gotową binarkę do zdekompilowania, więcej nie pomogę, bo to byłaby przesada :(.

0

Error 7 The type or namespace name 'DllImport' could not be found (are you missing a using directive or an assembly reference?) D:\c#\proba1\WindowsFormsApplication1\WindowsFormsApplication1\Form1.cs 39 6 WindowsFormsApplication1

Error 3 The type or namespace name 'MarshalAs' could not be found (are you missing a using directive or an assembly reference?) D:\c#\proba1\WindowsFormsApplication1\WindowsFormsApplication1\Form1.cs 34 72 WindowsFormsApplication1

tego typu błędy

0

No bez przesady....
using System.Runtime.InteropServices;

1 użytkowników online, w tym zalogowanych: 0, gości: 1