Posted by BigNuggets
Digon

PowerShell Based Host Deployment (.msi)

Step 1) Go to your Design & Deploy page and click Add Host>Host, do all your site/client settings and make sure Allow account assignment without confirmation is checked. Then download the Assignment Tool, click Save.

Step 2) Click the Edit button next to your newly created client host, copy the Configuration ID and the API token. Save those for later, now click Download MSI. (note: if you keep you're using the same configuration (logo, colors) for all of your MSI's you won't have to repeat this step for other sites/clients.)

Step 3) Uploaded your TeamViewer_Host.msi and your TeamViewer_Assignment.exe somewhere which will be accessible from where you want to deploy.
(e.g. http://mywebsite.com/TV/TeamViewer_Host.msi, http://mywebiste.com/TV/TeamViewer_Assignment.exe)

Step 4) Save those urls, now we're ready to run the script, you will have to find a way to bypass executionpolicy on PowerShell (it's pretty easy..), when you run the script use it as such (make sure you run as Admin)

.\Download-TV.ps1 -host_msi_url "http://mywebsite.com/TV/TeamViewer_Host.msi" -configuration_id "$config_id" -assingment_tool_url "http://mywebiste.com/TV/TeamViewer_Assignment.exe" -api_token "$api_token"

param (
    [Parameter(Mandatory=$true)][string]$host_msi_url,
    [Parameter(Mandatory=$true)][string]$configuration_id,
    [Parameter(Mandatory=$true)][string]$assingment_tool_url,
    [Parameter(Mandatory=$true)][string]$api_token
)

$tv_msi_path = $env:TEMP + "\TeamViewer_Host-idc$configuration_id.msi"
$assign_path = $env:TEMP + "\tvassign.exe"

if (Test-Path("C:\Program Files\TeamViewer\")) {
    #32
    Start-Process -Wait -FilePath "C:\Program Files\TeamViewer\uninstall.exe" -ArgumentList "/S"
    Remove-Item "C:\Program Files\TeamViewer\" -Force -Recurse
    echo "Removing existing TeamViewer install (32)"
} elseif (Test-Path("C:\Program Files (x86)\TeamViewer\uninstall.exe")) {
    #64
    Start-Process -Wait -FilePath "C:\Program Files (x86)\TeamViewer\" -ArgumentList "/S"
    Remove-Item "C:\Program Files (x86)\TeamViewer" -Force -Recurse
    echo "Removing existing TeamViewer install (64)"
}

$client = New-Object System.Net.WebClient
$client.DownloadFile($host_msi_url, $tv_msi_path)
$client.DownloadFile($assingment_tool_url, $assign_path)

echo "installing TV"
Start-Process -Wait -FilePath $tv_msi_path -ArgumentList "/qn"

if (! (Test-Path("C:\Program Files (x86)"))) {
    #32
    Start-Process -Wait -FilePath $assign_path -ArgumentList "-apitoken $([char]34)$api_token$([char]34) -datafile $([char]34)C:\Program Files\TeamViewer\AssignmentData.json$([char]34)"
    echo "Running configuration utility (32)"
} else {
    #64
    Start-Process -Wait -FilePath $assign_path -ArgumentList "-apitoken $([char]34)$api_token$([char]34) -datafile $([char]34)C:\Program Files (x86)\TeamViewer\AssignmentData.json$([char]34)"
    echo "Running configuration utility (64)"
}
1 Accepted Solution

Accepted Solutions
Highlighted
Posted by BigNuggets
Digon
Solution

Re: PowerShell Based Host Deployment (.msi)

# Get script parameters.
Param (
    [string]$customer_name = $(Read-Host "Customer name"),
    [string]$device_alias = $env:computername,
    [string]$msi_url = "https://yourwebhost.com/TeamViewer_Host.msi",
    [string]$assignment_tool_url = "https://yourwebhost.com/TeamViewer_Assignment.exe"
)

# Assignment variables. - MAKE SURE YOU SET THESE
$config_id = ""
$assign_token = ""
$policy_id = ""

# API variables.
$api_token = ""
$user_id = "" # Token must belong to this user.
$base_url = "https://webapi.teamviewer.com/"
$headers = @{"Authorization" = "Bearer $api_token"}

# Check to see if device already exists, prompt to delete it if it does
$devices = Invoke-RestMethod -Uri "$base_url/api/v1/devices" -Headers $headers
$existing_device = $devices.devices | where { $_.alias -eq $device_alias }
if ($existing_device) {
    $title = "Delete Device"
    $message = "A device with the name $device_alias already exists. Do you wish to delete it?"

    $yes = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes", `
        "Deletes the device $device_alias."

    $no = New-Object System.Management.Automation.Host.ChoiceDescription "&No", `
        "Cancels the current installation."

    $options = [System.Management.Automation.Host.ChoiceDescription[]]($yes, $no)

    $result = $host.ui.PromptForChoice($title, $message, $options, 0) 

    switch ($result) {
        0 {
            try {
                Invoke-RestMethod -Method Delete `
                    -Uri "$base_url/api/v1/devices/$($existing_device.device_id)" `
                    -Headers $headers
            }
            catch {
                throw "Error deleting device"
            }
        }
        1 {
            throw "Device already exists"
        }
    }
}

# Create a temporary directory at the root of the current drive.
$base_path = "$($pwd.drive.name):\TeamViewer_Install"
New-Item $base_path -type directory -Force

# Set download paths for MSI and assignment tool.
$tv_msi_path = "$base_path\TeamViewer_Host-idc$config_id.msi"
$assign_path = "$base_path\tvassign.exe"

# Determine if this is a 32-bit or a 64-bit machine.
if (${env:ProgramFiles(x86)}) {
    # 64-bit
    $program_files = ${env:ProgramFiles(x86)}
}
else {
    # 32-bit
    $program_files = $env:ProgramFiles
}

# Uninstall TeamViewer if it is currently installed.
$msi_wrapper = Get-WmiObject -Class Win32_Product -Filter "Name = 'TeamViewer 12 Host (MSI Wrapper)'"
if ($msi_wrapper) {
    echo "Removing existing TeamViewer installation"
    $msi_wrapper.Uninstall()
}

echo "Downloading TeamViewer MSI"
Invoke-WebRequest -Uri $msi_url -OutFile $tv_msi_path

echo "Downloading assignment tool"
Invoke-WebRequest -Uri $assignment_tool_url -OutFile $assign_path

echo "Installing TeamViewer"
$MSIArguments = @(
    "/I"
    ('"{0}"' -f $tv_msi_path)
    "/quiet"
)
Start-Process msiexec.exe -Wait -ArgumentList $MSIArguments

echo "Waiting for AssignmentData.json"
while (!(Test-Path "$program_files\TeamViewer\AssignmentData.json")) {
    Start-Sleep 10
}

$JSON_File = "$program_files\TeamViewer\AssignmentData.json"

# Get contents of AssignmentData.json
$JSON_Data = Get-Content $JSON_File -raw | ConvertFrom-Json

# Replace default TeamViewer group name with customer name and output to new file
$JSON_Data.group_name = $customer_name
$JSON_Data | ConvertTo-Json -Compress | Out-File "$base_path\assign.json" -Encoding Ascii

# Create and share the customer group if it doesn't already exist
$groups = Invoke-RestMethod -Uri "$base_url/api/v1/groups?name=$customer_name" -Headers $headers
if (!$groups.groups) {
    $payload = @{
        name      = $customer_name
        policy_id = $policy_id
    }

    echo "Creating $customer_name group"

    # Create group and get group ID
    $response = Invoke-RestMethod -Method Post -ContentType 'application/json' `
        -Uri "$base_url/api/v1/groups" -Body ($payload | ConvertTo-Json) `
        -Headers $headers
    $gid = $response.id

    echo "Sharing group to consultants"

    # Get list of TeamViewer users and exclude superuser.
    $users = Invoke-RestMethod -Uri "$base_url/api/v1/users?full_list=true" -Headers $headers
    $consultants = $users.users | where { $_.id -ne $user_id -and $_.active }

    # Create a mapping of user IDs to permissions.
    $uids = $consultants | foreach { @{userid = $_.id; permissions = "full"} }

    # Perform request to give users permissions on the group.
    $response = Invoke-RestMethod -Method Post -ContentType 'application/json' `
        -Uri "$base_url/api/v1/groups/$gid/share_group" `
        -Body (@{users = $uids} | ConvertTo-Json) `
        -Headers $headers
}

# Run the assignment tool
echo "Running assignment tool"
$AssignArguments = @(
    ('-apitoken "{0}"' -f $assign_token)
    ('-datafile "{0}\assign.json"' -f $base_path)
    "-verbose"
)
Start-Process -NoNewWindow -Wait -FilePath $assign_path -ArgumentList $AssignArguments

echo "Cleaning up"
Remove-Item $base_path -Force -Recurse

Hi,

Thanks for your follow up - this script in the original solution is pretty old though. Here is the updated script.

 

11 Replies
16 Replies
Posted by TeamViewer Staff
TeamViewer Staff

Re: PowerShell Based Host Deployment (.msi)

@BigNuggets

Thank you very much for your post here.

Could you please also provide the parameters you passed to the powershell script so that others can see how the whole script works.

Thanks once again for your excellent post!

 

Aaron Boshers
Support Engineer

If my reply answered your question, help out other users and click the Accept as a Solution button below.
You can also say thanks by clicking on the Thumbs Up button! Thanks for being an active member of our Community!
Posted by BigNuggets
Digon

Re: PowerShell Based Host Deployment (.msi)

@Aaron_Boshers

Yea sure, it's right on the bottom of step 4:

.\Download-TV.ps1 -host_msi_url "http://mywebsite.com/TV/TeamViewer_Host.msi" -configuration_id "$config_id" -assingment_tool_url "http://mywebiste.com/TV/TeamViewer_Assignment.exe" -api_token "$api_token"

Posted by CGPeter
Henagon

Re: PowerShell Based Host Deployment (.msi)

Awesome, this was exactly what I was looking for. Tested it out, and it works perfectly. Thank you!!

Posted by CGPeter
Henagon

Re: PowerShell Based Host Deployment (.msi)

Line 19 should be

Start-Process -Wait -FilePath "C:\Program Files (x86)\TeamViewer\uninstall.exe" -ArgumentList "/S"
Highlighted
Posted by BigNuggets
Digon
Solution

Re: PowerShell Based Host Deployment (.msi)

# Get script parameters.
Param (
    [string]$customer_name = $(Read-Host "Customer name"),
    [string]$device_alias = $env:computername,
    [string]$msi_url = "https://yourwebhost.com/TeamViewer_Host.msi",
    [string]$assignment_tool_url = "https://yourwebhost.com/TeamViewer_Assignment.exe"
)

# Assignment variables. - MAKE SURE YOU SET THESE
$config_id = ""
$assign_token = ""
$policy_id = ""

# API variables.
$api_token = ""
$user_id = "" # Token must belong to this user.
$base_url = "https://webapi.teamviewer.com/"
$headers = @{"Authorization" = "Bearer $api_token"}

# Check to see if device already exists, prompt to delete it if it does
$devices = Invoke-RestMethod -Uri "$base_url/api/v1/devices" -Headers $headers
$existing_device = $devices.devices | where { $_.alias -eq $device_alias }
if ($existing_device) {
    $title = "Delete Device"
    $message = "A device with the name $device_alias already exists. Do you wish to delete it?"

    $yes = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes", `
        "Deletes the device $device_alias."

    $no = New-Object System.Management.Automation.Host.ChoiceDescription "&No", `
        "Cancels the current installation."

    $options = [System.Management.Automation.Host.ChoiceDescription[]]($yes, $no)

    $result = $host.ui.PromptForChoice($title, $message, $options, 0) 

    switch ($result) {
        0 {
            try {
                Invoke-RestMethod -Method Delete `
                    -Uri "$base_url/api/v1/devices/$($existing_device.device_id)" `
                    -Headers $headers
            }
            catch {
                throw "Error deleting device"
            }
        }
        1 {
            throw "Device already exists"
        }
    }
}

# Create a temporary directory at the root of the current drive.
$base_path = "$($pwd.drive.name):\TeamViewer_Install"
New-Item $base_path -type directory -Force

# Set download paths for MSI and assignment tool.
$tv_msi_path = "$base_path\TeamViewer_Host-idc$config_id.msi"
$assign_path = "$base_path\tvassign.exe"

# Determine if this is a 32-bit or a 64-bit machine.
if (${env:ProgramFiles(x86)}) {
    # 64-bit
    $program_files = ${env:ProgramFiles(x86)}
}
else {
    # 32-bit
    $program_files = $env:ProgramFiles
}

# Uninstall TeamViewer if it is currently installed.
$msi_wrapper = Get-WmiObject -Class Win32_Product -Filter "Name = 'TeamViewer 12 Host (MSI Wrapper)'"
if ($msi_wrapper) {
    echo "Removing existing TeamViewer installation"
    $msi_wrapper.Uninstall()
}

echo "Downloading TeamViewer MSI"
Invoke-WebRequest -Uri $msi_url -OutFile $tv_msi_path

echo "Downloading assignment tool"
Invoke-WebRequest -Uri $assignment_tool_url -OutFile $assign_path

echo "Installing TeamViewer"
$MSIArguments = @(
    "/I"
    ('"{0}"' -f $tv_msi_path)
    "/quiet"
)
Start-Process msiexec.exe -Wait -ArgumentList $MSIArguments

echo "Waiting for AssignmentData.json"
while (!(Test-Path "$program_files\TeamViewer\AssignmentData.json")) {
    Start-Sleep 10
}

$JSON_File = "$program_files\TeamViewer\AssignmentData.json"

# Get contents of AssignmentData.json
$JSON_Data = Get-Content $JSON_File -raw | ConvertFrom-Json

# Replace default TeamViewer group name with customer name and output to new file
$JSON_Data.group_name = $customer_name
$JSON_Data | ConvertTo-Json -Compress | Out-File "$base_path\assign.json" -Encoding Ascii

# Create and share the customer group if it doesn't already exist
$groups = Invoke-RestMethod -Uri "$base_url/api/v1/groups?name=$customer_name" -Headers $headers
if (!$groups.groups) {
    $payload = @{
        name      = $customer_name
        policy_id = $policy_id
    }

    echo "Creating $customer_name group"

    # Create group and get group ID
    $response = Invoke-RestMethod -Method Post -ContentType 'application/json' `
        -Uri "$base_url/api/v1/groups" -Body ($payload | ConvertTo-Json) `
        -Headers $headers
    $gid = $response.id

    echo "Sharing group to consultants"

    # Get list of TeamViewer users and exclude superuser.
    $users = Invoke-RestMethod -Uri "$base_url/api/v1/users?full_list=true" -Headers $headers
    $consultants = $users.users | where { $_.id -ne $user_id -and $_.active }

    # Create a mapping of user IDs to permissions.
    $uids = $consultants | foreach { @{userid = $_.id; permissions = "full"} }

    # Perform request to give users permissions on the group.
    $response = Invoke-RestMethod -Method Post -ContentType 'application/json' `
        -Uri "$base_url/api/v1/groups/$gid/share_group" `
        -Body (@{users = $uids} | ConvertTo-Json) `
        -Headers $headers
}

# Run the assignment tool
echo "Running assignment tool"
$AssignArguments = @(
    ('-apitoken "{0}"' -f $assign_token)
    ('-datafile "{0}\assign.json"' -f $base_path)
    "-verbose"
)
Start-Process -NoNewWindow -Wait -FilePath $assign_path -ArgumentList $AssignArguments

echo "Cleaning up"
Remove-Item $base_path -Force -Recurse

Hi,

Thanks for your follow up - this script in the original solution is pretty old though. Here is the updated script.

 

11 Replies
Posted by Nfoster
Tetragon

Re: PowerShell Based Host Deployment (.msi)

BigNuggets, your post has Smiley Tongues at lines 65 and 69. It looks like it should be,

$program_files = ${envProgramFiles(x86)}

Howver to create a Smiley Tongue you would need to type : P (no space).

Can you please clarify what line 65 and 69 should be?

Posted by Nfoster
Tetragon

Re: PowerShell Based Host Deployment (.msi)

I am attempting to run this script but it does not work. I get prompted for "Customer name" which I am assuming is the registered company name with our license. Either way, it does not appear to matter what I type in as the script proceeds to the next line and starts downloading my shared Temaviewer files, but stops at 24KB and just sits there waiting for the "AssignmentData.json" file.

 

Please advise.

Posted by Nfoster
Tetragon

Re: PowerShell Based Host Deployment (.msi)

Ok got past the download issue. It will download and install, assign it to my TeamViewer account. However, if I try to run this again it fails to delete the device in my account and throws the following error,

"Error deleting device"

Line in referance:  throw "Error deleting device"

 

Posted by BigNuggets
Digon

Re: PowerShell Based Host Deployment (.msi)

The Customer Name is what you want it to show up as in your Computers & Contacts

Posted by Nfoster
Tetragon

Re: PowerShell Based Host Deployment (.msi)

Ok makes sense. I was able to pass that pawameter. However, I am not able to delete.

Error deleting device
At C:\temp\Download-TV.ps1:45 char:17
+ throw "Error deleting device"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (Error deleting device:String) [], RuntimeException
+ FullyQualifiedErrorId : Error deleting device

Please advise.

Posted by Nfoster
Tetragon

Re: PowerShell Based Host Deployment (.msi)

"BUMP"

Posted by Nfoster
Tetragon

Re: PowerShell Based Host Deployment (.msi)

"BUMP", "BUMP"

Posted by Nfoster
Tetragon

Re: PowerShell Based Host Deployment (.msi)

Anyone?

Posted by Nfoster
Tetragon

Re: PowerShell Based Host Deployment (.msi)

This script appears to hang on the "Waiting for AssignmentData.json" and then fails with the following,

Start-Process : This command cannot be run due to the error: This version of %1 is not compatible with the version of
Windows you're running. Check your computer's system information and then contact the software publisher.
At C:\temp\DTV12v1.ps1:146 char:1
+ Start-Process -NoNewWindow -Wait -FilePath $assign_path -ArgumentList ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Start-Process], InvalidOperationException
+ FullyQualifiedErrorId : InvalidOperationException,Microsoft.PowerShell.Commands.StartProcessCommand

Please advise.

Posted by Nfoster
Tetragon

Re: PowerShell Based Host Deployment (.msi)

Do you recall what might be causing the file download to stop at 256Kb?. It is an odd one for sure. The files names are correct but it only downloads the first 256Kb of both files. I have recreated everything from scratch and even have a support ticket in with MSFT. 

This script has been work for a while;

# Get script parameters.
Param (
[string]$customer_name = "TEST",
[string]$device_alias = $env:computername,
[string]$msi_url = "https://host/file",
[string]$assignment_tool_url = "https://host/file"
)

# Assignment variables. - MAKE SURE YOU SET THESE
$config_id = "CONFIG_ID_NUMBER"
$assign_token = "TOKEN_NUMBER"
$policy_id = "TEST"

# API variables.
$api_token = "TOKEN_NUMBER"
$user_id = "USER_ID" # Token must belong to this user.
$base_url = "https://webapi.teamviewer.com/"
$headers = @{"Authorization" = "Bearer $api_token"}

# Create a temporary directory at the root of the current drive.
$base_path = "$($pwd.drive.name):\TeamViewer_Install"
New-Item $base_path -type directory -Force

# Set download paths for MSI and assignment tool.
$tv_msi_path = "$base_path\TeamViewer_Host-idc$config_id.msi"
$assign_path = "$base_path\tvassign.exe"

# Determine if this is a 32-bit or a 64-bit machine.
if (${env:ProgramFiles(x86)}) {
# 64-bit
$program_files = ${env:ProgramFiles(x86)}
}
else {
# 32-bit
$program_files = $env:ProgramFiles
}

# Uninstall TeamViewer if it is currently installed.
$msi_wrapper = Get-WmiObject -Class Win32_Product -Filter "Name = 'TeamViewer 13 Host (MSI Wrapper)'"
if ($msi_wrapper) {
echo "Removing existing TeamViewer installation"
$msi_wrapper.Uninstall()
}

echo "Downloading TeamViewer MSI"
Invoke-WebRequest -Uri $msi_url -OutFile $tv_msi_path

echo "Downloading assignment tool"
Invoke-WebRequest -Uri $assignment_tool_url -OutFile $assign_path

echo "Installing TeamViewer"
$MSIArguments = @(
"/I"
('"{0}"' -f $tv_msi_path)
"/quiet"
)
Start-Process msiexec.exe -Wait -ArgumentList $MSIArguments

echo "Waiting for AssignmentData.json"
while (!(Test-Path "$program_files\TeamViewer\AssignmentData.json")) {
Start-Sleep 10
}

$JSON_File = "$program_files\TeamViewer\AssignmentData.json"

# Get contents of AssignmentData.json
$JSON_Data = Get-Content $JSON_File -raw | ConvertFrom-Json

# Replace default TeamViewer group name with customer name and output to new file
$JSON_Data.group_name = $customer_name
$JSON_Data | ConvertTo-Json -Compress | Out-File "$base_path\assign.json" -Encoding Ascii

# Create and share the customer group if it doesn't already exist
$groups = Invoke-RestMethod -Uri "$base_url/api/v1/groups?name=$customer_name" -Headers $headers
if (!$groups.groups) {
$payload = @{
name = $customer_name
policy_id = $policy_id
}

echo "Creating $customer_name group"

# Create group and get group ID
$response = Invoke-RestMethod -Method Post -ContentType 'application/json' `
-Uri "$base_url/api/v1/groups" -Body ($payload | ConvertTo-Json) `
-Headers $headers
$gid = $response.id

echo "Sharing group to consultants"

# Get list of TeamViewer users and exclude superuser.
$users = Invoke-RestMethod -Uri "$base_url/api/v1/users?full_list=true" -Headers $headers
$consultants = $users.users | where { $_.id -ne $user_id -and $_.active }

# Create a mapping of user IDs to permissions.
$uids = $consultants | foreach { @{userid = $_.id; permissions = "full"} }

# Perform request to give users permissions on the group.
$response = Invoke-RestMethod -Method Post -ContentType 'application/json' `
-Uri "$base_url/api/v1/groups/$gid/share_group" `
-Body (@{users = $uids} | ConvertTo-Json) `
-Headers $headers
}

# Run the assignment tool
echo "Running assignment tool"
$AssignArguments = @(
('-apitoken "{0}"' -f $assign_token)
('-datafile "{0}\assign.json"' -f $base_path)
"-verbose"
)
Start-Process -NoNewWindow -Wait -FilePath $assign_path -ArgumentList $AssignArguments

echo "Cleaning up"
Remove-Item $base_path -Force -Recurse

Posted by plasticarmyman
Electron

Re: PowerShell Based Host Deployment (.msi)

Where do you get some of your parameters?
I.E. 

assign_token, policy_id, user_id, base_url