Highlighted
Enthusiast
Enthusiast

Can a PowerCLI script display a prompt on a Guest OS?

So I'm writing a script to reboot all the VM's in a folder.  Very simple, no big deal.  What I'd like to know though is if there's a way in PowerCLI to put a prompt on the machines that they're being rebooted and somehow have a timer so a user can save any data if necessary and if perhaps they click ok it starts the reboot sooner and if not once the timer has counted down it reboots.  Is that possible using the Invoke-VM command or do I need to do something else?

0 Kudos
35 Replies
Highlighted
User Moderator
User Moderator

Just to make sure, these VMs are running a Windows guest OS?
And if yes, you only want to show this users that are logged on?

- run a PowerShell script through Invoke-VMScript.

- display a Windows form with 2 buttons, Cancel and Reboot Now.

- on the form add a timer, and display the timer value countdown in a text box.

- depending on the results (Cancel, Reboot Now or timer expires) return a value

- catch the returned value in the script that ran the Invoke-VMScript, and take appropriate action


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

0 Kudos
Highlighted
Enthusiast
Enthusiast

Correct.  They are all running Windows 10 x64.  And yes only show to users who are logged in, if they're not logged in (RDP only) then it reboots.

0 Kudos
Highlighted
Enthusiast
Enthusiast

So I found a script from someone else that will do the reboot and prompt, however when I try to run the Invoke-VMScript it seems to work, but nothing happens.  I have this in my script:

$script = '&env:script\CustomRestart.ps1'

Invoke-VMScript -vm $vm -ScriptText $script -ScriptType Powershell -GuestCredential $GuestCredential

Output appears fine in PowerCLI, but it doesn't run on the VM.  What am I missing?

0 Kudos
Highlighted
User Moderator
User Moderator

I would need to see what that script does.
Do you have a link, or else attach your version.


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

0 Kudos
Highlighted
Enthusiast
Enthusiast

Here's the link to the script I downloaded:

Script PowerShell GUI Restart Prompt

And here's the full script I have:

$vmlocation = Get-VM -Location Domain2 | sort Name
foreach ($vm in $vmlocation) {

$script = '&env:script\CustomRestart.ps1'

Invoke-VMScript -vm $vm -ScriptText "powershell.exe -file C:\users\emcclure\desktop\CustomRestart.ps1" -ScriptType Powershell -GuestCredential $GuestCredential | Format-List | Out-File reboot.txt -append

}

I've tried changing the $script to C:\script\CustomRestart.ps1 but that didn't make a difference either.  I know if I run the linked script above on a machine it works w/o issue.

0 Kudos
Highlighted
User Moderator
User Moderator

What do you have in env:script?

Is that an environment variable holding the location of a central script repository, accessible from each station?

Or is the script CustomRestart.ps1 copied to each station?


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

0 Kudos
Highlighted
Enthusiast
Enthusiast

Hi LucD,

So I made a change to the script, it now looks like this:

$vmlocation = Get-VM -Location Domain2 | sort Name #Gets folder where VM's are located, if folder name is not unique in vCenter it will reboot VM's in all folders with same name
foreach ($vm in $vmlocation) {

$script = C:\rebootscript\customrestart.ps1

Invoke-VMScript -vm $vm -ScriptText $script -ScriptType Powershell -GuestCredential $GuestCredential

}

I found that one of the machines I was testing on WinRM wasn't setup, so once I configured that and re-ran the script it prompted with the GUI for the reboot.  However when I added another machine to the folder and confirmed that WinRM was running on that and then ran the script again it only prompts on the machine I'm running the script from (2x since there's 2 machines in that folder).  How do I get past that?  I'm not sure why it worked one moment and did that the next.  I'd like to be able to put the script on a machine somewhere and just have a scheduled task to run the script at a certain time, but without rebooting the machine it runs from.

Edit:

This is the error I'm getting when I click cancel on the prompts on my machine:

Invoke-VMScript : 7/30/2018 10:18:19 AM Invoke-VMScript         Value cannot be found for the mandatory parameter ScriptText

Invoke-VMScript -vm $vm -ScriptText $script -ScriptType Powershell -G ...

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

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

  n

   + FullyQualifiedErrorId : Core_BaseCmdlet_UnknownError,VMware.VimAutomatio

  n.ViCore.Cmdlets.Commands.InvokeVmScript

0 Kudos
Highlighted
User Moderator
User Moderator

That's most probably because the script on the remote computer runs under the account you used to call Invoke-VMScript.

Anything you display from that script will not appear in the user's session.

There might be a possibility to use a MessageBox with the ServiceNotification option.

I'll have to check.


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

0 Kudos
Highlighted
Enthusiast
Enthusiast

Ok so another update on this.  When I change the code to this:

$GuestCredential = Get-Credential
$vmlocation = Get-VM -Location Domain2 | sort Name #Gets folder where VM's are located, if folder name is not unique in vCenter it will reboot VM's in all folders with same name
foreach ($vm in $vmlocation) {

$script = "\\pathtoshare\C$\rebootscript\CustomRestart.ps1"

Invoke-VMScript -vm $vm -ScriptText $script -ScriptType Powershell -GuestCredential $GuestCredential | Format-List | Out-File reboot.txt -append

}

It will prompt for credentials and run the Invoke-VMScript as if everything is ok.  Nothing outputs in the PowerCLI window.  But if I go to that reboot.txt file I see this:

VM           : test-machine

ExitCode     : 0

ScriptOutput : \\pathtoshare\C$\rebootscript\CustomRestart.ps1 :

               The term

               '\\pathtoshare\C$\rebootscript\CustomRestart.ps1' is

               not recognized as the name of a cmdlet, function,

               script file, or operable program. Check the spelling of the

               name, or if a path was included, verify that the path is

               correct and try again.

               At line:1 char:4

               + & {\\pathtoshare\C$\rebootscript\CustomRestart.ps1}

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

                   + CategoryInfo          : ObjectNotFound:

               (\\pathtoshare....stomRestart.ps1:String) [],

               CommandNotFoundException

                   + FullyQualifiedErrorId : CommandNotFoundException

Same thing happens if I just put "C:\rebootscript\CustomRestart.ps1" in the $script.

0 Kudos
Highlighted
Enthusiast
Enthusiast

So it also appears if I copy the script to the same path on the target machine it will run, but only the background which I really don't want as I want the user to be able to decide to reboot now or later.  This works from a machine that's on the same domain as the target machine and one that's not.

I've even changed the command to this:

Invoke-VMScript -vm $vm -ScriptText "C:\rebootscript\CustomRestart.ps1" -ScriptType PowerShell -GuestCredential $GuestCredential | Format-List | Out-File reboot.txt -append

But it still doesn't make a difference if the target machine doesn't have the script on it already.  When it reboots I get this in PowerCLI:

Invoke-VMScript : 7/30/2018 12:15:24 PM Invoke-VMScript         The guest operations agent could not be contacted.

At C:\Users\username\Desktop\GenScripts\GenRebootWithPrompt.ps1:28 char:1

+ Invoke-VMScript -vm $vm -ScriptText "C:\rebootscript\CustomRestart.ps ...

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

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

   ionsUnavailable

    + FullyQualifiedErrorId : Client20_VmGuestServiceImpl_GetProcessOutputInGu

   est_ViError,VMware.VimAutomation.ViCore.Cmdlets.Commands.InvokeVmScript

So unfortunately that means the reboot.txt file doesn't get anything in it either.

This is just strange.  I don't know how it worked that one time this morning and hasn't worked since.  I'm thinking it was a fluke if anything, but dang I just want it to prompt the user as if I ran the script locally.

0 Kudos
Highlighted
User Moderator
User Moderator

Was there an active session on the target machine with the same account that you use for the Invoke-VMScript?


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

0 Kudos
Highlighted
Enthusiast
Enthusiast

No.  A couple of them were logged in locally using a domain account (I used a local admin account in the Invoke-VMScript) and one had an RDP session with another domain account.

0 Kudos
Highlighted
User Moderator
User Moderator

Ok, I have been doing some more digging into the subject.

The script you are using will only work when you insert it in SCCM Task Sequence.

If not, you will not be able to show the form to users that are logged on with a different account than the one you use on the Invoke-VMScript cmdlet

I did find a standalone solution, but that will only work for users that are connected through a RDP session on the VM.

The reason for this limitation, is that the script uses the wtsapi32.dll.

There might be a possibility to do run-time linking to the wtsapi32.dll, as MSFT documents in Run-Time linking to Wtsapi32.dll

But I'm still experimenting with that.

In summary:

Session typeForm works
RDPyes
Localno, but looking at run-time linking


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

0 Kudos
Highlighted
Enthusiast
Enthusiast

Hi LucD,

So the solution you found, do you mean I have to be connected to the machine thru RDP or that it only show up on users who are RDP'ed to the machine?  If the latter that's fine as users can only access the machines thru RDP.

Thanks for your help on this.

0 Kudos
Highlighted
User Moderator
User Moderator

Only when users have RDP-ed into the machine.
I'll post the script tomorrow


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

0 Kudos
Highlighted
Enthusiast
Enthusiast

Hi LucD,

Any word on that script?

0 Kudos
Highlighted
User Moderator
User Moderator

I have it working, but I first had to update my Invoke-VMScriptPlus function to get round the +/- 2600 length limit that exists for the regular Invoke-VMScript PowerShell script.
And yes, the solution should work for RDP, not yet 100% about the local sessions.

I think this is turning into a blog post :smileycool:


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

0 Kudos
Highlighted
Enthusiast
Enthusiast

Hi LucD,

Thanks.  The users of the machines can only use RDP by design so that's perfect.  Looking forward to seeing what you have.

0 Kudos
Highlighted
User Moderator
User Moderator

Only need to fix an issue with Invoke-WebRequest and invalid certificates.
Post should be ready early next week.


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

0 Kudos