빠른 시작: MXC SDK를 사용하여 워크로드 실행

.NET, TypeScript 또는 Rust SDK를 사용하여 Windows 프로세스 격리에서 명령을 실행합니다. 각 예제에서는 샘플 입력을 만들고, 워크로드에서 해당 입력을 읽을 수 있도록 하고, 별도의 출력 폴더에 쓰기 권한을 부여합니다. 네트워크 및 UI 권한은 거부된 상태로 유지됩니다.

호스트 앱이 정책을 만들고 결과를 처리합니다. 명령은 MXC 내에서 실행됩니다. 나머지 호스트 앱은 그렇지 않습니다.

이 예제에서는 MXC 1.0 V1 SDK API를 사용합니다. V1 SDK는 내부적으로 안정적인 1.0.0 스키마를 사용하므로 요청에 스키마 버전을 지정할 필요가 없습니다. 호환되는 스키마 선택을 참조하세요.

Prerequisites

다음이 필요합니다:

  • 지원되는 ProcessContainer 환경이 있는 버전 24H2 이상인 Windows 11.
  • C#의 경우 .NET 8 SDK 이상과 Microsoft.Mxc.Sdk NuGet 패키지가 필요합니다.
  • TypeScript, npm, @microsoft/mxc-sdk 패키지, 그리고 Node.js 24 릴리스 계열의 24.21.0 이상 또는 Node.js 26.8.0 이상.
  • Rust의 경우 MSVC 빌드 도구와 mxc-sdk crate가 포함된 안정적인 Rust 도구 체인이 필요합니다. Windows Rust 개발 환경 설정을 참조하세요.
  • 설치 명령을 실행하기 위한 쓰기 가능한 작업 디렉터리와 PowerShell이 필요합니다.

지침에서는 NuGet.org, npm 및 crates.io의 MXC 1.0 패키지를 사용합니다. MXC 원본 빌드가 필요하지 않습니다.

예제를 실행하기 전에 플랫폼 지원을 확인하세요. 지원되는 Windows 버전이 모든 선택적 기능을 사용할 수 있다고 보장하지는 않습니다.

일부 호스트에서 MXC는 AppContainer 기반 대체 계층에서 프로세스 격리를 실행합니다. 해당 계층은 시스템 드라이브와 null 디바이스를 일회성으로 준비해야 하며 다시 시작할 때마다 null 디바이스 설정이 다시 설정됩니다. 준비가 누락되면 MXC의 호스트 프로브는 wxc-host-prep.exe 하위 명령을 실행하라는 경고를 반환합니다. TypeScript 예제에서는 getPlatformSupport()에서 이러한 경고를 출력하며, wxc-exec.exe --probe를 실행하여 호스트를 확인할 수도 있습니다. wxc-host-prep.exe에는 관리자 승인이 필요하므로 앱에서 실행하는 대신 관리자가 권장 명령을 실행하도록 합니다. 자세한 내용은 호스트 준비를 참조하세요.

1. 프로젝트 만들기

콘솔 앱을 만들고 NuGet.org에서 MXC 패키지를 추가합니다.

dotnet new console -n MxcQuickstart
Set-Location MxcQuickstart
dotnet add package Microsoft.Mxc.Sdk

2. 워크로드 정의 및 실행

프로세스 격리는 선택한 호스트 파일이 필요하고 보존된 환경이 없으므로 이 단기 명령에 적합합니다. 다른 워크로드에는 다른 컨테이너 유형이 필요할 수 있습니다.

호스트는 프로젝트 디렉터리 아래에 workspace\input 및 workspace\output을 만듭니다. 포함된 명령이 input.txt을 읽고 result.txt에 씁니다. 입력 디렉터리에 대한 쓰기 액세스 또는 다른 프로젝트 파일에 대한 액세스 권한을 받지 않습니다.

호스트는 자체 변수를 상속하는 대신 작고 명시적인 환경을 제공합니다. Windows ProcessContainer 워크로드에 대한 환경을 제공하는 경우 SystemRoot 및 LOCALAPPDATA를 모두 포함합니다. MXC는 둘 중 하나가 누락된 경우 시작하기 전에 요청을 거부합니다. 이 예제는 TMP, LOCALAPPDATA, TEMP에서 부여된 출력 디렉터리를 가리키므로 임시 파일 및 사용자별 파일이 정책 내에 유지됩니다.

Program.cs으로 대체합니다.

using Microsoft.Mxc.Sdk.V1;

if (!OperatingSystem.IsWindows())
{
    Console.Error.WriteLine("This example requires Windows.");
    return 1;
}

try
{
    var support = MxcPlatform.GetPlatformSupport();
    if (!support.IsSupported ||
        !support.AvailableMethods.Contains(ContainmentBackend.ProcessContainer))
    {
        Console.Error.WriteLine(support.Reason ?? "Windows ProcessContainer is unavailable.");
        return 1;
    }

    string inputDirectory = Path.GetFullPath(@"workspace\input");
    string outputDirectory = Path.GetFullPath(@"workspace\output");
    string outputFile = Path.Combine(outputDirectory, "result.txt");
    string commandInterpreter = Path.Combine(Environment.SystemDirectory, "cmd.exe");

    Directory.CreateDirectory(inputDirectory);
    Directory.CreateDirectory(outputDirectory);
    File.WriteAllText(Path.Combine(inputDirectory, "input.txt"), "Hello from MXC!\n");

    var request = new ContainerRequest(
        $"\"{commandInterpreter}\" /d /c type input.txt > \"{outputFile}\"")
    {
        Containment = new Containment.Process(),
        Filesystem = new FilesystemPolicy
        {
            ReadonlyPaths = { inputDirectory, commandInterpreter },
            ReadwritePaths = { outputDirectory },
        },
        // Omitted network and UI permissions remain denied.
        WorkingDirectory = inputDirectory,
        Environment = new()
        {
            ["SystemRoot"] = Environment.GetFolderPath(Environment.SpecialFolder.Windows),
            ["LOCALAPPDATA"] = outputDirectory,
            ["TEMP"] = outputDirectory,
            ["TMP"] = outputDirectory,
        },
        TimeoutMs = 30_000,
    };

    ExecutionResult result = await MxcContainer.RunAsync(request);
    Console.Write(result.Stdout);
    Console.Error.Write(result.Stderr);
    foreach (string warning in result.Warnings)
    {
        Console.Error.WriteLine(warning);
    }

    if (result.TimedOut)
    {
        Console.Error.WriteLine("The workload exceeded its timeout.");
        return 1;
    }

    Console.WriteLine($"Sandbox exited with code {result.ExitCode}");
    if (result.ExitCode == 0)
    {
        Console.Write(File.ReadAllText(outputFile));
    }
    return result.ExitCode;
}
catch (MxcException ex)
{
    Console.Error.WriteLine(ex);
    if (ex.Remediation is not null)
    {
        Console.Error.WriteLine(ex.Remediation);
    }
    return 1;
}

앱을 실행합니다.

dotnet run

각 버전은 다음을 출력합니다:

Sandbox exited with code 0
Hello from MXC!

workspace\output\result.txt를 검사할 수도 있습니다.

3. 거부된 작업 확인

명령이 읽기 전용 입력 디렉터리에 쓰려고 시도하도록 출력 파일 선언만 변경합니다.

string outputFile = Path.Combine(inputDirectory, "blocked.txt");

정책을 변경하지 않고 앱을 다시 실행하세요. 액세스 거부 오류와 0이 아닌 종료 코드가 발생하고 새 workspace\input\blocked.txt 파일은 생성되지 않을 것으로 예상됩니다. 원래 출력 파일 선언을 복원하고 허용된 작업이 여전히 성공하는지 확인하십시오.

허용된 실행이 실패하면 호스트 설정 또는 구성 오류를 리소스 사용 거부와 구분합니다. 학습 모드를 사용하여 해당 사항을 조사합니다. 정책을 자동으로 확대하지 마세요.

4. 예제 수정

샘플 명령 및 입력을 신뢰할 수 있는 대표 워크로드로 바꾸세요. 필수 도구 이진 파일, 라이브러리, 임시 파일 및 출력을 검토합니다. 태스크에 필요할 때만 네트워크 또는 UI 액세스를 추가하고, 선택한 백엔드가 의도한 제한을 적용할 수 있어야 합니다.

모든 대상 호스트에서 허용된 작업 및 거부된 작업을 테스트합니다. 학습 모드를 사용하여 정책을 구체화하는 경우 각 관찰을 검토하고 학습 또는 감사 설정 없이 강제 실행으로 완료합니다.

선택 사항: 코딩 에이전트 사용

에이전트에게 대상 플랫폼, SDK 언어 및 버전, 명령, 필요한 리소스, 수명 주기 및 격리 목표를 제공하세요. 이 프롬프트를 조정할 수 있습니다.

Use the MXC Learn quickstart and the documentation for my installed SDK release.
Integrate this workload through the .NET, TypeScript, or Rust SDK used by this project.

First identify the command, target platforms, input and output paths, network
and UI requirements, and whether state must persist between commands.
Explain the containment choice and create the narrowest policy that fits.
Run both permitted and denied cases and report the effective permissions.

Do not execute the workload outside MXC to get around a failure. Ask for my
approval before expanding access, changing host settings, or using permissive
Learning Mode. Treat observed resource access as evidence, not automatic grants.

에이전트의 가정 및 그에 따라 생성된 정책을 검토합니다. 에이전트는 통합을 지원할 수 있지만 신뢰할 수 있는 호스트 코드 또는 사람은 워크로드의 권한에 대한 변경 내용을 승인해야 합니다.

다음 단계