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.sstatic.net/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();
        }
    }
}
9
  • Have you checked the event log? Commented Sep 20, 2016 at 16:18
  • 1
    No, does executing the program (which then promptly exits) log anything in the event log? Commented Sep 20, 2016 at 16:22
  • 1
    And using ILDasm, and comparing with a "real" program that contains the same code, can you spot any differences? Commented Sep 20, 2016 at 16:23
  • 1
    Just add the /pdb option so you can debug the generated program. Commented Sep 20, 2016 at 16:25
  • 2
    "/target:winexe"? So a WinForms program? Try /target:exe instead. Commented Sep 20, 2016 at 16:26

1 Answer 1

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.

Sign up to request clarification or add additional context in comments.

4 Comments

ok, that explains alot. If I want to Invoke an assembly afterwards which has forms then, do I have to consider the constructor again?
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.
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.
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!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.