diff --git a/agent/src/main/java/com/microsoft/hydralab/agent/util/FileLoadUtil.java b/agent/src/main/java/com/microsoft/hydralab/agent/util/FileLoadUtil.java index f6799e9fb..e4787c7e2 100644 --- a/agent/src/main/java/com/microsoft/hydralab/agent/util/FileLoadUtil.java +++ b/agent/src/main/java/com/microsoft/hydralab/agent/util/FileLoadUtil.java @@ -19,7 +19,6 @@ import javax.annotation.Resource; import java.io.File; -import java.util.Arrays; import java.util.List; import java.util.concurrent.TimeUnit; @@ -88,14 +87,11 @@ public void loadAttachments(Task task) { public void installWinApp(StorageFileInfo attachment) { try { - Runtime runtime = Runtime.getRuntime(); File attachmentFile = downloadFile(attachment, appOptions.getTestPackageLocation(), attachment.getBlobPath()); - String installCommand = "& { Add-AppxPackage -ForceApplicationShutdown -forceupdatefromanyversion -Path '" + - attachmentFile.getAbsolutePath() + "' }"; - String[] command = new String[]{"Powershell.exe", "-Command", installCommand}; + ProcessBuilder processBuilder = createWinAppInstallProcess(attachmentFile); - log.info("Install Win-App start command array: {}", Arrays.asList(command)); - Process process = runtime.exec(command); + log.info("Install Win-App start command array: {}", processBuilder.command()); + Process process = processBuilder.start(); CommandOutputReceiver err = new CommandOutputReceiver(process.getErrorStream(), log); CommandOutputReceiver out = new CommandOutputReceiver(process.getInputStream(), log); err.start(); @@ -108,6 +104,15 @@ public void installWinApp(StorageFileInfo attachment) { } + static ProcessBuilder createWinAppInstallProcess(File attachmentFile) { + // Keep stored filenames out of PowerShell source; environment values are passed as data. + String installCommand = "& { Add-AppxPackage -ForceApplicationShutdown -forceupdatefromanyversion " + + "-Path $env:HYDRALAB_WIN_APP_PATH }"; + ProcessBuilder processBuilder = new ProcessBuilder("Powershell.exe", "-Command", installCommand); + processBuilder.environment().put("HYDRALAB_WIN_APP_PATH", attachmentFile.getAbsolutePath()); + return processBuilder; + } + public void loadCommonFile(StorageFileInfo attachment, Task task) { try { File loadFolder = new File(task.getResourceDir(), attachment.getLoadDir()); diff --git a/agent/src/test/java/com/microsoft/hydralab/agent/util/FileLoadUtilTest.java b/agent/src/test/java/com/microsoft/hydralab/agent/util/FileLoadUtilTest.java new file mode 100644 index 000000000..32079e0ef --- /dev/null +++ b/agent/src/test/java/com/microsoft/hydralab/agent/util/FileLoadUtilTest.java @@ -0,0 +1,52 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +package com.microsoft.hydralab.agent.util; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.util.List; + +class FileLoadUtilTest { + @Test + void winAppPathsArePassedAsDataNotPowerShellCode() { + List paths = List.of( + "packages\\normal.appxbundle", + "packages\\O'Brien.appxbundle", + "package folder\\my app.appxbundle", + "应用程序\\安装包.appxbundle", + "packages\\$env.appxbundle", + "packages\\`backtick`.appxbundle", + "packages\\semi;colon.appxbundle", + "packages\\repeated'''quotes.appxbundle", + "packages\\quote'; $unused = 'data'; '.appxbundle"); + List expectedCommand = List.of("Powershell.exe", "-Command", + "& { Add-AppxPackage -ForceApplicationShutdown -forceupdatefromanyversion " + + "-Path $env:HYDRALAB_WIN_APP_PATH }"); + + for (String path : paths) { + File attachmentFile = new File(path); + ProcessBuilder processBuilder = FileLoadUtil.createWinAppInstallProcess(attachmentFile); + + Assertions.assertEquals(expectedCommand, processBuilder.command(), path); + Assertions.assertEquals(attachmentFile.getAbsolutePath(), + processBuilder.environment().get("HYDRALAB_WIN_APP_PATH"), path); + } + } + + @Test + void winAppInstallPathsAreScopedToEachProcess() { + File firstFile = new File("packages\\first.appxbundle"); + File secondFile = new File("packages\\second.appxbundle"); + String parentPath = System.getenv("HYDRALAB_WIN_APP_PATH"); + + ProcessBuilder first = FileLoadUtil.createWinAppInstallProcess(firstFile); + ProcessBuilder second = FileLoadUtil.createWinAppInstallProcess(secondFile); + + Assertions.assertEquals(firstFile.getAbsolutePath(), first.environment().get("HYDRALAB_WIN_APP_PATH")); + Assertions.assertEquals(secondFile.getAbsolutePath(), second.environment().get("HYDRALAB_WIN_APP_PATH")); + Assertions.assertEquals(parentPath, System.getenv("HYDRALAB_WIN_APP_PATH")); + } +}