0

i want to use CMD.exe in my C# Program. The Problem is iam using normally The CMD to open Two Programs to convert Fotos from .png to .svg (ImageMagick.exe & Potrace.exe). That happend via CMD.exe with Tow Command-lines the firsstepe: magick convert image.png image.pnm the secondstep: potrace image.pnm image.svg How to call the CMD.exe to do this two commandslin in my C# Program ?

i try this commands Lines but he call just the CMD.exe and do not anything.

Compo
  • 36,585
  • 5
  • 27
  • 39
Sam
  • 31
  • 5
  • 4
    Why do you want to use `cmd.exe`? Why not launch the `magick` and `potrace` processes directly? – Mathias R. Jessen Jan 12 '23 at 13:02
  • When writing programs, i contrast to scripts, you would usually prefer to use libraries instead of other programs. There is for example [Magic.Net](https://github.com/dlemstra/Magick.NET) library for ImageMagic that might be used. – JonasH Jan 12 '23 at 13:10
  • ok, thanks. how should i write the Comman of Potrace? – Sam Jan 12 '23 at 14:01
  • There is a .NET port of *potrace*: https://github.com/daltonks/BitmapToVector – Yevhen Cherkes Jan 12 '23 at 14:38
  • var process = Process.Start("cmd", "'/C magick convert image.png image.pnm && potrace image.pnm image.svg'"); process.WaitForExit(); – Yevhen Cherkes Jan 12 '23 at 15:15
  • There is really no need to use the C# [Process class](https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.process) being a C# wrapper class for the Windows kernel library function [CreateProcess](https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw) called without or with a [STARTUPINFO](https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/ns-processthreadsapi-startupinfow) structure. `cmd.exe` calls also `CreateProcess` on running an executable like `magick.exe` and calls next `CreateProcess` for `Potrace.exe`. – Mofi Jan 13 '23 at 06:34
  • If `cmd.exe` can call `CreateProcess` to run `magick.exe` and wait for its self-termination without or with evaluation of exit code (the later would be better here for `magick.exe`) and can call next `CreateProcess` to run `Potrace.exe` and wait again for its self-termination. a C# coded application can use the `Process` class twice to do exactly the same without using `cmd.exe` at all as simple not needed for this task. I recommend to read the following Stack Overflow questions and answers on `magick.exe` and `Potrace.exe` are stored always in same directory as the C# coded application. – Mofi Jan 13 '23 at 06:39
  • [Which is better for getting assembly location: GetAssembly().Location or GetExecutingAssembly().Location?](https://stackoverflow.com/a/27060089/3074564) and [How can I get the application's path in a .NET console application?](https://stackoverflow.com/questions/837488/) and [Best way to get application folder path](https://stackoverflow.com/questions/6041332). A C# coded application should not expect that the current directory on starting it is the directory containing the C# coded executable which contains the other two executables, too. – Mofi Jan 13 '23 at 06:41
  • Well, best is the usage of libraries on being available as it is the case here. There is no execution of other executables needed at all in this case. The research phase of the development project was obviously skipped by you resulting in asking for help on an [XY problem](https://xyproblem.info/). I recommend for the future to spend some time in research on how a program writing task could be solved before even beginning writing the first code line. That can save a lot of time in development and avoid problems in future caused by wrong implementation because of having skipped the research. – Mofi Jan 13 '23 at 06:47

1 Answers1

0

If you use the C# Process class as shown in the code below, with process.WaitForExit() called after each process is started, then you can run the two commands separately as shown. I think the correct calls are in fact magick convert image.png image.pnm and then potrace image.pnm -b svg. This works for me and is what the code is doing.

The biggest problem here was getting C# to find the files it needs. To get this to work I put potrace in a subfolder of the project and copied it to the output directory, so you don't need to install it. I couldn't get this to work for ImageMagick. It appears to need to be installed to work, so in the end I just installed it. The files to be converted are similarly in a Files subfolder of the project with 'Copy to Output Directory' set on their project properties.

As some of the commenters have suggested it may be better to try one of the libraries that can be called directly from C# rather than starting separate processes, which are clearly more inefficient. However, my experience is that often this sort of wrapper project is not well-maintained versus the main project, so if the solution below works it may be fine.

I can upload the full project to GitHub if that would be helpful.

using System.Diagnostics;
using System.Reflection;
#nullable disable 
namespace ImageMagicPotrace
{
    internal class Program
    {
        static void Main(string[] args)
        {
            string path = Path.GetDirectoryName(Assembly.GetAssembly(typeof(Program)).Location);
            string filesPath = Path.Combine(path, "Files");

            string fileName = "image";

            string imageMagick = "magick.exe";
            string arg = $"convert \"{Path.Combine(filesPath, fileName + ".png")}\" \"{Path.Combine(filesPath, fileName + ".pnm")}\"";
            RunProcess(imageMagick, arg);

            string potrace = Path.Combine(path, @"potrace\potrace.exe");
            string arg2 = $"\"{Path.Combine(filesPath, fileName + ".pnm")}\" -b svg";
            RunProcess(potrace, arg2);

            Console.WriteLine("Done");
        }

        private static void RunProcess(string executable, string arg)
        {
            Console.WriteLine(executable);
            Console.WriteLine(arg);
            ProcessStartInfo start = new ProcessStartInfo(executable)
            {
                WindowStyle = ProcessWindowStyle.Hidden,
                Arguments = arg,
                UseShellExecute = false,
                CreateNoWindow = true
            };
            Process process = Process.Start(start);
            process.WaitForExit();
        }
    }
}
Rich N
  • 8,939
  • 3
  • 26
  • 33
  • nice! if you have a time, i would like to have it please on GitHub, thank you very much :) – Sam Jan 18 '23 at 14:39
  • This is now [available on GitHub](https://github.com/rich-newman/ImageMagickPotrace). Instructions are in the readme. – Rich N Jan 18 '23 at 17:18