windows-development-sandbox 1.23.2 → 1.25.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (211) hide show
  1. package/config.example.json +5 -3
  2. package/dist/app/features/data/data.def.d.ts +4 -4
  3. package/dist/app/features/data/data.run.d.ts +1 -1
  4. package/dist/app/features/defs.d.ts +161 -6
  5. package/dist/app/features/defs.js +7 -0
  6. package/dist/app/features/projects/projects.def.d.ts +1 -1
  7. package/dist/app/features/projects/projects.run.d.ts +1 -1
  8. package/dist/app/features/unreal/index.d.ts +2 -0
  9. package/dist/app/features/unreal/index.js +3 -0
  10. package/dist/app/features/unreal/unreal.def.d.ts +236 -0
  11. package/dist/app/features/unreal/unreal.def.js +379 -0
  12. package/dist/app/features/unreal/unreal.run.d.ts +96 -0
  13. package/dist/app/features/unreal/unreal.run.js +217 -0
  14. package/dist/app/registry.js +5 -0
  15. package/dist/bin/agent-sandbox.js +2 -2
  16. package/dist/bin/{chunk-7YPEDAJD.js → chunk-3GAXLATK.js} +58 -5
  17. package/dist/bin/{chunk-USTRSHIE.js → chunk-F4PVBN23.js} +2615 -1515
  18. package/dist/bin/{chunk-QFSJX2KW.js → chunk-G3TG4ZT7.js} +1 -1
  19. package/dist/bin/claude-host.js +2 -2
  20. package/dist/bin/claude-sbx.js +2 -2
  21. package/dist/bin/codex-sbx.js +2 -2
  22. package/dist/bin/gemini-sbx.js +2 -2
  23. package/dist/bin/sandbox.js +2 -2
  24. package/dist/bin/sbx-hide.js +2 -2
  25. package/dist/bin/sbx-show.js +2 -2
  26. package/dist/cli/commands/launch/launch.js +5 -2
  27. package/dist/cli/commands/registry.js +3 -0
  28. package/dist/cli/manifest.d.ts +18 -0
  29. package/dist/cli/manifest.js +26 -0
  30. package/dist/cli/menu/coverage-exempt.js +1 -0
  31. package/dist/cli/menu/pages/sandbox-page.d.ts +3 -0
  32. package/dist/cli/menu/pages/sandbox-page.js +34 -4
  33. package/dist/cli/menu/views.js +2 -0
  34. package/dist/core/config/defaults.js +18 -5
  35. package/dist/core/detect/toolchains.js +0 -6
  36. package/dist/core/schema/config.d.ts +10 -9
  37. package/dist/core/schema/pc-installs.d.ts +3 -1
  38. package/dist/core/schema/pc-installs.js +10 -1
  39. package/dist/core/schema/toolchains.d.ts +1 -2
  40. package/dist/core/schema/toolchains.js +4 -7
  41. package/dist/guest/accounts/kinds/epic.js +18 -13
  42. package/dist/guest/agents/agent-files.d.ts +11 -7
  43. package/dist/guest/agents/agent-files.js +37 -11
  44. package/dist/guest/agents/local-state.d.ts +2 -1
  45. package/dist/guest/agents/local-state.js +2 -1
  46. package/dist/guest/apps/after-install.d.ts +1 -1
  47. package/dist/guest/apps/after-install.js +6 -1
  48. package/dist/guest/apps/app-installer.d.ts +1 -0
  49. package/dist/guest/apps/app-installer.js +13 -3
  50. package/dist/guest/apps/comet-unpack.js +3 -2
  51. package/dist/guest/apps/resolvers-gamedev.js +55 -1
  52. package/dist/guest/boot/boot-console.d.ts +28 -0
  53. package/dist/guest/boot/boot-console.js +98 -0
  54. package/dist/guest/boot/boot.d.ts +8 -1
  55. package/dist/guest/boot/boot.js +80 -43
  56. package/dist/guest/boot/graph.d.ts +9 -5
  57. package/dist/guest/boot/graph.js +8 -2
  58. package/dist/guest/boot/guide.js +24 -0
  59. package/dist/guest/boot/progress-view.d.ts +116 -0
  60. package/dist/guest/boot/progress-view.js +456 -0
  61. package/dist/guest/boot/runner.d.ts +20 -10
  62. package/dist/guest/boot/runner.js +39 -47
  63. package/dist/guest/daemon/daemon.js +3 -0
  64. package/dist/guest/runtime/log-line.d.ts +7 -0
  65. package/dist/guest/runtime/log-line.js +18 -0
  66. package/dist/guest/runtime/log.d.ts +17 -4
  67. package/dist/guest/runtime/log.js +40 -17
  68. package/dist/guest/runtime/process.d.ts +9 -0
  69. package/dist/guest/runtime/process.js +69 -8
  70. package/dist/guest/setup/addon-mcp.d.ts +7 -0
  71. package/dist/guest/setup/addon-mcp.js +19 -4
  72. package/dist/guest/setup/browser-gpu.js +14 -11
  73. package/dist/guest/setup/environment.js +9 -4
  74. package/dist/guest/setup/headroom.js +4 -0
  75. package/dist/guest/setup/hooks.d.ts +2 -0
  76. package/dist/guest/setup/hooks.js +4 -0
  77. package/dist/guest/setup/path-plan.d.ts +12 -0
  78. package/dist/guest/setup/path-plan.js +18 -0
  79. package/dist/guest/toolchains/engines/epic-launcher.d.ts +26 -0
  80. package/dist/guest/toolchains/engines/epic-launcher.js +127 -0
  81. package/dist/guest/toolchains/engines/unreal-engines.d.ts +21 -1
  82. package/dist/guest/toolchains/engines/unreal-engines.js +163 -3
  83. package/dist/guest/toolchains/engines/unreal-status.d.ts +13 -0
  84. package/dist/guest/toolchains/engines/unreal-status.js +41 -0
  85. package/dist/guest/toolchains/native/debuggers.d.ts +6 -0
  86. package/dist/guest/toolchains/native/debuggers.js +57 -0
  87. package/dist/guest/toolchains/native/mesa.js +15 -8
  88. package/dist/guest/toolchains/native/rust-extras.d.ts +7 -0
  89. package/dist/guest/toolchains/native/rust-extras.js +23 -1
  90. package/dist/guest/toolchains/native/unreal.d.ts +2 -2
  91. package/dist/guest/toolchains/native/unreal.js +96 -20
  92. package/dist/guest/toolchains/native/visual-studio.d.ts +14 -14
  93. package/dist/guest/toolchains/native/visual-studio.js +145 -174
  94. package/dist/guest/toolchains/native/vs-persist.d.ts +189 -0
  95. package/dist/guest/toolchains/native/vs-persist.js +256 -0
  96. package/dist/guest/toolchains/native/vs-request.d.ts +6 -26
  97. package/dist/guest/toolchains/native/vs-request.js +16 -50
  98. package/dist/guest/toolchains/plan.js +23 -15
  99. package/dist/guest/toolchains/tools/vscode-profile.js +2 -0
  100. package/dist/host/accounts/kinds/epic.js +11 -5
  101. package/dist/host/accounts/source.d.ts +2 -0
  102. package/dist/host/accounts/source.js +1 -0
  103. package/dist/host/migrate/migrations/drop-vs-install-files.d.ts +5 -0
  104. package/dist/host/migrate/migrations/drop-vs-install-files.js +34 -0
  105. package/dist/host/migrate/registry.js +7 -1
  106. package/dist/host/pc-installs/discover.d.ts +2 -0
  107. package/dist/host/pc-installs/discover.js +25 -5
  108. package/dist/host/pc-installs/epic.d.ts +3 -0
  109. package/dist/host/pc-installs/epic.js +33 -2
  110. package/dist/host/pc-installs/source.d.ts +1 -1
  111. package/dist/host/pc-installs/unreal-vault.d.ts +11 -0
  112. package/dist/host/pc-installs/unreal-vault.js +78 -0
  113. package/dist/host/pc-installs/unreal.d.ts +36 -0
  114. package/dist/host/pc-installs/unreal.js +145 -2
  115. package/dist/host/profile/claude-profile.d.ts +8 -0
  116. package/dist/host/profile/claude-profile.js +43 -4
  117. package/dist/host/profile/index.d.ts +1 -1
  118. package/dist/host/profile/index.js +1 -1
  119. package/dist/runtime/agent.js +148 -33
  120. package/dist/runtime/daemon.js +3146 -1546
  121. package/dist/runtime/db.js +148 -33
  122. package/dist/runtime/main.js +3982 -2049
  123. package/dist/runtime/netproxy.js +84 -13
  124. package/dist/runtime/tool.js +125 -31
  125. package/dist/runtime/view.js +85 -14
  126. package/dist/selftest/agent-paths.test.js +18 -1
  127. package/dist/selftest/agent-settings.test.js +36 -5
  128. package/dist/selftest/agents-web.test.js +12 -0
  129. package/dist/selftest/boot-console.test.d.ts +2 -0
  130. package/dist/selftest/boot-console.test.js +291 -0
  131. package/dist/selftest/boot-runner.test.js +10 -12
  132. package/dist/selftest/engines.test.js +602 -3
  133. package/dist/selftest/guest-boot.test.js +7 -1
  134. package/dist/selftest/heavy-load.test.js +3 -1
  135. package/dist/selftest/hostile-input.test.js +11 -1
  136. package/dist/selftest/index.js +4 -0
  137. package/dist/selftest/layout.test.js +4 -0
  138. package/dist/selftest/menu-screens.js +3 -1
  139. package/dist/selftest/migrate.test.js +21 -0
  140. package/dist/selftest/mixamo.test.d.ts +2 -0
  141. package/dist/selftest/mixamo.test.js +60 -0
  142. package/dist/selftest/persisted-installs.test.js +169 -33
  143. package/dist/selftest/secrets.test.js +36 -1
  144. package/dist/selftest/support/engine-golden.js +5 -0
  145. package/dist/selftest/support/fixtures.d.ts +4 -3
  146. package/dist/selftest/support/unreal-sample.d.ts +2 -0
  147. package/dist/selftest/support/unreal-sample.js +83 -0
  148. package/dist/selftest/toolchains.test.js +32 -2
  149. package/dist/shared/accounts/index.d.ts +1 -1
  150. package/dist/shared/accounts/index.js +1 -1
  151. package/dist/shared/accounts/kinds/epic.d.ts +6 -1
  152. package/dist/shared/accounts/kinds/epic.js +11 -1
  153. package/dist/shared/apps/associations.d.ts +7 -0
  154. package/dist/shared/apps/associations.js +26 -0
  155. package/dist/shared/apps/catalogue-agents-web.d.ts +4 -1
  156. package/dist/shared/apps/catalogue-agents-web.js +5 -2
  157. package/dist/shared/apps/catalogue-gamedev.js +71 -1
  158. package/dist/shared/apps/index.d.ts +2 -0
  159. package/dist/shared/apps/index.js +2 -0
  160. package/dist/shared/apps/preview.d.ts +2 -0
  161. package/dist/shared/apps/preview.js +10 -0
  162. package/dist/shared/browser-policy.d.ts +14 -0
  163. package/dist/shared/browser-policy.js +22 -0
  164. package/dist/shared/channel/schema.d.ts +3 -6
  165. package/dist/shared/io/index.d.ts +1 -0
  166. package/dist/shared/io/index.js +1 -0
  167. package/dist/shared/io/rotate-log.d.ts +2 -0
  168. package/dist/shared/io/rotate-log.js +16 -0
  169. package/dist/shared/memory/policy.d.ts +5 -0
  170. package/dist/shared/memory/policy.js +7 -0
  171. package/dist/shared/paths/pc-installs.d.ts +13 -2
  172. package/dist/shared/paths/pc-installs.js +1 -0
  173. package/dist/shared/pty/terminal.js +2 -1
  174. package/dist/shared/readiness.d.ts +0 -1
  175. package/dist/shared/readiness.js +0 -1
  176. package/dist/shared/signer.d.ts +4 -0
  177. package/dist/shared/signer.js +2 -0
  178. package/dist/shared/unreal/engines.d.ts +161 -0
  179. package/dist/shared/unreal/engines.js +308 -0
  180. package/dist/shared/unreal/guide.d.ts +19 -0
  181. package/dist/shared/unreal/guide.js +105 -0
  182. package/dist/shared/unreal/index.d.ts +7 -0
  183. package/dist/shared/unreal/index.js +8 -0
  184. package/dist/shared/unreal/launcher-files.d.ts +88 -0
  185. package/dist/shared/unreal/launcher-files.js +292 -0
  186. package/dist/shared/unreal/mixamo.d.ts +5 -0
  187. package/dist/shared/unreal/mixamo.js +16 -0
  188. package/dist/shared/unreal/room.d.ts +17 -0
  189. package/dist/shared/unreal/room.js +34 -0
  190. package/dist/shared/unreal/status.d.ts +54 -0
  191. package/dist/shared/unreal/status.js +57 -0
  192. package/dist/shared/unreal/vault.d.ts +21 -0
  193. package/dist/shared/unreal/vault.js +67 -0
  194. package/dist/shared/unreal/vs-check.d.ts +39 -0
  195. package/dist/shared/unreal/vs-check.js +79 -0
  196. package/dist/sync/watcher.js +5 -1
  197. package/dist/web/index.html +1 -1
  198. package/dist/web/{main-CCILLX2M.js → main-FNE6XEHA.js} +84 -84
  199. package/native/csharp/HcsHost/AssemblyInfo.cs +3 -3
  200. package/native/csharp/HostTools/AssemblyInfo.cs +3 -3
  201. package/native/csharp/StorageHelper/AssemblyInfo.cs +3 -3
  202. package/package.json +1 -1
  203. package/sandbox/csharp/VsSetup.cs +210 -0
  204. package/sandbox/scripts/get-vs-setup.ps1 +93 -0
  205. package/sandbox/scripts/restore-visual-studio.ps1 +78 -0
  206. package/sandbox/scripts/save-visual-studio.ps1 +106 -0
  207. package/sandbox/scripts/set-registry-values.ps1 +35 -0
  208. package/schemas/config.schema.json +38 -9
  209. package/schemas/sandbox-config.schema.json +11 -8
  210. package/dist/guest/toolchains/native/autosdk.d.ts +0 -3
  211. package/dist/guest/toolchains/native/autosdk.js +0 -50
@@ -8,9 +8,9 @@ using System.Runtime.InteropServices;
8
8
  [assembly: AssemblyCompany("windows-development-sandbox (open source)")]
9
9
  [assembly: AssemblyProduct("Windows Development Sandbox")]
10
10
  [assembly: AssemblyCopyright("MIT License, windows-development-sandbox contributors")]
11
- [assembly: AssemblyVersion("1.23.2.0")]
12
- [assembly: AssemblyFileVersion("1.23.2.0")]
13
- [assembly: AssemblyInformationalVersion("1.23.2")]
11
+ [assembly: AssemblyVersion("1.25.0.0")]
12
+ [assembly: AssemblyFileVersion("1.25.0.0")]
13
+ [assembly: AssemblyInformationalVersion("1.25.0")]
14
14
  [assembly: ComVisible(false)]
15
15
  // computecore.dll and computestorage.dll are not KnownDLLs: load them from System32 only, never from the exe's folder.
16
16
  [assembly: DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
@@ -8,7 +8,7 @@ using System.Runtime.InteropServices;
8
8
  [assembly: AssemblyCompany("windows-development-sandbox (open source)")]
9
9
  [assembly: AssemblyProduct("Windows Development Sandbox")]
10
10
  [assembly: AssemblyCopyright("MIT License, windows-development-sandbox contributors")]
11
- [assembly: AssemblyVersion("1.23.2.0")]
12
- [assembly: AssemblyFileVersion("1.23.2.0")]
13
- [assembly: AssemblyInformationalVersion("1.23.2")]
11
+ [assembly: AssemblyVersion("1.25.0.0")]
12
+ [assembly: AssemblyFileVersion("1.25.0.0")]
13
+ [assembly: AssemblyInformationalVersion("1.25.0")]
14
14
  [assembly: ComVisible(false)]
@@ -9,7 +9,7 @@ using System.Runtime.InteropServices;
9
9
  [assembly: AssemblyCompany("windows-development-sandbox (open source)")]
10
10
  [assembly: AssemblyProduct("Windows Development Sandbox")]
11
11
  [assembly: AssemblyCopyright("MIT License, windows-development-sandbox contributors")]
12
- [assembly: AssemblyVersion("1.23.2.0")]
13
- [assembly: AssemblyFileVersion("1.23.2.0")]
14
- [assembly: AssemblyInformationalVersion("1.23.2")]
12
+ [assembly: AssemblyVersion("1.25.0.0")]
13
+ [assembly: AssemblyFileVersion("1.25.0.0")]
14
+ [assembly: AssemblyInformationalVersion("1.25.0")]
15
15
  [assembly: ComVisible(false)]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "windows-development-sandbox",
3
- "version": "1.23.2",
3
+ "version": "1.25.1",
4
4
  "description": "A disposable Windows Sandbox for development, with or without an AI agent (Claude Code, Codex, Gemini, opencode, ...): the folder you run it from is the workspace, toolchains and databases for your project install themselves, and nothing else on your PC is reachable.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -0,0 +1,210 @@
1
+ // The Visual Studio Setup Configuration API as UnrealBuildTool calls it (MicrosoftPlatformSDK: SetupConfiguration,
2
+ // ISetupConfiguration2.EnumAllInstances, ISetupInstance2): every instance with its state, version, product, path and
3
+ // packages. Loaded by scripts\get-vs-setup.ps1 (Add-Type), which adds the file checks and writes the JSON. C# 5.
4
+ using System;
5
+ using System.Collections.Generic;
6
+ using System.Runtime.InteropServices;
7
+ using FILETIME = System.Runtime.InteropServices.ComTypes.FILETIME;
8
+
9
+ namespace AgentSandbox
10
+ {
11
+ [ComImport]
12
+ [Guid("42843719-DB4C-46C2-8E7C-64F1816EFD5B")]
13
+ [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
14
+ public interface ISetupConfiguration
15
+ {
16
+ IEnumSetupInstances EnumInstances();
17
+ ISetupInstance GetInstanceForCurrentProcess();
18
+ ISetupInstance GetInstanceForPath([In, MarshalAs(UnmanagedType.LPWStr)] string path);
19
+ }
20
+
21
+ [ComImport]
22
+ [Guid("26AAB78C-4A60-49D6-AF3B-3C35BC93365D")]
23
+ [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
24
+ public interface ISetupConfiguration2 : ISetupConfiguration
25
+ {
26
+ new IEnumSetupInstances EnumInstances();
27
+ new ISetupInstance GetInstanceForCurrentProcess();
28
+ new ISetupInstance GetInstanceForPath([In, MarshalAs(UnmanagedType.LPWStr)] string path);
29
+ IEnumSetupInstances EnumAllInstances();
30
+ }
31
+
32
+ [ComImport]
33
+ [Guid("6380BCFF-41D3-4B2E-8B2E-BF8A6810C848")]
34
+ [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
35
+ public interface IEnumSetupInstances
36
+ {
37
+ void Next(
38
+ [In, MarshalAs(UnmanagedType.U4)] int celt,
39
+ [Out, MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.Interface, SizeParamIndex = 0)]
40
+ ISetupInstance[] rgelt,
41
+ [Out, MarshalAs(UnmanagedType.U4)] out int pceltFetched);
42
+ void Skip([In, MarshalAs(UnmanagedType.U4)] int celt);
43
+ void Reset();
44
+ IEnumSetupInstances Clone();
45
+ }
46
+
47
+ [ComImport]
48
+ [Guid("B41463C3-8866-43B5-BC33-2B0676F7F42E")]
49
+ [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
50
+ public interface ISetupInstance
51
+ {
52
+ [return: MarshalAs(UnmanagedType.BStr)] string GetInstanceId();
53
+ [return: MarshalAs(UnmanagedType.Struct)] FILETIME GetInstallDate();
54
+ [return: MarshalAs(UnmanagedType.BStr)] string GetInstallationName();
55
+ [return: MarshalAs(UnmanagedType.BStr)] string GetInstallationPath();
56
+ [return: MarshalAs(UnmanagedType.BStr)] string GetInstallationVersion();
57
+ [return: MarshalAs(UnmanagedType.BStr)] string GetDisplayName([In, MarshalAs(UnmanagedType.U4)] int lcid);
58
+ [return: MarshalAs(UnmanagedType.BStr)] string GetDescription([In, MarshalAs(UnmanagedType.U4)] int lcid);
59
+ [return: MarshalAs(UnmanagedType.BStr)] string ResolvePath([In, MarshalAs(UnmanagedType.LPWStr)] string path);
60
+ }
61
+
62
+ [ComImport]
63
+ [Guid("89143C9A-05AF-49B0-B717-72E218A2185C")]
64
+ [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
65
+ public interface ISetupInstance2 : ISetupInstance
66
+ {
67
+ [return: MarshalAs(UnmanagedType.BStr)] new string GetInstanceId();
68
+ [return: MarshalAs(UnmanagedType.Struct)] new FILETIME GetInstallDate();
69
+ [return: MarshalAs(UnmanagedType.BStr)] new string GetInstallationName();
70
+ [return: MarshalAs(UnmanagedType.BStr)] new string GetInstallationPath();
71
+ [return: MarshalAs(UnmanagedType.BStr)] new string GetInstallationVersion();
72
+ [return: MarshalAs(UnmanagedType.BStr)] new string GetDisplayName([In, MarshalAs(UnmanagedType.U4)] int lcid);
73
+ [return: MarshalAs(UnmanagedType.BStr)] new string GetDescription([In, MarshalAs(UnmanagedType.U4)] int lcid);
74
+ [return: MarshalAs(UnmanagedType.BStr)] new string ResolvePath([In, MarshalAs(UnmanagedType.LPWStr)] string path);
75
+ [return: MarshalAs(UnmanagedType.U4)] uint GetState();
76
+ [return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_UNKNOWN)]
77
+ ISetupPackageReference[] GetPackages();
78
+ ISetupPackageReference GetProduct();
79
+ [return: MarshalAs(UnmanagedType.BStr)] string GetProductPath();
80
+ [return: MarshalAs(UnmanagedType.IUnknown)] object GetErrors();
81
+ [return: MarshalAs(UnmanagedType.VariantBool)] bool IsLaunchable();
82
+ [return: MarshalAs(UnmanagedType.VariantBool)] bool IsComplete();
83
+ }
84
+
85
+ [ComImport]
86
+ [Guid("DA8D8A16-B2B6-4487-A2F1-594CCCCD6BF5")]
87
+ [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
88
+ public interface ISetupPackageReference
89
+ {
90
+ [return: MarshalAs(UnmanagedType.BStr)] string GetId();
91
+ [return: MarshalAs(UnmanagedType.BStr)] string GetVersion();
92
+ [return: MarshalAs(UnmanagedType.BStr)] string GetChip();
93
+ [return: MarshalAs(UnmanagedType.BStr)] string GetLanguage();
94
+ [return: MarshalAs(UnmanagedType.BStr)] string GetBranch();
95
+ [return: MarshalAs(UnmanagedType.BStr)] string GetType();
96
+ [return: MarshalAs(UnmanagedType.BStr)] string GetUniqueId();
97
+ [return: MarshalAs(UnmanagedType.VariantBool)] bool GetIsExtension();
98
+ }
99
+
100
+ [ComImport]
101
+ [Guid("177F0C4A-1CD3-4DE7-A32C-71DBBB9FA36D")]
102
+ [ClassInterface(ClassInterfaceType.None)]
103
+ public class SetupConfiguration
104
+ {
105
+ }
106
+
107
+ /// <summary>One instance as the Setup API reports it.</summary>
108
+ public class SetupInstanceInfo
109
+ {
110
+ public string InstanceId;
111
+ public string InstallationPath;
112
+ public string InstallationVersion;
113
+ public string ProductId;
114
+ public uint State;
115
+ public bool IsComplete;
116
+ public bool IsLaunchable;
117
+ public string[] Packages;
118
+ }
119
+
120
+ public static class VsSetup
121
+ {
122
+ /// <summary>InstanceState.Local: the instance's files are on this machine (the only ones UnrealBuildTool uses).</summary>
123
+ public const uint StateLocal = 1;
124
+
125
+ /// <summary>Every instance EnumAllInstances lists (complete or not), as UnrealBuildTool enumerates them.</summary>
126
+ public static SetupInstanceInfo[] AllInstances()
127
+ {
128
+ List<SetupInstanceInfo> found = new List<SetupInstanceInfo>();
129
+ ISetupConfiguration2 setup = (ISetupConfiguration2)new SetupConfiguration();
130
+ IEnumSetupInstances instances = null;
131
+ try
132
+ {
133
+ instances = setup.EnumAllInstances();
134
+ ISetupInstance[] one = new ISetupInstance[1];
135
+ while (true)
136
+ {
137
+ int fetched;
138
+ instances.Next(1, one, out fetched);
139
+ if (fetched == 0)
140
+ {
141
+ break;
142
+ }
143
+ ISetupInstance2 instance = (ISetupInstance2)one[0];
144
+ try
145
+ {
146
+ found.Add(Describe(instance));
147
+ }
148
+ finally
149
+ {
150
+ Marshal.ReleaseComObject(instance);
151
+ }
152
+ }
153
+ }
154
+ finally
155
+ {
156
+ if (instances != null)
157
+ {
158
+ Marshal.ReleaseComObject(instances);
159
+ }
160
+ Marshal.ReleaseComObject(setup);
161
+ }
162
+ return found.ToArray();
163
+ }
164
+
165
+ private static SetupInstanceInfo Describe(ISetupInstance2 instance)
166
+ {
167
+ SetupInstanceInfo info = new SetupInstanceInfo();
168
+ info.InstanceId = instance.GetInstanceId();
169
+ info.InstallationPath = instance.GetInstallationPath();
170
+ info.InstallationVersion = instance.GetInstallationVersion();
171
+ info.State = instance.GetState();
172
+ ISetupPackageReference product = instance.GetProduct();
173
+ if (product == null)
174
+ {
175
+ info.ProductId = "";
176
+ }
177
+ else
178
+ {
179
+ try
180
+ {
181
+ info.ProductId = product.GetId();
182
+ }
183
+ finally
184
+ {
185
+ Marshal.ReleaseComObject(product);
186
+ }
187
+ }
188
+ info.IsComplete = instance.IsComplete();
189
+ info.IsLaunchable = instance.IsLaunchable();
190
+ ISetupPackageReference[] packages = instance.GetPackages();
191
+ List<string> ids = new List<string>();
192
+ if (packages != null)
193
+ {
194
+ foreach (ISetupPackageReference package in packages)
195
+ {
196
+ try
197
+ {
198
+ ids.Add(package.GetId());
199
+ }
200
+ finally
201
+ {
202
+ Marshal.ReleaseComObject(package);
203
+ }
204
+ }
205
+ }
206
+ info.Packages = ids.ToArray();
207
+ return info;
208
+ }
209
+ }
210
+ }
@@ -0,0 +1,93 @@
1
+ #Requires -Version 5.1
2
+ # Looks for Visual Studio the way UnrealBuildTool does (guest/toolchains/engines/unreal-engines.ts runs it; the
3
+ # verdict is decided in vs-check.ts): every instance the Setup Configuration API lists (csharp\VsSetup.cs), the MSVC
4
+ # toolchains under each one's VC\Tools\MSVC that have the x64 compiler, and the Windows SDKs under each KitsRoot10 the
5
+ # registry names (HKLM in both views, HKCU) that have windows.h and the x64 kernel32.lib. Writes JSON to -ResultFile.
6
+ param([Parameter(Mandatory = $true)][string]$ResultFile)
7
+ $ErrorActionPreference = 'Stop'
8
+
9
+ Add-Type -Path (Join-Path $PSScriptRoot '..\csharp\VsSetup.cs')
10
+
11
+ $instances = New-Object System.Collections.ArrayList
12
+ $setupError = ''
13
+ try {
14
+ foreach ($i in [AgentSandbox.VsSetup]::AllInstances()) {
15
+ $toolchains = New-Object System.Collections.ArrayList
16
+ $msvc = Join-Path $i.InstallationPath 'VC\Tools\MSVC'
17
+ if (Test-Path -LiteralPath $msvc -PathType Container) {
18
+ foreach ($dir in Get-ChildItem -LiteralPath $msvc -Directory) {
19
+ $cl = Join-Path $dir.FullName 'bin\Hostx64\x64\cl.exe'
20
+ $link = Join-Path $dir.FullName 'bin\Hostx64\x64\link.exe'
21
+ [void]$toolchains.Add([ordered]@{
22
+ version = $dir.Name
23
+ cl = (Test-Path -LiteralPath $cl -PathType Leaf)
24
+ link = (Test-Path -LiteralPath $link -PathType Leaf)
25
+ })
26
+ }
27
+ }
28
+ $wanted = @('Microsoft.VisualStudio.Component.VC.Tools.x86.x64', 'Microsoft.VisualStudio.Workload.NativeGame',
29
+ 'Microsoft.VisualStudio.Workload.VCTools', 'Component.Unreal', 'Component.Unreal.Ide')
30
+ [void]$instances.Add([ordered]@{
31
+ instanceId = $i.InstanceId
32
+ installationPath = $i.InstallationPath
33
+ installationVersion = $i.InstallationVersion
34
+ productId = $i.ProductId
35
+ state = [int64]$i.State
36
+ isComplete = $i.IsComplete
37
+ isLaunchable = $i.IsLaunchable
38
+ packages = @($i.Packages | Where-Object { $wanted -contains $_ })
39
+ packageCount = @($i.Packages).Count
40
+ toolchains = @($toolchains)
41
+ })
42
+ }
43
+ } catch {
44
+ $setupError = $_.Exception.Message
45
+ }
46
+
47
+ $roots = New-Object System.Collections.ArrayList
48
+ $places = @(
49
+ @{ hive = [Microsoft.Win32.RegistryHive]::LocalMachine; view = [Microsoft.Win32.RegistryView]::Registry64; name = 'HKLM (64-bit)' },
50
+ @{ hive = [Microsoft.Win32.RegistryHive]::LocalMachine; view = [Microsoft.Win32.RegistryView]::Registry32; name = 'HKLM (32-bit)' },
51
+ @{ hive = [Microsoft.Win32.RegistryHive]::CurrentUser; view = [Microsoft.Win32.RegistryView]::Registry64; name = 'HKCU' }
52
+ )
53
+ foreach ($place in $places) {
54
+ $base = [Microsoft.Win32.RegistryKey]::OpenBaseKey($place.hive, $place.view)
55
+ try {
56
+ $key = $base.OpenSubKey('SOFTWARE\Microsoft\Windows Kits\Installed Roots')
57
+ if ($key) {
58
+ $value = [string]$key.GetValue('KitsRoot10')
59
+ $key.Close()
60
+ if ($value) { [void]$roots.Add([ordered]@{ where = $place.name; path = $value }) }
61
+ }
62
+ } finally {
63
+ $base.Close()
64
+ }
65
+ }
66
+
67
+ $sdks = New-Object System.Collections.ArrayList
68
+ $seen = @{}
69
+ foreach ($root in $roots) {
70
+ $include = Join-Path $root.path 'Include'
71
+ if ($seen.ContainsKey($include.ToLowerInvariant())) { continue }
72
+ $seen[$include.ToLowerInvariant()] = $true
73
+ if (-not (Test-Path -LiteralPath $include -PathType Container)) { continue }
74
+ foreach ($dir in Get-ChildItem -LiteralPath $include -Directory) {
75
+ if ($dir.Name -notmatch '^10\.\d+\.\d+\.\d+$') { continue }
76
+ [void]$sdks.Add([ordered]@{
77
+ version = $dir.Name
78
+ root = $root.path
79
+ windowsH = (Test-Path -LiteralPath (Join-Path $dir.FullName 'um\windows.h') -PathType Leaf)
80
+ kernel32 = (Test-Path -LiteralPath (Join-Path $root.path ('Lib\' + $dir.Name + '\um\x64\kernel32.lib')) -PathType Leaf)
81
+ ucrt = (Test-Path -LiteralPath (Join-Path $root.path ('Lib\' + $dir.Name + '\ucrt\x64\ucrt.lib')) -PathType Leaf)
82
+ })
83
+ }
84
+ }
85
+
86
+ $result = [ordered]@{
87
+ setupError = $setupError
88
+ instances = @($instances)
89
+ kitsRoots = @($roots)
90
+ sdks = @($sdks)
91
+ }
92
+ $json = ConvertTo-Json -InputObject $result -Depth 6
93
+ [System.IO.File]::WriteAllText($ResultFile, $json, (New-Object System.Text.UTF8Encoding($false)))
@@ -0,0 +1,78 @@
1
+ #Requires -Version 5.1
2
+ # Puts a saved Visual Studio back at boot, in seconds (guest/toolchains/native/visual-studio.ts; what goes where is
3
+ # decided in vs-persist.ts): the small folders programs look for at fixed paths are copied back, then the registry
4
+ # values that point at the big folders on the data disk and the Setup Configuration COM class are written. -PlanFile is
5
+ # JSON written by the runtime:
6
+ # copies: [{ name, from, to, mode: 'all' | 'missing' }] 'all': robocopy /E (only what differs is copied);
7
+ # 'missing': each subfolder only when the target has none
8
+ # registry: [{ view: '64'|'32', key, name, kind: 'string'|'expand'|'dword', value }] under HKLM ('' = default)
9
+ # Safe to run again. Exit 0 when everything is in place, 1 when a copy failed, 2 when a registry value could not be set.
10
+ param([Parameter(Mandatory = $true)][string]$PlanFile)
11
+ $ErrorActionPreference = 'Stop'
12
+
13
+ $plan = Get-Content -LiteralPath $PlanFile -Raw -Encoding UTF8 | ConvertFrom-Json
14
+ $robocopy = Join-Path $env:SystemRoot 'System32\Robocopy.exe'
15
+
16
+ function Copy-Folder([string]$From, [string]$To) {
17
+ New-Item -ItemType Directory -Force -Path $To | Out-Null
18
+ & $robocopy $From $To /E /COPY:DAT /XJ /R:1 /W:1 /MT:16 /NP /NFL /NDL /NJH /NJS | Where-Object { $_ -and $_.Trim() } | Out-Host
19
+ return $LASTEXITCODE
20
+ }
21
+
22
+ $copied = 0
23
+ $failed = New-Object System.Collections.ArrayList
24
+ foreach ($copy in @($plan.copies)) {
25
+ if (-not (Test-Path -LiteralPath $copy.from -PathType Container)) {
26
+ [void]$failed.Add($copy.name + ' (' + $copy.from + ' is missing)')
27
+ continue
28
+ }
29
+ if ($copy.mode -eq 'missing') {
30
+ foreach ($child in Get-ChildItem -LiteralPath $copy.from -Directory) {
31
+ $target = Join-Path $copy.to $child.Name
32
+ if (Test-Path -LiteralPath $target) { continue }
33
+ $code = Copy-Folder -From $child.FullName -To $target
34
+ if ($code -ge 8) { [void]$failed.Add($copy.name + '\' + $child.Name + ' (robocopy ' + $code + ')') }
35
+ }
36
+ $copied++
37
+ continue
38
+ }
39
+ $code = Copy-Folder -From $copy.from -To $copy.to
40
+ if ($code -ge 8) { [void]$failed.Add($copy.name + ' (robocopy ' + $code + ')') } else { $copied++ }
41
+ }
42
+ if ($failed.Count) {
43
+ Write-Error ('restore-visual-studio: could not copy ' + ($failed -join ', '))
44
+ exit 1
45
+ }
46
+
47
+ $set = 0
48
+ $bad = New-Object System.Collections.ArrayList
49
+ foreach ($entry in @($plan.registry)) {
50
+ $view = [Microsoft.Win32.RegistryView]::Registry64
51
+ if ($entry.view -eq '32') { $view = [Microsoft.Win32.RegistryView]::Registry32 }
52
+ $base = [Microsoft.Win32.RegistryKey]::OpenBaseKey([Microsoft.Win32.RegistryHive]::LocalMachine, $view)
53
+ try {
54
+ $key = $base.CreateSubKey([string]$entry.key)
55
+ try {
56
+ if ($entry.kind -eq 'dword') {
57
+ $key.SetValue([string]$entry.name, [int]$entry.value, [Microsoft.Win32.RegistryValueKind]::DWord)
58
+ } elseif ($entry.kind -eq 'expand') {
59
+ $key.SetValue([string]$entry.name, [string]$entry.value, [Microsoft.Win32.RegistryValueKind]::ExpandString)
60
+ } else {
61
+ $key.SetValue([string]$entry.name, [string]$entry.value, [Microsoft.Win32.RegistryValueKind]::String)
62
+ }
63
+ $set++
64
+ } finally {
65
+ $key.Close()
66
+ }
67
+ } catch {
68
+ [void]$bad.Add($entry.view + ':' + $entry.key + '\' + $entry.name + ' (' + $_.Exception.Message + ')')
69
+ } finally {
70
+ $base.Close()
71
+ }
72
+ }
73
+ if ($bad.Count) {
74
+ Write-Error ('restore-visual-studio: could not set ' + ($bad -join '; '))
75
+ exit 2
76
+ }
77
+ Write-Output ('Restored Visual Studio: ' + $copied + ' folders in place, ' + $set + ' registry values set')
78
+ exit 0
@@ -0,0 +1,106 @@
1
+ #Requires -Version 5.1
2
+ # Saves a finished Visual Studio install onto the data disk, once (guest/toolchains/native/visual-studio.ts; what goes
3
+ # where is decided in vs-persist.ts). -PlanFile is JSON written by the runtime:
4
+ # copies: [{ name, from, to, optional }] each mirrored with robocopy (/MIR); a missing optional one is skipped
5
+ # registry: [{ view: '64'|'32', key, names: [..] | null, recurse }] string and DWORD values read under HKLM
6
+ # resultFile: where the result goes, as JSON: { copied: [names], registry: [{ view, key, name, kind, value }] }
7
+ # -LowPriority runs it (and robocopy) below normal priority. Safe to run again: robocopy copies only what differs.
8
+ # Exit 0 when every copy worked, 1 when one failed (no result file then), 2 for a bad plan.
9
+ param(
10
+ [Parameter(Mandatory = $true)][string]$PlanFile,
11
+ [switch]$LowPriority
12
+ )
13
+ $ErrorActionPreference = 'Stop'
14
+
15
+ if ($LowPriority) {
16
+ try {
17
+ [System.Diagnostics.Process]::GetCurrentProcess().PriorityClass = [System.Diagnostics.ProcessPriorityClass]::BelowNormal
18
+ } catch {
19
+ # Normal priority only makes the copy compete a little more with the sessions.
20
+ }
21
+ }
22
+
23
+ $plan = Get-Content -LiteralPath $PlanFile -Raw -Encoding UTF8 | ConvertFrom-Json
24
+ if (-not $plan.resultFile -or -not $plan.copies) {
25
+ Write-Error 'save-visual-studio: the plan has no copies or no result file'
26
+ exit 2
27
+ }
28
+ $robocopy = Join-Path $env:SystemRoot 'System32\Robocopy.exe'
29
+
30
+ function Copy-Folder([string]$From, [string]$To) {
31
+ New-Item -ItemType Directory -Force -Path $To | Out-Null
32
+ # /MIR drops files a previous capture left; /XJ skips links (the data disk refuses them); /A-:R keeps read-only
33
+ # files rewritable by the next capture.
34
+ & $robocopy $From $To /MIR /COPY:DAT /XJ /A-:R /R:1 /W:1 /MT:16 /NP /NFL /NDL /NJH /NJS | Where-Object { $_ -and $_.Trim() } | Out-Host
35
+ return $LASTEXITCODE
36
+ }
37
+
38
+ $copied = New-Object System.Collections.ArrayList
39
+ $failed = New-Object System.Collections.ArrayList
40
+ foreach ($copy in @($plan.copies)) {
41
+ if (-not (Test-Path -LiteralPath $copy.from -PathType Container)) {
42
+ if ($copy.optional) { continue }
43
+ [void]$failed.Add($copy.name + ' (' + $copy.from + ' is missing)')
44
+ continue
45
+ }
46
+ $code = Copy-Folder -From $copy.from -To $copy.to
47
+ if ($code -ge 8) { [void]$failed.Add($copy.name + ' (robocopy ' + $code + ')') } else { [void]$copied.Add([string]$copy.name) }
48
+ }
49
+ if ($failed.Count) {
50
+ Write-Error ('save-visual-studio: could not save ' + ($failed -join ', '))
51
+ exit 1
52
+ }
53
+
54
+ function Get-View([string]$View) {
55
+ if ($View -eq '32') { return [Microsoft.Win32.RegistryView]::Registry32 }
56
+ return [Microsoft.Win32.RegistryView]::Registry64
57
+ }
58
+
59
+ function Read-Values([Microsoft.Win32.RegistryKey]$Key, [string]$Path, [string]$View, $Names, [bool]$Recurse, $Out) {
60
+ $options = [Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames
61
+ foreach ($name in $Key.GetValueNames()) {
62
+ if ($null -ne $Names -and -not ($Names -contains $name)) { continue }
63
+ $kind = $Key.GetValueKind($name)
64
+ $value = $Key.GetValue($name, $null, $options)
65
+ $label = $null
66
+ if ($kind -eq [Microsoft.Win32.RegistryValueKind]::String) { $label = 'string' }
67
+ elseif ($kind -eq [Microsoft.Win32.RegistryValueKind]::ExpandString) { $label = 'expand' }
68
+ elseif ($kind -eq [Microsoft.Win32.RegistryValueKind]::DWord) { $label = 'dword'; $value = [int]$value }
69
+ if ($null -eq $label -or $null -eq $value) { continue }
70
+ [void]$Out.Add([ordered]@{ view = $View; key = $Path; name = $name; kind = $label; value = $value })
71
+ }
72
+ if (-not $Recurse) { return }
73
+ foreach ($sub in $Key.GetSubKeyNames()) {
74
+ $child = $Key.OpenSubKey($sub)
75
+ if ($null -eq $child) { continue }
76
+ try {
77
+ Read-Values -Key $child -Path ($Path + '\' + $sub) -View $View -Names $Names -Recurse $true -Out $Out
78
+ } finally {
79
+ $child.Close()
80
+ }
81
+ }
82
+ }
83
+
84
+ $values = New-Object System.Collections.ArrayList
85
+ foreach ($read in @($plan.registry)) {
86
+ $base = [Microsoft.Win32.RegistryKey]::OpenBaseKey([Microsoft.Win32.RegistryHive]::LocalMachine, (Get-View $read.view))
87
+ try {
88
+ $key = $base.OpenSubKey([string]$read.key)
89
+ if ($null -eq $key) { continue }
90
+ try {
91
+ $names = $null
92
+ if ($null -ne $read.names) { $names = @($read.names) }
93
+ Read-Values -Key $key -Path ([string]$read.key) -View ([string]$read.view) -Names $names -Recurse ([bool]$read.recurse) -Out $values
94
+ } finally {
95
+ $key.Close()
96
+ }
97
+ } finally {
98
+ $base.Close()
99
+ }
100
+ }
101
+
102
+ $result = [ordered]@{ copied = @($copied.ToArray()); registry = @($values.ToArray()) }
103
+ $json = ConvertTo-Json -InputObject $result -Depth 6
104
+ [System.IO.File]::WriteAllText($plan.resultFile, $json, (New-Object System.Text.UTF8Encoding $false))
105
+ Write-Output ('Saved Visual Studio: ' + $copied.Count + ' folders, ' + $values.Count + ' registry values')
106
+ exit 0
@@ -0,0 +1,35 @@
1
+ #Requires -Version 5.1
2
+ # Writes string registry values from a plan (guest/toolchains/engines/unreal-engines.ts: the Unreal engines'
3
+ # registration and the .uproject file association; what goes where is decided in shared/unreal/engines.ts). -PlanFile
4
+ # is JSON written by the runtime:
5
+ # values: [{ hive: 'HKLM' | 'HKCU', key, name, value }] 64-bit view, '' = the default value
6
+ # Safe to run again. Exit 0 when every value is set, 2 when one could not be.
7
+ param([Parameter(Mandatory = $true)][string]$PlanFile)
8
+ $ErrorActionPreference = 'Stop'
9
+
10
+ $plan = Get-Content -LiteralPath $PlanFile -Raw -Encoding UTF8 | ConvertFrom-Json
11
+ $failed = New-Object System.Collections.ArrayList
12
+ $set = 0
13
+ foreach ($v in @($plan.values)) {
14
+ $hive = if ($v.hive -eq 'HKLM') { [Microsoft.Win32.RegistryHive]::LocalMachine } else { [Microsoft.Win32.RegistryHive]::CurrentUser }
15
+ $base = [Microsoft.Win32.RegistryKey]::OpenBaseKey($hive, [Microsoft.Win32.RegistryView]::Registry64)
16
+ try {
17
+ $key = $base.CreateSubKey([string]$v.key)
18
+ try {
19
+ $key.SetValue([string]$v.name, [string]$v.value, [Microsoft.Win32.RegistryValueKind]::String)
20
+ $set++
21
+ } finally {
22
+ $key.Close()
23
+ }
24
+ } catch {
25
+ [void]$failed.Add($v.hive + '\' + $v.key + ' ' + $v.name + ' (' + $_.Exception.Message + ')')
26
+ } finally {
27
+ $base.Close()
28
+ }
29
+ }
30
+ if ($failed.Count) {
31
+ Write-Host ('Could not set: ' + ($failed -join '; '))
32
+ exit 2
33
+ }
34
+ Write-Host ('Set ' + $set + ' registry values')
35
+ exit 0
@@ -554,6 +554,10 @@
554
554
  },
555
555
  "unrealEngines": {
556
556
  "anyOf": [
557
+ {
558
+ "type": "string",
559
+ "const": "auto"
560
+ },
557
561
  {
558
562
  "type": "boolean"
559
563
  },
@@ -565,7 +569,29 @@
565
569
  }
566
570
  }
567
571
  ],
568
- "description": "Unreal Engine versions installed with the Epic Games Launcher of this PC, read-only in the sandbox under C:\\PcInstalls: true = all of them, false = none, or a list (e.g. [\"5.4\"]). The agent can read their files."
572
+ "description": "Unreal Engine versions installed on this PC (with the Epic Games Launcher, or source builds it lists), read-only in the sandbox under C:\\PcInstalls\\unreal and registered there, so projects build with them without a download. \"auto\" = all of them whenever the sandbox is set up for Unreal, true = always, false = never, or a list (e.g. [\"5.4\"])."
573
+ },
574
+ "unrealEngineFolders": {
575
+ "maxItems": 8,
576
+ "type": "array",
577
+ "items": {
578
+ "type": "string",
579
+ "minLength": 3,
580
+ "maxLength": 260
581
+ },
582
+ "description": "Unreal Engine folders of this PC to use in the sandbox, writable (a source build, or a copy you build plugins into): each must hold Engine\\Build\\Build.version. Mapped under C:\\PcInstalls\\unreal and registered there."
583
+ },
584
+ "unrealAssets": {
585
+ "anyOf": [
586
+ {
587
+ "type": "string",
588
+ "const": "auto"
589
+ },
590
+ {
591
+ "type": "boolean"
592
+ }
593
+ ],
594
+ "description": "The Epic Games Launcher's vault cache of this PC (the Fab and Marketplace packs you downloaded), read-only in the sandbox at C:\\PcInstalls\\unreal\\Vault: what you download on your PC is there for the agents at once. \"auto\" = whenever the sandbox is set up for Unreal, true = always, false = never."
569
595
  },
570
596
  "unityEditors": {
571
597
  "anyOf": [
@@ -800,7 +826,7 @@
800
826
  "lld",
801
827
  "gnu"
802
828
  ],
803
- "description": "GNU host: \"lld\" links with Rust's own lld through MinGW's gcc (much less memory than GNU ld), \"gnu\" with GNU ld."
829
+ "description": "\"lld\" (default) links with Rust's own lld: through MinGW's gcc on the GNU host (much less memory than GNU ld), and instead of link.exe on the MSVC host (link.exe writes executables into mapped folders as all zeros: os error 1392). \"gnu\" keeps GNU ld / link.exe."
804
830
  },
805
831
  "linkSlots": {
806
832
  "anyOf": [
@@ -864,7 +890,7 @@
864
890
  "const": "auto"
865
891
  }
866
892
  ],
867
- "description": "Unreal Engine development: Visual Studio Community 2022 with the C++ game workload (MSVC, a Windows 11 SDK, .NET Framework targeting packs, Unreal integration and the Epic Games Launcher) and the DirectX End-User Runtime. A real installer: it runs every boot (~10 GB on the sandbox disk). The engine itself comes from the Epic Games Launcher or its source. true, false, or \"auto\" = only when the project has a .uproject or .uplugin."
893
+ "description": "Unreal Engine development: Visual Studio Community 2022 with the C++ game workload (MSVC, a Windows 11 SDK, .NET Framework targeting packs, Unreal integration and the Epic Games Launcher) and the DirectX End-User Runtime. Visual Studio is installed once and kept on the data disk (~6.5 GB); later boots put it back in seconds. The engine itself comes from the Epic Games Launcher or its source. true, false, or \"auto\" = only when the project has a .uproject or .uplugin."
868
894
  },
869
895
  "acceptLicense": {
870
896
  "type": "boolean",
@@ -877,17 +903,13 @@
877
903
  },
878
904
  "description": "More Visual Studio workload or component IDs to add, e.g. [\"Microsoft.VisualStudio.Component.VC.Llvm.Clang\"]."
879
905
  },
880
- "keepInstallFiles": {
881
- "type": "boolean",
882
- "description": "Keep an offline copy of the Visual Studio install files in tools\\visualstudio (~10 GB, made once), so later boots install without downloading them again. Skipped while that disk has too little room."
883
- },
884
906
  "visualStudio": {
885
907
  "type": "string",
886
908
  "enum": [
887
909
  "full",
888
- "autosdk"
910
+ "buildtools"
889
911
  ],
890
- "description": "\"full\": install Visual Studio Community (the engine finds it through the Setup API; ~10 GB, redone every boot). \"autosdk\" (experimental): skip Visual Studio and build an Unreal AutoSDK tree from the portable MSVC in tools\\unreal\\autosdk (kept between sandboxes); UnrealBuildTool finds MSVC through AutoSDK, but the editor's Visual Studio integration is not available. Needs toolchains.msvc (turned on for you)."
912
+ "description": "\"full\": Visual Studio Community with the C++ game workload (the IDE, its debugger and Unreal integration). \"buildtools\": only the Visual Studio Build Tools (MSVC, the Windows SDK and the .NET Framework parts UnrealBuildTool needs; no IDE). Either is installed once and kept on the data disk (tools\\visualstudio\\persist, ~6.5 GB for Community); later boots put it back in seconds."
891
913
  },
892
914
  "persistEngines": {
893
915
  "type": "boolean",
@@ -2030,6 +2052,13 @@
2030
2052
  "gitleaks",
2031
2053
  "ast-grep",
2032
2054
  "rust-analyzer",
2055
+ "krita",
2056
+ "inkscape",
2057
+ "audacity",
2058
+ "renderdoc",
2059
+ "f3d",
2060
+ "imagemagick",
2061
+ "nomacs",
2033
2062
  "lua-language-server",
2034
2063
  "stylua",
2035
2064
  "selene",