C # es el problema principal

10

Este rompecabezas de programación está inspirado en otra pregunta que se hizo ayer aquí pero que fue eliminada por el autor ...

El reto:

Cree un binario ejecutable (binario de Windows .EXE o Linux) usando Visual C # (o su IDE favorito de C #) que imprime el siguiente texto en la salida estándar:

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

... sin usar las 4 letras consecutivas PRINCIPALES que aparecen en cualquier archivo fuente!

Notas:

  • Si su código fuente contiene el texto remainder(por ejemplo), contiene las 4 letras consecutivas PRINCIPALES, sin embargo, si contiene mxainlas 4 letras ya no serían consecutivas, por mxainlo que estaría permitido.
  • No está permitido ejecutar ningún programa que no sea el IDE de C # ni cambiar la configuración del IDE de C # para ejecutar otros programas (pero los que normalmente se ejecutarían, como el compilador de C #).

    De lo contrario, simplemente podría decir: "Escribo un programa Pascal usando el IDE de C # e invoco el compilador Pascal en los pasos 'precompilación' de mi proyecto C #".

    Esto sería muy simple.

  • Los usuarios de un IDE que se puede ampliar utilizando "complementos" (o similares) o que tienen editores de archivos binarios incorporados (editores hexadecimales) tendrían una ventaja demasiado grande sobre los usuarios de otros IDE de C #.

    Por lo tanto, estas características tampoco deben usarse.

  • ¡El uso de otros editores no ASCII (como el editor de la ventana de diálogo) está explícitamente permitido!
  • El usuario que formuló la pregunta original propuso utilizar la barra diagonal inversa en los nombres de las funciones de la siguiente manera: como static void M\u0061in()esta respuesta ya ha sido leída por otros usuarios, ¡ya no será aceptada!
  • Un usuario preguntó si se le permitiría simplemente escribir un archivo .EXE en el editor de código fuente y guardar el archivo como ".exe" en lugar de ".cs". Respuesta: Dudo que esto sea posible porque los binarios válidos de Windows y Linux contienen bytes NUL. Sin embargo, si encuentra un binario válido que se puede crear de esta manera, tiene una solución válida.

El nombre de este sitio es "Rompecabezas de programación y código de golf" - este es un "rompecabezas de programación", no "código de golf": el desafío es encontrar una solución que funcione antes que todos los demás usuarios, no encontrar una solución más corta que todos los demás soluciones

¡Por lo tanto, la primera publicación que describe una solución de trabajo gana !

¡Buena suerte!

Por cierto: tengo una solución que funciona bajo Visual C # Express 2010.

Martin Rosenau
fuente
2
¿Qué me impide usar mi C # IDE como editor de texto (o binario) para escribir directamente un ejecutable?
feersum
2
¿Qué respuesta gana el desafío? ¿La primera respuesta válida? Debe especificar la condición ganadora
James
Si el IDE contiene algún editor hexadecimal o similar, esto NO estaría permitido. Si logras usar el editor de texto ASCII para escribir un archivo binario válido, esto estaría permitido. ¡Tenga en cuenta que un archivo binario válido contiene bytes en el rango de 0x00 a 0x1F!
Martin Rosenau
2
Creo que en general es un desafío interesante. "Escribir un programa C # sin main". Sin embargo, la mayoría de las reglas se refieren a qué herramientas / IDE utilizar y prohíben ciertos enfoques. Me encantaría ver más acertijos de programación (a diferencia del código de golf), pero este no está especificado. Recomiendo usar el sandbox la próxima vez.
James
44
... Considere la caja de arena la próxima vez.
gato

Respuestas:

5

Ventana interactiva de C #

Abra la ventana interactiva de C # (Ver> Otras ventanas> C # interactivo en Visual Studio 2015). Supongo que no todos los IDE tendrán esto.

Este enfoque ejecuta C # en la Ventana interactiva para crear un exe C # que imprima la cadena deseada sin que el autor escriba main. Como beneficio adicional, la IL del exe tampoco contiene main.

Ejecute el siguiente código en la ventana interactiva

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");

Use Environmnent.CurrentDirectorypara ver dónde se creó el exe. Ejecútelo para observar la salida deseada.

ingrese la descripción de la imagen aquí

IL resultante: ingrese la descripción de la imagen aquí

Leche
fuente
De hecho, me gusta más este, luego el WPF, porque en realidad no tienes Main () en tu Asamblea.
hstde
Tu solución es interesante. Es el segundo, por lo que ganará si los usuarios me convencen de que la primera publicación no es una solución válida (por alguna razón).
Martin Rosenau
Si me preguntas, realmente no importa qué publicación gane, ya que ambas son del mismo usuario.
hstde
@hstde - Lo siento, no vi esto. Gracias.
Martin Rosenau
@milk Has publicado dos soluciones válidas (bueno, algunos usuarios tienen dudas sobre la primera) para que ganes. Felicidades.
Martin Rosenau
3

Aplicación WPF

  1. Crea una nueva aplicación WPF. ingrese la descripción de la imagen aquí

  2. Reemplace todas las instancias de MainconMeow ingrese la descripción de la imagen aquí

  3. Cambiar el nombre MainWindow.xamla MeowWindow.xaml. Esto cambiará automáticamente el nombre MainWindow.xaml.csa MeowWindow.xaml.cs.

ingrese la descripción de la imagen aquí

  1. En las propiedades del proyecto, cambie el Tipo de salida para Console Applicationque se cree la consola. ingrese la descripción de la imagen aquí

  2. Agregue escritura de consola para la cadena de salida deseada en su MeowWindowconstructor ingrese la descripción de la imagen aquí

  3. Ctrl + Shift + F para confirmar que no hay ningún mainlugar en el directorio de origen. ingrese la descripción de la imagen aquí

  4. F5 / compilar y ejecutar. ingrese la descripción de la imagen aquí

Cómo funciona

Para aplicaciones WPF, Visual Studio genera el obj\Debug\App.g.csque contiene el Mainmétodo. El generado Maincrea una instancia de su aplicación WPF y la inicia.

Leche
fuente
Solución interesante ¿Alguien que piense que esta no es una solución válida? Si alguien piensa que esta publicación no es válida, publique un comentario. De lo contrario, declararé esta solución como ganadora porque obviamente fue la primera publicada.
Martin Rosenau
@MartinRosenau Creo que ya que podría descompilar la aplicación wpf y habría un método principal que no es válido, más fuertemente porque el mismo usuario publicó otra respuesta que no tiene esta ambigüedad
Acabo de ver que ambas respuestas fueron publicadas por el mismo usuario. En este caso, este usuario ganará de todos modos.
Martin Rosenau
0

Solo como referencia

Mi idea era similar a la segunda idea de "leche":

Encuentre una manera de permitir que el IDE ejecute código y escriba un ejecutable en el disco.

Mencioné explícitamente los archivos binarios de Windows y Linux porque pensé en escribir el archivo binario .EXE usando System.IO.File.WriteAllBytes()para que no fuera necesariamente un archivo .NET EXE.

Mi problema fue que VS Express 2010 parece no tener una consola interactiva, así que tuve que encontrar un reemplazo para eso. Encontré lo siguiente:

Cree un proyecto DLL con una ventana de diálogo y un control personalizado; compile el proyecto y agregue el control personalizado a la ventana de diálogo. El editor de la ventana de diálogo llamará al código del control personalizado, y en este código puede escribir el archivo .EXE en el disco ...

Martin Rosenau
fuente