2

What I need is that: I have a c# code and I want to build it in order to create a .bat file on desktop. So when I run this .bat file from desktop, it should execute the c# code.

Is there a way to change the settings or properties of c# project before compiling in order to create a .bat file that should run this c# code?

Abel
  • 56,041
  • 24
  • 146
  • 247
Davideg
  • 841
  • 4
  • 14
  • 23
  • Why not write a C# application, build an EXE and create a shortcut on the desktop? – fletcher Aug 04 '10 at 14:13
  • I don't understand. If you have a C# project and you want to compile it, what's wrong with clicking Build in Visual Studio? Are you trying to automate building? Or do you mean to interpret C# code, when `CSC.EXE` is not available? – Abel Aug 04 '10 at 14:14
  • I want to compile it and the outbut is .bat file? that`s all my friend.. – Davideg Aug 05 '10 at 03:58
  • 1
    Why do you want the .bat file? A C# project will compile to a .exe file - you can *launch* the .exe from a .bat if you desire, but you don't gain anything by doing so (unless you have other requirements that you haven't stated). – Dan Puzey Aug 05 '10 at 09:58

8 Answers8

13

Compile you C# code into a console application.

Then run this application using the batch file.

Create an file on you desktop called batch.bat (or whatever.bat) and put the following in it:

@echo off
[full path to your application]\[application name].exe [any additional parameters]

--- ALTERNATIVE ----

In the project properties, there is the option for Build Events. In the post build command line put the following:

echo @echo off > [path to desktop batchfile].bat
echo $(TargetPath) >> [path to desktop batchfile].bat
Adrian Regan
  • 2,240
  • 13
  • 11
  • You don't need to have a console application to be able to run it from a batch file ;) – Abel Aug 04 '10 at 15:45
  • how to create the batch file to run the console application using it? – Davideg Aug 05 '10 at 04:03
  • @Davideg I'm taking a stab in the dark here, but if you're asking how to physically create the batch file, just use a text editor like notepad and save the file as either *.bat or *.cmd – Chris Thompson Aug 09 '10 at 14:14
3

I understand your question somehow that you want to compile a C# source file using a batch program. Suppose your C# source file looks like this (save as "test.cs"):

using System;

public class Print
{
    public static void Main()
    {
        Console.WriteLine("Hurray I am printing to the CONSOLE!!");
    }
}

you can compile that as follows on the command prompt:

csc /out:test.exe test.cs

Which brings us to the batch file:

@ECHO OFF
csc /out:test.exe test.cs

Or, generalized, taking up argument nr 1 from the command line:

@ECHO OFF
csc /out:%1.exe %1
Abel
  • 56,041
  • 24
  • 146
  • 247
2

As an alternative, you may want to consider using the windows powershell instead of the regular old commandline. In the powershell you can work with arbitrary .net assemblies. In other words, you don't have to do anything in your C#/VB code to accommodate the commandline.

Angelo
  • 2,936
  • 5
  • 29
  • 44
2

Yes.

  1. In Visual Studio, right-click on your C# project and choose Properties
  2. Go to the Build Events tab
  3. In the post build box, type the following:

.

set batchName=%userprofile%\desktop\runCSharp.bat
echo @echo off > %batchName%
echo "$(TargetPath)" >> %batchName%
echo pause >> %batchName%

That will create a batch file on your desktop that will run the compiled c# program.

Scott Langham
  • 58,735
  • 39
  • 131
  • 204
1
  1. Right click on your desktop.
  2. Choose New from the menu
  3. Choose Text Document
  4. Type a name for the text document such as "RunCSharp.bat"
  5. Double click on the new file
  6. Copy the following code into it.
  7. Choose File Save from the menu
  8. Double click on the file.
  9. The C# code in the batch file will compile and run.

.

@echo off
set csfile=%temp%\temp.cs
echo // C# code > %csfile%
echo using System; >> %csfile%
echo using System.Text; >> %csfile%
echo namespace HelloWorld >> %csfile%
echo { >> %csfile%
echo   public class HelloWorldMain >> %csfile%
echo   { >> %csfile%
echo     public static void Main() >> %csfile%
echo     { >> %csfile%
echo        Console.WriteLine("Hello world!"); >> %csfile%
echo     } >> %csfile%
echo   } >> %csfile%
echo } >> %csfile%

csc /nologo /out:%temp%\temp.exe %csfile%
%temp%\temp.exe
pause
Scott Langham
  • 58,735
  • 39
  • 131
  • 204
  • 5
    Some people go to great lengths for pain. – Matthew Whited Aug 09 '10 at 14:18
  • It's a literal answer to a silly question. Sometimes these serve to finally illuminate to the OP what they are asking for. – Nick.Mc Jan 06 '17 at 13:33
  • @Nick.McDermaid - why silly question ? powershell has add-type cmd-let - similar capabilities would be handy in cmd too (moreover it's totally possible - without temp files and compiling an exe , though a little bit more verbose than in powershell) – npocmaka Jan 06 '17 at 18:16
0

You can simply create a batch file on the desktop that does the following

cd \<applicationdirectory>\bin\<release or debug depending on your build configuration>
START <application name>

All you need to do is create a .txt file on your desktop, place the commands above in the file (with the correct directories and names) and then rename the file to .bat

  • ok man.So if I have a test.exe file and I want to change it to test.bat file, all I want is to create test.txt file and write the directory of the test.exe above in the file then rename it to test.bat. Is that what you mean? or there is another thing to do? – Davideg Aug 05 '10 at 04:02
  • Did you try it? Why do you care what the extension is (exe vs bat?) Do you know the difference? a Bat is a text file and an exe is a binary file – Nick.Mc Jan 06 '17 at 13:34
0

I know it's so late but may be in future some one can get benefits.

In vs we can write batch by using console application

Open vs --> File --> New --> Project --> console application.

You can query in google regarding how to write console application.

Ilaya Bharathi
  • 93
  • 1
  • 14
  • Please, enhance your answer by adding more info about solution to the question – ddb Jul 23 '16 at 11:08
  • we can run through console application by creating exe . After successful Build, run the code through command prompt cd (your batch file path) > followed by application name or else we can create a task schedule to run the application – Ilaya Bharathi Jul 23 '16 at 11:26
0

You can check the self-compiled .net hybrids thread on dostips. The best technique according to me is the one that uses msbuild and inline tasks - it does not creates .exe files and there's no redundant output:

<!-- :
    @echo off


        echo -^- FROM BATCH

        set "CMD_ARGS=%*"
        ::::::  Starting C# code :::::::
        :: searching for msbuild location
        for /r "%SystemRoot%\Microsoft.NET\Framework\" %%# in ("*msbuild.exe") do  set "msb=%%#"

        if not defined  msb (
           echo no .net framework installed
           exit /b 10
        )

        rem ::::::::::  calling msbuid :::::::::
        call %msb% /nologo  /noconsolelogger "%~dpsfnx0"  /property:"H=From C#"
        rem ::::::::::::::::::::::::::::::::::::
        exit /b %errorlevel%
--> 


<Project ToolsVersion="$(MSBuildToolsVersion)" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Target Name="_">
    <_/>
  </Target>
  <UsingTask
    TaskName="_"
    TaskFactory="CodeTaskFactory"
    AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v$(MSBuildToolsVersion).dll" > 

    <ParameterGroup  >
         <Z ParameterType="System.String">$(H)</Z>
    </ParameterGroup>

    <Task>
      <Using Namespace="System" />
      <Code Type="Fragment" Language="cs">
        <![CDATA[
            String CMD_ARGS=Environment.GetEnvironmentVariable("CMD_ARGS");
            System.Console.WriteLine("-- "+"$(H)");  
        ]]>
      </Code>
    </Task>
  </UsingTask>
</Project>

The only one thing is that for command line arguments you'll have to create a variable in the batch part (e.g. set "CMD_ARGS=*%") and then extract this like environment variable from the C# code.

Another note is that you cant use directly -- string in the batch part because the xml will be not parsed.

Beware the first line the : is important as it uses the parsing priority of batch files - it will be interpreted as :<!-- which during the execution will be taken for label and not executed.

If you want to use a whole class follow this example (you need to extend ITask and Task and Execute method):

<!-- :
    @echo off


        echo -^- FROM BATCH

        set "CMD_ARGS=%*"
        ::::::  Starting C# code :::::::
        :: searching for msbuild location
        for /r "%SystemRoot%\Microsoft.NET\Framework\" %%# in ("*msbuild.exe") do  set "msb=%%#"

        if not defined  msb (
           echo no .net framework installed
           exit /b 10
        )

        rem ::::::::::  calling msbuid :::::::::
        call %msb% /nologo  /noconsolelogger "%~dpsfnx0"
        rem ::::::::::::::::::::::::::::::::::::
        exit /b %errorlevel%

--> 


<Project ToolsVersion="$(MSBuildToolsVersion)" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Target Name="Program">
    <Program/>
  </Target>
  <UsingTask
    TaskName="Program"
    TaskFactory="CodeTaskFactory"
    AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v$(MSBuildToolsVersion).dll" > 

    <Task>
      <Reference Include="$(MSBuildToolsPath)\System.Windows.Forms.dll"/>
      <Using Namespace="System" />

      <Code Type="Class" Language="cs">
        <![CDATA[
    using Microsoft.Build.Framework;
    using Microsoft.Build.Utilities;
    using System;

    public class Program:Task, ITask
    {
        public override bool Execute(){
            Console.WriteLine("Whoa");
            String CMD_ARGS=Environment.GetEnvironmentVariable("CMD_ARGS");
            System.Console.WriteLine("-- "+"$(MSBuildToolsVersion)"); 
            return true;
        }
    }
        ]]>
      </Code>
    </Task>
  </UsingTask>
</Project>

If you you need just a few methods(so simple fragment wont work) but not a whole class you can check this:

<!-- :
    @echo off


        echo -^- FROM BATCH

        set "CMD_ARGS=%*"
        ::::::  Starting C# code :::::::
        :: searching for msbuild location
        for /r "%SystemRoot%\Microsoft.NET\Framework\" %%# in ("*msbuild.exe") do  set "msb=%%#"

        if not defined  msb (
           echo no .net framework installed
           exit /b 10
        )

        rem ::::::::::  calling msbuid :::::::::
        call %msb% /nologo  /noconsolelogger "%~dpsfnx0"
        rem ::::::::::::::::::::::::::::::::::::
        exit /b %errorlevel%

--> 


<Project ToolsVersion="$(MSBuildToolsVersion)" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Target Name="_">
    <_/>
  </Target>
  <UsingTask
    TaskName="_"
    TaskFactory="CodeTaskFactory"
    AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v$(MSBuildToolsVersion).dll" > 

    <Task>
      <Reference Include="$(MSBuildToolsPath)\System.Windows.Forms.dll"/>
      <Using Namespace="System" />

      <Code Type="Method" Language="cs">
        <![CDATA[

        public override bool Execute(){
            MyMethod();
            return true;
        }

        void MyMethod(){
            Console.WriteLine("Whoa");
            String CMD_ARGS=Environment.GetEnvironmentVariable("CMD_ARGS");
            System.Console.WriteLine("-- "+"$(MSBuildToolsVersion)"); 
        }
        ]]>
      </Code>
    </Task>
  </UsingTask>
</Project>

With powershell Add-Type:

<# : batch portion
@echo off & setlocal

set "CMD_ARGS=%~1"

powershell -noprofile "iex (${%~f0} | out-string)"
goto :EOF

: end batch / begin powershell #>

param($psArg1 = $env:psArg1)


$CS = @" 
namespace PS {
  public class CS
  {
    public static void csEcho(string arg)
    { System.Console.WriteLine("echo from C# " + arg); }
  }
}
"@

Add-Type -TypeDefinition $CS -Language CSharp


[PS.CS]::csEcho($psArg1 + " and PowerShell")

With self-compiling:

// 2>nul||@goto :batch
/*
@echo off
setlocal

:: find csc.exe
set "csc="
for /r "%SystemRoot%\Microsoft.NET\Framework\" %%# in ("*csc.exe") do  set "csc=%%#"

if not exist "%csc%" (
   echo no .net framework installed
   exit /b 10
)

if not exist "%~n0.exe" (
   call %csc% /nologo /w:0 /out:"%~n0.exe" "%~dpsfnx0" || (
      exit /b %errorlevel% 
   )
)
%~n0.exe %*
endlocal & exit /b %errorlevel%

*/

using System;


class QE {
    static void Main(string[] args) {
         Console.WriteLine("Echo from C#");
    }
} 

And mind that sometimes JScript.NET will be enough - it requires less code ,has no redundant output and has access to the .NET classes (though is harder to use P/Invoke):

 @if (@X)==(@Y) @end /* JScript comment
@echo off
setlocal

for /f "tokens=* delims=" %%v in ('dir /b /s /a:-d  /o:-n "%SystemRoot%\Microsoft.NET\Framework\*jsc.exe"') do (
   set "jsc=%%v"
)

if not exist "%~n0.exe" (
    "%jsc%" /nologo /out:"%~n0.exe" "%~dpsfnx0"
)

%~n0.exe %*

endlocal & exit /b %errorlevel%


*/

import System;
Console.Write("Echo from .NET")
npocmaka
  • 55,367
  • 18
  • 148
  • 187