Showing posts with label GoToMeeting. Show all posts
Showing posts with label GoToMeeting. Show all posts

Friday, May 1, 2015

Further automating GoToMeeting on a Windows client

To continue to build on my previous post I decided to add a bit of id10t proofing to my automation script.

The only thing that the script does not do is logon the user (I mean, who really wants to handle (secure) user credentials in the first place).

This is here for my benefit, but I am sure that this can be useful to someone else.  There is nothing here that I did not discover through internet search or my own discovery.

I don't register an event monitor for a simple reason, I cannot guarantee that the execution of this program has admin rights.  Admin access on the local computer is required to register for an event, though it would be nice for a user to be able to register for user mode process events.

Enjoy!

<#
.SYNOPSIS
    This will install the full G2M client for hosting meetings if it is not already installed prior to joining the meeting.
.PARAMETERS
    $g2mId - the meeting ID that will be joined. This can be any g2m ID, the user will be 'joining' an existing meeting (theirs or someone else's).
    $g2mKill - if there is a G2M already running that will be killed and the passed G2M will be joined.
.AUTHOR
    Brian Ehlert, Citrix Labs, Redmond, WA
#>


function startG2m
{

Param(
    [parameter(Mandatory = $false)]
    [ValidateNotNullOrEmpty()]
    [string]$g2mId,
    [parameter(Mandatory = $false)]
    [boolean]$g2mKill = $false
)

    # finds the path of g2mstart.exe
    # each version is in its own folder so you have to find the latest / most recent version
    $gtmFolder = Get-ChildItem -Path $env:LOCALAPPDATA\Citrix\GotoMeeting -ErrorAction SilentlyContinue | Sort-Object -Property Name -Descending | Select-Object -First 1

    if ( !($gtmFolder) ) {
        "G2M is _not_ installed. Installing the hosting client."
       
        # Install the GTM client
        Start-Process "https://global.gotomeeting.com/meeting/host"

        Start-Sleep -Seconds 2
        # close the IE tab that was opened
        $ie = (New-Object -COM "Shell.Application").Windows() | where { $_.Name -eq "Internet Explorer" }

        foreach ($tab in $ie) {
            if ( $tab.LocationURL -match "download.citrixonline.com" ) {
                do {
                    Start-Sleep -Seconds 1
                } until ( $tab.Busy -eq $false )
                $tab.Quit()
            }
        }

        # wait for the client logon prompt
        Do { Start-Sleep -Seconds 2 } until ( Get-Process -Name "g2mlauncher" -ErrorAction SilentlyContinue )

        startG2m -g2mId $g2mId
    } else {
        # is there an existing G2M that needs to be killed?
        # if we reconnect to the same meeting too quickly we will have ourself as an orphaned attendee.
        if ($g2mKill) {
            if ((Get-Process -Name "g2mui" -ErrorAction SilentlyContinue)) {
                "Killing the running G2M"
                Get-Process -Name "g2mui" | Stop-Process -Force
                Do { Start-Sleep -Seconds 2 } until ((Get-Process -Name g2mlauncher -ErrorAction SilentlyContinue).Handles -lt 500)
            } else {"The user was not joined to a G2M"}
        }

        "G2M is installed, using the installed client"
        # build the path
        $g2mstartPath = $gtmFolder.FullName + "\g2mstart.exe"

        # Define the arguments - double quotes is important for g2mstart.exe
        $g2mArgs = ("'/Action Join' '/MeetingID $g2mId'" ).Replace("'",'"')

        # is there a G2M video conference running?  We will collide if there is.
        if (!(Get-Process -Name "g2*conference")) {
            if ( $g2mId ){
                "Joining the meeting"
                Start-Process -FilePath $g2mstartPath -ArgumentList $g2mArgs
            } else { "No G2M ID was provided" }
        } else { "A G2M is already running" }
    }
}


#Example
startG2m -g2mId 000000000 -g2mKill $true
Start-Sleep -Seconds 5  # wait for the conference to initialize
$process = Get-Process -Name "g2*conference"
Wait-Process -InputObject $process # wait for the person to end the conference
# Do something else
"boo!"

Tuesday, April 28, 2015

PowerShell launching GoToMeeting on Windows

It isn't every day that you need to execute GUI application commands via command line. 
After all there are some GUI applications that simply don't design for it and don't document it. 
It really is not a use case that they expect.

GoToMeeting is just one of those applications.  It is never anticipated that a person might want to launch a session via a command line.

Well, I recently had such a case.  And I have two different ways to handle this.

First, a little bit about the application. 
GoToMeeting is a user mode application that is 100% in a user's profile.  It is web based, and has a web based launcher that always delivers the latest and greatest client.  The client side application is not found under %ProgramFiles%.

Launching / Joining a Meeting:
Method 1 (the modern way):

Start-Process http://www.gotomeeting.com/join/$g2mId

Method 2 (the legacy way):
This method was the most prevalent result when I searched.  Send arguments to g2mstart.exe.
However, this is also the most problematic.  GoToMeeting updates its client pretty frequently, and each client is in a new folder, so if you want the latest client you have to do a bit of discovery and you must format the string properly.

# each version is in its own folder so you have to find the latest / most recent version
$gtmFolder = Get-ChildItem -Path $env:LOCALAPPDATA\Citrix\GotoMeeting | Sort-Object -Property Name -Descending | Select-Object -First 1

# build the path
$g2mstartPath = $gtmFolder.FullName + "\g2mstart.exe"

# Define the arguments - double quotes is important for g2mstart.exe
$g2mArgs = ("'/Action Join' '/MeetingID $g2mId'" ).Replace("'",'"')

# start the meeting
Start-Process -FilePath $g2mstartPath -ArgumentList $g2mArgs


It would be improper of me not to focus on the modern way of doing this.  The way that is expected.  However, the one thing that doing it that way will accomplish is that the client might be forced into an update.  If you don't want your client updated, but instead want a nice seamless join, you might want to use the legacy method.

Allow me to present the modern and legacy functions:


function startG2m {
Param(
 [string]$g2mId
)

  # start the meeting
  Start-Process http://www.gotomeeting.com/join/$g2mId
  Start-Sleep -Seconds 2

  # close the IE tab that was opened
  $ie = (New-Object -COM "Shell.Application").Windows() | where { $_.Name -eq "Internet Explorer" }

  foreach ($tab in $ie) {
    if ( $tab.LocationURL -match "gotomeeting.com" ) {
      do { 
Start-Sleep -Seconds 1 } until ( $tab.Busy -eq $false )
      $tab.Quit()
    }

  }
}



function startG2mLegacy {

Param(
 [string]$g2mId
)

  # finds the path of g2mstart.exe
  # each version is in its own folder so you have to find the latest / most recent version

  $gtmFolder = Get-ChildItem -Path $env:LOCALAPPDATA\Citrix\GotoMeeting | Sort-Object -Property Name -Descending | Select-Object -First 1

  # build the path
  $g2mstartPath = $gtmFolder.FullName + "\g2mstart.exe"

  # Define the arguments - double quotes is important for g2mstart.exe
  $g2mArgs = ("'/Action Join' '/MeetingID $g2mId'" ).Replace("'",'"')

  # start the meeting
  Start-Process -FilePath $g2mstartPath -ArgumentList $g2mArgs

}


Now, using these two functions is identical.

startG2m $g2mId

But, being a person who does test I always like a bit of error handling, I hate popup dialogs.  And I especially hate dialogs if they interrupt my nice automation - a real buzz killer.

Here I have two checks - 1. is there an existing meeting that I need to kill to connect to a new meeting ("there can be only one"  - the Highlander) and 2. Don't start it if one is running.

# is there an existing G2M that we need to kill?
# Note - if we reconnect to the same meeting too quickly we will have ourself as an orphaned attendee.
if ($g2mKill) {
  if ((Get-Process -Name "g2mui" -ErrorAction SilentlyContinue)) {
    "Killing the running G2M"
    Get-Process -Name "g2mui" | Stop-Process -Force
    Do { Start-Sleep -Seconds 2 } until ((Get-Process -Name g2mlauncher).Handles -lt 500)
  } else {"The user was not joined to a G2M"}
}

# is there a G2M video conference running? We will collide if there is.
if (!(Get-Process -Name "g2*conference")) {
  if ( $g2mId ){

    # Start the G2M
    startG2m -g2mId $g2mId
  } else { "No G2M ID was provided" }
} else { "A G2M is already running" }