2

I am using the CSharpCodeProvider in order to compile an .exe myself with variable parameters. Compiling works fine (doesn't return errors) and succeeds but when running it starts and instantly quits w/o any error or output. When changing the "Main" (e.g. to private or by renaming it) the compiler outputs that there is no valid Main Method, so the sample code shouldn't be the reason.

Does anyone have an answer/solution to this? I'm pretty lost on this one and would appreciate any helpful response. Thanks in advance ~

*EDIT:

compiled .exe output: https://i.stack.imgur.com/uB0nJ.jpg

Compiler:

using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Resources;
using System.Security.Cryptography;
using System.Text;
using Microsoft.CSharp;
using Packer.Properties;

namespace Packer
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            Console.WriteLine("Sample Compiler");
            Console.WriteLine(".ico-path: ");
            var icon = "E:\\sample.ico"; //Console.ReadLine();
            Console.WriteLine("> " + icon);
            Console.WriteLine("Target-exe: ");
            var target = "E:\\sample.exe"; //Console.ReadLine();
            Console.WriteLine("> " + target);
            var source = Resources.samplesource;
            // Compile with all params
            var success = CompileFromSource(source, target, icon);
            // Determine result
            Console.WriteLine(success ? "Successfully compiled." : "Compiling error.");
            if (success) Process.Start(target);
            Console.ReadLine();
        }

        private static bool CompileFromSource(string source, string output,
string icon = null, string[] resources = null)
        {
            var cParams = new CompilerParameters
            {
                GenerateInMemory = true,
                WarningLevel = 0,
                GenerateExecutable = true,
                OutputAssembly = output
            };
            var options = "/optimize+ /platform:x86 /target:winexe /unsafe";
            if (icon != null)
                options += " /win32icon:\"" + icon + "\"";
            // Set the options.
            cParams.CompilerOptions = options;
            cParams.TreatWarningsAsErrors = false;
            cParams.ReferencedAssemblies.Add("System.dll");
            cParams.ReferencedAssemblies.Add("System.Core.dll");
            cParams.ReferencedAssemblies.Add("System.Data.dll");
            // Check if the user specified any resource files. & Add them
            if (resources != null && resources.Length > 0)
            {
                // Loop through all resource files specified in the Resources[] array.
                foreach (var res in resources)
                {
                    // Add each resource file to the compiled stub.
                    cParams.EmbeddedResources.Add(res);
                }
            }
            // Dictionary variable is used to tell the compiler what we want
            var providerOptions = new Dictionary<string, string> {{"CompilerVersion", "v4.0"}};
            var results = new CSharpCodeProvider(providerOptions).CompileAssemblyFromSource(cParams, source);
            // Check if any errors occured while compiling.
            if (results.Errors.Count <= 0) return true;
            Console.WriteLine("The compiler has encountered {0} errors", results.Errors.Count);
            foreach (CompilerError err in results.Errors)
            {
                Console.WriteLine("{0}\nLine: {1} - Column: {2}\nFile: {3}", err.ErrorText, err.Line, err.Column,
                    err.FileName);
            }
            return false;
        }
    }
}

The code to compile:

using System;
using System.Text;

namespace CC2Runner
{
    public static class Program
    {
        public static void Main(string[] args)
        {
            try
            {
                Debug.WriteLine("Sample Starting...");
                Console.WriteLine("Sample Starting...");
                ...
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
            Console.ReadLine();
        }
    }
}
rici
  • 234,347
  • 28
  • 237
  • 341
ThexBasic
  • 715
  • 1
  • 6
  • 24
  • Have you checked the event log? – stuartd Sep 20 '16 at 16:18
  • If you are talking about the output from the compiler, yes. It returns true and prints 0 errors. - therefore Successfully compiles. Also I've checked the assembly using ILSpy and it looks just normal. – ThexBasic Sep 20 '16 at 16:22
  • 1
    No, does executing the program (which then promptly exits) log anything in the event log? – Lasse V. Karlsen Sep 20 '16 at 16:22
  • 1
    And using `ILDasm`, and comparing with a "real" program that contains the same code, can you spot any differences? – Lasse V. Karlsen Sep 20 '16 at 16:23
  • Lasse V. Karlsen, I've just included a picture of running the sample, it outputs nothing. – ThexBasic Sep 20 '16 at 16:25
  • 1
    Just add the /pdb option so you can debug the generated program. – Hans Passant Sep 20 '16 at 16:25
  • 2
    "/target:winexe"? So a WinForms program? Try `/target:exe` instead. – Lasse V. Karlsen Sep 20 '16 at 16:26
  • The program directly doesnt have forms but is invoking an assembly which has - Do I have to change something for that? I couldnt find any useful docs about the compiler parameters. – ThexBasic Sep 20 '16 at 16:30
  • Well, does your program do more than what you currently have in the example? Like trying to open a form **and that doesn't happen either**? Or have you simplified it down to what you have in the question in an attempt at finding the cause? Bear in mind that we can only answer the question that was asked, not the question you *should've* asked. Please post a [mcve] that you've verified have the same problem. – Lasse V. Karlsen Sep 20 '16 at 16:32

1 Answers1

6

You've made a WinForms program.

This does not have a console, nor does it output anything to the console it was started from.

How do I know? This:

var options = "/optimize+ /platform:x86 /target:winexe /unsafe";
                                        ^^^^^^^^^^^^^^

Which from csc:

 /target:exe                   Build a console executable (default) (Short
                               form: /t:exe)
 /target:winexe                Build a Windows executable (Short form:
                               /t:winexe)

Switch to /target:exe instead and it should work much better.

Lasse V. Karlsen
  • 380,855
  • 102
  • 628
  • 825
  • ok, that explains alot. If I want to Invoke an assembly afterwards which has forms then, do I have to consider the constructor again? – ThexBasic Sep 20 '16 at 16:34
  • Well, you would probably go back to `/target:winexe` but this does not in any way allow (or in the opposite case, disallow) you using forms. The main difference is whether the program will start with a console attached. If you want that, use `/target:exe`. If you don't want that, use `/target:winexe`. You should probably add the appropriate `Application.XYZ` method calls in your main method though, in either case. Look at a normal WinForms program to find the right statements to have by default. – Lasse V. Karlsen Sep 20 '16 at 16:36
  • But none of this matters if your current test for whether you successfully compiled the project is whether it outputs something to the console. If this is the case, you must create a console app, and this is done with `/target:exe`. – Lasse V. Karlsen Sep 20 '16 at 16:36
  • Setting `/target:exe` solved my problem for now. I am now working on integrating the other assembly and if I encounter a problem use your advise or post a seperate question. Thanks! – ThexBasic Sep 20 '16 at 16:39