How to run VMware commands from remote scripts on windows - powershell

Have a local basic Powershell form for searching and creating VMware virtual machines.
Using new powershell powerCLI module, as described in link
Let's take Get-VM for example:
LOGIC: Type a certain string in TextBox > click search > prints VM's status/parameters in the form
The problem is, I can't execute Get-VM straight away from the script, but first have to connect using Connect-VIServer command and only than Get-VM will work
Is there any way to do it from the script? Something similar to -m flag of commands plink or putty.
Like: Connect-VIServer -server testvc -flagForExample "commands_list.txt"

Yes, you can. Before providing an immediate answer I'd like to explain what is actually happening.
When you call Connect-VIServer the command sets the value of the variable $DefaultVIServer behind the scenes, which is later used by other cmdlets (such as Get-VM).
However, the Get-VM documentation states that there is a Server parameter available. Which means that you can store your server connection in a variable and then pass it to the Get-VM cmdlet.
Here's a pseudo-code example:
$server = Connect-VIServer -server testvc
Get-VM -Server $server
Furthermore, the Get-VM supports an array of servers, so theoretically you can run the cmdlet on multiple servers at once. For example:
$server1 = Connect-VIServer -server testvc
$server2 = Connect-VIServer -server testvc2
Get-VM -Server #($server1, $server2)

Related

How to start a process on remote computer using powershell WMI?

We are upgrading our servers and need to stop our application before we perform update and then start it back again.
I was reading online about this and most of the links talk about remoting but some of the machines don't have PSRemoting enabled and therefore I need to stick to using wmi.
Would appreciate some pointers on this ?
To terminate the process I am using something like below:
$processes=Get-WmiObject -Class Win32_Process -ComputerName $Address -Filter "name='$ProcessName'"
foreach ($process in $processes)
{
$returnval = $process.terminate()
$processid = $process.handle
if($returnval.returnvalue -eq 0) {
write-host "The process $ProcessName `($processid`) terminated successfully"
}
else {
write-host "The process $ProcessName `($processid`) termination has some problems"
}
}
You don't say what OS and PS version(s) you are trying to deal with.
You are not saying what or if you are having issues with what you posted.
Even using only WMI, you still must have Windows WMI properly configured to do this as well as know Windows is not out of the boxed configured to let you what you are after without making all the proper WinRM, WMI and firewall manual configs.
It's far simpler just to enable PSRemoting via GPO.
Otherwise, you will need tp look toward maybe winrs.exe or MS SysInternals psexec.
winrs
Windows remote Management allows you to manage and execute programs remotely.
PsExec v2.2
Also back to my what OS and PowerShell version you are using. There is the
Invoke-Wmi​Method
Which can lead to stuff like this ---
Invoke-WmiMethod -ComputerName $TargetMachine -Namespace root\cimv2 -Class Win32_Process..."

How to add vmware tag to a virtual machine if it has spaces in the tag name

I am trying to create a script that adds "Tags" to my virtual machine. I am using Powershell/PowerCLI to do this. I am able to add the names if there are no spaces in the tag name. For example, Application tag is name "Test" and it adds it to the server fine. But if the owner name is "John Doe" it will not take because of the space. Here is myscript thus far:
$vCenter = "test.com"
$ServerName = "test1"
Add-PSSnapin VMware.VimAutomation.Core
Connect-ViServer -server $vCenter -ErrorAction Stop
$AppTag = Read-Host "What is the Application tag name for $ServerName"
$myTag1 = Get-Tag $AppTag
$myVM = Get-VM "$ServerName"
New-TagAssignment -Tag $myTag1 -Entity $myVM
$AppOwnerTag = Read-Host "What is the Application Owner tag name for $ServerName"
$myTag2 = Get-Tag $AppOwnerTag
$myVM = Get-VM $ServerName
New-TagAssignment -Tag $myTag2 -Entity $myVM
$CreatedByTag = Read-Host "What is the Created By tag name for $ServerName"
$myTag3 = Get-Tag $CreatedByTag
$myVM = Get-VM $ServerName
New-TagAssignment -Tag $myTag3 -Entity $myVM
Yes, you may use spaces in your tag names. The problem you are running into may be due to the version of PowerShell, or an issue if you have multiple tags with the same name or the same tag across vCenters:
First confirm your PowerShell VMware PowerCLI version is at least 6.5.3 with the command Get-PowerCLIVersion, or if you like to be fancy Get-Module -Name VMware.* | Select Name,Version. According to VMware PowerCLI Blog for version 6.5.3, New-TagAssignment has a related issue and has been fixed. If you are unsure how to upgrade or install VMware PowerCLI, you can Import-Module VMware.PowerCLI as Administrator as described in this other VMware PowerCLI Installation Blog if you have the PackageManager installed as described in this 4sysops article.
Another thing is to confirm that the correct and only one vCenter is active if your query. For example, you may need to modify your command to New-TagAssignment -Tag $myTag3 -Entity $myVM -Server $vCenter. The $vCenter is the same name you use when you Connect-VIServer $vCenter, which in your case I assume is "test.com". If you logged into, and not out of, other vCenters before performing this query, this may be your fix. For example, I do not see Disconnect-VIServer $vCenter at the bottom of your script which is why I suggest this.
The last thing to try is you may have the same tag name in multiple tag categories. The recommendation in VMware Communities is to get the tag explicitly by specifying the category in the command, such as $myTag1 = Get-Tag $AppTag -Category $myCategory. Another less desirable option may be to rename your tags in those categories so they do not overlap.

Command .startservice() not working in Powershell

I have a little script where the user enters the script name (the description name) and has the option to modify the properties. This is done with a GUI interface: a textbox and some drop-down lists.
I tried several ways to make it but none of them worked.
Here is how I retrieve the service information:
$thisservice = Get-WmiObject -Class Win32_Service -ComputerName $Server | Where { $_.displayName -eq $serviceBox.text }
I look at $server computer and match up the "service display name" to the value contained in the textbox field: $_.displayName -eq $serviceBox.text. This works well, if I list the data I get exactly what is in the service console: .name, .description, .state, .startmode, .displayname
I store the service name in a variable:
$servicename = $thisservice.name
I know you can not start a service unless it is on "Manual" or "auto" so first I set it to auto. Here I tryed to different ways but none worked:
$servicename.ChangeStartMode("Auto")
and
Set-Service $servicename -StartupType Auto
and then I start the service (but this doesn't work either even if I preset the state-mode on Auto form the service manager):
$servicename.startservice()
Also the $servicename.stopservcie() fails.
I tried this on 2 different machines, on both I have admin rights, I tryed running the script with Admin mode, same result. I even tried it directly from PS console and I couldn't change the service state!
What am I doing wrong?
Your problem is here: $servicename = $thisservice.name
By doing that you set $servicename to be a string, not the service object. Therefore you can't call service methods on it any more.
You should be able to just do:
$thisservice.ChangeStartMode("Automatic")
$thisservice.StartService()

New-NetLbFoTeam: Unknown or Random InterfaceAlias names

I'm trying to automate the create of a NIC team during an unattended Windows Server 2012 R2 install.
I've got the following PowerShell code:
New-NetLbFoTeam -Name "LANTeam" -TeamMembers "Ethernet", "Ethernet 2" -TeamNicName "LAN" -TeamingMode SwitchIndependent -LoadBalancingAlgorithm TransportPorts -Confirm:$false -ErrorAction SilentlyContinue
That works well for my Dell servers, but the HP servers Windows randomly gives InterfaceAliases to. One install Ethernet 2 could be the Broadcom, the next it could be the NC373i card.
What I'm trying to accomplish is set the -TeamMembers parameter to be the two NICs that match "HP NC373i*" wildcard for the InterfaceDescription, or have a valid DHCP address. The other team I'll do something similar, but don't retrieve a valid IP address.
I've tried setting a hash table, but not getting it to stick in there correctly.
Any assistance would be greatly appreciated!
I was able to figure it out on my own. I output the get-netadapter output to a variable, and added that:
$adapters = Get-netAdapter –InterfaceDescription “HP NC*”
$nicList = #()
Foreach ($nic in $adapters) {$nicList += $nic.Name}
$team = New-NetLbfoTeam -Name “LANTeam” -TeamNicName “LAN” -TeamMembers ($nicList) -TeamingMode SwitchIndependent -LoadBalancingAlgorithm HyperVPort -Confirm:$false

Powershell to shut down a VM

I have a small Powershell script that is used to shut down my virtual machines in event of an extended power outage. It takes a specific VM object and forces a shutdown.
Function DirtyShutdown
{ param([VMware.VimAutomation.ViCore.Impl.V1.Inventory.VirtualMachineImpl]$VM )
$VM | Stop-VM -Confirm:$false
}
I would like to speed up this process using the start-job command to run all these tasks in parallel. I have tried using several variants including the following which I believe to be correct.
Start-Job -InputObject $VM -ScriptBlock{ $input | Shutdown-VMGuest -Confirm:$false }
Based on the Receive-Job output it appears the problem is the snap in in use (added before the above function is called) is not loaded in the context of Start-Job.
What is the correct syntax to make this happen?
While I appreciate the desire to use PowerShell v2's job subsystem for this task, note that vCenter has a built-in job system which you can take advantage of here. Most PowerCLI cmdlets which perform a change to your environment have a RunAsync parameter. To know which ones, run this piece of PowerShell code:
get-help * -parameter runasync
The RunAsync parameter will take your command(s) and queue them up in vCenter. The cmdlet will return a task object and then immediately return control back to your script.
To turn this into an answer in your case, simply append "-runasync" to the end of your Stop-VM command, like so:
$VM | Stop-VM -Confirm:$false -RunAsync
Each time you start a job, PowerShell creates a new runspace. This means a new environment that you may need to initialize, and that includes loading snap-ins and connecting to your VI Server. Start-Job has a parameter that you can use here called InitializationScript. Try something like this:
Start-Job -InitializationScript { Add-PSSnapin VMware.VimAutomation.Core } {
Connect-ViServer myserver
Get-VM foo | Stop-VM
}