VMware Cloud Community
MayurPatel
Expert
Expert

Invoke-VMScript to ps script using RunAsUser and LoadProfile as local administrator

Hello, I'd like to run the following PS script under a domain\service account which is a local admin on the machine.

The problem, I am having with the below script, that it needs to be logged in ie. load the user profile of the user in order to register all the services etc.

I found one example that Luc has provided, but I can seem to figure out how to make it work.

$script06 = 'Configure_XD_SiteA.ps1'

$ISOpath = 'D:\Deploy\Applications\Citrix\XenDesktop'

$fullpath06 = join-path -path $ISOpath -childpath $script06

$CTXServiceUser = "CTXLAB\Service.vad"

$CTXServicePWord = ConvertTo-SecureString -String "VMware1!" -AsPlainText -Force

$CTXServiceCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $CTXServiceUser, $CTXServicePWord

Write-Verbose -Message "Configure XenDesktop Site." -Verbose

Invoke-VMScript -VM $vm -ScriptText $fullpath06 -GuestCredential $CTXServiceCredential -ScriptType Powershell

Many thanks!

MP

0 Kudos
15 Replies
LucD
Leadership
Leadership

The script you are sending (-ScriptText) needs to be a string.

Place it between double quotes.

$fullpath06 = "join-path -path $ISOpath -childpath $script06"


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

0 Kudos
MayurPatel
Expert
Expert

Hello Luc, thank you for your reply.

I tried using $fullpath06 = "join-path -path $ISOpath -childpath $script06" but it didn't seem to solve my issue. The problem I am having is something to do with the interactive user logged on with a user profile. And because there is no user profile present on the machine, the installer is not able to create some registry/file entries. It throws the below error:

invoke-vmscript-error.JPG

It is complaining of using a Temp user profile which it does not like - the C:\Users\TEMP folder.

BTW. If I logon as the user manually, and log out. Then when I run the invoke-vmscript command, it seems to work.

0 Kudos
LucD
Leadership
Leadership

This is basically a Windows issue for which I don't have an immediate solution.

The Invoke-VMScript cmdlet stores the script you run by default in the user's TEMP folder.

But since the user has no profile, he has no TEMP folder.

I could add an option to my Invoke-VMScriptPlus function to allow the caller to specify where the files should be stored.

Let me check if I can get that running.


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

0 Kudos
MayurPatel
Expert
Expert

Yes, I understand. It is creating a temp profile but failing to initialized due to lack of permissions because the registry settings under Current User Key have not been created. That is quite typical.

Although I am not really a good scripter, I used the below powershell Windows Invoke-Command to create a "domain user" profile of the service account I am using. But I had to run it locally on the machine first in order to create the user profile and once the profile was created. I executed my original Invoke-VMscript command it seems to work fine.

$CTXServiceUser = "CTXLAB\Service.vad"

$CTXServicePWord = ConvertTo-SecureString -String "VMware1!" -AsPlainText -Force

$CTXServiceCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $CTXServiceUser, $CTXServicePWord

Invoke-Command -Scriptblock {Get-Host} -Credential $CTXServiceCredential -Computer localhost

I tried to use the below method but it is not able to remotely create a user profile.

$Script = [ScriptBlock]::Create(" Invoke-Command -Scriptblock {Get-Host} -Credential $CTXServiceCredential -Computer localhost; ")

Invoke-VMScript -VM $vm -ScriptText $Script -GuestCredential $CTXServiceCredential -ScriptType Powershell

Tempfolder.JPG

0 Kudos
MayurPatel
Expert
Expert

I used a workaround by changing the autologon registry settings: Although I must admit it is not very elegant and I need to find a way to scramble the user credentials.

$EnableAutologon = 'REG ADD "HKLM\Software\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultDomainName /t REG_SZ /d domainname /f;

REG ADD "HKLM\Software\Microsoft\Windows NT\CurrentVersion\Winlogon" /v AutoAdminLogon /t REG_SZ /d 1 /f;

REG ADD "HKLM\Software\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultDomainName /t REG_SZ /d domainname /f;

REG ADD "HKLM\Software\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultUserName /t REG_SZ /d username /f;

REG ADD "HKLM\Software\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultPassword /t REG_SZ /d password /f'

Write-Verbose -Message "Enable Autologon For Site Creation." -Verbose

Invoke-VMScript -VM $vm -ScriptText $EnableAutologon -GuestCredential $CTXLocalCredential -ScriptType Powershell

Then I have to restart the VM

Write-Verbose -Message "Restarting Server." -Verbose

$restart = 'Shutdown /r /t 0'

Invoke-VMScript -VM $vm -ScriptText $restart -GuestCredential $CTXLocalCredential -ScriptType Powershell

This workaround enables me to create the user profile and I can execute the configuration script and it works perfectly.

Amoung a few other things, for now I need to wait for the shutdown/startup using the VMTools, I must admit I am not very good when it comes to scripting for loops etc. I could do with your help on this.

0 Kudos
LucD
Leadership
Leadership

One way to wait for a restart of the Guest OS, is

  • first, wait till the VM is actually powered off
  • then wait for the VM to become powered on
  • and finally, wait till the GuestOperations are available again

I wouldn't do the restart from within the Invoke-VMScript script, but once that script returns, you could do something like this

$vmGuest = Stop-VMGuest -VM $vm -Confirm:$false -Verbose:$false

while ($vmGuest.VM.ExtensionData.Runtime.PowerState -ne 'poweredOff')

{

    Start-Sleep 2

    $vmGuest.VM.ExtensionData.UpdateViewData('Runtime.PowerState')

}

$vm = Start-VM -VM $vmName -Confirm:$false -Verbose:$false

while ($vm.PowerState -ne 'PoweredOn')

{

    Start-Sleep 2

    $vm = Get-VM -Name $VmName -Verbose:$false

}

while (-not $vm.ExtensionData.Guest.GuestOperationsReady)

{

    Start-Sleep 2

    $vm.ExtensionData.UpdateViewData('Guest')

}


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

0 Kudos
MayurPatel
Expert
Expert

Luc,

The reboot snippet worked like a charm and it is very clean and error free. Really was impressed Smiley Happy you are a masterclass with PowerCLI.

I am going to clean up my script and would like to add a few improvements and will be back shortly to ask for help

Thanks,

MP

0 Kudos
LucD
Leadership
Leadership

You're welcome Smiley Happy


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

0 Kudos
MayurPatel
Expert
Expert

Please ignore my post - I managed to figure it out.

0 Kudos
LucD
Leadership
Leadership

Care to share your solution?


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

0 Kudos
MayurPatel
Expert
Expert

Hi Luc,

Yes, sure... I was trying to attach an ISO image to the VM. This is how i managed to make it work - solution came from this forum.

1. Get-ChildItem -Path vmstore:\$DataCenter\$DS\iso\MDTLabBuilder7152v4.iso| Format-List

2. Get-VM -Name $Hostname | Get-CDDrive| Set-CDDrive -StartConnected $true -IsoPath '[SAN0480] iso\MDTLabBuilder7152v4.iso' -Confirm:$false

But one thing I must admit I could not do is how to use a variable to make it easy to modify easily. Perhaps you can lend me a hand here Smiley Happy

1. The ISO file name = MDTLabBuilder7152v4.iso

2. How to use the Datastore variable $DS in place of -IsoPath '[SAN0480] iso\MDTLabBuilder7152v4.iso'

0 Kudos
LucD
Leadership
Leadership

Thanks for that.

You can use variable substitution in a string, but you will have to use double quotes.

There is no variable substitution when using single quotes.

You can also store the ISO name in a variable.

$isoName = 'MDTLabBuilder7152v4.iso'

Then you can do

-IsoPath "[$($ds.Name)] iso\$isoName"


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

0 Kudos
MayurPatel
Expert
Expert

Thanks Luc,

I tried the above method and it does attach the iso image to the VM, which was great but for some reason it throws up the below error. Are you able to shed any light as to why

pastedImage_0.png

This is the line number in my script:

pastedImage_5.png

0 Kudos
LucD
Leadership
Leadership

What does this return?

Get-VM -Name $Hostname | Get-CDDrive | Select *

And what do you have in $DS?

Is that a Datastore object or a string with the name of the Datatstore?

If it is the name of the Datastore, the line should be

Get-VM -Name $Hostname | Get-CDDrive |

Set-CDDrive -IsoPath "[$DS] iso\$isoName" -StartConnected $true -Confirm:$false


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

0 Kudos
MayurPatel
Expert
Expert

Get-VM -Name $Hostname | Get-CDDrive |

Set-CDDrive -IsoPath "[$DS] iso\$isoName" -StartConnected $true -Confirm:$false

The above worked perfectly, I am very pleased. Smiley Happy Luc, thank you so much for your help.

I am loving the usefulness of the Invoke-Script command - it is just amazing how cleaningly one can deploy new VMs and even configure the apps/services and in some cases without even needing any network connectivity.

0 Kudos