3

I am trying to run a batch file using C#

The batch file for the test purposes contains

msg * Test

It works if I run it manually.

Then I use the following code to run this .bat file

filePath = full path to batch file

var startInfo = new ProcessStartInfo
{
    Arguments = "/C \"" + filePath + "\"",
    FileName = "cmd.exe",
    UseShellExecute = true
};
Process p = Process.Start(startInfo);

and it does not work ->

cannot find msg

What I am doing wrong?

P.S. the batch file should not be changed.

miduja
  • 31
  • 3

3 Answers3

0

Try this way: batchfile:

set "msg=%SystemRoot%\System32\msg.exe"
if not exist "%msg%" set "msg=%SystemRoot%\Sysnative\msg.exe"
"%msg%" * Hello 

code:

string sFile = <full path to batch file>;
 Process.Start("cmd.exe", "/c " + sFile);
  • Thank you for the answer, but how can I run it without changing the batch file? ```msg``` command is just an example – miduja Jul 24 '19 at 09:35
  • For example - if you copy msg.exe to batchfile directory, it will not be necessary to specify the path manually – Igor Chepik Jul 24 '19 at 10:24
0

The problem is the location of the file (msg.exe) in the different OS versions (32bit/64bit)

I suppose it helps How can I execute msg.exe by C# in windows?

Edited: It works fine -

class Program
{
    static void Main(string[] args)
    {
        int ExitCode;

        try
        {
            var returnedMsgPath = string.Empty;

            if (LocateMsgExe(out returnedMsgPath))
            {
                var startInfo = new ProcessStartInfo()
                {
                    FileName = returnedMsgPath,
                    Arguments = @"* /v Hello",
                    UseShellExecute = false,
                    CreateNoWindow = true,
                    RedirectStandardError = true,
                    RedirectStandardOutput = true
                };

                var p = Process.Start(startInfo);
                p.WaitForExit();
                // *** Read the streams ***
                string output = p.StandardOutput.ReadToEnd();
                string error = p.StandardError.ReadToEnd();

                ExitCode = p.ExitCode;

                MessageBox.Show("output >>" + (String.IsNullOrEmpty(output) ? "(none)" : output));
                MessageBox.Show("error>>" + (String.IsNullOrEmpty(error) ? "(none)" : error));
                MessageBox.Show("ExitCode: " + ExitCode.ToString(), "ExecuteCommand");
                p.Close();
            }
            else
            {
                MessageBox.Show("Not found");
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }

    public static bool LocateMsgExe(out string returnedMsgPath)
    {
        returnedMsgPath = null;
        string[] msgPaths = new string[] { Environment.ExpandEnvironmentVariables(@"%windir%\system32\msg.exe"),
                                 Environment.ExpandEnvironmentVariables(@"%windir%\sysnative\msg.exe") };

        foreach (string msgPath in msgPaths)
        {
            if (File.Exists(msgPath))
            {
                returnedMsgPath = msgPath;
                return true;
            }
        }

        return false;
    }
}
Firo
  • 30,626
  • 4
  • 55
  • 94
  • As i understand the question, it is running a batch file and the Program does not know what's in it. The problem is that it works when starting the batch in explorer but not through code. – Firo Jul 24 '19 at 09:22
  • Did you read my comment? I know the solution you posted works, but it is for a different Problem. Msg was only used to test it. It will also not work for other commands. – Firo Jul 24 '19 at 11:08
  • what is the problem instead "msg" to use "ping" or "echo" or something else? – Vadym Polshcha Jul 24 '19 at 13:28
  • @VadymPolshcha if msg does not work in the testing case, something else also will not work. That is the point to use msg.exe – miduja Jul 25 '19 at 06:18
0

Probably need some authorization, you may try the following code:

static void ExecuteCommand(string command)
{
    int exitCode;
    ProcessStartInfo processInfo;
    Process process;

    processInfo = new ProcessStartInfo("cmd.exe", "/c " + command);
    processInfo.CreateNoWindow = true;
    processInfo.Domain = "domain"; // Your own domain
    processInfo.UserName = "userName"; // Your own user name
    System.Security.SecureString s = new System.Security.SecureString();
    s.AppendChar('p'); // Your own password
    s.AppendChar('a');
    s.AppendChar('s');
    s.AppendChar('s');
    s.AppendChar('w');
    s.AppendChar('o');
    s.AppendChar('r');
    s.AppendChar('d');
    processInfo.Password = s;
    processInfo.UseShellExecute = false;
    // *** Redirect the output ***
    processInfo.RedirectStandardError = true;
    processInfo.RedirectStandardOutput = true;

    process = Process.Start(processInfo);
    process.WaitForExit();

    // *** Read the streams ***
    // Warning: This approach can lead to deadlocks, see Edit #2
    string output = process.StandardOutput.ReadToEnd();
    string error = process.StandardError.ReadToEnd();

    exitCode = process.ExitCode;

    Console.WriteLine("output>>" + (String.IsNullOrEmpty(output) ? "(none)" : 
 output));
    Console.WriteLine("error>>" + (String.IsNullOrEmpty(error) ? "(none)" : 
 error));
    Console.WriteLine("ExitCode: " + exitCode.ToString(), "ExecuteCommand");
    process.Close();
}

static void Main()
{
    ExecuteCommand(@"C:\displayMsg.bat");
}   

You may check your domain in Control Panel >> User Account >> Manage User Accounts

Source of reference: source

Yeoh FS
  • 21
  • 7