VMware Cloud Community
Jstrat31
Enthusiast
Enthusiast

Script to provision and configure domain controller: Working fine but getting error

I've been working on a script to setup a dc and forest using PowerCLI. I've got the script working fine but its throwing the below error.

VERBOSE: Configuring AD Forest on testvmdc

Invoke-VMScript : 1/27/2020 10:39:56 PM Invoke-VMScript A general system error occurred: vix error codes = (3016, 0).

At C:\Scripts\Dev\Create-DomainController_DEV_Jay.ps1:88 char:1

+ Invoke-VMScript -ScriptText $ConfigureNewDomain -VM $DomainController ...

+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : NotSpecified: (:) [Invoke-VMScript], SystemError

    + FullyQualifiedErrorId : Client20_VmGuestServiceImpl_GetProcessOutputInGuest_ViError,VMware.VimAutomation.ViCore.Cmdlets.Commands.InvokeVmScript

I'm trying to figure out why I'm getting the error when it does not appear to effect the script.

pastedImage_4.png

Here's the script so for. I'm sure It's pretty ugly lol

$DomainControllerVMName = "testvmdc"

# ------This Section Sets the Credentials to be used to connect to Guest VMs that are NOT part of a Domain------

# NOTE - Make sure you input the local credentials for your domain controller virtual machines below. This is used for logins prior to them being promoted to DCs.

# This should be the same local credentials as defined within the template that you are using for the domain controller VM.

$DCLocalUser = "$DomainControllerVMName\administrator"

$DCLocalPWord = ConvertTo-SecureString -String "P@ssword" -AsPlainText -Force

$DCLocalCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $DCLocalUser, $DCLocalPWord

# The below credentials are used by operations below once the domain controller virtual machines and the new domain are in place. These credentials should match the credentials

# used during the provisioning of the new domain.

$DomainUser = "TEST\administrator"

$DomainPWord = ConvertTo-SecureString -String "P@ssword" -AsPlainText -Force

$DomainCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $DomainUser, $DomainPWord

$DCLocalCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $DCLocalUser, $DCLocalPWord

#####network Config######

# Domain Controller VM IPs Below

# NOTE: Insert IP info in IP SubnetMask Gateway Order

# NOTE: For the purposes of this script we do not define static DNS settings for this single DC VM as it will point to itself for DNS after provisioning of the new domain.

# You could add an additional netsh line below to assign static DNS settings in the event you need to do so. See the File Server Section below for further details.

$DCNetworkSettings = 'netsh interface ip set address "Ethernet0" static 172.69.0.20 255.255.255.0 172.69.0.254'

Write-Verbose -Message "Getting ready to change IP Settings on VM $DomainControllerVMName." -Verbose

Invoke-VMScript -ScriptText $DCNetworkSettings -VM $DomainControllerVMName -GuestCredential $DCLocalCredential

# NOTE - The Below Sleep Command is due to it taking a few seconds for VMware Tools to read the IP Change so that we can return the below output.

# This is strctly informational and can be commented out if needed, but it's helpful when you want to verify that the settings defined above have been

# applied successfully within the VM. We use the Get-VM command to return the reported IP information from Tools at the Hypervisor Layer.

Start-Sleep 30

$DCEffectiveAddress = (Get-VM $DomainControllerVMName).guest.ipaddress[0]

Write-Verbose -Message "Assigned IP for VM [$DomainControllerVMName] is [$DCEffectiveAddress]" -Verbose

#####Domain config##########

# This Command will Install the AD Role on the target virtual machine.

$InstallADRole = 'Install-WindowsFeature -Name "AD-Domain-Services" -Restart'

Write-Verbose -Message "Installing AD Roles on $DomainControllerVMName" -Verbose

Invoke-VMScript -ScriptText $InstallADRole -VM $DomainControllerVMName -GuestCredential $DCLocalCredential

Write-Verbose -Message "AD Roles have been installed on $DomainControllerVMName" -Verbose

#Install DNS Roles

Write-Verbose -Message "Installing DNS Roles on $DomainControllerVMName" -Verbose

# This section installs the DNS roles

$InstallDNSRole = 'Install-WindowsFeature -Name DNS -IncludeAllSubFeature -IncludeManagementTools'

Invoke-VMScript -ScriptText $InstallDNSRole -VM $DomainControllerVMName -GuestCredential $DCLocalCredential

#Invoke-VMScript -ScriptText 'Install-WindowsFeature -Name DNS -IncludeAllSubFeature -IncludeManagementTools' -VM TestVMDC -GuestCredential $DCLocalCredential

Write-Verbose -Message "DNS Roles have been installed on $DomainControllerVMName" -Verbose

# Configure Domain

# This Scriptblock will define settings for a new AD Forest and then provision it with said settings.

# NOTE - Make sure to define the DSRM Password below in the line below that defines the $DSRMPWord Variable!!!!

$ConfigureNewDomain = 'Write-Verbose -Message "Configuring Active Directory" -Verbose;

                       $DomainMode = "WinThreshold";

                       $ForestMode = "WinThreshold";

                       $DomainName = "Test.local";

                       $DSRMPWord = ConvertTo-SecureString -String "P@ssword" -AsPlainText -Force;

                       Install-ADDSForest -ForestMode $ForestMode -DomainMode $DomainMode -DomainName $DomainName -InstallDns -SafeModeAdministratorPassword $DSRMPWord -Force'

Write-Verbose -Message "Configuring AD Forest on $DomainControllerVMName" -Verbose

Invoke-VMScript -ScriptText $ConfigureNewDomain -VM $DomainControllerVMName -GuestCredential $DCLocalCredential | Out-Null

# Script Block for configuration of AD automatically reboots the machine after provisioning

Write-Verbose -Message "Rebooting $DomainControllerVMName to Complete Forest Provisioning" -Verbose

# Below sleep command is in place as the reboot needed from the above command doesn't always happen before the wait-tools command is run

Start-Sleep -Seconds 60

Wait-Tools -VM $DomainControllerVMName -TimeoutSeconds 300

Write-Verbose -Message "Installation of Domain Services and Forest Provisioning on $DomainControllerVMName Complete" -Verbose

#This section installs AD Tools

Write-Verbose -Message "Installing AD Tools on $DomainControllerVMName" -Verbose

$InstallADtools = 'ADD-WindowsFeature RSAT-Role-Tools'

Invoke-VMScript -ScriptText $InstallADtools -VM $DomainControllerVMName -GuestCredential $DomainCredential

Write-Verbose -Message "Install of AD Tools on $DomainControllerVMName completed" -Verbose

#Create SHORTCUTS

# Create Active directory Users and Computers shortcut on the public desktop

Write-Verbose -Message "Creating Active directory Users and Computers Desktop shortcut on $DomainControllerVMName" -Verbose

$ADshortcut = '

$SourceFileLocation = "$env:SystemRoot\System32\dsa.msc"

$ShortcutLocation = "C:\Users\Public\Desktop\Active directory Users and Computers.lnk"

#New-Object : Creates an instance of a Microsoft .NET Framework or COM object.

#-ComObject WScript.Shell: This creates an instance of the COM object that represents the WScript.Shell for invoke CreateShortCut

$WScriptShell = New-Object -ComObject WScript.Shell

$Shortcut = $WScriptShell.CreateShortcut($ShortcutLocation)

$Shortcut.TargetPath = $SourceFileLocation

#Save the Shortcut to the TargetPath

$Shortcut.Save() '

Invoke-VMScript -ScriptText $ADshortcut -VM $DomainControllerVMName -GuestCredential $DomainCredential | Out-Null

Write-Verbose -Message "Done Creating Active directory Users and Computers Desktop shortcut on $DomainControllerVMName" -Verbose

# Create DNS on the public desktop

Write-Verbose -Message "Creating DNS Desktop shortcut on $DomainControllerVMName" -Verbose

$DNSshortcut = '

$SourceFileLocation = "$env:SystemRoot\System32\dnsmgmt.msc"

$ShortcutLocation = "C:\Users\Public\Desktop\DNS.lnk"

#New-Object : Creates an instance of a Microsoft .NET Framework or COM object.

#-ComObject WScript.Shell: This creates an instance of the COM object that represents the WScript.Shell for invoke CreateShortCut

$WScriptShell = New-Object -ComObject WScript.Shell

$Shortcut = $WScriptShell.CreateShortcut($ShortcutLocation)

$Shortcut.TargetPath = $SourceFileLocation

#Save the Shortcut to the TargetPath

$Shortcut.Save() '

Invoke-VMScript -ScriptText $DNSshortcut -VM $DomainControllerVMName -GuestCredential $DomainCredential | Out-Null

Write-Verbose -Message "Done creating DNS Desktop shortcut on $DomainControllerVMName" -Verbose

Jason Hartley VMware Systems Specialist "Develop the skill of sensing problems when they are still small and taking care of them before they become intractable"—Robert Greene http://privatecloudky.com/
0 Kudos
4 Replies
LucD
Leadership
Leadership

Could this be caused by what is described in KB2148803?


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
Jstrat31
Enthusiast
Enthusiast

LucD - First off I'd like to thank you for you contributions to these forums!!!

That error kind of sounds like what might be happening. The VM is restarting and losing connection to vcenter in the process, causing the error.

I'm guessing PowerCLI is expecting the output the results of the Invoke-VMScript but since a domain forest is being configured the O/S is restarted and can't output the results of the script.

Only thing about that KB is I'm not using integrated containers, I'm cloning from a template.

The section of the script that throws the error is during the domain forest provisioning.

Like I said, the script is working but my OCD hates that error. I'd like everything to be as clean as possible.

Jason Hartley VMware Systems Specialist "Develop the skill of sensing problems when they are still small and taking care of them before they become intractable"—Robert Greene http://privatecloudky.com/
0 Kudos
LucD
Leadership
Leadership

Thanks.

I have experienced similar.

A script that needs to reboot the VM, but the reboot happens too fast for the Invoke-VMScript to return.

Hence a similar error.

What I did as a bypass, I added the script to the Windows Scheduled Task manager with a start time 10-20 seconds in the future.

Then my Invoke-VMScript comes back without error, and on the calling side I wait for the restart to have completed.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
Jstrat31
Enthusiast
Enthusiast

Managed to get the script working after redoing most of it. I'm sure it could use some cleaning up and formatting. I'm still trying to get my PowerShell Chops up to speed.

This will prompt the user for all required inputs. All except the DSRM password, this needs to be hard coded in the script for now. I haven't been able to get that working yet. I think the Read-Host in the variable for that password may need to be in paranises for it to work. I'll test that out later.

Next step it to make one to provision and configure a Horizon Connection server as well as a file server. My end goal is to automate an entire Horizon deployment. Wish me luck lol.

#####################################

# User defined Variables

#####################################

# Name of vCenter Server

$vCenter = Read-Host "vCenter Server"

# Username of vCenter Server

$vCenterUsr = Read-Host "vCenter Username"

# Password of vCenter Server

$vCenterPas = Read-Host "vCenter Password"

# Name of the newly created VM

$DomainControllerVMName = Read-Host "Provide Domain Controller VM name"

# Cluster where new VM will be provisoned

$TargetCluster = Get-Cluster -Name (Read-Host "Provide Target Cluster")

#Template to Cone for new VM

$SourceVMTemplate = Get-Template -Name (Read-Host "Provide VM Template to Clone")

#VM Customization Specifications to use for new VM

$SourceCustomSpec = Get-OSCustomizationSpec -Name (Read-Host "VM Customization Specifications to use for new VM")

# VM IP Address

$DCIP = Read-Host "Domain Controller IP"

# VM Subnetmask

$DCNemtsk = Read-Host "Domain Controller SubnetMask"

# VM Gateway

$DCGW = Read-Host "Domain Controller Gateway"

####User Information######

$localuser = Read-Host "Provide Local Admin User (administrator)"

$localpassword = Read-Host "Provide local user password"

# FQDN of New Domain

$FQDN = Read-Host "Enter Domin FQDN"

# ------This Section Sets the Credentials to be used to connect to Guest VMs that are NOT part of a Domain------

# NOTE - Make sure you input the local credentials for your domain controller virtual machines below. This is used for logins prior to them being promoted to DCs.

# This should be the same local credentials as defined within the template that you are using for the domain controller VM.

$DCLocalUser = "$DomainControllerVMName\$localuser"

$DCLocalPWord = ConvertTo-SecureString -String "$localpassword" -AsPlainText -Force

$DCLocalCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $DCLocalUser, $DCLocalPWord

# The below credentials are used by operations below once the domain controller virtual machines and the new domain are in place. These credentials should match the credentials

# used during the provisioning of the new domain.

$DomainUser = "$FQDN\$localuser"

$DomainPWord = ConvertTo-SecureString -String "$localpassword" -AsPlainText -Force

$DomainCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $DomainUser, $DomainPWord

$DCLocalCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $DCLocalUser, $DCLocalPWord

##############################################################################################################################################################

#####################################

# Script Execution starts here

#####################################

#Connect to vCenter

Connect-VIServer $vCenter -User $vCenterUsr -Password $vCenterPas

##############################################################################

######## This Section Deploys the new VM(s) using a pre-built template #######

######## and then applies a customization specification to it.          #######

######## It then waits for Provisioning To Finish                       #######

##############################################################################

Write-Verbose -Message "Deploying Virtual Machine with Name: [$DomainControllerVMName] using Template: [$SourceVMTemplate] and Customization Specification: [$SourceCustomSpec] on Cluster: [$TargetCluster] and waiting for completion" -Verbose

New-VM -Name $DomainControllerVMName -Template $SourceVMTemplate -ResourcePool $TargetCluster -OSCustomizationSpec $SourceCustomSpec

Write-Verbose -Message "Virtual Machine $DomainControllerVMName Deployed. Powering On" -Verbose

Start-VM -VM $DomainControllerVMName

# We first verify that the guest customization has finished on on the new DC VM by using the below loops to look for the relevant events within vCenter.

Write-Verbose -Message "Verifying that Customization for VM $DomainControllerVMName has started ..." -Verbose

while($True)

{

$DCvmEvents = Get-VIEvent -Entity $DomainControllerVMName

$DCstartedEvent = $DCvmEvents | Where { $_.GetType().Name -eq "CustomizationStartedEvent" }

if ($DCstartedEvent)

{

break

}

else

{

Start-Sleep -Seconds 5

}

}

Write-Verbose -Message "Customization of VM $DomainControllerVMName has started. Checking for Completed Status......." -Verbose

while($True)

{

$DCvmEvents = Get-VIEvent -Entity $DomainControllerVMName

$DCSucceededEvent = $DCvmEvents | Where { $_.GetType().Name -eq "CustomizationSucceeded" }

        $DCFailureEvent = $DCvmEvents | Where { $_.GetType().Name -eq "CustomizationFailed" }

if ($DCFailureEvent)

{

Write-Warning -Message "Customization of VM $DomainControllerVMName failed" -Verbose

            return $False

}

if ($DCSucceededEvent)

{

            break

}

        Start-Sleep -Seconds 5

}

Write-Verbose -Message "Customization of VM $DomainControllerVMName Completed Successfully!" -Verbose

# NOTE - The below Sleep command is to help prevent situations where the post customization reboot is delayed slightly causing

# the Wait-Tools command to think everything is fine and carrying on with the script before all services are ready. Value can be adjusted for your environment.

Start-Sleep -Seconds 60

Write-Verbose -Message "Waiting for VM $DomainControllerVMName to complete post-customization reboot." -Verbose

Wait-Tools -VM $DomainControllerVMName -TimeoutSeconds 300

# NOTE - Another short sleep here to make sure that other services have time to come up after VMware Tools are ready.

Start-Sleep -Seconds 200

##################################################################################

######## This Section Configures the Networking on the newly provisoned VM #######

##################################################################################

# Domain Controller VM IPs Below

# NOTE: Insert IP info in IP SubnetMask Gateway Order

# NOTE: For the purposes of this script we do not define static DNS settings for this single DC VM as it will point to itself for DNS after provisioning of the new domain.

# You could add an additional netsh line below to assign static DNS settings in the event you need to do so. See the File Server Section below for further details.

$DCNetworkSettings = "netsh interface ip set address Ethernet0 static $DCIP $DCNemtsk $DCGW"

Write-Verbose -Message "Getting ready to change IP Settings on VM $DomainControllerVMName." -Verbose

Invoke-VMScript -ScriptText $DCNetworkSettings -VM $DomainControllerVMName -GuestCredential $DCLocalCredential

# NOTE - The Below Sleep Command is due to it taking a few seconds for VMware Tools to read the IP Change so that we can return the below output.

# This is strctly informational and can be commented out if needed, but it's helpful when you want to verify that the settings defined above have been

# applied successfully within the VM. We use the Get-VM command to return the reported IP information from Tools at the Hypervisor Layer.

Start-Sleep 30

$DCEffectiveAddress = (Get-VM $DomainControllerVMName).guest.ipaddress[0]

Write-Verbose -Message "Assigned IP for VM [$DomainControllerVMName] is [$DCEffectiveAddress]" -Verbose

Start-Sleep 60

##############################################################################

######## This Section Installs the AD roles on the newly provisoned VM #######

##############################################################################

Write-Verbose -Message "Installing AD Roles on $DomainControllerVMName" -Verbose

$InstallADRole = 'Install-WindowsFeature -Name "AD-Domain-Services" -Restart'

Invoke-VMScript -ScriptText $InstallADRole -VM $DomainControllerVMName -GuestCredential $DCLocalCredential

Write-Verbose -Message "AD Roles have been installed on $DomainControllerVMName" -Verbose

Start-Sleep 60

###############################################################################################

##############################################################################

######## This Section Installs the DNS roles on the newly provisoned VM #######

##############################################################################

Write-Verbose -Message "Installing DNS Roles on $DomainControllerVMName" -Verbose

$InstallDNSRole = 'Install-WindowsFeature -Name DNS -IncludeAllSubFeature -IncludeManagementTools'

Invoke-VMScript -ScriptText $InstallDNSRole -VM $DomainControllerVMName -GuestCredential $DCLocalCredential

Write-Verbose -Message "DNS Roles have been installed on $DomainControllerVMName" -Verbose

Start-Sleep 60

################################################################################################

##############################################################################

######## This Section Installs the AD Tools on the newly provisoned VM #######

##############################################################################

Write-Verbose -Message "Installing AD Tools on $DomainControllerVMName" -Verbose

$InstallADtools = 'ADD-WindowsFeature RSAT-Role-Tools'

Invoke-VMScript -ScriptText $InstallADtools -VM $DomainControllerVMName -GuestCredential $DCLocalCredential

Write-Verbose -Message "AD Tools have have been installed on $DomainControllerVMName" -Verbose

Start-Sleep 60

##############################################################################

######## This Section Configures the Domain and AD Forest ###################

##############################################################################

# AD Forest varibles

$DomainMode = "WinThreshold"

$ForestMode = "WinThreshold"

$DomainName = $FQDN

# AD Forest install script input for Invoke-VMScript                    

$ConfigureNewDomain = "Install-ADDSForest -ForestMode $ForestMode -DomainMode $DomainMode -DomainName $DomainName -InstallDns -SafeModeAdministratorPassword (ConvertTo-SecureString -String Password -AsPlainText -Force)  -Force"

Write-Verbose -Message "Configuring AD Forest $FQDN on $DomainControllerVMName" -Verbose

#Promots VM to domain controller and configures forest

Invoke-VMScript -ScriptText $ConfigureNewDomain -VM $DomainControllerVMName -GuestCredential $DCLocalCredential -ErrorAction SilentlyContinue

Write-Verbose -Message "Domain has been configured. Please wait for $DomainControllerVMName to Reboot and apply settings (This may take some time)" -Verbose

Start-Sleep -Seconds 120

Wait-Tools -VM $DomainControllerVMName -TimeoutSeconds 600 | Out-Null

Write-Verbose -Message "VM has finished Restarting" -Verbose

##############################################################################

######## This Section Configures the Desktop Shortcuts     ###################

##############################################################################

# Create Active directory Users and Computers shortcut on the public desktop

Write-Verbose -Message "Creating Active directory Users and Computers Desktop shortcut on $DomainControllerVMName" -Verbose

$ADshortcut = '

$SourceFileLocation = "$env:SystemRoot\System32\dsa.msc"

$ShortcutLocation = "C:\Users\Public\Desktop\Active directory Users and Computers.lnk"

#New-Object : Creates an instance of a Microsoft .NET Framework or COM object.

#-ComObject WScript.Shell: This creates an instance of the COM object that represents the WScript.Shell for invoke CreateShortCut

$WScriptShell = New-Object -ComObject WScript.Shell

$Shortcut = $WScriptShell.CreateShortcut($ShortcutLocation)

$Shortcut.TargetPath = $SourceFileLocation

#Save the Shortcut to the TargetPath

$Shortcut.Save() '

Invoke-VMScript -ScriptText $ADshortcut -VM $DomainControllerVMName -GuestCredential $DomainCredential | Out-Null

Write-Verbose -Message "Done Creating Active directory Users and Computers Desktop shortcut on $DomainControllerVMName" -Verbose

# Create DNS on the public desktop

Write-Verbose -Message "Creating DNS Desktop shortcut on $DomainControllerVMName" -Verbose

$DNSshortcut = '

$SourceFileLocation = "$env:SystemRoot\System32\dnsmgmt.msc"

$ShortcutLocation = "C:\Users\Public\Desktop\DNS.lnk"

#New-Object : Creates an instance of a Microsoft .NET Framework or COM object.

#-ComObject WScript.Shell: This creates an instance of the COM object that represents the WScript.Shell for invoke CreateShortCut

$WScriptShell = New-Object -ComObject WScript.Shell

$Shortcut = $WScriptShell.CreateShortcut($ShortcutLocation)

$Shortcut.TargetPath = $SourceFileLocation

#Save the Shortcut to the TargetPath

$Shortcut.Save() '

Invoke-VMScript -ScriptText $DNSshortcut -VM $DomainControllerVMName -GuestCredential $DomainCredential | Out-Null

Write-Verbose -Message "Done creating DNS Desktop shortcut on $DomainControllerVMName" -Verbose

Jason Hartley VMware Systems Specialist "Develop the skill of sensing problems when they are still small and taking care of them before they become intractable"—Robert Greene http://privatecloudky.com/
0 Kudos