C # jest głównym problemem

10

Ta łamigłówka programowa jest inspirowana innym pytaniem, które zostało tu zadane wczoraj, ale które zostało usunięte przez autora ...

Wyzwanie:

Utwórz wykonywalny plik binarny (plik binarny Windows .EXE lub Linux) za pomocą Visual C # (lub ulubionego C # IDE), który wypisuje następujący tekst na standardowe wyjście:

Main() is the main method of C# programs!

... bez użycia 4 kolejnych liter MAIN pojawiających się w dowolnym pliku źródłowym!

Uwagi:

  • Jeśli twój kod źródłowy zawiera tekst remainder(na przykład), zawiera 4 kolejne litery GŁÓWNE, jednak jeśli zawiera mxain4 litery, nie będzie kolejnych, więc mxainbyłoby to dozwolone.
  • Nie wolno uruchamiać żadnych programów poza C # IDE ani zmieniać ustawień C # IDE w celu uruchamiania innych programów (ale tych, które normalnie działałoby, takich jak kompilator C #).

    W przeciwnym razie możesz po prostu powiedzieć: „Piszę program Pascal za pomocą C # IDE i wywołuję kompilator Pascal w krokach„ wstępnej kompilacji ”mojego projektu C #”.

    To byłoby zbyt proste.

  • Użytkownicy IDE, które można rozszerzać za pomocą „wtyczek” (lub podobnych) lub którzy mają wbudowane edytory plików binarnych (edytory szesnastkowe), mieliby zbyt dużą przewagę nad użytkownikami innych IDE C #.

    Dlatego te pióra nie powinny być również używane.

  • Używanie innych edytorów innych niż ASCII (takich jak edytor okien dialogowych) jest wyraźnie dozwolone!
  • Użytkownik zadający oryginalne pytanie zaproponował użycie odwrotnego ukośnika w nazwach funkcji w następujący sposób: static void M\u0061in()Ponieważ odpowiedź ta została już odczytana przez innych użytkowników, nie będzie już akceptowana!
  • Użytkownik zapytał, czy można po prostu wpisać plik .EXE do edytora kodu źródłowego i zapisać plik jako „.exe” zamiast „.cs”. Odpowiedź: Nie wątpię, że jest to możliwe, ponieważ zarówno prawidłowe pliki binarne systemu Windows, jak i Linux zawierają bajty NUL. Jeśli jednak znajdziesz poprawny plik binarny, który można utworzyć w ten sposób, masz prawidłowe rozwiązanie.

Nazwa tej strony to „Programowanie łamigłówek i Code Golf” - jest to „Programming Puzzle”, a nie „Code Golf”: Wyzwaniem jest znalezienie działającego rozwiązania przed wszystkimi innymi użytkownikami, a nie znalezienie rozwiązania krótszego niż wszystkie inne rozwiązania.

Dlatego wygrywa pierwszy post opisujący działające rozwiązanie !

Powodzenia!

Nawiasem mówiąc: Mam rozwiązanie działające pod Visual C # Express 2010.

Martin Rosenau
źródło
2
Co powstrzymuje mnie od używania mojego C # IDE jako edytora tekstowego (lub binarnego) do bezpośredniego wpisywania pliku wykonywalnego?
feersum
2
Która odpowiedź wygrywa wyzwanie? Pierwsza ważna odpowiedź? Powinieneś określić warunek wygranej
James
Jeśli IDE zawiera edytor szesnastkowy lub podobny, NIE byłoby to dozwolone. Jeśli uda Ci się użyć edytora tekstu ASCII do wpisania prawidłowego pliku binarnego, byłoby to dozwolone. Zauważ, że poprawny plik binarny zawiera bajty z zakresu od 0x00 do 0x1F!
Martin Rosenau,
2
Myślę, że jest to ogólnie interesujące wyzwanie. „Napisz program w języku C # bez głównego”. Jednak większość zasad dotyczy narzędzi / IDE, których należy używać, i zakazuje pewnych podejść. Chciałbym zobaczyć więcej zagadek programistycznych (w przeciwieństwie do golfa kodowego), ale ta jest nieokreślona. Następnym razem zaleciłbym użycie piaskownicy .
James
4
... Następnym razem rozważ piaskownicę .
kot

Odpowiedzi:

5

Interaktywne okno C #

Otwórz okno interaktywne C # (Widok> Inne okna> C # Interactive w Visual Studio 2015). Podejrzewam, że nie wszystkie IDE będą to miały.

To podejście wykonuje C # w oknie interaktywnym w celu utworzenia exe C #, który drukuje pożądany ciąg bez pisania autora main. Jako bonus, IL exe również nie zawiera main.

Uruchom następujący kod w oknie interaktywnym

using System.Reflection;
using System.Reflection.Emit;
var appMeow = (dynamic)System.Type.GetType("System.AppDom" + "ain").GetProperty("CurrentDom" + "ain", BindingFlags.GetProperty | BindingFlags.Static | BindingFlags.Public).GetValue(null);
var asmName = new AssemblyName("MEOW");
var asmBuilder = appMeow.DefineDynamicAssembly(asmName, AssemblyBuilderAccess.RunAndSave);
var module = asmBuilder.DefineDynamicModule("MEOW", "MEOW.exe");
var typeBuilder = module.DefineType("Meow", TypeAttributes.Public);
var entryPoint = typeBuilder.DefineMethod("EntryPoint", MethodAttributes.Static | MethodAttributes.Public);
var il = entryPoint.GetILGenerator();
il.Emit(OpCodes.Ldstr, "Meow() is the meow method of C# programs!");
il.Emit(OpCodes.Ldstr, "eow");
il.Emit(OpCodes.Ldstr, "ain");
il.EmitCall(OpCodes.Call, typeof(string).GetMethod("Replace", new[] { typeof(string), typeof(string) }), null);
il.EmitCall(OpCodes.Call, typeof(Console).GetMethod("Write", new[] { typeof(string) }), null);
il.Emit(OpCodes.Ret);
var type = typeBuilder.CreateType();
asmBuilder.SetEntryPoint(type.GetMethods()[0]);
asmBuilder.Save("MEOW.exe");

Użyj, Environmnent.CurrentDirectoryaby zobaczyć, gdzie utworzono plik exe. Uruchom go, aby obserwować pożądaną moc wyjściową.

wprowadź opis zdjęcia tutaj

Wynikowa IL: wprowadź opis zdjęcia tutaj

mleko
źródło
Właściwie podoba mi się ten, bardziej niż WPF, ponieważ tak naprawdę nie masz Main () w swoim Zgromadzeniu.
hstde
Twoje rozwiązanie jest interesujące. Jest to drugi, więc wygrasz, jeśli użytkownicy przekonają mnie, że pierwszy post nie jest prawidłowym rozwiązaniem (z jakiego powodu).
Martin Rosenau
Jeśli mnie zapytasz, tak naprawdę nie ma znaczenia, który post wygra, ponieważ oba pochodzą od tego samego użytkownika.
hstde
@hstde - Przepraszam, nie widziałem tego. Dzięki.
Martin Rosenau,
@ mleko Opublikowałeś dwa prawidłowe rozwiązania (cóż, niektórzy użytkownicy mają wątpliwości co do pierwszego), więc wygrywasz. Gratulacje.
Martin Rosenau,
3

Aplikacja WPF

  1. Utwórz nową aplikację WPF. wprowadź opis zdjęcia tutaj

  2. Zastąpić wszystkie wystąpienia MainzMeow wprowadź opis zdjęcia tutaj

  3. Zmień nazwę MainWindow.xamlna MeowWindow.xaml. To automatycznie zmieni nazwę MainWindow.xaml.csna MeowWindow.xaml.cs.

wprowadź opis zdjęcia tutaj

  1. We właściwościach projektu zmień Typ danych wyjściowych na, Console Applicationaby konsola została utworzona. wprowadź opis zdjęcia tutaj

  2. Dodaj zapis w konsoli dla żądanego ciągu wyjściowego w swoim MeowWindowkonstruktorze wprowadź opis zdjęcia tutaj

  3. Ctrl + Shift + F, aby potwierdzić, że nie ma mainnigdzie w katalogu źródłowym. wprowadź opis zdjęcia tutaj

  4. F5 / skompiluj i uruchom. wprowadź opis zdjęcia tutaj

Jak to działa

W przypadku aplikacji WPF program Visual Studio generuje metodę, obj\Debug\App.g.csktóra zawiera tę Mainmetodę. Wygenerowany Maintworzy instancję aplikacji WPF i uruchamia ją.

mleko
źródło
Ciekawe rozwiązanie Ktoś, kto uważa, że ​​to nie jest prawidłowe rozwiązanie? Jeśli ktoś uważa, że ​​ten post jest nieprawidłowy, prosimy o komentarz. W przeciwnym razie zadeklaruję to rozwiązanie jako zwycięskie, ponieważ oczywiście było to pierwsze opublikowane.
Martin Rosenau
@MartinRosenau Wydaje mi się, że skoro można było zdekompilować aplikację wpf i istniałaby główna metoda, że ​​jest ona nieprawidłowa, mocniej, ponieważ ten sam użytkownik opublikował inną odpowiedź, która nie ma tej dwuznaczności
Właśnie zobaczyłem, że obie odpowiedzi zostały opublikowane przez tego samego użytkownika. W takim przypadku ten użytkownik i tak wygra.
Martin Rosenau,
0

Tylko jako odniesienie

Mój pomysł był podobny do drugiego pomysłu „mleka”:

Znajdź sposób, aby IDE wykonało kod i zapisało plik wykonywalny na dysku.

Ja wyraźnie wspomniałem o plikach binarnych Windows i Linux, ponieważ myślałem o zapisaniu pliku binarnego .EXE, System.IO.File.WriteAllBytes()aby nie był to plik .NET EXE.

Mój problem polegał na tym, że VS Express 2010 wydaje się nie mieć interaktywnej konsoli, więc musiałem znaleźć zamiennik - znalazłem następujące:

Utwórz projekt DLL z oknem dialogowym i kontrolką niestandardową; skompiluj projekt i dodaj niestandardową kontrolkę do okna dialogowego. Edytor okien dialogowych wywoła następnie kod niestandardowego elementu sterującego - w tym kodzie możesz zapisać plik .EXE na dysku ...

Martin Rosenau
źródło