Search code examples
c#processcommand

C# Impossible to Run Command with Spaces in the EXE


I am trying to execute this command via C# from Visual Studio 2017 target framework is .NET 4.5. No matter what I tried wrapping it in quotes it doesn't fire due to there being a space in the EXE file's name. I read everyone else fixed this issue by wrapping them in quotes well it's not working. I am on Windows 10.0.19045.4046

static void Main(string[] args)
{
    // Export Current Settings
    string cncmd = GetCnCMD();
    string AMD3D = (System.IO.Path.GetTempPath() + @"\AMD3DSettings.zip").Replace(@"\\", @"\");

    Run("\"" + cncmd + "\" export \"" + AMD3D + "\" >%TMP%\\Log3d.txt");
}

static void Run(string command)
{
    Console.WriteLine(command);

    System.Diagnostics.Process process = new System.Diagnostics.Process();

    System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
    startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal;
    startInfo.FileName = @"cmd.exe";
    startInfo.Arguments = "/k " + command;

    process.StartInfo = startInfo;
    process.Start();
    process.WaitForExit();
}

public static string GetCnCMD()
{
    try
    {
        RegistryKey HKLM = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);
        RegistryKey cnkey = HKLM.OpenSubKey(@"SOFTWARE\AMD\CN");

        string dir = (string) cnkey.GetValue("InstallDir");

        if (dir.EndsWith(@"\") || dir.EndsWith(@"/"))
        {
            dir = dir.Substring(0, dir.Length - 1);
        }

        return dir + @"\cncmd.exe";
    }
    catch(Exception e)
    {
        Console.Error.WriteLine(e.Message + " " + e.GetType());
        string HOMEDRIVE = Environment.GetFolderPath(Environment.SpecialFolder.System).Substring(0, 1);
        string cncmd = HOMEDRIVE + @":\Program Files\AMD\CNext\CNext\cncmd.exe";

        if (File.Exists(cncmd))
            return cncmd;

        cncmd = HOMEDRIVE + @":\Program Files (x86)\AMD\CNext\CNext\cncmd.exe";

        if (File.Exists(cncmd))
            return cncmd;

        // Check older or newer likely paths
        cncmd = HOMEDRIVE + @":\Program Files\AMD\CNext\cncmd.exe";

        if (File.Exists(cncmd))
            return cncmd;

        cncmd = HOMEDRIVE + @":\Program Files (x86)\AMD\CNext\cncmd.exe";

        if (File.Exists(cncmd))
            return cncmd;
    }

    return null;
}

Output cmd window 1:

"C:\Program Files\AMD\CNext\CNext\cncmd.exe" export "C:\Users\jredfox\AppData\Local\Temp\AMD3DSettings.zip" >%TMP%\Log3d.txt

Output cmd window 2:

'C:\Program' is not recognized as an internal or external command, operable program or batch file.


Solution

  • startInfo.Arguments = $@"/k ""{command}""";
    

    Just wrap your command string in another pair of quotation marks if the command string contains multiple quotation mark pairs, because cmd will strip the outmost quotation marks. See the document to know the rules of the /k switch: cmd.exe

    Addtional notes:

    1. I suggest you to add the /s switch, so regardless of whether the command string complies with those rules, the above method is always applicable.

    2. Using the /k switch will require you to manually exit the cmd process. If this is not what you expected, you should replace it with the /c switch.

      startInfo.Arguments = $@"/s /c ""{command}""";