10
\$\begingroup\$

This programming puzzle is inspired by another question which has been asked here yesterday but which was deleted by the author...

The challenge:

Create an executable binary (Windows .EXE or Linux binary) using Visual C# (or your favorite C# IDE) which prints the following text to the standard output:

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

... without using the 4 consecutive letters M-A-I-N appearing in any source file!

Notes:

  • If your source code contains the text remainder (for example) it contains the 4 consecutive letters M-A-I-N, however if it contains mxain the 4 letters would not be consecutive any more so mxain would be allowed.
  • You are not allowed to run any programs but the C# IDE nor change the settings of the C# IDE to run other programs (but the ones it would normally run such as the C# compiler).

    Otherwise you could simply say: "I write a Pascal program using the C# IDE and invoke the Pascal compiler in the 'pre-build' steps of my C# project".

    This would be too simple.

  • Users of an IDE that can be extending using "plug-ins" (or similar) or that have built-in binary file editors (hex-editors) would have a too large advantage over users of other C# IDEs.

    Therefore these featrues should also not be used.

  • Using the other non-ASCII-Editors (such as the dialog window editor) is explicitly allowed!
  • The user asking the original question proposed using the backslash in function names just like this: static void M\u0061in() Because this answer has already been read by other users it will not be accepted any more!
  • A user asked if it would be allowed to simply type in an .EXE file into the source code editor and to save the file as ".exe" instead of ".cs". Answer: I doub't that this is possible because both valid Windows and Linux binaries contain NUL bytes. However if you find a valid binary that can be created this way you have a valid solution.

The name of this site is "Programming Puzzles & Code Golf" - this is a "Programming Puzzle", not "Code Golf": The challenge is to find a working solution before all other users, not to find a solution shorter than all other solutions.

Therefore the first post describing a working solution wins!

Good luck!

By the way: I have a solution working under Visual C# Express 2010.

\$\endgroup\$
  • 2
    \$\begingroup\$ What stops me from using my C# IDE as a text (or binary) editor to directly type out an executable? \$\endgroup\$ – feersum Oct 19 '16 at 20:05
  • 2
    \$\begingroup\$ Which answer wins the challenge? The first valid answer? You should specify the winning condition \$\endgroup\$ – James Oct 19 '16 at 20:07
  • \$\begingroup\$ If the IDE contains some hexadecimal editor or similar this would NOT be allowed. If you manage to use the ASCII text editor to type in a valid binary file this would be allowed. Note that a valid binary file contains bytes in the range 0x00 to 0x1F! \$\endgroup\$ – Martin Rosenau Oct 19 '16 at 20:08
  • 2
    \$\begingroup\$ I think this is overall an interesting challenge. "Write a C# program without main". However, most of the rules are about which tools/IDEs to use and banning certain approaches. I'd love to see more programming puzzles, (as opposed to code-golf) but this one is underspecified. I'd recommend using the sandbox next time. \$\endgroup\$ – James Oct 19 '16 at 20:24
  • 4
    \$\begingroup\$ ...Consider the sandbox next time. \$\endgroup\$ – cat Oct 19 '16 at 21:53
5
\$\begingroup\$

C# Interactive Window

Open the C# Interactive Window (View > Other Windows > C# Interactive in Visual Studio 2015). I suppose not all IDEs will have this.

This approach executes C# in the Interactive Window in order to create a C# exe that prints the desired string without the author ever writing main. As a bonus, the exe's IL also does not contain main.

Run the following code in the Interactive Window

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.CurrentDirectory to see where the exe was created. Run it to observe the desired output.

enter image description here

Resulting IL: enter image description here

\$\endgroup\$
  • \$\begingroup\$ I actually like this one better, then the WPF one, because you actually have no Main() in your Assembly whatsoever. \$\endgroup\$ – hstde Oct 21 '16 at 6:11
  • \$\begingroup\$ Your solution is interesting. It is the second one so you will win if the users should convince me that the first post is not a valid solution (for what reason ever). \$\endgroup\$ – Martin Rosenau Oct 21 '16 at 6:17
  • \$\begingroup\$ If you ask me it doesn't really matter which post wins, since they are both by the same user. \$\endgroup\$ – hstde Oct 21 '16 at 13:57
  • \$\begingroup\$ @hstde - Sorry, I did not see this. Thanks. \$\endgroup\$ – Martin Rosenau Oct 22 '16 at 10:06
  • \$\begingroup\$ @milk You posted two valid solutions (well, some users have doubt about the first one) so you win. Congratulations. \$\endgroup\$ – Martin Rosenau Oct 22 '16 at 10:08
3
\$\begingroup\$

WPF Application

  1. Create a new WPF application. enter image description here

  2. Replace all instances of Main with Meow enter image description here

  3. Rename MainWindow.xaml to MeowWindow.xaml. This will automatically rename MainWindow.xaml.cs to MeowWindow.xaml.cs.

enter image description here

  1. In project properties, change the Output type to Console Application so the console is created. enter image description here

  2. Add console write for the desired output string in your MeowWindow constructor enter image description here

  3. Ctrl+Shift+F to confirm there's no main anywhere in the source directory. enter image description here

  4. F5 / compile and run. enter image description here

How it works

For WPF applications, Visual Studio generates obj\Debug\App.g.cs which contains the Main method. The generated Main creates an instance of your WPF app and starts it.

\$\endgroup\$
  • \$\begingroup\$ Interesting solution. Anyone who thinks that this is not a valid solution? If anyone thinks that this post is not valid please post a comment. Otherwise I will declare this solution the winning one because it was obviously the first one posted. \$\endgroup\$ – Martin Rosenau Oct 21 '16 at 6:11
  • \$\begingroup\$ @MartinRosenau I feel that since you could decompile the wpf app and there would be a main method that this is invalid, more strongly because the same user posted another answer that does not have this ambiguity \$\endgroup\$ – user19547 Oct 21 '16 at 20:03
  • \$\begingroup\$ I just saw that both answers were posted by the same user. In this case this user will win anyway. \$\endgroup\$ – Martin Rosenau Oct 22 '16 at 10:06
0
\$\begingroup\$

Just as a reference

My idea was similar to "milk"'s second idea:

Find a way to let the IDE execute code and write an executable to the disk.

I explicitly mentioned Windows and Linux binaries because I thought about writing the binary .EXE file using System.IO.File.WriteAllBytes() so it would not neccessarily be a .NET EXE file.

My problem was that VS Express 2010 seems not to have an interactive console so I had to find a replacement for that - I found the following:

Create a DLL project with a dialog window and a custom control; compile the project and add the custom control to the dialog window. The dialog window editor will then call the code of the custom control - and in this code you may write the .EXE file to the disk...

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.