1

I wish to launch the Windows 10 Store App Paint3D and make it open a JPG image. I'll be using Java but would be happy to see CMD / C# / Windows API answers. This isn't a question about how to use ProcessBuilder.

Unlike the standard MS Paint application, Paint3D is from Windows Store and does not have Windows executable or alias. Paint3D does support launch url-protocol ms-paint: which can be used in a web browser or launched from Windows CMD.EXE as start ms-paint:.

This code shows 2 ways I've tried to launch Paint3D, one opens Paint3D correctly - but uses mspaint.exe, and the second opens Paint3D but with no image.

Does anyone have an idea whether it is possible to run Paint3D to open with JPG without launching via mspaint.exe?

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;

public class LaunchPaint3D
{
    public static void exec(String[] cmd) throws InterruptedException, IOException
    {
        System.out.println("exec "+Arrays.toString(cmd));

        Path tmpdir = Path.of(System.getProperty("java.io.tmpdir"));
        ProcessBuilder pb = new ProcessBuilder(cmd);

        Path out = tmpdir.resolve(cmd[0]+"-stdout.log");
        Path err = tmpdir.resolve(cmd[0]+"-stderr.log");
        pb.redirectError(out.toFile());
        pb.redirectOutput(err.toFile());

        Process p = pb.start();
        int rc = p.waitFor();

        System.out.println("Exit "+rc +' '+(rc == 0 ? "OK":"**** ERROR ****")
                          +" STDOUT \""+Files.readString(out)+'"'
                          +" STDERR \""+Files.readString(err)+'"');
        System.out.println();
    }

    public static void main(String[] args) throws InterruptedException, IOException
    {
        var jpg = Path.of(args[0]).toAbsolutePath();

        System.out.println("Open "+jpg+" isRegularFile="+Files.isRegularFile(jpg));

        String[] cmdA = new String[] {"mspaint.exe", jpg.toString()+" /ForceBootstrapPaint3D"};
        String[] cmdB = new String[] {"cmd", "/c", "start", "ms-paint:", jpg.toString()};
        // Also tried String[] cmdB = new String[] {"cmd", "/c", "start", "ms-paint:"+jpg.toString()};

        System.out.println("Open Paint3D using MS-PAINT.EXE");
        exec(cmdA);

        System.out.println("PRESS RETURN");
        System.in.read();

        System.out.println("Open Paint3D using URL-PROTOCOL");
        exec(cmdB);

        System.out.println("END");
    }
}

Example test run of the above:

Open c:\temp\small.jpg isRegularFile=true
Open Paint3D using MS-PAINT.EXE
exec [mspaint.exe, c:\temp\small.jpg /ForceBootstrapPaint3D]
Exit 0 OK STDOUT "" STDERR ""

PRESS RETURN

Open Paint3D using URL-PROTOCOL
exec [cmd, /c, start, ms-paint:, c:\temp\small.jpg]
Exit 0 OK STDOUT "" STDERR ""

END
DuncG
  • 12,137
  • 2
  • 21
  • 33
  • Does this answer your question? [Execute external program in java](https://stackoverflow.com/questions/13991007/execute-external-program-in-java) – Pitto Apr 24 '20 at 19:47
  • Paint3D is not an external program as such, but is from Windows Store and does not appear to have an EXE which can be referenced in Runtime.exec() or ProcessBuilder.start(). – DuncG Apr 25 '20 at 11:36

2 Answers2

1

I have found a solution which uses the old Paint application which supports launching to Paint 3D with the passed file argument. The Windows registry also shows this mechanism is used within Windows for editing various image file types such as JPG:

Computer\HKEY_CLASSES_ROOT\SystemFileAssociations\.jpg\Shell\3D Edit\command
=>
%SystemRoot%\system32\mspaint.exe "%1" /ForceBootstrapPaint3D

Run from CMD.EXE:

mspaint "C:\TEMP\A.jpg" /ForceBootstrapPaint3D

Java equivalent:

new ProcessBuilder("mspaint.exe", "c:\\TEMP\\A.jpg /ForceBootstrapPaint3D" ).start()
DuncG
  • 12,137
  • 2
  • 21
  • 33
-1

You should show the source code that does not work. I assume that you forgot that the backslash character introduces an escape sequence. Replace them by double backslash \\ or /.

Stefan
  • 1,789
  • 1
  • 11
  • 16
  • The Java code is exactly as typed. Run jshell> new ProcessBuilder("cmd", "/k", "start", "ms-paint:").start() – DuncG Apr 24 '20 at 20:16
  • But what I need is how I adjust or replace the above to make the Paint3D app open an existing file – DuncG Apr 24 '20 at 20:19
  • Your example does not show how you passed the name of the image file. Have you tried with with ```\\``` or ```/```? – Stefan Apr 26 '20 at 09:37
  • As "start ms-paint: C:\Temp\A.JPG" does not work the same command in Java also does not work: jshell> f.getAbsolutePath() $3 ==> "c:\\TEMP\\A.jpg" jshell> var p = new ProcessBuilder("cmd", "/k", "start", "ms-paint:", f.getAbsolutePath()) p ==> java.lang.ProcessBuilder@20322d26 jshell> p.start() – DuncG Apr 26 '20 at 11:03