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?
Published my solution, see Message To All Users, And Their Reply
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Hi LucD,
Thanks for the help on this. I feel like an idiot asking this, but how do I import the Invoke-VMScriptPlus as a module in PowerShell or PowerCLI? I thought I could save the code as a ps1 or pds1 but it definitely didn't like the pds1 when I tried to import it. I just want to make sure I have everything setup right before I give it a shot and so I know how to show other users on my team in case they ever need to run this.
At the moment I didn't place it in a module.
There a couple of ways to make the function known to your system:
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Hi LucD,
Ok when I try to get everything to run I wind up getting this issue:
Resolve-DnsName : The term 'Resolve-DnsName' 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 C:\Users\emcclure\Desktop\GenScripts\Invoke-VMScriptPlus.ps1:237 char:13
+ $hostName = Resolve-DnsName -Name $ip | Select-Object -ExpandProperty ...
+ ~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Resolve-DnsName:String) [], Com
mandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Invoke-WebRequest : Cannot bind parameter 'Uri'. Cannot convert value
"https://:443/guestFile?id=197&token=52e6ffc7-9002-4ea5-e2bd-33599ea10971197"
to type "System.Uri". Error: "Invalid URI: The hostname could not be parsed."
At C:\Users\emcclure\Desktop\GenScripts\Invoke-VMScriptPlus.ps1:239 char:38
+ $copyResult = Invoke-WebRequest -Uri $filePath -Method Put -Body $Scr ...
+ ~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Invoke-WebRequest], Parame
terBindingException
+ FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerSh
ell.Commands.InvokeWebRequestCommand
ScripText copy failed!Status
At C:\Users\emcclure\Desktop\GenScripts\Invoke-VMScriptPlus.ps1:241 char:1
+ Throw "ScripText copy failed!`rStatus $($copyResult.StatusCode)`r$(($ ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (ScripText copy failed!Status
:String) [], RuntimeException
+ FullyQualifiedErrorId : ScripText copy failed!Status
What did I do wrong?
Ok figured that out. I was running from Windows 7 and that module isn't on there. I went to a Windows 10 machine and didn't get that error, but now I get this:
Cannot find the type for custom attribute 'MyOBN'. Make sure that the assembly that contains this type is loaded.
At C:\Windows\System32\WindowsPowerShell\v1.0\Modules\Invoke-VMScriptPlus\Invoke-VMScriptPlus.psm1:81 char:1
+ [MyOBN('VirtualMachine')]
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: ([MyOBN('VirtualMachine')]:AttributeAst) [], RuntimeException
+ FullyQualifiedErrorId : CustomAttributeTypeNotFound
Did you copy the class MyOBN that I provided in the same post as the Invoke-VMScriptPlus V2 post?
The easiest way is to copy everything in one .ps1 file.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Ok so I copied the Invoke-VMScriptPlus v2 and Message to all users into one ps1 file and called it AllForOne.ps1. I try running that, but I just get errors. Initially if I just leave things the way they are I get this:
Invoke-VMScriptPlus : Cannot process argument transformation on parameter 'VM'. Index was out of range. Must be
non-negative and less than the size of the collection.
Parameter name: index
At C:\Users\emcclure\Desktop\GenScripts\AllForOne.ps1:436 char:31
+ $result = Invoke-VMScriptPlus @sInvP
+ ~~~~~~
+ CategoryInfo : InvalidData: (:) [Invoke-VMScriptPlus], ParameterBindingArgumentTransformationException
+ FullyQualifiedErrorId : ParameterArgumentTransformationError,Invoke-VMScriptPlus
You cannot call a method on a null-valued expression.
At C:\Users\emcclure\Desktop\GenScripts\AllForOne.ps1:436 char:1
+ $result = Invoke-VMScriptPlus @sInvP
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
Then if I change the VM name you have in there to something I want to reboot I get this:
ConvertTo-SecureString : Cannot bind argument to parameter 'String' because it is null.
At C:\Users\emcclure\Desktop\GenScripts\AllForOne.ps1:424 char:41
+ $sPswd = ConvertTo-SecureString -String $pswd -AsPlainText -Force
+ ~~~~~
+ CategoryInfo : InvalidData: (:) [ConvertTo-SecureString], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ConvertToSe
cureStringCommand
Exception calling "GetNetworkCredential" with "0" argument(s): "Object reference not set to an instance of an object."
At C:\Users\emcclure\Desktop\GenScripts\AllForOne.ps1:196 char:1
+ $GuestUser = $GuestCredential.GetNetworkCredential().username
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : NullReferenceException
Exception calling "GetNetworkCredential" with "0" argument(s): "Object reference not set to an instance of an object."
At C:\Users\emcclure\Desktop\GenScripts\AllForOne.ps1:197 char:1
+ $plainGuestPassword = $GuestCredential.GetNetworkCredential().passwor ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : NullReferenceException
Exception calling "CreateTemporaryFileInGuest" with "5" argument(s): "A general system error occurred: vix error codes
= (3033, 0).
" Exception calling "GetNetworkCredential" with "0" argument(s): "Object reference not set to an instance of an
object." Exception calling "GetNetworkCredential" with "0" argument(s): "Object reference not set to an instance of an
object." Cannot bind argument to parameter 'String' because it is null. You cannot call a method on a null-valued
expression. Cannot process argument transformation on parameter 'VM'. Index was out of range. Must be non-negative and
less than the size of the collection.
Parameter name: index 8/6/2018 10:08:56 AM Get-VM VM with name 'vEng' was not found using the specified filter(s).
8/2/2018 2:17:09 PM Set-NetworkAdapter The network "@{Cluster=z610; Name=VLAN3653; VLanId=3653}" doesn't exist on the
host. 8/2/2018 1:58:55 PM Get-VM VM with name 'rsupdtest2' was not found using the specified filter(s). Cannot
validate argument on parameter 'NetworkAdapter'. The argument is null. Provide a valid value for the argument, and
then try running the command again. 8/2/2018 1:58:54 PM Get-NetworkAdapter Please specify at least one of the
following: VirtualMachine, Template or Snapshot. 8/2/2018 1:58:54 PM Get-NetworkAdapter Could not find
VirtualMachine with name 'rsupdtest2'. 8/2/2018 1:58:47 PM Move-VM Value cannot be found for the mandatory parameter
VM 8/2/2018 1:58:47 PM Move-VM Could not find VirtualMachine with name 'rsupdtest2'. 8/2/2018 1:55:20 PM
Import-VApp The file item 'EN-W10ERS3x86_disk0.vmdk' does not match the hash from the manifest. 7/31/2018 2:08:02 PM
Set-NetworkAdapter The network "@{Cluster=z610; Name=VLAN3653; VLanId=3653}" doesn't exist on the host. 7/30/2018
12:05:09 PM Invoke-VMScript The guest operations agent could not be contacted. [0].Exception.Message
At C:\Users\emcclure\Desktop\GenScripts\AllForOne.ps1:220 char:1
+ Throw "$error[0].Exception.Message"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (Exception calli...ception.Message:String) [], RuntimeException
+ FullyQualifiedErrorId : Exception calling "CreateTemporaryFileInGuest" with "5" argument(s): "A general system e
rror occurred: vix error codes = (3033, 0).
" Exception calling "GetNetworkCredential" with "0" argument(s): "Object reference not set to an instance of an ob
ject." Exception calling "GetNetworkCredential" with "0" argument(s): "Object reference not set to an instance of
an object." Cannot bind argument to parameter 'String' because it is null. You cannot call a method on a null-valu
ed expression. Cannot process argument transformation on parameter 'VM'. Index was out of range. Must be non-negat
ive and less than the size of the collection.
Parameter name: index 8/6/2018 10:08:56 AM Get-VM VM with name 'vEng' was not found using the specified filter(s)
. 8/2/2018 2:17:09 PM Set-NetworkAdapter The network "@{Cluster=z610; Name=VLAN3653; VLanId=3653}" doesn't exist
on the host. 8/2/2018 1:58:55 PM Get-VM VM with name 'rsupdtest2' was not found using the specified filter(s).
Cannot validate argument on parameter 'NetworkAdapter'. The argument is null. Provide a valid value for the argum
ent, and then try running the command again. 8/2/2018 1:58:54 PM Get-NetworkAdapter Please specify at least one o
f the following: VirtualMachine, Template or Snapshot. 8/2/2018 1:58:54 PM Get-NetworkAdapter Could not find Vir
tualMachine with name 'rsupdtest2'. 8/2/2018 1:58:47 PM Move-VM Value cannot be found for the mandatory paramete
r VM 8/2/2018 1:58:47 PM Move-VM Could not find VirtualMachine with name 'rsupdtest2'. 8/2/2018 1:55:20 PM Impo
rt-VApp The file item 'EN-W10ERS3x86_disk0.vmdk' does not match the hash from the manifest. 7/31/2018 2:08:02 PM
Set-NetworkAdapter The network "@{Cluster=z610; Name=VLAN3653; VLanId=3653}" doesn't exist on the host. 7/30/20
18 12:05:09 PM Invoke-VMScript The guest operations agent could not be contacted. [0].Exception.Message
So the machine names you see there, rsupdtest2 and EN-W10ERS3x86 are not machine names I specified in the script, so I don't know why it's pulling those. All I just really want to do is take your scripts and put them into this one:
$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 = '&C:\Users\emcclure\Desktop\GenScripts\RebootMessage.ps1'
Invoke-VMScriptPlus -vm $vm -ScriptText "C:\Users\emcclure\Desktop\GenScripts\RebootMessage.ps1" -ScriptType PowerShell -GuestCredential $GuestCredential | Format-List | Out-File reboot.txt -append
}
So that way all VM's in a folder I specify just get the prompt all at once. I'd make it a scheduled task to happen on a certain day, but I'm still new to PowerShell and thinking I'm just not doing something right to make this all work.
Looks like you didn't update all the required fields.
I do for example see my test VM with the name 'vEng' in your errors.
I would need to see the .ps1 file you created.
Can you attach it?
Mask away the sensitive fields you might have in there
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Try the attached .ps1 file.
You will have to update lines 424 & 425 with an account and password.
This account needs to be able to run scripts on the target station and access the DLL API
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Hi LucD,
So I ran the script from my desktop machine and get this:
Resolve-DnsName : ip.removed.in-addr.arpa : DNS name does not exist
At C:\Users\emcclure\Desktop\test.ps1:237 char:19
+ $hostName = Resolve-DnsName -Name $ip | Select-Object -ExpandPr ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ResourceUnavailable: (ip.removed.in-addr.arpa:String) [Resolve-DnsName], Win32Excepti
on
+ FullyQualifiedErrorId : DNS_ERROR_RCODE_NAME_ERROR,Microsoft.DnsClient.Commands.ResolveDnsName
Invoke-WebRequest : Cannot bind parameter 'Uri'. Cannot convert value
"https://:443/guestFile?id=197&token=52cfa257-a30a-19ea-d060-af7c849421d1197" to type "System.Uri". Error: "Invalid
URI: The hostname could not be parsed."
At C:\Users\emcclure\Desktop\test.ps1:239 char:44
+ $copyResult = Invoke-WebRequest -Uri $filePath -Method Put -Bod ...
+ ~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Invoke-WebRequest], ParameterBindingException
+ FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
ScripText copy failed!Status
At C:\Users\emcclure\Desktop\test.ps1:241 char:9
+ Throw "ScripText copy failed!`rStatus $($copyResult.StatusCod ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (ScripText copy failed!Status :String) [], RuntimeException
+ FullyQualifiedErrorId : ScripText copy failed!Status
I figured it's in a different location, so let's use a machine that's in the same location that's on the same vCenter server. So I ran it from there (with the proper creds) and nothing. It appears to run, doesn't give me any errors or any output, just goes to the next line in PowerCLI as if it's all good. I figure I'll try running it in PowerShell on that same machine and all I get is this:
Unable to find type [VMware.VimAutomation.ViCore.Types.V1.Inventory.VirtualMachine].
At C:\Users\emcclure\Desktop\test.ps1:117 char:5
+ [VMware.VimAutomation.ViCore.Types.V1.Inventory.VirtualMachine[]] ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (VMware.VimAutom....VirtualMachine:TypeName) [], RuntimeException
+ FullyQualifiedErrorId : TypeNotFound
You cannot call a method on a null-valued expression.
At C:\Users\emcclure\Desktop\test.ps1:440 char:1
+ $result = Invoke-VMScriptPlus @sInvP
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
So what am I missing? I should be able to run this from anywhere right and it should just work? It should be able to find the machine in the vCenter and run the script? For the creds I'm using the local administrator account, so that shouldn't be a problem as far as permissions go.
Looks like DNS resolution doesn't work on the machine where you call the Invoke-VMScriptPlus function.
The function replaces the IP in the URI (for the script upload to the VM's guest OS) returned by Guest Operations.
This is done to avoid certificate errors on the HTTPS connection
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Ok, I'm not sure why DNS resolution would not work on the machine I'm typing this from as I can go anywhere on the internet, access internal resources by dns name, etc without issue. When I run the script from a machine that's in the same subnet and location as the target machine though the script just runs, but that's it. Nothing appears on the target machine. I've even disabled AV to make sure that wasn't causing a problem. Windows firewall is off as well, so this makes no sense to me as to why it's not working. This is rather confusing and I was hoping this would work, but I just don't understand why it's working for you and not for me.
The DNS name resolution is required to translate the IP address in the URI returned by the Guest Operations.
That URI is used to upload the script, via the ESXi node, to the VM.
In your output it looks like the name resolution of the IP address of the ESXi node on which the target VM is running, doesn't work.
All subsequent errors are a consequence of this 1st error.
You can check if this returns anything on your station
Resolve-DnsName -Name $ip
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Hi LucD,
Looking at this page: Invoke-VMScriptPlus v2 - LucD notes do I need to be using PowerShell v6.0.2? I think I'm running 5.1 right now. If so where did you download it exactly so I can use the same version?
Thanks.
No, PS 5.1 is fine
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference