VMware Horizon Community
pegduffy
Contributor
Contributor
Jump to solution

Is it possible to programmtically, using 6.5.1 PS and API 7.1, to Reset/Refresh Horizon Desktop in a Problem State using PowerShell using only an HVServer connection

I read this article.

Reset/Refresh Horizon Desktop in a Problem State using PowerShell

I read the answer here : Various_Scripts/remove_faulty_VDI_desktop.ps1 at master · Magneet/Various_Scripts · GitHub

Is there a way, not to remove of delete the Agent_Unreachable machine but to just try a desktop refresh or the equivalent, without doing a Connect-VIServer, but using only  the HV server connection?

I have tried many of the API commands of this nature but can not seem to find a way to do this without a VIServer connection.

Is it possible? Has anyone done it? Would you be willing to share a snippet of your code to guide me.

I have been able to get-hvsummary for each Pool, using -State Unreachable.

Basically, my VMware sysadmins believe this is possible and I am tryng to write the code. I have looked at many calls in the API but get message like "You need a connection to VI Server."

I have a script  making a list of machines in an unreachable state...and then 15 minutes later, by writing results to files and reading previous file back in again....if machine is still unreachable 15 minutes later I want to do whatever is equivalent to a Desktop_Refresh. I have machineids etc.

Peg Duffy

1 Solution

Accepted Solutions
jrodsguitar
Enthusiast
Enthusiast
Jump to solution

*Updated the script slightly.*

https://get-cj.com/2018/04/02/how-to-refresh-vmware-horizon-desktops-using-powershell-powercli/

I was inspired by pegduffy​ after you posted that snippet of code. I wrote a new function that refreshes a desktop or a list of desktops. Much of the reference for this comes from the various VMWare sites and Horizon API reference pages. Please post your solution as well when you find it. If you want Smiley Happy  It's good to see the way others do it. Good learning experience.

Example:

$machines = ('machinename1', 'machinename2')

refresh-ViewDesktop -machines $machines -viewserver  'Horizon_Connection_Server'

function refresh-ViewDesktop {

  [CmdletBinding()]

  [OutputType([PSCustomObject])]

    param(

              

        [string[]]$machines,

        [string]$viewserver

       

    )

$cred = Get-Credential

$hvServer = Connect-HVServer -server $viewserver -Credential $cred

$hvServices = $hvServer.ExtensionData

$queryService = New-Object VMware.Hv.QueryServiceService

$query = New-Object VMware.Hv.QueryDefinition 

$query.queryEntityType = 'MachineNamesView'

[VMware.Hv.QueryFilter []] $filters = @()

foreach ($machine in $machines){

       

    $filters += new-object VMware.Hv.QueryFilterEquals -property @{'memberName' = 'base.name'; 'value' = $machine}

}

$orFilter = new-object VMware.Hv.QueryFilterOr -property @{'filters' =  $filters}

$query.Filter = $orFilter

$queryResults = $queryService.QueryService_Create($hvServices,$query)

$finalmachine = @()

foreach ($result in $queryResults.Results){

    [VMware.Hv.MachineNamesView]$machineNamesView = $result

    $properties = @{

             

        machineid = $machineNamesView.id

        names = $machineNamesView.base.name

        desktopId = $machineNamesView.base.Desktop

                }

    $finalmachine += New-Object -TypeName pscustomobject -Property $properties

}

$desktopService = New-Object VMware.Hv.DesktopService

$machineService = New-Object VMware.Hv.MachineService

foreach($object in $finalmachine){

    $desktoprefreshSpec = New-Object VMware.Hv.DesktopRefreshSpec

    $desktoprefresheSpecHelper = New-Object VMware.Hv.DesktopService+DesktopRefreshSpecHelper

    $desktoprefreshSpec.Machines = $object.machineid

    $desktoprefreshSpec.LogoffSetting = $desktoprefresheSpecHelper.LOGOFF_SETTING_FORCE_LOGOFF

    $desktoprefreshSpec.StartTime = $null

    $desktopService.Desktop_Refresh($hvServices, $machineNamesView.base.Desktop,$desktoprefreshSpec)

    Write-Output ""

    Write-Output "Refreshing Machines"

    $($object.names)

    }

}

Disclaimer: ~I'm just an IT enthusiast with no certs, no degrees, no training, in any of this crap, but I know my way around google so that's all that matters. -Jose Rodriguez~

Blog: https://powershell.house/

View solution in original post

12 Replies
jrodsguitar
Enthusiast
Enthusiast
Jump to solution

Why are your VMWare admins not writing this script? Anyway. I had a few minutes and thought this would be be helpful to you:

You'l need this PowerCLI-Example-Scripts/Modules/VMware.Hv.Helper at master · vmware/PowerCLI-Example-Scripts · GitH...

This gives you the full arsenal of the Horizon API and the vmware.view.broker snapin from the Horizon server in case you want to do other things.

You could also replace, from line 31, the Send-VDIVMReset with Send-VDILinkedCloneRefresh for example if you needed to do a refresh instead of a reset and so on.

You're welcome Smiley Wink

#Jose Rodriguez

$viewserver = "NAME_OF_VIEW_SERVER"

if($cred -eq $null){

$cred = Get-Credential

}

if($connect -eq $null){

$connect = Connect-HVServer -server $viewserver -Credential $cred

}

$session = New-PSSession -Computername $viewserver

$scriptBlock = {

    Add-PSSnapin vmware.view.broker

}

 

#Run the script block on the connection server.  $argument1 will become $computer in the scriptblock and so forth

Invoke-Command -Session $session -ScriptBlock $scriptBlock

Import-PSSession -Session $session -Prefix VDI -Module VMware*

 

(Get-HVMachine -PoolName NAME_OF_POOL).base | where {$_.basicstate -eq 'AGENT_UNREACHABLE'} | foreach { Get-VDIDesktopVM -Name $_.name | Send-VDIVMReset -id $_.id }

Remove-PSSession $session

~I'm just an IT enthusiast with no certs, no degrees, no training, in any of this crap, but I know my around google so that's all that matters. -Jose Rodriguez~

Blog: https://powershell.house/
Magneet
Hot Shot
Hot Shot
Jump to solution

can be done certainly, have written it out on my blog: https://www.retouw.nl/powercli/removing-faulty-horizon-desktops-using-powercli/

I see I might need to change it so it doesn't use the vmware.hv.helper (needs lots of improvements, working on that) and you can choose to remove or reset, just comment the right line out

pegduffy
Contributor
Contributor
Jump to solution

Jose,

Thanks so much for your answer. I am sorry I steered you wrong. I am using Horizon 7 Version 7.2 so I can not use snap-ins. The commandlets you are using are no longer available.

No Send-VDILinkedCloneRefresh in this version. Just the View API - VMware API Explorer - VMware {code}

View API 7.1.0, Agent version 7.2.0

I would like to do what is on the View Horizon Admin Center Version 7 as

Catalog -> Desktop Pools -> Select one of the Pools....-> Look at Inventory of Machines -> Select one -> View Composer -> Refresh

So the previous Send-VDILinkedCloneRefresh is probably what I needed prior to this version.

I am using VMWare.Hv.Helper....but no equivalent commandlets there that I can tell.

Reply
0 Kudos
pegduffy
Contributor
Contributor
Jump to solution

Magneet,

I do not want to delete the machine. I want to Refresh it only.

Is it possible to do this using only a connection to an HVserver....Connect-HVServer but not using a Connect-VIServer?

I did see your code and you solution. Perhaps what I am attempting is not possible.

Do you know?

Reply
0 Kudos
pegduffy
Contributor
Contributor
Jump to solution

Interested parties,

It took a bit of browsing git hub....but I think

I just found code on github that may have the snippet I need.

GitHub - cjrege/HorizonView: VMware Horizon View PowerShell Module

Specifically see function Invoke-ViewComposerTask

And in that function:

   if ($Refresh){
   $refreshSpec = New-Object VMware.Hv.DesktopRefreshSpec
   $refreshSpecHelper = New-Object VMware.Hv.DesktopService+DesktopRefreshSpecHelper
   switch ($LogOffSetting){
   "WAIT_FOR_LOGOFF" {
   $refreshSpec.LogoffSetting = $refreshSpecHelper.LOGOFF_SETTING_WAIT_FOR_LOGOFF
  }
   "FORCE_LOGOFF" {
   $refreshSpec.LogoffSetting = $refreshSpecHelper.LOGOFF_SETTING_FORCE_LOGOFF
  }
  default {
   throw "Logoff setting not permitted"
  }
  }
   if ($StartTime){
   $refreshSpec.StartTime = $StartTime
  }
   if ($StartNow){
   $refreshSpec.StartTime = (Get-Date).AddMinutes(1)
  }
   $refreshSpec.Machines = $machines.Id
   $refreshSpec.StopOnFirstError = $StopOnFirstError
   # Execute refresh
   Write-Host Refreshing $desktopPool.Base.Name -ForegroundColor Cyan
   $desktopService.Desktop_Refresh($HvServices, $desktopPoolId, $refreshSpec)
  }

Don't know why this was pasted into a table...but here you can see the code above that should refresh the desktop using machine id

Written by user cjrege. I am going to try now. Thanks to all and will post when I solve this.

jrodsguitar
Enthusiast
Enthusiast
Jump to solution

*Updated the script slightly.*

https://get-cj.com/2018/04/02/how-to-refresh-vmware-horizon-desktops-using-powershell-powercli/

I was inspired by pegduffy​ after you posted that snippet of code. I wrote a new function that refreshes a desktop or a list of desktops. Much of the reference for this comes from the various VMWare sites and Horizon API reference pages. Please post your solution as well when you find it. If you want Smiley Happy  It's good to see the way others do it. Good learning experience.

Example:

$machines = ('machinename1', 'machinename2')

refresh-ViewDesktop -machines $machines -viewserver  'Horizon_Connection_Server'

function refresh-ViewDesktop {

  [CmdletBinding()]

  [OutputType([PSCustomObject])]

    param(

              

        [string[]]$machines,

        [string]$viewserver

       

    )

$cred = Get-Credential

$hvServer = Connect-HVServer -server $viewserver -Credential $cred

$hvServices = $hvServer.ExtensionData

$queryService = New-Object VMware.Hv.QueryServiceService

$query = New-Object VMware.Hv.QueryDefinition 

$query.queryEntityType = 'MachineNamesView'

[VMware.Hv.QueryFilter []] $filters = @()

foreach ($machine in $machines){

       

    $filters += new-object VMware.Hv.QueryFilterEquals -property @{'memberName' = 'base.name'; 'value' = $machine}

}

$orFilter = new-object VMware.Hv.QueryFilterOr -property @{'filters' =  $filters}

$query.Filter = $orFilter

$queryResults = $queryService.QueryService_Create($hvServices,$query)

$finalmachine = @()

foreach ($result in $queryResults.Results){

    [VMware.Hv.MachineNamesView]$machineNamesView = $result

    $properties = @{

             

        machineid = $machineNamesView.id

        names = $machineNamesView.base.name

        desktopId = $machineNamesView.base.Desktop

                }

    $finalmachine += New-Object -TypeName pscustomobject -Property $properties

}

$desktopService = New-Object VMware.Hv.DesktopService

$machineService = New-Object VMware.Hv.MachineService

foreach($object in $finalmachine){

    $desktoprefreshSpec = New-Object VMware.Hv.DesktopRefreshSpec

    $desktoprefresheSpecHelper = New-Object VMware.Hv.DesktopService+DesktopRefreshSpecHelper

    $desktoprefreshSpec.Machines = $object.machineid

    $desktoprefreshSpec.LogoffSetting = $desktoprefresheSpecHelper.LOGOFF_SETTING_FORCE_LOGOFF

    $desktoprefreshSpec.StartTime = $null

    $desktopService.Desktop_Refresh($hvServices, $machineNamesView.base.Desktop,$desktoprefreshSpec)

    Write-Output ""

    Write-Output "Refreshing Machines"

    $($object.names)

    }

}

Disclaimer: ~I'm just an IT enthusiast with no certs, no degrees, no training, in any of this crap, but I know my way around google so that's all that matters. -Jose Rodriguez~

Blog: https://powershell.house/
Magneet
Hot Shot
Hot Shot
Jump to solution

I agree on jrodsguitar's solution but it's stupid that the spec is required that only makes it more complicated Smiley Happy

pegduffy
Contributor
Contributor
Jump to solution

The solution posted will work. Here is my solution. (different and not yet refactored so forgive)

Magneet
Hot Shot
Hot Shot
Jump to solution

pegduffy​ & jrodsguitar​ you guys want to put this in the vmware.hv.helper module? Could do it as well myself for you based on your work

pegduffy
Contributor
Contributor
Jump to solution

Magneet,

Please feel free to use any of my code. And thank you for the hv.helper module. I suspect you tcan integrate the code better than I into that module. I have used the module in my code as you see and thank you again for that.

I am now testing my code in a test environment by putting test machines in unreachable_agent state - basically logging into a specific desktop and killing of the Agent service, -  and then refreshing them (my test environment is isolated into a single pool specific test pool). I have tested a bit before posting so the code works for me. Please enjoy. Nice to be able to "pay it forward".


Thanks to you, cjrege, and  jrodsguitar!

jrodsguitar
Enthusiast
Enthusiast
Jump to solution

Yes that would be cool. I've learned so much from the community so giving back is not a problem Smiley Happy

Blog: https://powershell.house/
Reply
0 Kudos
Magneet
Hot Shot
Hot Shot
Jump to solution

not sure when but I will definitely try to get this into the module, I am also just a contributor to it by the way. Untill now I only fixed or found a few bugs but have a couple of new functions & fixes waiting for a commit Smiley Happy

Reply
0 Kudos