$ vagrant -v
Vagrant 2.0.0
macOS 10.12.6
Windows Server 2016
# Vagrant File (Vagrantfile)
# http://docs.vagrantup.com/v2/vagrantfile/index.html
# Windows guests can't even be used with Vagrant versions less than 1.3.5.
Vagrant.require_version ">= 1.3.5"
if Vagrant::VERSION < '1.6.0'
# Vagrant versions less than 1.6.x do not have a built-in way to
# communicate with Windows guest images.For versions less than 1.6.x
# the vagrant-windows plugin is required.
Vagrant.require_plugin "vagrant-windows"
end
# http://docs.vagrantup.com/v2/vagrantfile/machine_settings.html
Vagrant.configure("2") do |config|
# This setting will download the atlas box at
# https://atlas.hashicorp.com/ferventcoder/boxes/win2012r2-x64-nocm
config.vm.box = "BasicTheProgram/windows_2016"
# http://docs.vagrantup.com/v2/providers/configuration.html
# http://docs.vagrantup.com/v2/virtualbox/configuration.html
config.vm.provider :virtualbox do |v, override|
# Show the GUI
v.gui = true
# 4GB RAM
v.customize ["modifyvm", :id, "--memory", "4096"]
# 2 CPUs
v.customize ["modifyvm", :id, "--cpus", "2"]
# Video RAM is 32 MB
v.customize ["modifyvm", :id, "--vram", 32]
# For better DNS resolution
v.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]
# No audio
v.customize ["modifyvm", :id, "--audio", "none"]
# Clipboard enabled
v.customize ["modifyvm", :id, "--clipboard", "bidirectional"]
v.customize ["modifyvm", :id, "--draganddrop", "hosttoguest"]
# For performance
v.customize ["modifyvm", :id, "--usb", "off"]
# Huge performance gain here
v.linked_clone = true if Vagrant::VERSION >= '1.8.0'
end
# https://www.vagrantup.com/docs/hyperv/configuration.html
# https://technet.microsoft.com/en-us/library/dn798297(v=ws.11).aspx
config.vm.provider :hyperv do |v, override|
# 4GB RAM
v.memory = 4096
# 2 CPUs
v.cpus = 2
# The time in seconds to wait for the virtual machine to report an IP address
v.ip_address_timeout = 130
# Use differencing disk instead of cloning whole VHD
v.differencing_disk = true
v.vm_integration_services = {
guest_service_interface: true,
heartbeat: true,
key_value_pair_exchange: true,
shutdown: true,
time_synchronization: true,
vss: true
}
end
# timeout of waiting for image to stop running - may be a deprecated setting
config.windows.halt_timeout = 20
# username/password for accessing the image
config.winrm.username = "vagrant"
config.winrm.password = "vagrant"
# explicitly tell Vagrant the guest is Windows
config.vm.guest = :windows
if Vagrant::VERSION >= '1.6.0'
# If we are on greater than v1.6.x, we are using the built-in version
# of communicating with Windows. For versions less than 1.6 the
# `vagrant-windows` plugin would need to be installed and uses monkey
# patching to override the communicator.
config.vm.communicator = "winrm"
end
# Synced folders - http://docs.vagrantup.com/v2/synced-folders/
# A synced folder is a fancy term for shared folders - it takes a folder on
# the host and shares it with the guest (vagrant) image. The entire folder
# where the Vagrantfile is located is always shared as `c:\vagrant` (the
# naming of this directory being `vagrant` is just a coincedence).
# Share `packages` directory as `C:\packages`
config.vm.synced_folder "packages", "/packages"
config.vm.synced_folder "/Users/tanner/projects/", "/projects"
#config.vm.synced_folder "temp", "/Users/vagrant/AppData/Local/Temp/chocolatey"
# not recommended for sharing, it may have issues with `vagrant sandbox rollback`
#config.vm.synced_folder "chocolatey", "/ProgramData/chocolatey"
# Port forward WinRM / RDP
# Vagrant 1.9.3 - if you run into Errno::EADDRNOTAVAIL (https://github.com/mitchellh/vagrant/issues/8395),
# add host_ip: "127.0.0.1" for it to work
config.vm.network :forwarded_port, guest: 5985, host: 5985, id: "winrm", auto_correct: true #, host_ip: "127.0.0.1"
config.vm.network :forwarded_port, guest: 3389, host: 3389, id: "rdp", auto_correct: true #, host_ip: "127.0.0.1"
# Port forward SSH (ssh is forwarded by default in most versions of Vagrant,
# but be sure). This is not necessary if you are not using SSH, but it doesn't
# hurt anything to have it
config.vm.network :forwarded_port, guest: 22, host: 2222, id: "ssh", auto_correct: true #, host_ip: "127.0.0.1"
# Provisioners - http://docs.vagrantup.com/v2/provisioning/
# In this specific vagrant usage, we are using the shell provisioner
# http://docs.vagrantup.com/v2/provisioning/shell.html
if Vagrant::VERSION < '1.8.0'
config.vm.provision :shell, :path => "shell/PrepareWindows.ps1"
config.vm.provision :shell, :path => "shell/InstallNet4.ps1"
config.vm.provision :shell, :path => "shell/InstallChocolatey.ps1"
config.vm.provision :shell, :path => "shell/NotifyGuiAppsOfEnvironmentChanges.ps1"
else
config.vm.provision :shell, :path => "shell/PrepareWindows.ps1", :powershell_elevated_interactive => true
config.vm.provision :shell, :path => "shell/InstallNet4.ps1", :powershell_elevated_interactive => true
config.vm.provision :shell, :path => "shell/InstallChocolatey.ps1", :powershell_elevated_interactive => true
config.vm.provision :shell, :path => "shell/NotifyGuiAppsOfEnvironmentChanges.ps1", :powershell_elevated_interactive => true
config.vm.provision :shell, :path => "shell/InstallToolchain.ps1", :powershell_elevated_interactive => true
end
$packageTestScript = <<SCRIPT
setx.exe trigger 1 # run arbitrary win32 application so LASTEXITCODE is 0
$ErrorActionPreference = "Stop"
$env:PATH +=";$($env:SystemDrive)\\ProgramData\\chocolatey\\bin"
# https://github.com/chocolatey/choco/issues/512
$validExitCodes = @(0, 1605, 1614, 1641, 3010)
Write-Output "Testing package if a line is uncommented."
# THIS IS WHAT YOU CHANGE
# - uncomment one of the two and edit it appropriately
# - See the README for details
#choco.exe install -fdvy INSERT_NAME --version INSERT_VERSION --allow-downgrade
#choco.exe install -fdvy INSERT_NAME --allow-downgrade --source "'c:\\packages;http://chocolatey.org/api/v2/'"
$exitCode = $LASTEXITCODE
Write-Host "Exit code was $exitCode"
if ($validExitCodes -contains $exitCode) {
Exit 0
}
Exit $exitCode
SCRIPT
if Vagrant::VERSION < '1.8.0'
config.vm.provision :shell, :inline => $packageTestScript
else
config.vm.provision :shell, :inline => $packageTestScript, :powershell_elevated_interactive => true
end
end
https://gist.github.com/basictheprogram/9cb025b9c6f3f78a5b10132130c21883
The shell provisions should execute and not error out.
$ vagrant up
==> default: Checking if box 'BasicTheProgram/windows_2016' is up to date...
==> default: Running provisioner: shell...
default: Running: shell/PrepareWindows.ps1 as c:tmp\vagrant-shell.ps1
==> default: (10,8):UserId:
==> default: At line:72 char:1
==> default: + $folder.RegisterTaskDefinition($task_name, $task, 6, $username, $pass ...
==> default: + ~~~~~~~~~~~~~~~
==> default: + CategoryInfo : OperationStopped: (:) [], ArgumentException
==> default: + FullyQualifiedErrorId : System.ArgumentException
==> default: The system cannot find the file specified. (Exception from HRESULT: 0x80070002)
==> default: At line:74 char:1
==> default: + $registered_task = $folder.GetTask("\$task_name")
==> default: + ~~~~~~~~~~~
==> default: + CategoryInfo : OperationStopped: (:) [], FileNotFoundException
==> default: + FullyQualifiedErrorId : System.IO.FileNotFoundException
==> default: You cannot call a method on a null-valued expression.
==> default: At line:75 char:1
==> default: + $registered_task.Run($null) | Out-Null
==> default: + ~~~~~~~~~~
==> default: + CategoryInfo : InvalidOperation: (:) [], RuntimeException
==> default: + FullyQualifiedErrorId : InvokeMethodOnNull
Built Windows Server 2016 with packer using this https://github.com/StefanScherer/packer-windows
$ packer build -only=virtualbox-iso windows_2016.json
Packer completes without warning or errors.
Commenting out all config.vm.provision the VM spins up and functions normally.
I added a "shell/Noop.ps1", la blank file and the above error still thrown.
I changed "shell/Noop.ps1" to
Write-Host "Testing"
the above error still thrown.
Edit 1
Interactive shell on the Windows 2016 Server I find c:tmp\vagrant-shell.ps1 and it's my Noop.ps1 testing script. Executing this script from a powershell command line works as expected.

Edit 2
Does Vagrant use scheduled tasks for powershell provisioners?
Vaguely recall having issues with 2003 scheduled tasks when we moved to 2008. Could this be a similar problem going from 2008 to 2016?
Turned on debug, got the below output
$ vagrant up --debug
DEBUG winrmshell: [WinRM] Command created for $username = 'vagrant'
$password = 'vagrant'
$script_file = 'c:/windows/temp/winrm-elevated-shell-7bf83477-461e-42c3-aefa-3ccb548603e9.ps1'
$interactive = 'false'
$pass_to_use = $password
$logon_type = 1
$logon_type_xml = "<LogonType>Password</LogonType>"
if($pass_to_use.length -eq 0) {
$pass_to_use = $null
$logon_type = 5
$logon_type_xml = ""
}
if($interactive -eq 'true') {
$logon_type = 3
$logon_type_xml = "<LogonType>InteractiveTokenOrPassword</LogonType>"
}
$task_name = "WinRM_Elevated_Shell"
$out_file = [System.IO.Path]::GetTempFileName()
$err_file = [System.IO.Path]::GetTempFileName()
$task_xml = @'
<?xml version="1.0" encoding="UTF-16"?>
<Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
<Principals>
<Principal id="Author">
<UserId>{username}</UserId>
{logon_type}
<RunLevel>HighestAvailable</RunLevel>
</Principal>
</Principals>
<Settings>
<MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
<DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
<StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>
<AllowHardTerminate>true</AllowHardTerminate>
<StartWhenAvailable>false</StartWhenAvailable>
<RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
<IdleSettings>
<StopOnIdleEnd>false</StopOnIdleEnd>
<RestartOnIdle>false</RestartOnIdle>
</IdleSettings>
<AllowStartOnDemand>true</AllowStartOnDemand>
<Enabled>true</Enabled>
<Hidden>false</Hidden>
<RunOnlyIfIdle>false</RunOnlyIfIdle>
<WakeToRun>false</WakeToRun>
<ExecutionTimeLimit>PT24H</ExecutionTimeLimit>
<Priority>4</Priority>
</Settings>
<Actions Context="Author">
<Exec>
<Command>cmd</Command>
<Arguments>{arguments}</Arguments>
</Exec>
</Actions>
</Task>
'@
$arguments = "/c powershell.exe -executionpolicy bypass -NoProfile -File $script_file > $out_file 2>$err_file"
$task_xml = $task_xml.Replace("{arguments}", $arguments)
$task_xml = $task_xml.Replace("{username}", $username)
$task_xml = $task_xml.Replace("{logon_type}", $logon_type_xml)
$schedule = New-Object -ComObject "Schedule.Service"
$schedule.Connect()
$task = $schedule.NewTask($null)
$task.XmlText = $task_xml
$folder = $schedule.GetFolder("\")
$folder.RegisterTaskDefinition($task_name, $task, 6, $username, $pass_to_use, $logon_type, $null) | Out-Null
Typed the above into an interactive powershell, all went well until
PS C:\Users\vagrant> $folder.RegisterTaskDefinition($task_name, $task, 6, $username, $pass_to_use, $logon_type, $null)
(27,4):Actions:
At line:1 char:1
+ $folder.RegisterTaskDefinition($task_name, $task, 6, $username, $pass ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (:) [], ArgumentException
+ FullyQualifiedErrorId : System.ArgumentException
Left off the "| Out-Null"
After a lot of research I found that Windows Server 2016 does not allow schedule tasks to be run as non-Administrator.
Even with the vagrant user in the Administrators group it does not allow vagrant user to create schedule tasks.
I enabled the local Administrator, set the password changed the VagrantFile as below:
config.winrm.username = "Administrator"
config.winrm.password = "Vagrant1234"
And provisioned the VM again and things work
$ vagrant up --provision
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Running provisioner: shell...
default: Running: shell/Noop.ps1 as c:\tmp\vagrant-shell.ps1
==> default: Testing
http://bit.ly/2zqIaNU
No, non-admin cannot manage scheduled tasks unless run as an administrator.
http://bit.ly/2zqBAqS
Hints at the problem
http://bit.ly/2ztbtjb
Another hint at the problem
Edit 1
Might be a macOS issue or how Vagrant implements WinRM on macOS?
Looks like using Windows7 as a host things work as expected.
https://groups.google.com/d/msg/vagrant-up/lKS1cs9mLpM/L7pnTUMfBAAJ
I can reproduce on a Windows 7 Enterprise host as well. Vagrant 2.0.0, VirtualBox 5.1.30 and your basebox given in the Vagrantfile above.
Well provisioning also works with this box with
config.vm.provision :shell, :path => "shell/hello.ps1", privileged: false
config.vm.provision :shell, :path => "shell/PrepareWindows.ps1", privileged: false
config.vm.provision :shell, :path => "shell/InstallNet4.ps1", privileged: false
config.vm.provision :shell, :path => "shell/InstallChocolatey.ps1", privileged: false
config.vm.provision :shell, :path => "shell/NotifyGuiAppsOfEnvironmentChanges.ps1", privileged: false
This disables the scheduled task inside the winrm communicator. As the basebox does not have UAC enabled and user vagrant is in the Administrators group it also works, but looks weird. But this is the way I do it in other Vagrantfiles as well. And this does not really notify the GUI apps, so the last provision script "NotifyGuiAppsOfEnvironmentChanges.ps1" has no effect. Open a powershell terminal and type choco results in command not found error.
Provisioning also works with the :powershell_elevated_interactive => true if I use a Windows Server 2016 basebox with Build 14393.rs1_release.170731_1934.
Provisioning fails with :powershell_elevated_interactive => true or without the privileged: false flag using a Windows Server 2016 basebox with Build 14393.rs1_release.170917_1700.
==> default: Running provisioner: shell...
default: Running: shell/PrepareWindows.ps1 as c:\tmp\vagrant-shell.ps1
==> default: (10,8):UserId:
==> default: At line:72 char:1
==> default: + $folder.RegisterTaskDefinition($task_name, $task, 6, $username, $pass ...
==> default: + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
==> default: + CategoryInfo : OperationStopped: (:) [], ArgumentException
==> default: + FullyQualifiedErrorId : System.ArgumentException
==> default: The system cannot find the file specified. (Exception from HRESULT: 0x80070002)
==> default: At line:74 char:1
==> default: + $registered_task = $folder.GetTask("\$task_name")
==> default: + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
==> default: + CategoryInfo : OperationStopped: (:) [], FileNotFoundException
==> default: + FullyQualifiedErrorId : System.IO.FileNotFoundException
==> default: You cannot call a method on a null-valued expression.
==> default: At line:75 char:1
==> default: + $registered_task.Run($null) | Out-Null
==> default: + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
==> default: + CategoryInfo : InvalidOperation: (:) [], RuntimeException
==> default: + FullyQualifiedErrorId : InvokeMethodOnNull
Vagrant host macOS 10.12.6
Vagrant 2.0.0
VirtualBox 5.1.30
Windows Server 2016 Build 14393.rs1_release.170917-1700
Changing the provisioning to look like this:
config.vm.provision :shell, :path => "shell/Noop.ps1", privileged: false
config.vm.provision :shell, :path => "shell/PrepareWindows.ps1", privileged: false
config.vm.provision :shell, :path => "shell/InstallNet4.ps1", privileged: false
config.vm.provision :shell, :path => "shell/InstallChocolatey.ps1", privileged: false
config.vm.provision :shell, :path => "shell/NotifyGuiAppsOfEnvironmentChanges.ps1",privileged: false
config.vm.provision :shell, :path => "shell/InstallToolchain.ps1", privileged: false
Allows all provisioning to work as expected.
As a vagrant user trying to work with Windows Server 2016, thank you @basictheprogram and @StefanScherer for your work on this. I experienced this issue, as well, and can confirm that this is also a problem when using the VMware Fusion provider. The privileged: false workaround is working for me and seems to be sufficient for now, though I'd love to see an official solution.
so, the scheduled task is designed to work around issues with PSremoting, for instance, if I try and run 'choco install powershell -y' this will result in the task failing with error 5 (access denied). What I don't understand is why the same code works as Administrator, even though vagrant is also a local administrator. This is what I see from vagrant:
[DBG]: PS C:\Windows\system32>> register-scheduledtask -taskname $task_name -xml $task.XmlText -user $username -Password $pass_to_use
register-scheduledtask : The parameter is incorrect.
(10,8):UserId:
At line:1 char:1
+ register-scheduledtask -taskname $task_name -xml $task.XmlText -user $username - ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (PS_ScheduledTask:Root/Microsoft/...S_ScheduledTask) [Register-ScheduledTask], CimException
+ FullyQualifiedErrorId : HRESULT 0x80070057,Register-ScheduledTask
If I change the code to use "Administrator", everything works fine. I've also tried making the vagrant account password suitably 'complex' without any change in behaviour.
SYSTEM works fine, and avoids having to pass in credentials at all, by default:
[DBG]: PS C:\Windows\system32>> register-scheduledtask -taskname $task_name -xml $task.XmlText -user SYSTEM
TaskPath TaskName State
-------- -------- -----
\ WinRM_Elevated_Shell Ready
Couple things of note - vagrant uses https://github.com/WinRb/winrm-elevated as the means to run elevated. This will run as system if no password is passed in, but Vagrant doesn't provide a parameter for this. I can create another user with local admin rights and this works, so it's something specific about the vagrant user.
This is the error received from RegisterTaskDefinition:
default: Exception calling "RegisterTaskDefinition" with "7" argument(s): "(10,8):UserId:"
default: At line:72 char:1
default: + $folder.RegisterTaskDefinition($task_name, $task, 6, $username, $pass_to_use, $l ...
default: + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
default: + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
default: + FullyQualifiedErrorId : ComMethodTargetInvocation
I've just found it'll work with the vagrant account if you specify the username as
config.winrm.username = 'vagrant\vagrant'
This doesn't really work for me, because as part of provisioning I rename the guest to match the name of the VM. The ability to use SYSTEM to register the task would be much cleaner, imo. For the time being, I've worked around it by using 'administrator'.
Is there any update on this issue?
I'm seeing it with vagrant version 2.1.2 on VMWare Fusion 10.1.2.
I'm caught between a rock and a hard place. If I change to config.winrm.username = 'vagrant\vagrant' I can get my provisioners to work, but vagrant up fails until I change it back to config.winrm.username = 'vagrant' or just comment out the line in the Vagrantfile.
+1 here. Everything was working fine until >= 2.2.1. See the following issues for repro:
https://github.com/clong/DetectionLab/issues/168
https://github.com/clong/DetectionLab/issues/172
Setting privileged: false seems to be a workaround for now.
@clong Thanks for the report of the issue! For the windows boxes you are using, do they include customized username values for the winrm communicator within the nested Vagrantfile?
@chrisroberts nope, the Vagrantfile doesn't specify a username for the winrm provider and uses the defaults.
@chrisroberts On my setup I have the following statements in the box's nested Vagrantfile:
config.vm.communicator = "winrm"
# Admin user name and password
config.winrm.username = "vagrant"
config.winrm.password = "vagrant"
Hi there,
It looks like this has been resolved within a previously shipped version of Vagrant so I am now closing this issue. If the original issue was not fully resolved, please reopen this issue or create a new one.
Cheers!
I'm going to lock this issue because it has been closed for _30 days_ โณ. This helps our maintainers find and focus on the active issues.
If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.
Most helpful comment
I've just found it'll work with the vagrant account if you specify the username as
This doesn't really work for me, because as part of provisioning I rename the guest to match the name of the VM. The ability to use SYSTEM to register the task would be much cleaner, imo. For the time being, I've worked around it by using 'administrator'.