├── License.txt ├── README.md ├── WindowsSandboxTools.psd1 ├── WindowsSandboxTools.psm1 ├── archive ├── README.txt └── Start-WindowsSandbox.ps1 ├── changelog.md ├── docs ├── Export-WsbConfiguration.md ├── Get-WsbConfiguration.md ├── New-WsbConfiguration.md ├── New-WsbMappedFolder.md └── Start-WindowsSandbox.md ├── en-us └── WindowsSandboxTools-help.xml ├── formats └── wsbConfiguration.format.ps1xml ├── functions ├── Export-WsbConfiguration.ps1 ├── Get-WsbConfiguration.ps1 ├── New-WsbConfiguration.ps1 ├── New-WsbMappedFolder.ps1 ├── Start-WindowsSandbox.ps1 └── private.ps1 ├── images ├── db.png ├── gazoo.bmp ├── sandbox.jpg └── start-windowssandbox.png ├── wsbScripts ├── Install-VSCodeSandbox.ps1 ├── README.md ├── Set-SandboxDesktop.ps1 ├── basic.ps1 ├── demo-config.ps1 ├── demo.cmd ├── sandbox-basic.cmd ├── sandbox-config-pluralsight.ps1 ├── sandbox-config-presentation.ps1 ├── sandbox-config.ps1 ├── sandbox-setup-pluralsight.cmd ├── sandbox-setup-presentation.cmd ├── sandbox-setup.cmd └── sandbox-toast.ps1 └── wsbconfig ├── README.md ├── WinSandBx.wsb ├── basic.wsb ├── demo.wsb ├── pluralsight.wsb ├── presentation.wsb ├── sample.wsb └── work.wsb /License.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jdhitsolutions/WindowsSandboxTools/9f2a0b71140b293c5769b939aac4899d26a1503b/License.txt -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Windows Sandbox Tools 2 | 3 | ![sandbox](images/sandbox.jpg) 4 | 5 | [![PSGallery Version](https://img.shields.io/powershellgallery/v/WindowsSandboxTools.png?style=for-the-badge&label=PowerShell%20Gallery)](https://www.powershellgallery.com/packages/WindowsSandboxTools/) [![PSGallery Downloads](https://img.shields.io/powershellgallery/dt/WindowsSandboxTools.png?style=for-the-badge&label=Downloads)](https://www.powershellgallery.com/packages/WindowsSandboxTools/) 6 | 7 | This repository is a collection of PowerShell tools and scripts that I use to run and configure the Windows Sandbox feature that was introduced in Windows 10 2004. Many of the commands in this repository were first demonstrated on my [blog](https://jdhitsolutions.com/blog/powershell/7621/doing-more-with-windows-sandbox/). I strongly recommend you read the blog post before trying any of the code. As I mention in the blog post, most of the code here will __reduce the security__ of the Windows Sandbox application. This is a trade-off I am willing to make for the sake of functionality that meets *my* requirements. You have to decide how much of the code you would like to use. 8 | 9 | __*All code is offered as-is with no guarantees. Nothing in this repository should be considered production-ready or used in critical environments without your extensive testing and validation.*__ 10 | 11 | ## Installing the Windows Sandbox 12 | 13 | You need to have the 2004 version of Windows 10 or later. The Windows Sandbox will run a containerized version of your operating system. I don't know off-hand if it is supported on Windows 10 Home or Education editions. Otherwise, you should be able to run these PowerShell commands to get started: 14 | 15 | ```powershell 16 | Get-WindowsOptionalFeature -Online -FeatureName Containers-DisposableClientVM 17 | Enable-WindowsOptionalFeature -Online -FeatureName Containers-DisposableClientVM 18 | ``` 19 | 20 | ## The WindowsSandBoxTools Module 21 | 22 | I have created a PowerShell module called `WindowsSandBoxTools`. In this module are functions designed to make it easier to view a `wsb` configuration, create a new configuration, and export a configuration to a file. The module functions use several PowerShell class definitions. 23 | 24 | You can read the Microsoft documentation on creating a Windows Sandbox configuration at [https://docs.microsoft.com/windows/security/threat-protection/windows-sandbox/windows-sandbox-configure-using-wsb-file](https://docs.microsoft.com/windows/security/threat-protection/windows-sandbox/windows-sandbox-configure-using-wsb-file). The module commands are designed to abstract the process of creating the XML configuration files which have a `.wsb` extension. 25 | 26 | Install the module from the PowerShell Gallery. 27 | 28 | ```powershell 29 | Install-Module WindowsSandboxTools 30 | ``` 31 | 32 | The module should work in Windows PowerShell and PowerShell 7 on Windows platforms. 33 | 34 | ### [Start-WindowsSandbox](docs/Start-WindowsSandbox.md) 35 | 36 | The [`Start-WindowsSandbox`](docs/Start-WindowsSandbox.mx) function is my primary tool. It has an alias of `wsb`. You can specify the path to the wsb file. 37 | 38 | ![Start-WindowsSandbox](images/start-windowssandbox.png) 39 | 40 | If you use the `NoSetup` parameter, it will launch the default Windows Sandbox. In either usage, you can specify display dimensions for the sandbox. The `WindowSize` parameter expects an array of width and height, like 1024,768. My default is 1920,1080. You may have to drag the window slightly to force the sandbox to redraw the screen and remove the horizontal scrollbar. Setting the display is tricky, and I don't know if what I am using will work for everyone, so if you don't get the results you expect, please post an issue. 41 | 42 | The sandbox will start and then minimize while any configurations you may have are executed. 43 | 44 | ### [Get-WsbConfiguration](docs/Get-WsbConfiguration.md) 45 | 46 | If you have created custom configurations, or intend to use the samples from this module, `Get-WsbConfiguration` will display information about the configuration. 47 | 48 | ```text 49 | PS C:\> Get-WsbConfiguration d:\wsb\simple.wsb 50 | WARNING: No value detected for LogonCommand. This may be intentional on your part. 51 | 52 | 53 | Name: Simple 54 | 55 | vGPU : Enable 56 | MemoryInMB : 8192 57 | AudioInput : Default 58 | VideoInput : Default 59 | ClipboardRedirection : Default 60 | PrinterRedirection : Default 61 | Networking : Default 62 | ProtectedClient : Default 63 | LogonCommand : 64 | MappedFolders : C:\scripts -> C:\scripts [RO:False] 65 | ``` 66 | 67 | The command uses a custom format file to display the configuration. I have also found a way to insert metadata into the wsb file which (so far) doesn't appear to interfere with the Windows Sandbox application. 68 | 69 | ```text 70 | PS C:\> Get-WsbConfiguration d:\wsb\simple.wsb -MetadataOnly 71 | 72 | Author Name Description Updated 73 | ------ ---- ----------- ------- 74 | Jeff Hicks Simple a simple configuration with mapping to C:\Scripts 12/10/2021 8:50:03 AM 75 | ``` 76 | 77 | ### [New-WsbConfiguration](docs/New-WsbConfiguration.md) 78 | 79 | This is how you can create a new Windows Sandbox configuration. 80 | 81 | ```powershell 82 | $params = @{ 83 | Networking = "Default" 84 | LogonCommand = "c:\data\demo.cmd" 85 | MemoryInMB = 2048 86 | PrinterRedirection = "Disable" 87 | MappedFolder = (New-WsbMappedFolder -HostFolder d:\data -SandboxFolder c:\data -ReadOnly) 88 | Name = "MyDemo" 89 | Description = "A demo WSB configuration" 90 | } 91 | $new = New-WsbConfiguration @params 92 | ``` 93 | 94 | The `LogonCommand` value is relative to the WindowsSandbox. This code will create a `wsbConfiguration` object. 95 | 96 | ```text 97 | 98 | Name: MyDemo 99 | 100 | vGPU : Default 101 | MemoryInMB : 2048 102 | AudioInput : Default 103 | VideoInput : Default 104 | ClipboardRedirection : Default 105 | PrinterRedirection : Disable 106 | Networking : Default 107 | ProtectedClient : Default 108 | LogonCommand : c:\data\demo.cmd 109 | MappedFolders : d:\data -> c:\data [RO:True] 110 | ``` 111 | 112 | You could modify this object as necessary. 113 | 114 | ```powershell 115 | $new.vGPU = "Enable" 116 | $new.Metadata.Updated = Get-Date 117 | ``` 118 | 119 | The last step is to export the configuration to a `wsb` file. 120 | 121 | ```powershell 122 | $new | Export-WsbConfiguration -Path d:\wsb\demo.wsb 123 | ``` 124 | 125 | Which will create this file: 126 | 127 | ```xml 128 | 129 | 130 | MyDemo 131 | Jeff 132 | A demo WSB configuration 133 | 07/10/2022 15:40:54 134 | 135 | Enable 136 | 2048 137 | Default 138 | Default 139 | Default 140 | Disable 141 | Default 142 | Default 143 | 144 | c:\data\demo.cmd 145 | 146 | 147 | 148 | d:\data 149 | c:\data 150 | True 151 | 152 | 153 | 154 | ``` 155 | 156 | I can easily launch this configuration. 157 | 158 | ```powershell 159 | Start-WindowsSandbox -Configuration D:\wsb\demo.wsb 160 | ``` 161 | 162 | ### [New-WsbMappedFolder](docs/New-WsbMappedFolder.md) 163 | 164 | Use this command to create a mapped folder object. 165 | 166 | ```powershell 167 | $map = New-WsbMappedFolder -HostFolder c:\work -SandboxFolder c:\work 168 | ``` 169 | 170 | Once created, you can use this in a new configuration. 171 | 172 | ```powershell 173 | New-WsbConfiguration -Name work -MappedFolder $map -Description "Work sandbox" 174 | ``` 175 | 176 | ### [Export-WSBConfiguration](docs/Export-WsbConfiguration.md) 177 | 178 | After you have created a new configuration, you will want to save it to a file. 179 | 180 | ```powershell 181 | New-WsbConfiguration -Name work -LogonCommand "$wsbScripts\basic.cmd" -MemoryInMB (4096*2) -MappedFolder (New-WsbMappedFolder -HostFolder d:\work -SandboxFolder c:\work) -Description "My work WSB configuration" | Export-WsbConfiguration -Path "$wsbConfigPath\work.wsb" 182 | ``` 183 | 184 | The exported file must have a `.wsb` file extension. Save the file to your `$wsbConfigPath` location. 185 | 186 | You should get a file like this: 187 | 188 | ```xml 189 | 190 | 191 | work 192 | Jeff 193 | My work WSB configuration 194 | 07/18/2022 15:43:24 195 | 196 | Default 197 | 8192 198 | Default 199 | Default 200 | Default 201 | Default 202 | Default 203 | Default 204 | 205 | C:\scripts\windowssandboxtools\wsbScripts\basic.cmd 206 | 207 | 208 | 209 | c:\work 210 | c:\work 211 | False 212 | 213 | 214 | 215 | ``` 216 | 217 | ## My Configuration Scripts 218 | 219 | My default [configuration script](wsbScripts/demo-config.ps1) takes about 4 minutes to complete. I use the [BurntToast](https://github.com/Windos/BurntToast) module to show a Windows Action Center notification when it is complete. 220 | 221 | When you import the module, it will define two global variables. `$wsbConfigPath` points to the location of your wsb files. `$wsbScripts` points to the location of your supporting scripts. By default, these variables will point to directories in the module root. You will most like want to update these variables to point to your location. I set this in my PowerShell profile script. 222 | 223 | __You need to verify and update path references if you use any of the configurations or scripts in this module.__ 224 | 225 | ## RoadMap 226 | 227 | This is a list of items I'd like to address or handle more efficiently: 228 | 229 | + Look for a way to organize script components used for `LogonCommand` settings. 230 | + Use a default shared folder that can be a bit more generic. 231 | + Add a better way to provide or integrate toast notifications. 232 | + Create a graphical interface for creating configurations. 233 | 234 | Feel free to post enhancment suggestions in Issues. 235 | -------------------------------------------------------------------------------- /WindowsSandboxTools.psd1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jdhitsolutions/WindowsSandboxTools/9f2a0b71140b293c5769b939aac4899d26a1503b/WindowsSandboxTools.psd1 -------------------------------------------------------------------------------- /WindowsSandboxTools.psm1: -------------------------------------------------------------------------------- 1 | #turn on verbose output 2 | if ($MyInvocation.line -match "Verbose") { 3 | $VerbosePreference = "Continue" 4 | } 5 | 6 | #region class definitions 7 | 8 | Write-Verbose "Defining classes" 9 | #these need to be in the module file 10 | Class wsbMetadata { 11 | [string]$Author = $env:USERNAME 12 | [string]$Name 13 | [string]$Description 14 | [datetime]$Updated 15 | 16 | wsbMetadata([string]$Name) { 17 | $this.Name = $Name 18 | } 19 | wsbMetadata([string]$Name, [string]$Description) { 20 | $this.Name = $Name 21 | $this.Description = $Description 22 | } 23 | } 24 | 25 | Class wsbMappedFolder { 26 | [string]$HostFolder 27 | [string]$SandboxFolder 28 | [bool]$ReadOnly = $True 29 | 30 | wsbMappedFolder([string]$HostFolder, [string]$SandboxFolder, [bool]$ReadOnly) { 31 | $this.HostFolder = $HostFolder 32 | $this.SandboxFolder = $SandboxFolder 33 | $this.ReadOnly = $ReadOnly 34 | } 35 | } 36 | 37 | Class wsbConfiguration { 38 | [ValidateSet("Default", "Enable", "Disable")] 39 | [string]$vGPU = "Default" 40 | [string]$MemoryInMB = 4096 41 | [ValidateSet("Default", "Enable", "Disable")] 42 | [string]$AudioInput = "Default" 43 | [ValidateSet("Default", "Enable", "Disable")] 44 | [string]$VideoInput = "Default" 45 | [ValidateSet("Default", "Disable")] 46 | [string]$ClipboardRedirection = "Default" 47 | [ValidateSet("Default", "Enable", "Disable")] 48 | [string]$PrinterRedirection = "Default" 49 | [ValidateSet("Default", "Disable")] 50 | [string]$Networking = "Default" 51 | [ValidateSet("Default", "Enable", "Disable")] 52 | [string]$ProtectedClient = "Default" 53 | [string]$LogonCommand 54 | [wsbMappedFolder[]]$MappedFolder 55 | [wsbMetadata]$Metadata 56 | } 57 | #endregion 58 | 59 | #dot source the module functions 60 | Get-ChildItem -Path $psscriptroot\functions\*.ps1 | 61 | ForEach-Object { 62 | Write-Verbose "Dot source $($_.fullname)" 63 | . $_.fullname 64 | } 65 | 66 | #only define variables if they don't already exist. 67 | Write-Verbose "Configuring global variables" 68 | #define a global variable for the configuration directory 69 | Try { 70 | [void](Get-Variable -Name wsbConfigPath -Scope global -ErrorAction Stop) 71 | } 72 | Catch { 73 | $global:wsbConfigPath = "$psscriptroot\wsbconfig" 74 | } 75 | 76 | #define a global variable for configuration scripts 77 | Try { 78 | [void](Get-Variable -Name wsbScripts -Scope global -ErrorAction Stop) 79 | } 80 | Catch { 81 | $global:wsbScripts = "$psscriptroot\wsbScripts" 82 | } 83 | 84 | $msg = @" 85 | Using these global variables 86 | 87 | Windows Sandbox Tools 88 | --------------------- 89 | 90 | `$wsbConfigPath = $wsbConfigPath 91 | `$wsbScripts = $wsbScripts 92 | 93 | You may want to change these values. 94 | 95 | "@ 96 | 97 | Write-Verbose $msg 98 | 99 | #Turn off module scoped Verbose output 100 | if ($VerbosePreference = "Continue") { 101 | $VerbosePreference = "SilentyContinue" 102 | } -------------------------------------------------------------------------------- /archive/README.txt: -------------------------------------------------------------------------------- 1 | These are original script files that formed the foundation of this module. -------------------------------------------------------------------------------- /archive/Start-WindowsSandbox.ps1: -------------------------------------------------------------------------------- 1 | Function Start-WindowsSandbox { 2 | [cmdletbinding(SupportsShouldProcess, DefaultParameterSetName = "config")] 3 | [alias("wsb")] 4 | [OutputType("none")] 5 | 6 | Param( 7 | [Parameter(Position = 0, ParameterSetName = "config", HelpMessage = "Specify the path to a wsb file.")] 8 | [ValidateScript( { Test-Path $_ })] 9 | #this is my default configuration 10 | [string]$Configuration = "c:\scripts\WindowsSandboxTools\WinSandBx.wsb", 11 | [Parameter(ParameterSetName = "normal", HelpMessage = "Start with no customizations.")] 12 | [switch]$NoSetup, 13 | [Parameter(HelpMessage = "Specify desktop resolutions as an array like 1280,720. The default is 1920,1080.")] 14 | [int[]]$WindowSize = @(1920, 1080) 15 | ) 16 | 17 | Write-Verbose "Starting $($myinvocation.mycommand)" 18 | 19 | #dot source functions to change the window state and size 20 | . C:\scripts\WindowsSandboxTools\Set-WindowState.ps1 21 | . C:\scripts\WindowsSandboxTools\Set-MainWindowSize.ps1 22 | 23 | if ($NoSetup) { 24 | Write-Verbose "Launching default WindowsSandbox.exe" 25 | if ($PSCmdlet.shouldProcess("default configuration", "Launch Windows Sandbox")) { 26 | c:\windows\system32\WindowsSandbox.exe 27 | } 28 | } 29 | else { 30 | Write-Verbose "Launching WindowsSandbox using configuration file $Configuration" 31 | 32 | #create a file watcher if calling a configuration that uses it 33 | if ($Configuration -match "WinSandBx|presentation") { 34 | Write-Verbose "Registering a temporary file system watcher" 35 | #you can specify parameters for RegisterWatcher or modify the 36 | #file to use your own defaults. 37 | &$PSScriptroot\RegisterWatcher.ps1 | Out-Null 38 | } 39 | 40 | if ($PSCmdlet.shouldProcess($Configuration, "Launch Windows Sandbox")) { 41 | Start-Process -filepath $Configuration 42 | } 43 | } 44 | 45 | #WindowsSandbox.exe launches a child process, WindowsSandboxClient. 46 | #That is the process that needs to be minimized 47 | if ($pscmdlet.shouldProcess("WindowsSandboxClient", "Waiting for process")) { 48 | 49 | Write-Verbose "Waiting for child process WindowsSandboxClient" 50 | do { 51 | Start-Sleep -Seconds 1 52 | } Until (Get-Process -Name WindowsSandboxClient -ErrorAction SilentlyContinue) 53 | 54 | #give the process a chance to complete 55 | Start-Sleep -Seconds 5 56 | } 57 | 58 | Write-Verbose "Setting Window size to $($WindowSize -join 'x')" 59 | if ($pscmdlet.shouldProcess("WindowsSandboxClient", "Modifying Window size and state")) { 60 | $clientProc = Get-Process -Name WindowsSandboxClient 61 | #values to pass to the function are a percentage of the desired size 62 | [int]$width = $WindowSize[0]*.6667 63 | [int]$Height = $WindowSize[1]*.6667 64 | 65 | Set-WindowSize -handle $clientproc.MainWindowHandle -width $width -height $height 66 | 67 | #Configure the Windows Sandbox to run minimized (Issue #2) 68 | Write-Verbose "Minimizing child process WindowsSandboxClient" 69 | $clientProc | Set-WindowState -State minimize 70 | } 71 | Write-Verbose "Ending $($myinvocation.mycommand). Any script configurations will continue in the Windows Sandbox." 72 | Write-Host "Windows Sandbox has been launched. You may need to wait for any configurations to complete." -foregroundColor green 73 | } 74 | 75 | -------------------------------------------------------------------------------- /changelog.md: -------------------------------------------------------------------------------- 1 | # Change Log for Windows SandBox Tools 2 | 3 | ## v1.1.0 4 | 5 | ### Changed 6 | 7 | - Updated license. 8 | - General code cleanup. 9 | - Updated help documentation. 10 | - Modified `Get-WSBConfiguration` to accept paths from the pipeline. 11 | 12 | ### Added 13 | 14 | - Added missing online help links 15 | 16 | ## v1.0.0 17 | 18 | + Updated `Start-WindowsSandbox` to not scale resolutions. 19 | + Fixed bug in `Start-WindowsSandbox` that was testing for a configuration when using the basic configuration. [Issue 4](https://github.com/jdhitsolutions/WindowsSandboxTools/issues/4) 20 | + Reorganized module layout. 21 | + Added my configurations and scripts. 22 | + Moved class definitions to the root module file. 23 | + Updated help documentation. 24 | + Updated `New-WsbMappedFolder` to use a switch for `-Readonly`. 25 | + Fixed bug where Verbose remained on if importing the module with `-Verbose`. 26 | + Updated `README.md`. 27 | + Published to the PowerShell Gallery 28 | 29 | ## December 14, 2020 30 | 31 | + Code cleanup for the sake of clarity. 32 | + Migrated commands to a module, `WindowsSandboxTools`. 33 | + Made `Configuration` parameter mandatory in `Start-WindowsSandbox`. 34 | + Fixed default logo path in `RegisterWatcher`. 35 | + Added timestamp to verbose messages in `Start-WindowsSandbox`. 36 | + Modified `Register-Watcher` to remove any left-over event subscriber. 37 | + Created a global variable `wsbConfigPath` which can be used to reference a centralized location for WSB files. 38 | + Created a global variable `wsbScripts` which can be used to reference a centralized location for scripts. 39 | + Added argument completer for the `Configuration` parameter in `Start-WindowsSandbox` and `Get-WsbConfiguration`. 40 | + Updated `Start-WindowsSandbox` to test if an instance is already running and display a warning if it is. 41 | + Updated setup scripts and sample configuration files. 42 | 43 | ## September 10, 2020 44 | 45 | + Changed default screen size in `Start-WindowsSandbox` to 1920x1080. 46 | + Created commands, `Get-WsbConfiguration`, `New-WsbConfiguration`, `New-WsbMappedFolder`, and `Export-WsbConfiguration` for creating and managing `wsb` files. The enhanced files can include metadata information. These functions are defined in a module file, `wsbFunctions.psm1`. 47 | + Created `wsbConfiguration.format.ps1xml` to display the `wsbConfiguration` object as a formatted list by default. 48 | + Fixed `Start-Process` parameter bug in `Start-WindowsSandbox`. 49 | + Modified `RegisterWatcher.ps1` to let the user define the flag file. The default is `C:\scripts\sandbox.flag`. 50 | + Modified `RegisterWatcher.ps1` to let the user define settings for the toast notifications. Defaults are mine. 51 | + Updated `Start-WindowsSandbox` to better handle `-Whatif` support. 52 | + Updated `README.md` 53 | 54 | ## August 31, 2020 55 | 56 | + Added code to minimize Windows Sandbox window when running a configuration. (Issue #2) 57 | + Minor tweaks to the WSB configuration files. 58 | + Added `-WhatIf` support to `Start-WindowsSandbox` and `RegisterWatcher.ps1`. 59 | + Added `Set-WindowState` function. 60 | + Modified `Sandbox-toast.ps1` to make the toast announcement silent. 61 | + Added Sound to local toast notification. 62 | + Added code to adjust the window size. This the closest I can get to setting a desktop resolution. (Issue #1) 63 | + Added presentation configurations and setup scripts. 64 | 65 | ## August 27, 2020 66 | 67 | + initial commit 68 | + Added `README.md` 69 | + Updated scripts to reflect the new path. 70 | + Added a file system watcher to send a toast notification when my configuration is complete. 71 | -------------------------------------------------------------------------------- /docs/Export-WsbConfiguration.md: -------------------------------------------------------------------------------- 1 | --- 2 | external help file: WindowsSandboxTools-help.xml 3 | Module Name: WindowsSandboxTools 4 | online version: https://bit.ly/3PkXMvl 5 | schema: 2.0.0 6 | --- 7 | 8 | # Export-WsbConfiguration 9 | 10 | ## SYNOPSIS 11 | 12 | Export a WSB configuration to an XML file. 13 | 14 | ## SYNTAX 15 | 16 | ```yaml 17 | Export-WsbConfiguration [-Configuration] -Path [-NoClobber] [-WhatIf] [-Confirm][] 18 | ``` 19 | 20 | ## DESCRIPTION 21 | 22 | This command will take an existing Windows Sandbox Configuration object and export it to an XML file. 23 | 24 | ## EXAMPLES 25 | 26 | ### Example 1 27 | 28 | ```powershell 29 | PS C:\> New-WsbConfiguration -Name demo -LogonCommand C:\scripts\wsbscripts\sandbox-basic.cmd -MemoryInMB (4096*2) -MappedFolder (New-WsbMappedFolder -HostFolder c:\scratch -SandboxFolder c:\junk) -Description "My test WSB configuration" | Export-WsbConfiguration -Path c:\scratch\scratch.wsb 30 | ``` 31 | 32 | ## PARAMETERS 33 | 34 | ### -Configuration 35 | 36 | Specify a wsbConfiguration object. 37 | 38 | ```yaml 39 | Type: wsbConfiguration 40 | Parameter Sets: (All) 41 | Aliases: 42 | 43 | Required: True 44 | Position: 0 45 | Default value: None 46 | Accept pipeline input: True (ByValue) 47 | Accept wildcard characters: False 48 | ``` 49 | 50 | ### -Confirm 51 | 52 | Prompts you for confirmation before running the cmdlet. 53 | 54 | ```yaml 55 | Type: SwitchParameter 56 | Parameter Sets: (All) 57 | Aliases: cf 58 | 59 | Required: False 60 | Position: Named 61 | Default value: None 62 | Accept pipeline input: False 63 | Accept wildcard characters: False 64 | ``` 65 | 66 | ### -NoClobber 67 | 68 | Don't overwrite an existing file. 69 | 70 | ```yaml 71 | Type: SwitchParameter 72 | Parameter Sets: (All) 73 | Aliases: 74 | 75 | Required: False 76 | Position: Named 77 | Default value: None 78 | Accept pipeline input: False 79 | Accept wildcard characters: False 80 | ``` 81 | 82 | ### -Path 83 | 84 | Specify the path and filename. 85 | It must end in .wsb 86 | 87 | ```yaml 88 | Type: String 89 | Parameter Sets: (All) 90 | Aliases: 91 | 92 | Required: True 93 | Position: Named 94 | Default value: None 95 | Accept pipeline input: False 96 | Accept wildcard characters: False 97 | ``` 98 | 99 | ### -WhatIf 100 | 101 | Shows what would happen if the cmdlet runs. 102 | The cmdlet is not run. 103 | 104 | ```yaml 105 | Type: SwitchParameter 106 | Parameter Sets: (All) 107 | Aliases: wi 108 | 109 | Required: False 110 | Position: Named 111 | Default value: None 112 | Accept pipeline input: False 113 | Accept wildcard characters: False 114 | ``` 115 | 116 | ### CommonParameters 117 | 118 | This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). 119 | 120 | ## INPUTS 121 | 122 | ### wsbConfiguration 123 | 124 | ## OUTPUTS 125 | 126 | ### System.IO.FileInfo 127 | 128 | ## NOTES 129 | 130 | Learn more about PowerShell: http://jdhitsolutions.com/blog/essential-powershell-resources/ 131 | 132 | ## RELATED LINKS 133 | 134 | [New-WsbConfiguration](New-WsbConfiguration.md) 135 | -------------------------------------------------------------------------------- /docs/Get-WsbConfiguration.md: -------------------------------------------------------------------------------- 1 | --- 2 | external help file: WindowsSandboxTools-help.xml 3 | Module Name: WindowsSandboxTools 4 | online version: https://bit.ly/44aWC9X 5 | schema: 2.0.0 6 | --- 7 | 8 | # Get-WsbConfiguration 9 | 10 | ## SYNOPSIS 11 | 12 | Get a Windows Sandbox configuration. 13 | 14 | ## SYNTAX 15 | 16 | ```yaml 17 | Get-WsbConfiguration [-Path] [-MetadataOnly] [] 18 | ``` 19 | 20 | ## DESCRIPTION 21 | 22 | This command will give you information about a sandbox configuration. 23 | 24 | ## EXAMPLES 25 | 26 | ### Example 1 27 | 28 | ```powershell 29 | PS C:\> Get-WsbConfiguration C:\Scripts\WindowsSandboxTools\wsbConfig\dev.wsb 30 | 31 | Name: C:\scripts\wsbconfig\dev.wsb 32 | 33 | vGPU : Enable 34 | MemoryInMB : 8192 35 | AudioInput : Disable 36 | VideoInput : Default 37 | ClipboardRedirection : Default 38 | PrinterRedirection : Default 39 | Networking : Default 40 | ProtectedClient : Disable 41 | LogonCommand : C:\scripts\wsbScripts\sandbox-setup.cmd 42 | MappedFolders : C:\scripts -> C:\scripts [RO:False] 43 | C:\Pluralsight -> C:\Pluralsight [RO:True] 44 | ``` 45 | 46 | ### Example 2 47 | 48 | ```powershell 49 | PS C:\> Get-WsbConfiguration C:\Scripts\WindowsSandboxTools\wsbConfig\dev.wsb -MetadataOnly 50 | 51 | Author Name Description Updated 52 | ------ ---- ----------- ------- 53 | Jeff C:\scripts\wsbconfig\dev.wsb A test wsb file 12/10/2020 8:50:03 AM 54 | ``` 55 | 56 | ## PARAMETERS 57 | 58 | ### -MetadataOnly 59 | 60 | Only display metadata information. 61 | 62 | ```yaml 63 | Type: SwitchParameter 64 | Parameter Sets: (All) 65 | Aliases: 66 | 67 | Required: False 68 | Position: Named 69 | Default value: None 70 | Accept pipeline input: False 71 | Accept wildcard characters: False 72 | ``` 73 | 74 | ### -Path 75 | 76 | Specify the path to the .wsb file. The command will autocomplete to the $wsbConfigPath variable. 77 | 78 | ```yaml 79 | Type: String 80 | Parameter Sets: (All) 81 | Aliases: 82 | 83 | Required: True 84 | Position: 0 85 | Default value: None 86 | Accept pipeline input: True (ByValue) 87 | Accept wildcard characters: False 88 | ``` 89 | 90 | ### CommonParameters 91 | 92 | This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). 93 | 94 | ## INPUTS 95 | 96 | ### None 97 | 98 | ## OUTPUTS 99 | 100 | ### wsbConfiguration 101 | 102 | ## NOTES 103 | 104 | Learn more about PowerShell: http://jdhitsolutions.com/blog/essential-powershell-resources/ 105 | 106 | ## RELATED LINKS 107 | 108 | [New-WsbConfiguration](New-WsbConfiguration.md) 109 | -------------------------------------------------------------------------------- /docs/New-WsbConfiguration.md: -------------------------------------------------------------------------------- 1 | --- 2 | external help file: WindowsSandboxTools-help.xml 3 | Module Name: WindowsSandboxTools 4 | online version: https://bit.ly/3qSqCJA 5 | schema: 2.0.0 6 | --- 7 | 8 | # New-WsbConfiguration 9 | 10 | ## SYNOPSIS 11 | 12 | Create a new Windows Sandbox configuration. 13 | 14 | ## SYNTAX 15 | 16 | ### name (Default) 17 | 18 | ```yaml 19 | New-WsbConfiguration [-vGPU ] [-MemoryInMB ] [-AudioInput ] [-VideoInput ] [-ClipboardRedirection ] [-PrinterRedirection ] [-Networking ] [-ProtectedClient ] [-LogonCommand ] [-MappedFolder ] -Name [-Description ] [-Author ] [] 20 | ``` 21 | 22 | ### meta 23 | 24 | ```yaml 25 | New-WsbConfiguration [-vGPU ] [-MemoryInMB ] [-AudioInput ] [-VideoInput ] [-ClipboardRedirection ] [-PrinterRedirection ] [-Networking ] [-ProtectedClient ] [-LogonCommand ] [-MappedFolder ] 26 | [-Metadata ] [] 27 | ``` 28 | 29 | ## DESCRIPTION 30 | 31 | This command will create a new Wsbconfiguration object. Use Export-Wsbconfiguration to save it to disk. 32 | 33 | ## EXAMPLES 34 | 35 | ### Example 1 36 | 37 | ```powershell 38 | PS C:\> $new = New-WsbConfiguration -Name demo -LogonCommand C:\scripts\wsbscripts\sandbox-basic.cmd -MemoryInMB (4096*2) -MappedFolder (New-WsbMappedFolder -HostFolder c:\scratch -SandboxFolder c:\junk) -description "My scratch configuration" 39 | ``` 40 | 41 | ## PARAMETERS 42 | 43 | ### -AudioInput 44 | 45 | ```yaml 46 | Type: String 47 | Parameter Sets: (All) 48 | Aliases: 49 | Accepted values: Default, Enable, Disable 50 | 51 | Required: False 52 | Position: Named 53 | Default value: Default 54 | Accept pipeline input: True (ByPropertyName) 55 | Accept wildcard characters: False 56 | ``` 57 | 58 | ### -Author 59 | 60 | Who is the author? 61 | 62 | ```yaml 63 | Type: String 64 | Parameter Sets: name 65 | Aliases: 66 | 67 | Required: False 68 | Position: Named 69 | Default value: current user 70 | Accept pipeline input: False 71 | Accept wildcard characters: False 72 | ``` 73 | 74 | ### -ClipboardRedirection 75 | 76 | ```yaml 77 | Type: String 78 | Parameter Sets: (All) 79 | Aliases: 80 | Accepted values: Default, Disable 81 | 82 | Required: False 83 | Position: Named 84 | Default value: Default 85 | Accept pipeline input: True (ByPropertyName) 86 | Accept wildcard characters: False 87 | ``` 88 | 89 | ### -Description 90 | 91 | Provide a description for this configuration. 92 | 93 | ```yaml 94 | Type: String 95 | Parameter Sets: name 96 | Aliases: 97 | 98 | Required: False 99 | Position: Named 100 | Default value: None 101 | Accept pipeline input: False 102 | Accept wildcard characters: False 103 | ``` 104 | 105 | ### -LogonCommand 106 | 107 | The path and file are relative to the Windows Sandbox configuration. 108 | 109 | ```yaml 110 | Type: Object 111 | Parameter Sets: (All) 112 | Aliases: 113 | 114 | Required: False 115 | Position: Named 116 | Default value: None 117 | Accept pipeline input: True (ByPropertyName) 118 | Accept wildcard characters: False 119 | ``` 120 | 121 | ### -MappedFolder 122 | 123 | Specify a mapped folder object. 124 | 125 | ```yaml 126 | Type: wsbMappedFolder[] 127 | Parameter Sets: (All) 128 | Aliases: 129 | 130 | Required: False 131 | Position: Named 132 | Default value: None 133 | Accept pipeline input: True (ByPropertyName) 134 | Accept wildcard characters: False 135 | ``` 136 | 137 | ### -MemoryInMB 138 | 139 | ```yaml 140 | Type: String 141 | Parameter Sets: (All) 142 | Aliases: 143 | 144 | Required: False 145 | Position: Named 146 | Default value: 4096 147 | Accept pipeline input: True (ByPropertyName) 148 | Accept wildcard characters: False 149 | ``` 150 | 151 | ### -Metadata 152 | 153 | A set of metadata values. This will typically be configured by default. 154 | 155 | ```yaml 156 | Type: wsbMetadata 157 | Parameter Sets: meta 158 | Aliases: 159 | 160 | Required: False 161 | Position: Named 162 | Default value: None 163 | Accept pipeline input: False 164 | Accept wildcard characters: False 165 | ``` 166 | 167 | ### -Name 168 | 169 | Give the configuration a name 170 | 171 | ```yaml 172 | Type: String 173 | Parameter Sets: name 174 | Aliases: 175 | 176 | Required: True 177 | Position: Named 178 | Default value: None 179 | Accept pipeline input: False 180 | Accept wildcard characters: False 181 | ``` 182 | 183 | ### -Networking 184 | 185 | ```yaml 186 | Type: String 187 | Parameter Sets: (All) 188 | Aliases: 189 | Accepted values: Default, Disable 190 | 191 | Required: False 192 | Position: Named 193 | Default value: Default 194 | Accept pipeline input: True (ByPropertyName) 195 | Accept wildcard characters: False 196 | ``` 197 | 198 | ### -PrinterRedirection 199 | 200 | ```yaml 201 | Type: String 202 | Parameter Sets: (All) 203 | Aliases: 204 | Accepted values: Default, Enable, Disable 205 | 206 | Required: False 207 | Position: Named 208 | Default value: Default 209 | Accept pipeline input: True (ByPropertyName) 210 | Accept wildcard characters: False 211 | ``` 212 | 213 | ### -ProtectedClient 214 | 215 | ```yaml 216 | Type: String 217 | Parameter Sets: (All) 218 | Aliases: 219 | Accepted values: Default, Enable, Disable 220 | 221 | Required: False 222 | Position: Named 223 | Default value: Default 224 | Accept pipeline input: True (ByPropertyName) 225 | Accept wildcard characters: False 226 | ``` 227 | 228 | ### -VideoInput 229 | 230 | ```yaml 231 | Type: String 232 | Parameter Sets: (All) 233 | Aliases: 234 | Accepted values: Default, Enable, Disable 235 | 236 | Required: False 237 | Position: Named 238 | Default value: Default 239 | Accept pipeline input: True (ByPropertyName) 240 | Accept wildcard characters: False 241 | ``` 242 | 243 | ### -vGPU 244 | 245 | ```yaml 246 | Type: String 247 | Parameter Sets: (All) 248 | Aliases: 249 | Accepted values: Default, Enable, Disable 250 | 251 | Required: False 252 | Position: Named 253 | Default value: Default 254 | Accept pipeline input: True (ByPropertyName) 255 | Accept wildcard characters: False 256 | ``` 257 | 258 | ### CommonParameters 259 | 260 | This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). 261 | 262 | ## INPUTS 263 | 264 | ### System.String 265 | 266 | ### System.Object 267 | 268 | ### wsbMappedFolder[] 269 | 270 | ## OUTPUTS 271 | 272 | ### wsbConfiguration 273 | 274 | ## NOTES 275 | 276 | Learn more about PowerShell: http://jdhitsolutions.com/blog/essential-powershell-resources/ 277 | 278 | ## RELATED LINKS 279 | 280 | [New-WsbMappedFolder](New-WsbMappedFolder.md) 281 | 282 | [Export-WsbConfiguration](Export-WsbConfiguration.md) 283 | -------------------------------------------------------------------------------- /docs/New-WsbMappedFolder.md: -------------------------------------------------------------------------------- 1 | --- 2 | external help file: WindowsSandboxTools-help.xml 3 | Module Name: WindowsSandboxTools 4 | online version: https://bit.ly/3PkPqUH 5 | schema: 2.0.0 6 | --- 7 | 8 | # New-WsbMappedFolder 9 | 10 | ## SYNOPSIS 11 | 12 | Create a mapped folder object. 13 | 14 | ## SYNTAX 15 | 16 | ```yaml 17 | New-WsbMappedFolder [-HostFolder] [-SandboxFolder] [-ReadOnly] [] 18 | ``` 19 | 20 | ## DESCRIPTION 21 | 22 | You this folder to create a new mapped folder object. You can use this when creating a new Windows sandbox configuration. The sandbox will only have a C: drive. 23 | 24 | ## EXAMPLES 25 | 26 | ### Example 1 27 | 28 | ```powershell 29 | PS C:\> $map = New-WsbMappedFolder -HostFolder c:\work -SandboxFolder c:\work 30 | PS C:\> New-WsbConfiguration -Name work -MappedFolder $map -Description "Work sandbox" 31 | ``` 32 | 33 | Create a shared folder with write access and then use that object in a new configuration. 34 | 35 | ## PARAMETERS 36 | 37 | ### -HostFolder 38 | 39 | Specify the path to the local folder you want to map. This folder must already exist. 40 | 41 | ```yaml 42 | Type: String 43 | Parameter Sets: (All) 44 | Aliases: 45 | 46 | Required: True 47 | Position: 0 48 | Default value: None 49 | Accept pipeline input: True (ByPropertyName) 50 | Accept wildcard characters: False 51 | ``` 52 | 53 | ### -ReadOnly 54 | 55 | Specify if you want the mapping to be Read-Only. 56 | 57 | ```yaml 58 | Type: SwitchParameter 59 | Parameter Sets: (All) 60 | Aliases: 61 | 62 | Required: False 63 | Position: Named 64 | Default value: None 65 | Accept pipeline input: True (ByPropertyName) 66 | Accept wildcard characters: False 67 | ``` 68 | 69 | ### -SandboxFolder 70 | 71 | Specify the mapped folder for the Windows Sandbox. 72 | It must start with C:\ 73 | 74 | ```yaml 75 | Type: String 76 | Parameter Sets: (All) 77 | Aliases: 78 | 79 | Required: True 80 | Position: 1 81 | Default value: None 82 | Accept pipeline input: True (ByPropertyName) 83 | Accept wildcard characters: False 84 | ``` 85 | 86 | ### CommonParameters 87 | 88 | This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). 89 | 90 | ## INPUTS 91 | 92 | ### System.String 93 | 94 | ## OUTPUTS 95 | 96 | ### wsbMappedFolder 97 | 98 | ## NOTES 99 | 100 | Learn more about PowerShell: http://jdhitsolutions.com/blog/essential-powershell-resources/ 101 | 102 | ## RELATED LINKS 103 | 104 | [New-WsbConfiguration](New-WsbConfiguration.md) 105 | -------------------------------------------------------------------------------- /docs/Start-WindowsSandbox.md: -------------------------------------------------------------------------------- 1 | --- 2 | external help file: WindowsSandboxTools-help.xml 3 | Module Name: WindowsSandboxTools 4 | online version: https://bit.ly/42Wde4i 5 | schema: 2.0.0 6 | --- 7 | 8 | # Start-WindowsSandbox 9 | 10 | ## SYNOPSIS 11 | 12 | Start a Windows sandbox configuration. 13 | 14 | ## SYNTAX 15 | 16 | ### config (Default) 17 | 18 | ```yaml 19 | Start-WindowsSandbox [-Configuration] [-WindowSize ] [-WhatIf] [-Confirm] [] 20 | ``` 21 | 22 | ### normal 23 | 24 | ```yaml 25 | Start-WindowsSandbox [-NoSetup] [-WindowSize ] [-WhatIf] [-Confirm] [] 26 | ``` 27 | 28 | ## DESCRIPTION 29 | 30 | Use this command, or its alias wsb, to launch Windows Sandbox. You can specify a configuration or use -NoSetup to run the default sandbox. 31 | 32 | ## EXAMPLES 33 | 34 | ### Example 1 35 | 36 | ```powershell 37 | PS C:\> Start-WindowsSandbox -noSetup -windowsize 1024,768 38 | ``` 39 | 40 | This will launch the default Windows sandobx and attempt to configure the screen resolution to 1024x768. 41 | 42 | ### Example 2 43 | 44 | ```powershell 45 | PS C:\> Start-WindowsSandbox $wsbconfigPath\presentation.wsb 46 | ``` 47 | 48 | ## PARAMETERS 49 | 50 | ### -Configuration 51 | 52 | Specify the path to a wsb file. The command will autocomplete using the $wsbConfigPath variable. 53 | 54 | ```yaml 55 | Type: String 56 | Parameter Sets: config 57 | Aliases: 58 | 59 | Required: True 60 | Position: 0 61 | Default value: None 62 | Accept pipeline input: False 63 | Accept wildcard characters: False 64 | ``` 65 | 66 | ### -Confirm 67 | 68 | Prompts you for confirmation before running the cmdlet. 69 | 70 | ```yaml 71 | Type: SwitchParameter 72 | Parameter Sets: (All) 73 | Aliases: cf 74 | 75 | Required: False 76 | Position: Named 77 | Default value: None 78 | Accept pipeline input: False 79 | Accept wildcard characters: False 80 | ``` 81 | 82 | ### -NoSetup 83 | 84 | Start with no customizations. 85 | 86 | ```yaml 87 | Type: SwitchParameter 88 | Parameter Sets: normal 89 | Aliases: 90 | 91 | Required: False 92 | Position: Named 93 | Default value: None 94 | Accept pipeline input: False 95 | Accept wildcard characters: False 96 | ``` 97 | 98 | ### -WhatIf 99 | 100 | Shows what would happen if the cmdlet runs. 101 | The cmdlet is not run. 102 | 103 | ```yaml 104 | Type: SwitchParameter 105 | Parameter Sets: (All) 106 | Aliases: wi 107 | 108 | Required: False 109 | Position: Named 110 | Default value: None 111 | Accept pipeline input: False 112 | Accept wildcard characters: False 113 | ``` 114 | 115 | ### -WindowSize 116 | 117 | Specify desktop resolutions as an array like 1280,720. 118 | The default is 1920,1080. This feature may not be 100% correct and should be considered an experimental feature. 119 | 120 | ```yaml 121 | Type: Int32[] 122 | Parameter Sets: (All) 123 | Aliases: 124 | 125 | Required: False 126 | Position: Named 127 | Default value: 1920,1080 128 | Accept pipeline input: False 129 | Accept wildcard characters: False 130 | ``` 131 | 132 | ### CommonParameters 133 | 134 | This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). 135 | 136 | ## INPUTS 137 | 138 | ### None 139 | 140 | ## OUTPUTS 141 | 142 | ### none 143 | 144 | ## NOTES 145 | 146 | Learn more about PowerShell: http://jdhitsolutions.com/blog/essential-powershell-resources/ 147 | 148 | ## RELATED LINKS 149 | 150 | [Get-WsbConfiguration](Get-WsbConfiguration.md) 151 | -------------------------------------------------------------------------------- /en-us/WindowsSandboxTools-help.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Export-WsbConfiguration 6 | Export 7 | WsbConfiguration 8 | 9 | Export a WSB configuration to an XML file. 10 | 11 | 12 | 13 | This command will take an existing Windows Sandbox Configuration object and export it to an XML file. 14 | 15 | 16 | 17 | Export-WsbConfiguration 18 | 19 | Configuration 20 | 21 | Specify a wsbConfiguration object. 22 | 23 | wsbConfiguration 24 | 25 | wsbConfiguration 26 | 27 | 28 | None 29 | 30 | 31 | Confirm 32 | 33 | Prompts you for confirmation before running the cmdlet. 34 | 35 | 36 | SwitchParameter 37 | 38 | 39 | False 40 | 41 | 42 | NoClobber 43 | 44 | Don't overwrite an existing file. 45 | 46 | 47 | SwitchParameter 48 | 49 | 50 | False 51 | 52 | 53 | Path 54 | 55 | Specify the path and filename. It must end in .wsb 56 | 57 | String 58 | 59 | String 60 | 61 | 62 | None 63 | 64 | 65 | WhatIf 66 | 67 | Shows what would happen if the cmdlet runs. The cmdlet is not run. 68 | 69 | 70 | SwitchParameter 71 | 72 | 73 | False 74 | 75 | 76 | 77 | 78 | 79 | Configuration 80 | 81 | Specify a wsbConfiguration object. 82 | 83 | wsbConfiguration 84 | 85 | wsbConfiguration 86 | 87 | 88 | None 89 | 90 | 91 | Confirm 92 | 93 | Prompts you for confirmation before running the cmdlet. 94 | 95 | SwitchParameter 96 | 97 | SwitchParameter 98 | 99 | 100 | False 101 | 102 | 103 | NoClobber 104 | 105 | Don't overwrite an existing file. 106 | 107 | SwitchParameter 108 | 109 | SwitchParameter 110 | 111 | 112 | False 113 | 114 | 115 | Path 116 | 117 | Specify the path and filename. It must end in .wsb 118 | 119 | String 120 | 121 | String 122 | 123 | 124 | None 125 | 126 | 127 | WhatIf 128 | 129 | Shows what would happen if the cmdlet runs. The cmdlet is not run. 130 | 131 | SwitchParameter 132 | 133 | SwitchParameter 134 | 135 | 136 | False 137 | 138 | 139 | 140 | 141 | 142 | wsbConfiguration 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | System.IO.FileInfo 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | Learn more about PowerShell: http://jdhitsolutions.com/blog/essential-powershell-resources/ 162 | 163 | 164 | 165 | 166 | -------------------------- Example 1 -------------------------- 167 | PS C:\> New-WsbConfiguration -Name demo -LogonCommand C:\scripts\wsbscripts\sandbox-basic.cmd -MemoryInMB (4096*2) -MappedFolder (New-WsbMappedFolder -HostFolder c:\scratch -SandboxFolder c:\junk) -Description "My test WSB configuration" | Export-WsbConfiguration -Path c:\scratch\scratch.wsb 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | Online Version: 176 | https://bit.ly/3PkXMvl 177 | 178 | 179 | New-WsbConfiguration 180 | 181 | 182 | 183 | 184 | 185 | 186 | Get-WsbConfiguration 187 | Get 188 | WsbConfiguration 189 | 190 | Get a Windows Sandbox configuration. 191 | 192 | 193 | 194 | This command will give you information about a sandbox configuration. 195 | 196 | 197 | 198 | Get-WsbConfiguration 199 | 200 | Path 201 | 202 | Specify the path to the .wsb file. The command will autocomplete to the $wsbConfigPath variable. 203 | 204 | String 205 | 206 | String 207 | 208 | 209 | None 210 | 211 | 212 | MetadataOnly 213 | 214 | Only display metadata information. 215 | 216 | 217 | SwitchParameter 218 | 219 | 220 | False 221 | 222 | 223 | 224 | 225 | 226 | MetadataOnly 227 | 228 | Only display metadata information. 229 | 230 | SwitchParameter 231 | 232 | SwitchParameter 233 | 234 | 235 | False 236 | 237 | 238 | Path 239 | 240 | Specify the path to the .wsb file. The command will autocomplete to the $wsbConfigPath variable. 241 | 242 | String 243 | 244 | String 245 | 246 | 247 | None 248 | 249 | 250 | 251 | 252 | 253 | None 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | wsbConfiguration 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | Learn more about PowerShell: http://jdhitsolutions.com/blog/essential-powershell-resources/ 273 | 274 | 275 | 276 | 277 | -------------------------- Example 1 -------------------------- 278 | PS C:\> Get-WsbConfiguration C:\Scripts\WindowsSandboxTools\wsbConfig\dev.wsb 279 | 280 | Name: C:\scripts\wsbconfig\dev.wsb 281 | 282 | vGPU : Enable 283 | MemoryInMB : 8192 284 | AudioInput : Disable 285 | VideoInput : Default 286 | ClipboardRedirection : Default 287 | PrinterRedirection : Default 288 | Networking : Default 289 | ProtectedClient : Disable 290 | LogonCommand : C:\scripts\wsbScripts\sandbox-setup.cmd 291 | MappedFolders : C:\scripts -> C:\scripts [RO:False] 292 | C:\Pluralsight -> C:\Pluralsight [RO:True] 293 | 294 | 295 | 296 | 297 | 298 | -------------------------- Example 2 -------------------------- 299 | PS C:\> Get-WsbConfiguration C:\Scripts\WindowsSandboxTools\wsbConfig\dev.wsb -MetadataOnly 300 | 301 | Author Name Description Updated 302 | ------ ---- ----------- ------- 303 | Jeff C:\scripts\wsbconfig\dev.wsb A test wsb file 12/10/2020 8:50:03 AM 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | Online Version: 312 | https://bit.ly/44aWC9X 313 | 314 | 315 | New-WsbConfiguration 316 | 317 | 318 | 319 | 320 | 321 | 322 | New-WsbConfiguration 323 | New 324 | WsbConfiguration 325 | 326 | Create a new Windows Sandbox configuration. 327 | 328 | 329 | 330 | This command will create a new Wsbconfiguration object. Use Export-Wsbconfiguration to save it to disk. 331 | 332 | 333 | 334 | New-WsbConfiguration 335 | 336 | AudioInput 337 | 338 | 339 | 340 | 341 | Default 342 | Enable 343 | Disable 344 | 345 | String 346 | 347 | String 348 | 349 | 350 | Default 351 | 352 | 353 | Author 354 | 355 | Who is the author? 356 | 357 | String 358 | 359 | String 360 | 361 | 362 | current user 363 | 364 | 365 | ClipboardRedirection 366 | 367 | 368 | 369 | 370 | Default 371 | Disable 372 | 373 | String 374 | 375 | String 376 | 377 | 378 | Default 379 | 380 | 381 | Description 382 | 383 | Provide a description for this configuration. 384 | 385 | String 386 | 387 | String 388 | 389 | 390 | None 391 | 392 | 393 | LogonCommand 394 | 395 | The path and file are relative to the Windows Sandbox configuration. 396 | 397 | Object 398 | 399 | Object 400 | 401 | 402 | None 403 | 404 | 405 | MappedFolder 406 | 407 | Specify a mapped folder object. 408 | 409 | wsbMappedFolder[] 410 | 411 | wsbMappedFolder[] 412 | 413 | 414 | None 415 | 416 | 417 | MemoryInMB 418 | 419 | 420 | 421 | String 422 | 423 | String 424 | 425 | 426 | 4096 427 | 428 | 429 | Name 430 | 431 | Give the configuration a name 432 | 433 | String 434 | 435 | String 436 | 437 | 438 | None 439 | 440 | 441 | Networking 442 | 443 | 444 | 445 | 446 | Default 447 | Disable 448 | 449 | String 450 | 451 | String 452 | 453 | 454 | Default 455 | 456 | 457 | PrinterRedirection 458 | 459 | 460 | 461 | 462 | Default 463 | Enable 464 | Disable 465 | 466 | String 467 | 468 | String 469 | 470 | 471 | Default 472 | 473 | 474 | ProtectedClient 475 | 476 | 477 | 478 | 479 | Default 480 | Enable 481 | Disable 482 | 483 | String 484 | 485 | String 486 | 487 | 488 | Default 489 | 490 | 491 | VideoInput 492 | 493 | 494 | 495 | 496 | Default 497 | Enable 498 | Disable 499 | 500 | String 501 | 502 | String 503 | 504 | 505 | Default 506 | 507 | 508 | vGPU 509 | 510 | 511 | 512 | 513 | Default 514 | Enable 515 | Disable 516 | 517 | String 518 | 519 | String 520 | 521 | 522 | Default 523 | 524 | 525 | 526 | New-WsbConfiguration 527 | 528 | AudioInput 529 | 530 | 531 | 532 | 533 | Default 534 | Enable 535 | Disable 536 | 537 | String 538 | 539 | String 540 | 541 | 542 | Default 543 | 544 | 545 | ClipboardRedirection 546 | 547 | 548 | 549 | 550 | Default 551 | Disable 552 | 553 | String 554 | 555 | String 556 | 557 | 558 | Default 559 | 560 | 561 | LogonCommand 562 | 563 | The path and file are relative to the Windows Sandbox configuration. 564 | 565 | Object 566 | 567 | Object 568 | 569 | 570 | None 571 | 572 | 573 | MappedFolder 574 | 575 | Specify a mapped folder object. 576 | 577 | wsbMappedFolder[] 578 | 579 | wsbMappedFolder[] 580 | 581 | 582 | None 583 | 584 | 585 | MemoryInMB 586 | 587 | 588 | 589 | String 590 | 591 | String 592 | 593 | 594 | 4096 595 | 596 | 597 | Metadata 598 | 599 | A set of metadata values. This will typically be configured by default. 600 | 601 | wsbMetadata 602 | 603 | wsbMetadata 604 | 605 | 606 | None 607 | 608 | 609 | Networking 610 | 611 | 612 | 613 | 614 | Default 615 | Disable 616 | 617 | String 618 | 619 | String 620 | 621 | 622 | Default 623 | 624 | 625 | PrinterRedirection 626 | 627 | 628 | 629 | 630 | Default 631 | Enable 632 | Disable 633 | 634 | String 635 | 636 | String 637 | 638 | 639 | Default 640 | 641 | 642 | ProtectedClient 643 | 644 | 645 | 646 | 647 | Default 648 | Enable 649 | Disable 650 | 651 | String 652 | 653 | String 654 | 655 | 656 | Default 657 | 658 | 659 | VideoInput 660 | 661 | 662 | 663 | 664 | Default 665 | Enable 666 | Disable 667 | 668 | String 669 | 670 | String 671 | 672 | 673 | Default 674 | 675 | 676 | vGPU 677 | 678 | 679 | 680 | 681 | Default 682 | Enable 683 | Disable 684 | 685 | String 686 | 687 | String 688 | 689 | 690 | Default 691 | 692 | 693 | 694 | 695 | 696 | AudioInput 697 | 698 | 699 | 700 | String 701 | 702 | String 703 | 704 | 705 | Default 706 | 707 | 708 | Author 709 | 710 | Who is the author? 711 | 712 | String 713 | 714 | String 715 | 716 | 717 | current user 718 | 719 | 720 | ClipboardRedirection 721 | 722 | 723 | 724 | String 725 | 726 | String 727 | 728 | 729 | Default 730 | 731 | 732 | Description 733 | 734 | Provide a description for this configuration. 735 | 736 | String 737 | 738 | String 739 | 740 | 741 | None 742 | 743 | 744 | LogonCommand 745 | 746 | The path and file are relative to the Windows Sandbox configuration. 747 | 748 | Object 749 | 750 | Object 751 | 752 | 753 | None 754 | 755 | 756 | MappedFolder 757 | 758 | Specify a mapped folder object. 759 | 760 | wsbMappedFolder[] 761 | 762 | wsbMappedFolder[] 763 | 764 | 765 | None 766 | 767 | 768 | MemoryInMB 769 | 770 | 771 | 772 | String 773 | 774 | String 775 | 776 | 777 | 4096 778 | 779 | 780 | Metadata 781 | 782 | A set of metadata values. This will typically be configured by default. 783 | 784 | wsbMetadata 785 | 786 | wsbMetadata 787 | 788 | 789 | None 790 | 791 | 792 | Name 793 | 794 | Give the configuration a name 795 | 796 | String 797 | 798 | String 799 | 800 | 801 | None 802 | 803 | 804 | Networking 805 | 806 | 807 | 808 | String 809 | 810 | String 811 | 812 | 813 | Default 814 | 815 | 816 | PrinterRedirection 817 | 818 | 819 | 820 | String 821 | 822 | String 823 | 824 | 825 | Default 826 | 827 | 828 | ProtectedClient 829 | 830 | 831 | 832 | String 833 | 834 | String 835 | 836 | 837 | Default 838 | 839 | 840 | VideoInput 841 | 842 | 843 | 844 | String 845 | 846 | String 847 | 848 | 849 | Default 850 | 851 | 852 | vGPU 853 | 854 | 855 | 856 | String 857 | 858 | String 859 | 860 | 861 | Default 862 | 863 | 864 | 865 | 866 | 867 | System.String 868 | 869 | 870 | 871 | 872 | 873 | 874 | 875 | System.Object 876 | 877 | 878 | 879 | 880 | 881 | 882 | 883 | wsbMappedFolder[] 884 | 885 | 886 | 887 | 888 | 889 | 890 | 891 | 892 | 893 | wsbConfiguration 894 | 895 | 896 | 897 | 898 | 899 | 900 | 901 | 902 | Learn more about PowerShell: http://jdhitsolutions.com/blog/essential-powershell-resources/ 903 | 904 | 905 | 906 | 907 | -------------------------- Example 1 -------------------------- 908 | PS C:\> $new = New-WsbConfiguration -Name demo -LogonCommand C:\scripts\wsbscripts\sandbox-basic.cmd -MemoryInMB (4096*2) -MappedFolder (New-WsbMappedFolder -HostFolder c:\scratch -SandboxFolder c:\junk) -description "My scratch configuration" 909 | 910 | 911 | 912 | 913 | 914 | 915 | 916 | Online Version: 917 | https://bit.ly/3qSqCJA 918 | 919 | 920 | New-WsbMappedFolder 921 | 922 | 923 | 924 | Export-WsbConfiguration 925 | 926 | 927 | 928 | 929 | 930 | 931 | New-WsbMappedFolder 932 | New 933 | WsbMappedFolder 934 | 935 | Create a mapped folder object. 936 | 937 | 938 | 939 | You this folder to create a new mapped folder object. You can use this when creating a new Windows sandbox configuration. The sandbox will only have a C: drive. 940 | 941 | 942 | 943 | New-WsbMappedFolder 944 | 945 | HostFolder 946 | 947 | Specify the path to the local folder you want to map. This folder must already exist. 948 | 949 | String 950 | 951 | String 952 | 953 | 954 | None 955 | 956 | 957 | SandboxFolder 958 | 959 | Specify the mapped folder for the Windows Sandbox. It must start with C:\ 960 | 961 | String 962 | 963 | String 964 | 965 | 966 | None 967 | 968 | 969 | ReadOnly 970 | 971 | Specify if you want the mapping to be Read-Only. 972 | 973 | 974 | SwitchParameter 975 | 976 | 977 | False 978 | 979 | 980 | 981 | 982 | 983 | HostFolder 984 | 985 | Specify the path to the local folder you want to map. This folder must already exist. 986 | 987 | String 988 | 989 | String 990 | 991 | 992 | None 993 | 994 | 995 | ReadOnly 996 | 997 | Specify if you want the mapping to be Read-Only. 998 | 999 | SwitchParameter 1000 | 1001 | SwitchParameter 1002 | 1003 | 1004 | False 1005 | 1006 | 1007 | SandboxFolder 1008 | 1009 | Specify the mapped folder for the Windows Sandbox. It must start with C:\ 1010 | 1011 | String 1012 | 1013 | String 1014 | 1015 | 1016 | None 1017 | 1018 | 1019 | 1020 | 1021 | 1022 | System.String 1023 | 1024 | 1025 | 1026 | 1027 | 1028 | 1029 | 1030 | 1031 | 1032 | wsbMappedFolder 1033 | 1034 | 1035 | 1036 | 1037 | 1038 | 1039 | 1040 | 1041 | Learn more about PowerShell: http://jdhitsolutions.com/blog/essential-powershell-resources/ 1042 | 1043 | 1044 | 1045 | 1046 | -------------------------- Example 1 -------------------------- 1047 | PS C:\> $map = New-WsbMappedFolder -HostFolder c:\work -SandboxFolder c:\work 1048 | PS C:\> New-WsbConfiguration -Name work -MappedFolder $map -Description "Work sandbox" 1049 | 1050 | Create a shared folder with write access and then use that object in a new configuration. 1051 | 1052 | 1053 | 1054 | 1055 | 1056 | Online Version: 1057 | https://bit.ly/3PkPqUH 1058 | 1059 | 1060 | New-WsbConfiguration 1061 | 1062 | 1063 | 1064 | 1065 | 1066 | 1067 | Start-WindowsSandbox 1068 | Start 1069 | WindowsSandbox 1070 | 1071 | Start a Windows sandbox configuration. 1072 | 1073 | 1074 | 1075 | Use this command, or its alias wsb, to launch Windows Sandbox. You can specify a configuration or use -NoSetup to run the default sandbox. 1076 | 1077 | 1078 | 1079 | Start-WindowsSandbox 1080 | 1081 | Configuration 1082 | 1083 | Specify the path to a wsb file. The command will autocomplete using the $wsbConfigPath variable. 1084 | 1085 | String 1086 | 1087 | String 1088 | 1089 | 1090 | None 1091 | 1092 | 1093 | Confirm 1094 | 1095 | Prompts you for confirmation before running the cmdlet. 1096 | 1097 | 1098 | SwitchParameter 1099 | 1100 | 1101 | False 1102 | 1103 | 1104 | WhatIf 1105 | 1106 | Shows what would happen if the cmdlet runs. The cmdlet is not run. 1107 | 1108 | 1109 | SwitchParameter 1110 | 1111 | 1112 | False 1113 | 1114 | 1115 | WindowSize 1116 | 1117 | Specify desktop resolutions as an array like 1280,720. The default is 1920,1080. This feature may not be 100% correct and should be considered an experimental feature. 1118 | 1119 | Int32[] 1120 | 1121 | Int32[] 1122 | 1123 | 1124 | 1920,1080 1125 | 1126 | 1127 | 1128 | Start-WindowsSandbox 1129 | 1130 | Confirm 1131 | 1132 | Prompts you for confirmation before running the cmdlet. 1133 | 1134 | 1135 | SwitchParameter 1136 | 1137 | 1138 | False 1139 | 1140 | 1141 | NoSetup 1142 | 1143 | Start with no customizations. 1144 | 1145 | 1146 | SwitchParameter 1147 | 1148 | 1149 | False 1150 | 1151 | 1152 | WhatIf 1153 | 1154 | Shows what would happen if the cmdlet runs. The cmdlet is not run. 1155 | 1156 | 1157 | SwitchParameter 1158 | 1159 | 1160 | False 1161 | 1162 | 1163 | WindowSize 1164 | 1165 | Specify desktop resolutions as an array like 1280,720. The default is 1920,1080. This feature may not be 100% correct and should be considered an experimental feature. 1166 | 1167 | Int32[] 1168 | 1169 | Int32[] 1170 | 1171 | 1172 | 1920,1080 1173 | 1174 | 1175 | 1176 | 1177 | 1178 | Configuration 1179 | 1180 | Specify the path to a wsb file. The command will autocomplete using the $wsbConfigPath variable. 1181 | 1182 | String 1183 | 1184 | String 1185 | 1186 | 1187 | None 1188 | 1189 | 1190 | Confirm 1191 | 1192 | Prompts you for confirmation before running the cmdlet. 1193 | 1194 | SwitchParameter 1195 | 1196 | SwitchParameter 1197 | 1198 | 1199 | False 1200 | 1201 | 1202 | NoSetup 1203 | 1204 | Start with no customizations. 1205 | 1206 | SwitchParameter 1207 | 1208 | SwitchParameter 1209 | 1210 | 1211 | False 1212 | 1213 | 1214 | WhatIf 1215 | 1216 | Shows what would happen if the cmdlet runs. The cmdlet is not run. 1217 | 1218 | SwitchParameter 1219 | 1220 | SwitchParameter 1221 | 1222 | 1223 | False 1224 | 1225 | 1226 | WindowSize 1227 | 1228 | Specify desktop resolutions as an array like 1280,720. The default is 1920,1080. This feature may not be 100% correct and should be considered an experimental feature. 1229 | 1230 | Int32[] 1231 | 1232 | Int32[] 1233 | 1234 | 1235 | 1920,1080 1236 | 1237 | 1238 | 1239 | 1240 | 1241 | None 1242 | 1243 | 1244 | 1245 | 1246 | 1247 | 1248 | 1249 | 1250 | 1251 | none 1252 | 1253 | 1254 | 1255 | 1256 | 1257 | 1258 | 1259 | 1260 | Learn more about PowerShell: http://jdhitsolutions.com/blog/essential-powershell-resources/ 1261 | 1262 | 1263 | 1264 | 1265 | -------------------------- Example 1 -------------------------- 1266 | PS C:\> Start-WindowsSandbox -noSetup -windowsize 1024,768 1267 | 1268 | This will launch the default Windows sandobx and attempt to configure the screen resolution to 1024x768. 1269 | 1270 | 1271 | 1272 | -------------------------- Example 2 -------------------------- 1273 | PS C:\> Start-WindowsSandbox $wsbconfigPath\presentation.wsb 1274 | 1275 | 1276 | 1277 | 1278 | 1279 | 1280 | 1281 | Online Version: 1282 | https://bit.ly/42Wde4i 1283 | 1284 | 1285 | Get-WsbConfiguration 1286 | 1287 | 1288 | 1289 | 1290 | -------------------------------------------------------------------------------- /formats/wsbConfiguration.format.ps1xml: -------------------------------------------------------------------------------- 1 |  2 | 5 | 6 | 7 | 8 | 9 | default 10 | 11 | wsbConfiguration 12 | 13 | 14 | 22 | $_.metadata.Name 23 | 24 | 25 | 26 | 27 | 28 | 29 | 33 | 34 | 35 | vGPU 36 | 37 | 38 | 39 | MemoryInMB 40 | 41 | 42 | 43 | AudioInput 44 | 45 | 46 | 47 | VideoInput 48 | 49 | 50 | 51 | ClipboardRedirection 52 | 53 | 54 | 55 | PrinterRedirection 56 | 57 | 58 | 59 | Networking 60 | 61 | 62 | 63 | ProtectedClient 64 | 65 | 66 | 67 | LogonCommand 68 | 69 | 70 | 71 | 72 | $mf = @() 73 | foreach ($f in $_.mappedfolder) { 74 | $mf+= "{0} -> {1} [RO:{2}]" -f $f.hostfolder,$f.sandboxfolder,$f.readonly 75 | } 76 | $mf -join "`n" 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /functions/Export-WsbConfiguration.ps1: -------------------------------------------------------------------------------- 1 | function Export-WsbConfiguration { 2 | [CmdletBinding(SupportsShouldProcess)] 3 | [OutputType([System.io.fileInfo])] 4 | param ( 5 | [Parameter(Mandatory, Position = 0, ValueFromPipeline, HelpMessage = "Specify a wsbConfiguration object.")] 6 | [ValidateNotNullOrEmpty()] 7 | [wsbConfiguration]$Configuration, 8 | [Parameter(Mandatory, HelpMessage = "Specify the path and filename. It must end in .wsb")] 9 | [ValidatePattern("\.wsb$")] 10 | #verify the parent path exists 11 | [ValidateScript( { Test-Path $(Split-Path $_ -Parent) })] 12 | [String]$Path, 13 | [Parameter(HelpMessage = "Don't overwrite an existing file")] 14 | [Switch]$NoClobber 15 | ) 16 | Begin { 17 | Write-Verbose "[$((Get-Date).TimeOfDay) BEGIN] Starting $($MyInvocation.MyCommand)" 18 | <# 19 | Convert the path to a valid FileSystem path. Normally, I would use Convert-Path 20 | but it will fail if the file doesn't exist. Instead, I'll split the path, convert 21 | the root and recreate it. 22 | #> 23 | $parent = Convert-Path (Split-Path -Path $Path -Parent) 24 | $leaf = Split-Path -Path $Path -Leaf 25 | $cPath = Join-Path -Path $parent -ChildPath $leaf 26 | } #begin 27 | Process { 28 | Write-Verbose "[$((Get-Date).TimeOfDay) PROCESS] Creating an XML document" 29 | $xml = New-Object System.Xml.XmlDocument 30 | $config = $xml.CreateElement("element", "Configuration", "") 31 | 32 | #add my custom metadata 33 | Write-Verbose "[$((Get-Date).TimeOfDay) PROCESS] Inserting metadata" 34 | $meta = $xml.CreateElement("element", "Metadata", "") 35 | $metaprops = "Name", "Author", "Description", "Updated" 36 | foreach ($prop in $metaprops) { 37 | Write-Verbose "[$((Get-Date).TimeOfDay) PROCESS] ..$prop = $($configuration.Metadata.$prop)" 38 | $item = $xml.CreateElement($prop) 39 | $item.set_innertext($configuration.Metadata.$prop) 40 | [void]$meta.AppendChild($item) 41 | } 42 | [void]$config.AppendChild($meta) 43 | 44 | #add primary properties 45 | Write-Verbose "[$((Get-Date).TimeOfDay) PROCESS] Adding primary data" 46 | $mainprops = "vGPU", "MemoryInMB", "AudioInput", "VideoInput", "ClipboardRedirection", "PrinterRedirection", 47 | "Networking", "ProtectedClient" 48 | foreach ($prop in $mainprops) { 49 | Write-Verbose "[$((Get-Date).TimeOfDay) PROCESS] ..$prop = $($configuration.$prop)" 50 | $item = $xml.CreateElement($prop) 51 | $item.set_innertext($configuration.$prop) 52 | [void]$config.AppendChild($item) 53 | } 54 | if ($Configuration.LogonCommand) { 55 | Write-Verbose "[$((Get-Date).TimeOfDay) PROCESS] Adding a logon command" 56 | $logon = $xml.CreateElement("element", "LogonCommand", "") 57 | $cmd = $xml.CreateElement("Command") 58 | Write-Verbose "[$((Get-Date).TimeOfDay) PROCESS] ..$($configuration.LogonCommand)" 59 | $cmd.set_innerText($configuration.LogonCommand) 60 | [void]$logon.AppendChild($cmd) 61 | [void]$config.AppendChild($logon) 62 | } 63 | if ($Configuration.MappedFolder) { 64 | Write-Verbose "[$((Get-Date).TimeOfDay) PROCESS] Adding mapped folders" 65 | $mapped = $xml.CreateElement("element", "MappedFolders", "") 66 | foreach ($f in $Configuration.MappedFolder) { 67 | Write-Verbose "[$((Get-Date).TimeOfDay) PROCESS] $($f.HostFolder) -> $($f.SandboxFolder) [RO:$($f.ReadOnly)]" 68 | $mf = $xml.CreateElement("element", "MappedFolder", "") 69 | "HostFolder", "SandboxFolder", "ReadOnly" | 70 | ForEach-Object { 71 | $item = $xml.CreateElement($_) 72 | $item.set_innertext($f.$_) 73 | [void]$mf.AppendChild($item) 74 | } 75 | [void]$mapped.appendChild($mf) 76 | } 77 | [void]$config.AppendChild($mapped) 78 | } 79 | 80 | [void]$xml.AppendChild($config) 81 | 82 | Write-Verbose "[$((Get-Date).TimeOfDay) PROCESS] Exporting configuration to $cPath" 83 | if ($PSCmdlet.ShouldProcess($cpath)) { 84 | if ((Test-Path -Path $cPath) -AND $NoClobber) { 85 | Write-Warning "A file exists at $cPath and NoClobber was specified." 86 | } 87 | else { 88 | $xml.Save($cPath) 89 | } 90 | } #WhatIf 91 | 92 | } #process 93 | End { 94 | Write-Verbose "[$((Get-Date).TimeOfDay) END ] Ending $($MyInvocation.MyCommand)" 95 | } #end 96 | } 97 | -------------------------------------------------------------------------------- /functions/Get-WsbConfiguration.ps1: -------------------------------------------------------------------------------- 1 | Function Get-WsbConfiguration { 2 | [CmdletBinding()] 3 | [OutputType('wsbConfiguration')] 4 | Param( 5 | [Parameter( 6 | Position = 0, 7 | Mandatory, 8 | ValueFromPipeline, 9 | HelpMessage = 'Specify the path to the .wsb file.' 10 | )] 11 | [ValidatePattern('\.wsb$')] 12 | [ValidateScript( { Test-Path $_ })] 13 | [ArgumentCompleter( { if (Test-Path $global:wsbConfigPath) { (Get-ChildItem $Global:wsbConfigPath).FullName } })] 14 | [String]$Path, 15 | 16 | [Parameter(HelpMessage = 'Only display metadata information.')] 17 | [Switch]$MetadataOnly 18 | ) 19 | 20 | Begin { 21 | Write-Verbose "[$((Get-Date).TimeOfDay) BEGIN ] Starting $($MyInvocation.MyCommand)" 22 | } #begin 23 | Process { 24 | 25 | $cPath = Convert-Path $Path 26 | Write-Verbose "Getting configuration from $cPath" 27 | 28 | [xml]$wsb = Get-Content -Path $cPath 29 | 30 | Write-Verbose 'Building property list' 31 | $properties = [System.Collections.Generic.List[object]]::new() 32 | $properties.AddRange($wsb.configuration.PSAdapted.PSObject.properties.name) 33 | if ($properties.Contains('LogonCommand')) { 34 | [void]($properties.Remove('LogonCommand')) 35 | $properties.Add(@{Name = 'LogonCommand'; Expression = { $wsb.configuration.logonCommand.Command } }) 36 | } 37 | if ($properties.Contains('MappedFolders')) { 38 | [void]($properties.Remove('MappedFolders')) 39 | $properties.Add(@{Name = 'MappedFolder'; Expression = { 40 | $wsb.Configuration.MappedFolders.MappedFolder | 41 | Select-Object *folder, @{Name = 'ReadOnly'; Expression = { if ($_.ReadOnly -eq 'True') { $True } else { $False } } } | 42 | New-WsbMappedFolder | New-WsbMappedFolder } 43 | }) 44 | } 45 | 46 | Write-Verbose 'Get metadata information' 47 | if ($wsb.configuration.metadata) { 48 | Write-Verbose 'Existing metadata found' 49 | $meta = [wsbMetadata]::new($wsb.Configuration.metadata.Name, $wsb.configuration.metadata.Description) 50 | $meta.updated = $wsb.configuration.metadata.updated 51 | $meta.author = $wsb.configuration.metadata.author 52 | } 53 | else { 54 | Write-Verbose 'Defining new metadata' 55 | $meta = [wsbMetadata]::new($cPath) 56 | $meta.updated = Get-Date 57 | } 58 | 59 | if ($MetadataOnly) { 60 | Write-Verbose 'Displaying metadata only' 61 | $meta 62 | } 63 | else { 64 | Write-Verbose 'Sending configuration to New-WsbConfiguration' 65 | $wsb.configuration | Select-Object -Property $properties | New-WsbConfiguration -metadata $meta 66 | Write-Verbose "Ending $($MyInvocation.MyCommand)" 67 | } 68 | } #process 69 | End { 70 | Write-Verbose "[$((Get-Date).TimeOfDay) END ] Ending $($MyInvocation.MyCommand)" 71 | } #end 72 | } 73 | -------------------------------------------------------------------------------- /functions/New-WsbConfiguration.ps1: -------------------------------------------------------------------------------- 1 | Function New-WsbConfiguration { 2 | [CmdletBinding(DefaultParameterSetName = "name")] 3 | [OutputType("wsbConfiguration")] 4 | Param( 5 | [Parameter(ValueFromPipelineByPropertyName)] 6 | [ValidateSet("Default", "Enable", "Disable")] 7 | [String]$vGPU = "Default", 8 | 9 | [Parameter(ValueFromPipelineByPropertyName)] 10 | [ValidateScript( { $_ -ge 1024 })] 11 | [String]$MemoryInMB = 4096, 12 | 13 | [Parameter(ValueFromPipelineByPropertyName)] 14 | [ValidateSet("Default", "Enable", "Disable")] 15 | [String]$AudioInput = "Default", 16 | 17 | [Parameter(ValueFromPipelineByPropertyName)] 18 | [ValidateSet("Default", "Enable", "Disable")] 19 | [String]$VideoInput = "Default", 20 | 21 | [Parameter(ValueFromPipelineByPropertyName)] 22 | [ValidateSet("Default", "Disable")] 23 | [String]$ClipboardRedirection = "Default", 24 | 25 | [Parameter(ValueFromPipelineByPropertyName)] 26 | [ValidateSet("Default", "Enable", "Disable")] 27 | [String]$PrinterRedirection = "Default", 28 | 29 | [Parameter(ValueFromPipelineByPropertyName)] 30 | [ValidateSet("Default", "Disable")] 31 | [String]$Networking = "Default", 32 | 33 | [Parameter(ValueFromPipelineByPropertyName)] 34 | [ValidateSet("Default", "Enable", "Disable")] 35 | [String]$ProtectedClient = "Default", 36 | 37 | [Parameter(ValueFromPipelineByPropertyName, HelpMessage = "The path and file are relative to the Windows Sandbox")] 38 | [object]$LogonCommand, 39 | 40 | [Parameter(ValueFromPipelineByPropertyName)] 41 | [wsbMappedFolder[]]$MappedFolder, 42 | 43 | [Parameter(ParameterSetName = "meta")] 44 | [wsbMetadata]$Metadata, 45 | 46 | [parameter(Mandatory, ParameterSetName = "name", HelpMessage = "Give the configuration a name")] 47 | [String]$Name, 48 | 49 | [parameter(ParameterSetName = "name", HelpMessage = "Provide a description")] 50 | [String]$Description, 51 | 52 | [parameter(ParameterSetName = "name", HelpMessage = "Who is the author?")] 53 | [String]$Author = $env:USERNAME 54 | ) 55 | 56 | Begin { 57 | Write-Verbose "[$((Get-Date).TimeOfDay) BEGIN] Starting $($MyInvocation.MyCommand)" 58 | $new = [wsbConfiguration]::new() 59 | } #begin 60 | Process { 61 | Write-Verbose "[$((Get-Date).TimeOfDay) PROCESS] Creating a configuration" 62 | Write-Verbose ($PSBoundParameters | Out-String) 63 | 64 | if ($logonCommand -is [String]) { 65 | $cmd = $LogonCommand 66 | } 67 | elseif ($logonCommand.Command) { 68 | $cmd = $logonCommand.Command 69 | } 70 | else { 71 | Write-Warning "No value detected for LogonCommand. This may be intentional on your part." 72 | $cmd = $Null 73 | } 74 | 75 | $new.vGPU = $vGPU 76 | $new.MemoryInMB = $MemoryInMB 77 | $new.AudioInput = $AudioInput 78 | $new.VideoInput = $VideoInput 79 | $new.ClipboardRedirection = $ClipboardRedirection 80 | $new.PrinterRedirection = $PrinterRedirection 81 | $new.Networking = $Networking 82 | $new.ProtectedClient = $ProtectedClient 83 | $new.LogonCommand = $cmd 84 | $new.MappedFolder = $MappedFolder 85 | 86 | if (-Not $metadata) { 87 | $metadata = [wsbMetadata]::new($Name, $Description) 88 | $metadata.author = $author 89 | $metadata.updated = Get-Date 90 | } 91 | 92 | Write-Verbose "[$((Get-Date).TimeOfDay) PROCESS] Setting metadata" 93 | $new.metadata = $metadata 94 | $new 95 | 96 | } #process 97 | End { 98 | Write-Verbose "[$((Get-Date).TimeOfDay) END ] Ending $($MyInvocation.MyCommand)" 99 | } #end 100 | } 101 | -------------------------------------------------------------------------------- /functions/New-WsbMappedFolder.ps1: -------------------------------------------------------------------------------- 1 | Function New-WsbMappedFolder { 2 | [CmdletBinding()] 3 | [OutputType("wsbMappedFolder")] 4 | Param( 5 | [Parameter(Position = 0, Mandatory, ValueFromPipelineByPropertyName, HelpMessage = "Specify the path to the local folder you want to map.")] 6 | [ValidateScript( { Test-Path $_ })] 7 | [String]$HostFolder, 8 | 9 | [Parameter(Position = 1, Mandatory, ValueFromPipelineByPropertyName, HelpMessage = "Specify the mapped folder for the Windows Sandbox. It must start with C:\")] 10 | [ValidateNotNullOrEmpty()] 11 | [ValidatePattern('^C:\\')] 12 | [String]$SandboxFolder, 13 | 14 | [Parameter(ValueFromPipelineByPropertyName, HelpMessage = "Specify if you want the mapping to be Read-Only.")] 15 | #[ValidateSet("True", "False")] 16 | [Switch]$ReadOnly 17 | ) 18 | 19 | Begin { 20 | Write-Verbose "[$((Get-Date).TimeOfDay) BEGIN] Starting $($MyInvocation.MyCommand)" 21 | } #begin 22 | Process { 23 | Write-Verbose "[$((Get-Date).TimeOfDay) PROCESS] Processing" 24 | 25 | [wsbMappedFolder]::New($HostFolder, $SandboxFolder, $ReadOnly) 26 | } #process 27 | End { 28 | Write-Verbose "[$((Get-Date).TimeOfDay) END ] Ending $($MyInvocation.MyCommand)" 29 | } #end 30 | } 31 | -------------------------------------------------------------------------------- /functions/Start-WindowsSandbox.ps1: -------------------------------------------------------------------------------- 1 | Function Start-WindowsSandbox { 2 | [CmdletBinding(SupportsShouldProcess, DefaultParameterSetName = "config")] 3 | [alias("wsb")] 4 | [OutputType("none")] 5 | 6 | Param( 7 | [Parameter(Position = 0, Mandatory, ParameterSetName = "config", HelpMessage = "Specify the path to a wsb file.")] 8 | [ValidateScript( { Test-Path $_ })] 9 | [ArgumentCompleter( { if (Test-Path $global:wsbConfigPath) { (Get-ChildItem $Global:wsbConfigPath).FullName } })] 10 | [String]$Configuration, 11 | 12 | [Parameter(ParameterSetName = "normal", HelpMessage = "Start with no customizations.")] 13 | [Switch]$NoSetup, 14 | 15 | [Parameter(HelpMessage = "Specify desktop resolutions as an array like 1280,720. The default is 1920,1080.")] 16 | [int[]]$WindowSize = @(1920, 1080) 17 | ) 18 | 19 | Write-Verbose "[$((Get-Date).TimeOfDay)] Starting $($MyInvocation.MyCommand)" 20 | 21 | #test if Windows Sandbox is already running 22 | $test = Get-Process -ErrorAction SilentlyContinue -Name WindowsSandbox* 23 | if ($test) { 24 | Write-Warning "An instance of Windows Sandbox is already running." 25 | #bail out 26 | return 27 | } 28 | if ($NoSetup) { 29 | Write-Verbose "[$((Get-Date).TimeOfDay)] Launching default WindowsSandbox.exe" 30 | if ($PSCmdlet.ShouldProcess("default configuration", "Launch Windows Sandbox")) { 31 | Start-Process -FilePath $env:windir\system32\WindowsSandbox.exe 32 | } 33 | } 34 | else { 35 | Write-Verbose "[$((Get-Date).TimeOfDay)] Launching WindowsSandbox using configuration file $Configuration" 36 | 37 | #TODO - Parameterize this behavior 38 | #create a file watcher if calling a configuration that uses it 39 | if ($Configuration -match "WinSandBx|presentation") { 40 | Write-Verbose "[$((Get-Date).TimeOfDay)] Registering a temporary file system watcher" 41 | <# 42 | Some configurations will create "flag" file in a shared folder to indicate 43 | the setup and configuration is complete. 44 | 45 | RegisterWatcher is a private function in this module 46 | #> 47 | # TODO : pass arguments to RegisterWatcher from this function ? 48 | [void](Register-Watcher) 49 | } 50 | 51 | if ($PSCmdlet.ShouldProcess($Configuration, "Launch Windows Sandbox")) { 52 | Start-Process -FilePath $Configuration 53 | } 54 | } 55 | 56 | #WindowsSandbox.exe launches a child process, WindowsSandboxClient. 57 | #That is the process that needs to be minimized 58 | if ($PSCmdlet.ShouldProcess("WindowsSandboxClient", "Waiting for process")) { 59 | 60 | Write-Verbose "[$((Get-Date).TimeOfDay)] Waiting for child process WindowsSandboxClient" 61 | do { 62 | Start-Sleep -Seconds 1 63 | } Until (Get-Process -Name WindowsSandboxClient -ErrorAction SilentlyContinue) 64 | 65 | #give the process a chance to complete 66 | Start-Sleep -Seconds 5 67 | } 68 | 69 | Write-Verbose "[$((Get-Date).TimeOfDay)] Setting Window size to $($WindowSize -join 'x')" 70 | if ($PSCmdlet.ShouldProcess("WindowsSandboxClient", "Modifying Window size and state")) { 71 | $clientProc = Get-Process -Name WindowsSandboxClient 72 | #values to pass to the function are a percentage of the desired size 73 | #TODO: figure out scaling in display resolution set to scale 74 | [Int]$width = $WindowSize[0] #* .6667 75 | [Int]$Height = $WindowSize[1] # * .6667 76 | Write-Verbose "[$((Get-Date).TimeOfDay)] Modifying handle $($clientproc.mainwindowhandle) with a width of $($WindowSize[0]) and height of $($WindowSize[1])" 77 | 78 | Set-WindowSize -handle $clientproc.MainWindowHandle -width $width -height $height 79 | 80 | #Configure the Windows Sandbox to run minimized (Issue #2) 81 | Write-Verbose "[$((Get-Date).TimeOfDay)] Minimizing child process WindowsSandboxClient" 82 | $clientProc | Set-WindowState -State minimize 83 | } 84 | 85 | if ($Configuration) { 86 | $wsb = Get-WsbConfiguration -Path $Configuration 87 | if ($wsb.LogonCommand) { 88 | Write-Verbose "[$((Get-Date).TimeOfDay)] Running logon command $($wsb.LogonCommand) in the Windows Sandbox." 89 | } 90 | 91 | if ($wsb.MappedFolder) { 92 | Write-Verbose "[$((Get-Date).TimeOfDay)] Mapping these folders" 93 | $wsb.MappedFolder | Out-String | Write-Verbose 94 | } 95 | } 96 | Write-Verbose "[$((Get-Date).TimeOfDay)] Ending $($MyInvocation.MyCommand)." 97 | 98 | Write-Host "[$((Get-Date).TimeOfDay)] Windows Sandbox has been launched. You may need to wait for any configurations to complete." -ForegroundColor green 99 | } 100 | -------------------------------------------------------------------------------- /functions/private.ps1: -------------------------------------------------------------------------------- 1 | 2 | Function Set-WindowSize { 3 | #from https://gist.github.com/coldnebo/1148334 4 | 5 | [CmdletBinding(SupportsShouldProcess)] 6 | Param( 7 | [Parameter( 8 | Position = 0, 9 | HelpMessage = "What is the MainWindowHandle?", 10 | ValueFromPipeline, 11 | ValueFromPipelineByPropertyName 12 | )] 13 | [ValidateNotNullOrEmpty()] 14 | [Alias("handle")] 15 | [System.IntPtr]$MainWindowHandle = (Get-Process -id $pid).MainWindowHandle, 16 | [Alias("x")] 17 | [Int]$Width = 1280, 18 | [Alias("y")] 19 | [Int]$Height = 720 20 | ) 21 | 22 | Begin { 23 | Write-Verbose "Starting $($MyInvocation.MyCommand)" 24 | Write-Verbose "Using a window width of $Width" 25 | Write-Verbose "Using a window Height of $height" 26 | Write-Verbose "Adding type code" 27 | 28 | Add-Type @" 29 | using System; 30 | using System.Runtime.InteropServices; 31 | 32 | public class Win32 { 33 | [DllImport("user32.dll")] 34 | [return: MarshalAs(UnmanagedType.Bool)] 35 | public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect); 36 | 37 | [DllImport("user32.dll")] 38 | [return: MarshalAs(UnmanagedType.Bool)] 39 | public static extern bool GetClientRect(IntPtr hWnd, out RECT lpRect); 40 | 41 | [DllImport("user32.dll")] 42 | [return: MarshalAs(UnmanagedType.Bool)] 43 | public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint); 44 | } 45 | 46 | public struct RECT 47 | { 48 | public int Left; // x position of upper-left corner 49 | public int Top; // y position of upper-left corner 50 | public int Right; // x position of lower-right corner 51 | public int Bottom; // y position of lower-right corner 52 | } 53 | 54 | "@ 55 | 56 | } #begin 57 | 58 | Process { 59 | 60 | #verify handle and get process 61 | Write-Verbose "Verifying process with MainWindowHandle of $MainWindowhandle" 62 | 63 | $proc = (Get-Process).where( { $_.mainwindowhandle -eq $MainWindowhandle }) 64 | 65 | if (-NOT $proc.mainwindowhandle) { 66 | Write-Warning "Failed to find a process with a MainWindowHandle of $MainWndowhandle" 67 | #bail out 68 | Return 69 | } 70 | 71 | Write-Verbose "Creating rectangle objects" 72 | $rcWindow = New-Object RECT 73 | $rcClient = New-Object RECT 74 | 75 | Write-Verbose "Getting current settings" 76 | [Win32]::GetWindowRect($MainWindowHandle, [ref]$rcWindow) | Out-Null 77 | [Win32]::GetClientRect($MainWindowHandle, [ref]$rcClient) | Out-Null 78 | Write-Verbose "rcWindow = $($rcWindow | Out-String)" 79 | Write-Verbose "rcClient = $($rcClient | Out-String)" 80 | Write-Verbose "Setting new coordinates" 81 | 82 | #WhatIf 83 | if ($PSCmdlet.ShouldProcess("$($proc.MainWindowTitle) to $width by $height")) { 84 | $dx = ($rcWindow.Right - $rcWindow.Left) - $rcClient.Right 85 | $dy = ($rcWindow.Bottom - $rcWindow.Top) - $rcClient.Bottom 86 | 87 | Write-Verbose "Moving window using dx = $dx and dy = $dy" 88 | 89 | [void]([Win32]::MoveWindow($MainWindowHandle, 0, 0, $width + $dx, $height + $dy, $true )) 90 | 91 | } #close WhatIf 92 | 93 | } #process 94 | 95 | End { 96 | Write-Verbose "Ending $($MyInvocation.MyCommand)" 97 | } #end 98 | 99 | } #end Set-WindowSize function 100 | 101 | function Set-WindowState { 102 | <# 103 | .LINK 104 | https://gist.github.com/Nora-Ballard/11240204 105 | #> 106 | 107 | [CmdletBinding(DefaultParameterSetName = 'InputObject')] 108 | param( 109 | [Parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true)] 110 | [Object[]] $InputObject, 111 | 112 | [Parameter(Position = 1)] 113 | [ValidateSet('FORCEMINIMIZE', 'HIDE', 'MAXIMIZE', 'MINIMIZE', 'RESTORE', 114 | 'SHOW', 'SHOWDEFAULT', 'SHOWMAXIMIZED', 'SHOWMINIMIZED', 115 | 'SHOWMINNOACTIVE', 'SHOWNA', 'SHOWNOACTIVATE', 'SHOWNORMAL')] 116 | [String] $State = 'SHOW' 117 | ) 118 | 119 | Begin { 120 | $WindowStates = @{ 121 | 'FORCEMINIMIZE' = 11 122 | 'HIDE' = 0 123 | 'MAXIMIZE' = 3 124 | 'MINIMIZE' = 6 125 | 'RESTORE' = 9 126 | 'SHOW' = 5 127 | 'SHOWDEFAULT' = 10 128 | 'SHOWMAXIMIZED' = 3 129 | 'SHOWMINIMIZED' = 2 130 | 'SHOWMINNOACTIVE' = 7 131 | 'SHOWNA' = 8 132 | 'SHOWNOACTIVATE' = 4 133 | 'SHOWNORMAL' = 1 134 | } 135 | 136 | $Win32ShowWindowAsync = Add-Type -MemberDefinition @' 137 | [DllImport("user32.dll")] 138 | public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow); 139 | '@ -Name "Win32ShowWindowAsync" -Namespace Win32Functions -PassThru 140 | 141 | if (!$global:MainWindowHandles) { 142 | $global:MainWindowHandles = @{ } 143 | } 144 | } 145 | 146 | Process { 147 | foreach ($process in $InputObject) { 148 | if ($process.MainWindowHandle -eq 0) { 149 | if ($global:MainWindowHandles.ContainsKey($process.Id)) { 150 | $handle = $global:MainWindowHandles[$process.Id] 151 | } 152 | else { 153 | Write-Error "Main Window handle is '0'" 154 | continue 155 | } 156 | } 157 | else { 158 | $handle = $process.MainWindowHandle 159 | $global:MainWindowHandles[$process.Id] = $handle 160 | } 161 | 162 | $Win32ShowWindowAsync::ShowWindowAsync($handle, $WindowStates[$State]) | Out-Null 163 | Write-Verbose ("Set Window State '{1} on '{0}'" -f $MainWindowHandle, $State) 164 | } 165 | } 166 | } 167 | 168 | Function Register-Watcher { 169 | [CmdletBinding(SupportsShouldProcess)] 170 | Param( 171 | [Parameter(HelpMessage = "Enter the full filename and path to the flag file. The file will be created in the sandbox in a shared folder.")] 172 | [ValidateNotNullOrEmpty()] 173 | [String]$Flag = "C:\scripts\sandbox.flag", 174 | [Parameter(HelpMessage = "Enter the title for the toast notification.")] 175 | [String]$Title = "Windows Sandbox", 176 | [Parameter(HelpMessage = "Enter the path to an image file for the toast notification.")] 177 | [ValidateScript( { Test-Path $_ })] 178 | [String]$Logo = "$PSScriptRoot\..\images\sandbox.jpg", 179 | [Parameter(HelpMessage = "Specify the sound to play for the toast notification.")] 180 | [ValidateSet('Default', 'IM', 'Mail', 'Reminder', 'SMS', 'Alarm', 'Alarm2', 'Alarm3', 181 | 'Alarm4', 'Alarm5', 'Alarm6', 'Alarm7', 'Alarm8', 'Alarm9', 'Alarm10', 'Call', 182 | 'Call2', 'Call3', 'Call4', 'Call5', 'Call6', 'Call7', 'Call8', 'Call9', 'Call10', 183 | 'None' 184 | )] 185 | [String]$Sound = "Call10" 186 | ) 187 | 188 | #the event subscriber identifier 189 | $SourceID = "WatchWSB" 190 | 191 | if (Test-Path -Path $flag) { 192 | Remove-Item $flag 193 | } 194 | 195 | #check for any left over event subscribers and remove them so we start clean 196 | Try { 197 | $sub = Get-EventSubscriber -SourceIdentifier $SourceID -ErrorAction Stop 198 | $sub | Unregister-Event 199 | } 200 | Catch { 201 | #ignore errors because it means the event subscriber doesn't exist 202 | } 203 | 204 | $rFlag = $flag.replace("\", "\\") 205 | $query = "Select * from __InstanceCreationEvent Within 10 where TargetInstance ISA 'CIM_DATAFILE' AND TargetInstance.Name='$rflag'" 206 | 207 | #define the action scriptblock text 208 | $sb = @" 209 | `$params = @{ 210 | Text = "Your Windows Sandbox is ready." 211 | Header = `$(New-BTHeader -Id 1 -Title "$Title") 212 | Applogo = "$logo" 213 | Sound = "$sound" 214 | } 215 | 216 | New-BurntToastNotification @params 217 | Start-Sleep -Seconds 10 218 | Try { 219 | Unregister-Event WatchWSB -erroraction stop 220 | } 221 | Catch { 222 | #don't do anything 223 | } 224 | if (Test-Path $flag) { 225 | Remove-Item $Flag 226 | } 227 | "@ 228 | 229 | $action = [scriptblock]::Create($sb) 230 | 231 | if ($PSCmdlet.ShouldProcess($query, "Register Event")) { 232 | Register-CimIndicationEvent -query $query -source $SourceID -Action $action 233 | } #WhatIf 234 | } 235 | -------------------------------------------------------------------------------- /images/db.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jdhitsolutions/WindowsSandboxTools/9f2a0b71140b293c5769b939aac4899d26a1503b/images/db.png -------------------------------------------------------------------------------- /images/gazoo.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jdhitsolutions/WindowsSandboxTools/9f2a0b71140b293c5769b939aac4899d26a1503b/images/gazoo.bmp -------------------------------------------------------------------------------- /images/sandbox.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jdhitsolutions/WindowsSandboxTools/9f2a0b71140b293c5769b939aac4899d26a1503b/images/sandbox.jpg -------------------------------------------------------------------------------- /images/start-windowssandbox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jdhitsolutions/WindowsSandboxTools/9f2a0b71140b293c5769b939aac4899d26a1503b/images/start-windowssandbox.png -------------------------------------------------------------------------------- /wsbScripts/Install-VSCodeSandbox.ps1: -------------------------------------------------------------------------------- 1 | #Install-VSCodeSandbox.ps1 2 | 3 | <# 4 | This script will download and install the most current x64 version of VS Code 5 | and install the PowerShell extension 6 | #> 7 | 8 | $file = Join-Path -Path $env:temp -ChildPath 'VSCodeSetup-x64.exe' 9 | Invoke-WebRequest -Uri "https://update.code.visualstudio.com/latest/win32-x64-user/stable" -OutFile $file -DisableKeepAlive -UseBasicParsing 10 | 11 | $loadInf = '@ 12 | [Setup] 13 | Lang=english 14 | Dir=C:\Program Files\Microsoft VS Code 15 | Group=Visual Studio Code 16 | NoIcons=0 17 | Tasks=desktopicon,addcontextmenufiles,addcontextmenufolders,addtopath 18 | @' 19 | 20 | $infPath = Join-Path -path $env:TEMP -child load.inf 21 | $loadInf | Out-File $infPath 22 | 23 | Start-Process -FilePath $file -ArgumentList "/VERYSILENT /LOADINF=${infPath}" -Wait 24 | 25 | #add extensions 26 | Start-Process -FilePath "C:\Program Files\Microsoft VS Code\bin\code.cmd" -ArgumentList "--install-extension ms-vscode.PowerShell" 27 | 28 | if (Test-Path Function:\log) { 29 | log "VSCode Setup Complete" 30 | } 31 | -------------------------------------------------------------------------------- /wsbScripts/README.md: -------------------------------------------------------------------------------- 1 | # wsbScripts 2 | 3 | The files in this folder can be called from the WSB files. These files are offered as samples of what you might do. This location is referenced by default with the `wsbScripts` variable when you import the module. It is recommended that you create a location outside of this module and copy any of these files to that location. In your PowerShell profile, you can import the module and then update the global variable. 4 | 5 | ```powershell 6 | Import-Module WindowsSandboxTools 7 | $global:wsbScripts = "d:\wsb\code" 8 | ``` 9 | 10 | Most of these scripts are intended to be run *IN* the Windows Sandbox, so any paths must be relative to the sandbox. 11 | -------------------------------------------------------------------------------- /wsbScripts/Set-SandboxDesktop.ps1: -------------------------------------------------------------------------------- 1 | # Set-SandboxDesktop.ps1 2 | # my Pluralsight-related configuration 3 | 4 | function Update-Wallpaper { 5 | [CmdletBinding(SupportsShouldProcess)] 6 | Param( 7 | [Parameter(Position = 0, HelpMessage = "The path to the wallpaper file.")] 8 | [alias("wallpaper")] 9 | [ValidateScript( { Test-Path $_ })] 10 | [String]$Path = $(Get-ItemPropertyValue -Path 'hkcu:\Control Panel\Desktop\' -Name Wallpaper) 11 | ) 12 | 13 | Add-Type @" 14 | 15 | using System; 16 | using System.Runtime.InteropServices; 17 | using Microsoft.Win32; 18 | 19 | namespace Wallpaper 20 | { 21 | public class UpdateImage 22 | { 23 | [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] 24 | 25 | private static extern int SystemParametersInfo (int uAction, int uParam, string lpvParam, int fuWinIni); 26 | 27 | public static void Refresh(string path) 28 | { 29 | SystemParametersInfo( 20, 0, path, 0x01 | 0x02 ); 30 | } 31 | } 32 | } 33 | "@ 34 | 35 | if ($PSCmdlet.ShouldProcess($path)) { 36 | [Wallpaper.UpdateImage]::Refresh($Path) 37 | } 38 | } 39 | 40 | Function Restart-Explorer { 41 | <# 42 | .Synopsis 43 | Restart the Windows Explorer process. 44 | #> 45 | [CmdletBinding(SupportsShouldProcess)] 46 | [OutputType("None")] 47 | Param() 48 | 49 | Write-Verbose "[$((Get-Date).TimeOfDay) BEGIN ] Starting $($MyInvocation.MyCommand)" 50 | Write-Verbose "[$((Get-Date).TimeOfDay) BEGIN ] Stopping Explorer.exe process" 51 | Get-Process -Name Explorer | Stop-Process -Force 52 | #give the process time to start 53 | Start-Sleep -Seconds 2 54 | Try { 55 | Write-Verbose "[$((Get-Date).TimeOfDay) BEGIN ] Verifying Explorer restarted" 56 | $p = Get-Process -Name Explorer -ErrorAction stop 57 | } 58 | Catch { 59 | Write-Warning "Manually restarting Explorer" 60 | Try { 61 | Start-Process explorer.exe 62 | } 63 | Catch { 64 | #this should never be called 65 | Throw $_ 66 | } 67 | } 68 | Write-Verbose "[$((Get-Date).TimeOfDay) END ] Ending $($MyInvocation.MyCommand)" 69 | } 70 | 71 | #configure the taskbar and hide icons 72 | 73 | <# if (-not (Test-Path -Path hkcu:\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer)) { 74 | [void](New-Item -Path hkcu:\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer) 75 | } #> 76 | 77 | Set-ItemProperty -Path hkcu:\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer\ -Name HideClock -Value 1 -force 78 | Set-ItemProperty -Path hkcu:\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer\ -Name HideSCAVolume -Value 1 -force 79 | Set-ItemProperty -Path hkcu:\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer\ -Name HideSCANetwork -Value 1 -force 80 | 81 | #hide news feed 82 | Set-ItemProperty -path hkcu:\SOFTWARE\Microsoft\Windows\CurrentVersion\Feeds\ -name ShellFeedsTaskBarViewMode -Value 2 -force 83 | 84 | <# if (-not (Test-Path -Path hkcu:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced)) { 85 | [void](New-Item -Path hkcu:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced) 86 | } #> 87 | 88 | Set-ItemProperty -Path hkcu:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced -Name HideIcons -Value 1 -force 89 | 90 | Write-Host "set wallpaper" -ForegroundColor cyan 91 | #configure wallpaper 92 | Set-ItemProperty -Path 'hkcu:\Control Panel\Desktop\' -Name Wallpaper -Value C:\Pluralsight\Wallpaper\Pluralsight_Wallpaper_Fall_2015_Black.jpg 93 | Set-ItemProperty -Path 'hkcu:\Control Panel\Desktop\' -Name WallpaperOriginX -Value 0 94 | Set-ItemProperty -Path 'hkcu:\Control Panel\Desktop\' -Name WallpaperOriginY -Value 0 95 | Set-ItemProperty -Path 'hkcu:\Control Panel\Desktop\' -Name WallpaperStyle -Value 10 96 | 97 | Update-WallPaper 98 | 99 | <# 100 | This doesn't work completely in newer versions of Windows 10 101 | Invoke-Command {c:\windows\System32\RUNDLL32.EXE user32.dll,UpdatePerUserSystemParameters 1,True} 102 | #this is a bit harsh but it works 103 | #> 104 | 105 | Restart-Explorer 106 | 107 | if (Test-Path function:\log) { 108 | log "Desktop configuration complete" 109 | } 110 | -------------------------------------------------------------------------------- /wsbScripts/basic.ps1: -------------------------------------------------------------------------------- 1 | Enable-PSRemoting -Force -SkipNetworkProfileCheck 2 | Set-DnsClientServerAddress -ServerAddresses 1.1.1.1 -InterfaceAlias Ethernet 3 | Install-PackageProvider -Name nuget -force -ForceBootstrap -MinimumVersion '2.8.5.201' -Scope AllUsers 4 | Install-Module PSScriptTools,BurntToast -force 5 | New-BurntToastNotification -Text "Basic sandbox setup complete." -------------------------------------------------------------------------------- /wsbScripts/demo-config.ps1: -------------------------------------------------------------------------------- 1 | #this script runs IN the Windows Sandbox 2 | 3 | $logParams = @{ 4 | Filepath = "C:\log\setup.txt" 5 | Append = $True 6 | } 7 | 8 | "[$(Get-Date)] Starting $($MyInvocation.MyCommand)" | Out-File @logParams 9 | 10 | "[$(Get-Date)] Enabling PSRemoting" | Out-File @logParams 11 | Enable-PSRemoting -Force -SkipNetworkProfileCheck 12 | 13 | "[$(Get-Date)] Set DNS Server to 1.1.1.1" | Out-File @logParams 14 | Set-DnsClientServerAddress -InterfaceIndex (Get-NetAdapter).ifIndex -ServerAddresses 1.1.1.1 15 | 16 | "[$(Get-Date)] Install latest nuget package provider" | Out-File @logParams 17 | Install-PackageProvider -name nuget -force -forcebootstrap -scope allusers 18 | 19 | "[$(Get-Date)] Update PackageManagement and PowerShellGet modules" | Out-File @logParams 20 | Install-Module PackageManagement, PowerShellGet -Force 21 | 22 | #run remaining commands in parallel background jobs 23 | "[$(Get-Date)] Update help" | Out-File @logParams 24 | Start-Job -Name "Help-Update" -ScriptBlock { Update-Help -Force } 25 | 26 | "[$(Get-Date)] Installing default modules" | Out-File @logParams 27 | Start-Job -Name "Module-Install" -ScriptBlock { Install-Module PSScriptTools, BurntToast -Force } 28 | 29 | "[$(Get-Date)] Install Windows Terminal" | Out-File @logParams 30 | Start-Job -Name "Windows-Terminal" -ScriptBlock { Install-Module WTToolbox -Force ; Install-WTRelease } 31 | 32 | #wait for everything to finish 33 | "[$(Get-Date)] Waiting for jobs to finish" | Out-File @logParams 34 | Get-Job | Wait-Job 35 | 36 | foreach ($job in (Get-Job)) { 37 | $result = "Job {0} {1} [{2}]" -f $job.name, $job.state, (New-TimeSpan -Start $job.PSBeginTime -End $job.PSEndTime) 38 | "[$(Get-Date)] $result" | Out-File @logParams 39 | } 40 | 41 | "[$(Get-Date)] Starting Windows Terminal" | Out-File @logParams 42 | Start-Process wt.exe "-M new-tab -d C:\ -p Windows PowerShell" 43 | 44 | "[$(Get-Date)] Setting the host notification flag" | Out-File @logParams 45 | Get-Date | Out-File -FilePath c:\scripts\sandbox.flag 46 | 47 | "[$(Get-Date)] Sending toast notification in the Windows Sandbox" | Out-File @logParams 48 | 49 | $params = @{ 50 | Text = "Windows Sandbox configuration is complete." 51 | Header = $(New-BTHeader -Id 1 -Title "Your Sandbox") 52 | Silent = $True 53 | } 54 | 55 | New-BurntToastNotification @params 56 | -------------------------------------------------------------------------------- /wsbScripts/demo.cmd: -------------------------------------------------------------------------------- 1 | REM demo.cmd 2 | REM This code runs in the context of the Windows Sandbox 3 | mkdir c:\log 4 | 5 | REM set execution policy first so that a setup script can be run 6 | powershell.exe -command "&{ Set-ExecutionPolicy RemoteSigned -force }" 7 | 8 | REM Now run the true configuration script 9 | REM C:\Scripts has been mapped to the local C:\Scripts in the WSB file 10 | powershell.exe -file c:\scripts\demo-config.ps1 -------------------------------------------------------------------------------- /wsbScripts/sandbox-basic.cmd: -------------------------------------------------------------------------------- 1 | REM sandbox-basic.cmd 2 | REM This code runs in the context of the Windows Sandbox 3 | 4 | REM set execution policy first so that a setup script can be run 5 | powershell.exe -command "&{Set-ExecutionPolicy RemoteSigned -force}" 6 | 7 | REM Add an all users all hosts profile script 8 | powershell.exe -command "&{'[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12' | out-file C:\Windows\System32\WindowsPowerShell\v1.0\profile.ps1 }" 9 | 10 | REM Now run the true configuration script 11 | REM C:\Scripts has been mapped to the local C:\Scripts in the WSB file 12 | powershell.exe -file c:\scripts\wsbScripts\basic.ps1 -------------------------------------------------------------------------------- /wsbScripts/sandbox-config-pluralsight.ps1: -------------------------------------------------------------------------------- 1 | #this script runs IN the Windows Sandbox under Windows PowerShell 5.1 2 | 3 | $SetupPath = "C:\scripts\wsbScripts" 4 | 5 | #create a log file of the configuration process. 6 | Function log { 7 | Param( 8 | [String]$msg, 9 | [String]$log = "C:\work\wsblog.txt" 10 | ) 11 | 12 | "[{0}] {1}" -f (Get-Date), $msg | Out-File -FilePath $log -Encoding ascii -Append 13 | } 14 | 15 | log "Install package provider" 16 | Install-PackageProvider -name nuget -force -forcebootstrap -scope allusers 17 | 18 | log "Updating package management" 19 | Install-Module PackageManagement, PowerShellGet, PSReadLine, WTToolbox -Force 20 | 21 | #run updates and installs in the background 22 | log "Updating Windows PowerShell Help" 23 | Start-Job { PowerShell -command { Update-Help -Force } } 24 | log "Installing default modules: PSScriptTools, PSTeachingTools, BurntToast" 25 | Start-Job { Install-Module PSScriptTools, PSTeachingTools, BurntToast -Force } 26 | log "Installing PSReleaseTools and PowerShell 7.x" 27 | Start-Job { 28 | $msi = (Get-Item C:\shared\PowerShell-7.1*msi).FullName 29 | Start-Process -FilePath $msi -ArgumentList "/quiet REGISTER_MANIFEST=1 ADD_PATH=1 ENABLE_PSREMOTING=1 ADD_EXPLORER_CONTEXT_MENU_OPENPowerShell=1 ADD_FILE_CONTEXT_MENU_RUNPowerShell=1" -Wait 30 | 31 | #update help 32 | C:\Program` Files\PowerShell\7\pwsh.exe -command { Update-Help -Force } 33 | 34 | #copy profile 35 | $myprofile = "C:\Pluralsight\Pluralsight-psprofile.ps1" 36 | 37 | Copy-Item -Path $myprofile -Destination 'C:\Program Files\PowerShell\7\profile.ps1' 38 | Install-Module Microsoft.PowerShell.ConsoleGuiTools -force 39 | } 40 | 41 | log "Installing Applications" 42 | Start-Job { 43 | Add-AppxPackage -Path c:\pluralsight\PowerpointViewer.appx 44 | C:\scripts\Download-Winget.ps1 -install -AddPrequisites 45 | # winget install git 46 | winget install microsoft.edge 47 | winget install Microsoft.WindowsTerminal 48 | } 49 | 50 | #set DNS 51 | Set-DnsClientServerAddress -InterfaceIndex (Get-NetAdapter).ifIndex -ServerAddresses 1.1.1.1 52 | 53 | <# log "Hiding tray icons" 54 | Start-Job { 55 | if (-not (Test-Path -path hkcu:\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer)) { 56 | [void](New-Item -path hkcu:\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer) 57 | } 58 | Set-ItemProperty -path hkcu:\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer\ -Name HideClock -Value 1 59 | Set-ItemProperty -path hkcu:\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer\ -Name HideSCAVolume -Value 1 60 | Set-ItemProperty -path hkcu:\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer\ -Name HideSCANetwork -Value 1 61 | if (-not (Test-Path -path hkcu:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced)) { 62 | [void](New-Item -path hkcu:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced) 63 | } 64 | 65 | Set-ItemProperty -path hkcu:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced -Name HideIcons -Value 1 66 | 67 | 68 | } #> 69 | 70 | log "Installing fonts" 71 | Start-Job { 72 | $FontSource = "C:\Pluralsight\1 INSTALL FONTS" 73 | $shell = New-Object -ComObject Shell.Application -ErrorAction stop 74 | $fontFolder = $shell.Namespace(0x14) 75 | #find already installed font files from the registry 76 | $installedfiles = @() 77 | $regLocation = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts" 78 | 79 | if (Test-Path $reglocation) { 80 | $props = (Get-Item $regLocation).property 81 | if ($props) { 82 | $installedfiles += Get-ItemPropertyValue -Path $reglocation -Name $props 83 | } 84 | } 85 | else { 86 | Write-Warning "$reglocation not found. This is OK." 87 | } 88 | $reguser = 'HKCU:\Software\Microsoft\Windows NT\CurrentVersion\Fonts' 89 | $props = (Get-Item $reguser).property 90 | if ($props) { 91 | Write-Host "Adding $($props.count) user installed fonts" 92 | $installedfiles += Get-ItemPropertyValue -Path $reguser -Name $props | Split-Path -Leaf 93 | } 94 | 95 | Get-ChildItem -Path $Fontsource -File | ForEach-Object { 96 | #Write-Host "Testing $($_.name)" 97 | if ($installedFiles -notcontains $_.name) { 98 | Write-Host "installing $($_.name) from $($_.FullName)" -ForegroundColor green 99 | $fontFolder.copyHere($_.FullName) 100 | } 101 | else { 102 | Write-Host "$($_.name) already installed" -ForegroundColor yellow 103 | } 104 | } #foreach 105 | } 106 | 107 | log "Configure desktop" 108 | Start-Job { 109 | Write-Host "Copy a default profile for all users all hosts" -ForegroundColor cyan 110 | $myprofile = "C:\Pluralsight\Pluralsight-psprofile.ps1" 111 | #Windows PowerShell 112 | Copy-Item -Path $myprofile -Destination 'C:\Windows\System32\WindowsPowerShell\v1.0\profile.ps1' 113 | 114 | Write-Host "Configure Trusted Hosts" -ForegroundColor Cyan 115 | Set-Item WSMan:\localhost\Client\TrustedHosts -Value "prospero" -Force -PassThru 116 | 117 | Write-Host "add cmdkey entry for host" -ForegroundColor Cyan 118 | cmdkey /add:Prospero /user:Jeff /pass:Beth2005 119 | 120 | #run configure desktop script 121 | C:\scripts\wsbscripts\Set-SandboxDesktop.ps1 122 | 123 | #hide the search box 124 | Set-ItemProperty -Path HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Search -Name SearchBoxTaskbarMode -Value 0 -Type DWord -Force 125 | 126 | Write-Host "auto-hide the Taskbar" -ForegroundColor cyan 127 | . C:\scripts\TaskbarTools.ps1 128 | #this will force a restart of Explorer 129 | Enable-AutoHideTaskBar 130 | 131 | } 132 | 133 | #wait for everything to finish 134 | log "Waiting for background jobs to complete" 135 | Get-Job | Out-String | Out-File "C:\work\wsblog.txt" -Encoding ascii -Append 136 | Get-Job | Wait-Job 137 | #Get-Job | Receive-Job | Out-File "C:\work\wsblog.txt" -Encoding ascii -append 138 | 139 | #reset Explorer so that registry changes take 140 | #log "Resetting Explorer" 141 | #Get-Process Explorer | Stop-Process 142 | 143 | log "Start Windows Terminal" 144 | wt.exe 145 | Start-Sleep -Seconds 5 146 | log "Copy Windows Terminal settings" 147 | Copy-Item -Path c:\shared\settings.json -Destination C:\Users\WDAGUtilityAccount\AppData\Local\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json -Force 148 | 149 | #log "Set the flag on the host" 150 | #Get-Date | Out-File -FilePath c:\scripts\sandbox.flag 151 | 152 | log "Ending configuration script" 153 | log "Sending toast notification in the Windows Sandbox" 154 | &(Join-Path -Path $SetupPath -ChildPath sandbox-toast.ps1) 155 | 156 | #Start-Sleep -Seconds 30 157 | #Remove-Item c:\scripts\sandbox.flag 158 | -------------------------------------------------------------------------------- /wsbScripts/sandbox-config-presentation.ps1: -------------------------------------------------------------------------------- 1 | #this script runs IN the Windows Sandbox 2 | 3 | $SetupPath = "C:\scripts\wsbScripts" 4 | 5 | #create a log file of the configuration process. 6 | Function log { 7 | Param( 8 | [String]$msg, 9 | [String]$log = "C:\work\wsblog.txt" 10 | ) 11 | 12 | "[{0}] {1}" -f (Get-Date), $msg | Out-File -FilePath $log -Encoding ascii -Append 13 | } 14 | 15 | log "Updating package management" 16 | Install-Module PackageManagement, PowerShellGet -Force 17 | 18 | #run updates and installs in the background 19 | log "Updating Windows PowerShell Help" 20 | Start-Job { PowerShell -command { Update-Help -Force } } 21 | log "Installing default modules: PSScriptTools, PSTypeExtensionTools,PSTeachingTools, BurntToast" 22 | Start-Job { Install-Module PSScriptTools, PSTeachingTools, PSTypeExtensionTools, BurntToast -Force } 23 | log "Installing PSReleaseTools and PowerShell 7 + Preview" 24 | Start-Job { 25 | Install-Module PSReleaseTools -Force 26 | Install-PowerShell -Mode quiet -EnableRemoting -EnableContextMenu 27 | Install-PSPreview -Mode quiet -EnableRemoting -EnableContextMenu 28 | #update help 29 | C:\Program` Files\PowerShell\7\pwsh.exe -command { Update-Help -Force } 30 | } 31 | log "Installing Windows Terminal" 32 | start-job { 33 | Install-module WTToolbox -force 34 | Install-WindowsTerminal 35 | } 36 | 37 | log "Installing PowerPoint Mobile" 38 | Start-Job { Add-AppxPackage -Path c:\shared\PowerpointViewer.appx } 39 | 40 | log "Installing Applications" 41 | Start-Job { 42 | Function log { 43 | Param( 44 | [String]$msg, 45 | [String]$log = "C:\work\wsblog.txt" 46 | ) 47 | 48 | "[{0}] {1}" -f (Get-Date), $msg | Out-File -FilePath $log -Encoding ascii -Append 49 | } 50 | Add-AppxPackage -Path c:\pluralsight\PowerpointViewer.appx 51 | C:\scripts\Download-Winget.ps1 -install -AddPrequisites 52 | if (Get-Command winget) { 53 | log "Installing Git" 54 | winget install git.git 55 | log "Installing VSCode" 56 | winget install Microsoft.visualStudioCode 57 | log "Configuring VSCode" 58 | &'C:\Users\WDAGUtilityAccount\AppData\Local\Programs\Microsoft VS Code\bin\code.cmd' --install-extension ms-vscode.PowerShell 59 | &'C:\Users\WDAGUtilityAccount\AppData\Local\Programs\Microsoft VS Code\bin\code.cmd' --install-extension CoenraadS.bracket-pair-colorizer-2 60 | &'C:\Users\WDAGUtilityAccount\AppData\Local\Programs\Microsoft VS Code\bin\code.cmd' --install-extension TylerLeonhardt.vscode-inline-values-PowerShell 61 | Copy-item -path C:\shared\vscode-settings.json -Destination "c:\Users\WDAGUtilityAccount\AppData\Roaming\Code\User\settings.json" 62 | 63 | Log "Installing Edge" 64 | winget install microsoft.edge 65 | # 8/16/2021 Winget is failing to install this 66 | #Log "Installing Windows Terminal" 67 | 3winget install Microsoft.WindowsTerminal 68 | } 69 | 70 | else { 71 | log "winget not found" 72 | } 73 | } 74 | 75 | #set DNS 76 | log "Configure DNS to 1.1.1.1" 77 | Set-DnsClientServerAddress -InterfaceIndex (Get-NetAdapter).ifIndex -ServerAddresses 1.1.1.1 78 | 79 | #these settings appear to be different for Windows 11 80 | log "Hiding tray icons" 81 | Start-Job { 82 | if (-not (Test-Path -Path hkcu:\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer)) { 83 | [void](New-Item -Path hkcu:\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer) 84 | } 85 | Set-ItemProperty -Path hkcu:\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer\ -Name HideClock -Value 1 86 | Set-ItemProperty -Path hkcu:\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer\ -Name HideSCAVolume -Value 1 87 | Set-ItemProperty -Path hkcu:\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer\ -Name HideSCANetwork -Value 1 88 | if (-not (Test-Path -Path hkcu:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced)) { 89 | [void](New-Item -Path hkcu:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced) 90 | } 91 | 92 | Set-ItemProperty -Path hkcu:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced -Name HideIcons -Value 1 93 | } 94 | #wait for everything to finish 95 | log "Waiting for background jobs to complete" 96 | Get-Job | Wait-Job 97 | 98 | #reset Explorer so that registry changes take 99 | log "Resetting Explorer" 100 | Get-Process Explorer | Stop-Process 101 | 102 | log "Sending toast notification in the Windows Sandbox" 103 | &(Join-Path -Path $SetupPath -ChildPath sandbox-toast.ps1) 104 | 105 | #set the flag on the host 106 | Get-Date | Out-File -FilePath c:\scripts\sandbox.flag 107 | 108 | log "Ending configuration script" 109 | -------------------------------------------------------------------------------- /wsbScripts/sandbox-config.ps1: -------------------------------------------------------------------------------- 1 | #this script runs IN the Windows Sandbox 2 | 3 | $SetupPath = "C:\scripts\wsbScripts" 4 | 5 | #create a log file of the configuration process. 6 | Function log { 7 | Param( 8 | [String]$msg, 9 | [String]$log = "C:\work\wsblog.txt" 10 | ) 11 | 12 | "[{0}] {1}" -f (Get-Date), $msg | Out-File -FilePath $log -Encoding ascii -Append 13 | } 14 | 15 | #add the logging function to each background job 16 | $init = { 17 | Function log { 18 | Param( 19 | [String]$msg, 20 | [String]$log = "C:\work\wsblog.txt" 21 | ) 22 | 23 | "[{0}] {1}" -f (Get-Date), $msg | Out-File -FilePath $log -Encoding ascii -Append 24 | } 25 | } 26 | 27 | #using splatting to pass this parameter. Using PSDefaultParameterValues failed for some reason. 28 | $jobparams = @{InitializationScript = $init} 29 | 30 | $begin = Get-Date 31 | log "Starting Windows Sandbox configuration $($MyInvocation.MyCommand)" 32 | log "Enabling PowerShell remoting" 33 | Enable-PSRemoting -Force -SkipNetworkProfileCheck 34 | 35 | log "Install package provider" 36 | Install-PackageProvider -name nuget -force -forcebootstrap -scope allusers 37 | 38 | log "Updating package management" 39 | Install-Module PackageManagement, PowerShellGet,PSReadLine -Force 40 | 41 | #run updates and installs in the background 42 | log "Setting DNS server to 1.1.1.1" 43 | Set-DnsClientServerAddress -InterfaceIndex (Get-NetAdapter).ifIndex -ServerAddresses 1.1.1.1 44 | 45 | log "Installing VSCode" 46 | Start-Job -name VSCode -FilePath (Join-Path -Path $SetupPath -ChildPath Install-vscodesandbox.ps1) @jobparams 47 | 48 | log "Updating Windows PowerShell Help" 49 | #Start-Job -ScriptBlock { PowerShell -command { Update-Help -Force } ; log "Help updated" } @jobparams 50 | Start-Job -name "Help-Update" -ScriptBlock { Update-Help -Force ; log "Help updated" } @jobparams 51 | 52 | log "Installing default modules: PSScriptTools, PSTeachingTools, BurntToast" 53 | Start-Job -name "Module-Install" -ScriptBlock { 54 | Install-Module PSScriptTools, PSTeachingTools, BurntToast -Force ; 55 | log "PowerShell modules installed" } @jobparams 56 | 57 | log "Installing PSReleaseTools and PowerShell 7 + Preview" 58 | Start-Job -name "PS7-Install" -ScriptBlock { 59 | Install-Module PSReleaseTools -Force 60 | $msi = (Get-Item C:\shared\PowerShell-7.1*.msi).FullName 61 | Start-Process -FilePath $msi -ArgumentList "/quiet REGISTER_MANIFEST=1 ADD_PATH=1 ENABLE_PSREMOTING=1 ADD_EXPLORER_CONTEXT_MENU_OPENPowerShell=1 ADD_FILE_CONTEXT_MENU_RUNPowerShell=1" 62 | $msi = (Get-Item C:\shared\PowerShell-7*preview*.msi).FullName 63 | Start-Process -FilePath $msi -ArgumentList "/quiet REGISTER_MANIFEST=1 ADD_PATH=1 ENABLE_PSREMOTING=1 ADD_EXPLORER_CONTEXT_MENU_OPENPowerShell=1 ADD_FILE_CONTEXT_MENU_RUNPowerShell=1" 64 | 65 | #Install-PowerShell -Mode quiet -EnableRemoting -EnableContextMenu 66 | #Install-PSPreview -Mode quiet -EnableRemoting -EnableContextMenu 67 | #update help 68 | C:\Program` Files\PowerShell\7\pwsh.exe -command { Update-Help -Force } 69 | log "PowerShell 7 installed" 70 | } @jobparams 71 | 72 | log "Installing Windows Terminal" 73 | Start-Job -name "Windows-Terminal" -ScriptBlock { Install-Module WTToolbox -Force ; Install-WTRelease ; log "Windows Terminal installed" } @jobparams 74 | 75 | log "Configuring desktop settings" 76 | Start-Job -Name "Desktop-Config" -FilePath (Join-Path -Path $SetupPath -ChildPath Set-SandboxDesktop.ps1) @jobparams 77 | 78 | log "Installing Winget and additional apps" 79 | Start-Job -name "Winget" -ScriptBlock { 80 | C:\scripts\Download-Winget.ps1 -install -AddPrequisites 81 | winget install git 82 | winget install microsoft.edge 83 | log "Winget and other apps installed" 84 | } @jobparams 85 | 86 | #wait for everything to finish 87 | log "Waiting for background jobs to complete" 88 | Get-Job | Wait-Job 89 | 90 | #add jobs to the log 91 | Get-Job | ForEach-Object { 92 | $msg = "Job: {0} {1} [{2}]" -f $_.name, $_.state, ( New-TimeSpan -Start $_.PSBeginTime -End $_.PSEndTime) 93 | log $msg 94 | } 95 | 96 | log "Starting Windows Terminal" 97 | Start-Process wt.exe "-M new-tab -p PowerShell -d C:\ ; split-pane -V -p Windows PowerShell ; focus-tab --target 0" 98 | 99 | Log "Setting the host notification flag" 100 | Get-Date | Out-File -FilePath c:\scripts\sandbox.flag 101 | 102 | log "Sending toast notification in the Windows Sandbox" 103 | &(Join-Path -Path $SetupPath -ChildPath sandbox-toast.ps1) 104 | 105 | log "Ending configuration script $($MyInvocation.MyCommand)" 106 | log "Configuration completed in $(New-Timespan -start $begin)" 107 | log "Have a nice day!" 108 | -------------------------------------------------------------------------------- /wsbScripts/sandbox-setup-pluralsight.cmd: -------------------------------------------------------------------------------- 1 | REM sandbox-setup.cmd 2 | REM This code runs in the context of the Windows Sandbox 3 | REM Create my standard Work folder 4 | mkdir c:\work 5 | 6 | REM set execution policy first so that a setup script can be run 7 | REM and then run the configuration script 8 | powershell.exe -command "&{Set-ExecutionPolicy RemoteSigned -force ; Enable-PSRemoting -force -SkipNetworkProfileCheck; Install-PackageProvider -name nuget -force -forcebootstrap -scope allusers;c:\scripts\wsbScripts\sandbox-config-pluralsight.ps1}" 9 | 10 | -------------------------------------------------------------------------------- /wsbScripts/sandbox-setup-presentation.cmd: -------------------------------------------------------------------------------- 1 | REM sandbox-setup.cmd 2 | REM This code runs in the context of the Windows Sandbox 3 | REM Create my standard Work folder 4 | mkdir c:\work 5 | 6 | REM set execution policy first so that a setup script can be run 7 | REM and then run the configuration script 8 | powershell.exe -command "&{Set-ExecutionPolicy RemoteSigned -force ; Enable-PSRemoting -force -SkipNetworkProfileCheck; Install-PackageProvider -name nuget -force -forcebootstrap -scope allusers;c:\scripts\wsbScripts\sandbox-config-presentation.ps1}" 9 | 10 | -------------------------------------------------------------------------------- /wsbScripts/sandbox-setup.cmd: -------------------------------------------------------------------------------- 1 | REM sandbox-setup.cmd 2 | REM This code runs in the context of the Windows Sandbox 3 | 4 | REM Create my standard Work folder 5 | mkdir c:\work 6 | 7 | REM set execution policy first so that a setup script can be run 8 | powershell.exe -command "&{Set-ExecutionPolicy RemoteSigned -force}" 9 | 10 | REM Now run the true configuration script 11 | REM C:\Scripts has been mapped to the local C:\Scripts in the WSB file 12 | powershell.exe -file c:\scripts\wsbScripts\sandbox-config.ps1 -------------------------------------------------------------------------------- /wsbScripts/sandbox-toast.ps1: -------------------------------------------------------------------------------- 1 | #sandbox-toast.ps1 2 | 3 | #Send a toast notification in the sandbox when the configuration is complete. 4 | #This will require the BurntToast module to be installed in the Windows Sandbox. 5 | 6 | $params = @{ 7 | Text = "Windows Sandbox configuration is complete. See C:\Work\wsblog.txt." 8 | Header = $(New-BTHeader -Id 1 -Title "Windows Sandbox") 9 | Applogo = "c:\scripts\gazoo.bmp" 10 | Silent = $False 11 | } 12 | 13 | New-BurntToastNotification @params -------------------------------------------------------------------------------- /wsbconfig/README.md: -------------------------------------------------------------------------------- 1 | # wsbConfig 2 | 3 | The files in the folder are sample and reference WSB files. This location is referenced by default with the `wsbConfigPath` variable when you import the module. It is recommended that you create a location outside of this module and copy any of these files to that location. In your PowerShell profile, you can import the module and then update the global variable. 4 | 5 | ```powershell 6 | Import-Module WindowsSandboxTools 7 | $global:wsbConfigPath = "d:\wsb\configs 8 | ``` 9 | 10 | You can create new configurations with `New-WsbConfiguration` and then save them to a file with `Export-WsbConfiguration`. File references in the file must use FileSystem paths. 11 | -------------------------------------------------------------------------------- /wsbconfig/WinSandBx.wsb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | C:\scripts 7 | C:\scripts 8 | false 9 | 10 | 11 | C:\Pluralsight 12 | C:\Pluralsight 13 | true 14 | 15 | 16 | C:\Shared 17 | c:\shared 18 | false 19 | 20 | 21 | Enable 22 | Disable 23 | Disable 24 | Default 25 | 8192 26 | 27 | C:\scripts\wsbScripts\sandbox-setup.cmd 28 | 29 | 30 | 31 | 34 | -------------------------------------------------------------------------------- /wsbconfig/basic.wsb: -------------------------------------------------------------------------------- 1 | 2 | 3 | C:\scripts\wsbconfig\basic.wsb 4 | Jeff Hicks 5 | Basic sandbox with Scripts and shared folder 6 | 12/21/2020 9:30 AM 7 | 8 | Enable 9 | 8192 10 | Disable 11 | Default 12 | Default 13 | Default 14 | Default 15 | Disable 16 | 17 | C:\scripts\wsbScripts\sandbox-basic.cmd 18 | 19 | 20 | 21 | C:\scripts 22 | C:\scripts 23 | False 24 | 25 | 26 | C:\shared 27 | C:\shared 28 | False 29 | 30 | 31 | -------------------------------------------------------------------------------- /wsbconfig/demo.wsb: -------------------------------------------------------------------------------- 1 | 2 | 3 | demo 4 | Jeff 5 | This is a demonstration WSB file. 6 | 12/10/2020 09:00:54 7 | 8 | Enable 9 | 8192 10 | Default 11 | Default 12 | Default 13 | Default 14 | Default 15 | Default 16 | 17 | c:\scripts\wsbscripts\demo.cmd 18 | 19 | 20 | 21 | C:\Scripts 22 | C:\Scripts 23 | False 24 | 25 | 26 | -------------------------------------------------------------------------------- /wsbconfig/pluralsight.wsb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | C:\scripts 7 | C:\scripts 8 | false 9 | 10 | 11 | 12 | C:\Pluralsight 13 | C:\Pluralsight 14 | True 15 | 16 | 17 | C:\Shared 18 | C:\shared 19 | False 20 | 21 | 22 | Enable 23 | Default 24 | 16384 25 | 26 | 27 | C:\scripts\wsbScripts\sandbox-setup-pluralsight.cmd 28 | 29 | -------------------------------------------------------------------------------- /wsbconfig/presentation.wsb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | C:\scripts 7 | C:\scripts 8 | false 9 | 10 | 11 | 12 | C:\Presentations 13 | C:\presentations 14 | false 15 | 16 | 17 | C:\Shared 18 | C:\shared 19 | False 20 | 21 | 22 | Enable 23 | Default 24 | 8192 25 | 26 | 27 | C:\scripts\wsbScripts\sandbox-setup-presentation.cmd 28 | 29 | -------------------------------------------------------------------------------- /wsbconfig/sample.wsb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Sample 5 | Jeff Hicks 6 | a simple configuration with drive mappings 7 | 2020-09-10 08:47:10Z 8 | 9 | Enable 10 | Default 11 | 8192 12 | 13 | 14 | 15 | C:\scripts 16 | C:\scripts 17 | true 18 | 19 | 20 | 21 | D:\shared 22 | C:\shared 23 | false 24 | 25 | 26 | -------------------------------------------------------------------------------- /wsbconfig/work.wsb: -------------------------------------------------------------------------------- 1 | 2 | 3 | work 4 | Jeff 5 | My work WSB configuration 6 | 07/18/2022 15:43:24 7 | 8 | Default 9 | 8192 10 | Default 11 | Default 12 | Default 13 | Default 14 | Default 15 | Default 16 | 17 | C:\scripts\windowssandboxtools\wsbScripts\basic.cmd 18 | 19 | 20 | 21 | c:\work 22 | c:\work 23 | False 24 | 25 | 26 | --------------------------------------------------------------------------------