Script cannot write to ticket

This original script this script is based off worked last week, but is not working today, nor is this subset script. Here is the script:

Passed variables: $AdminPass, $AssetName, $Ticket, & $Tech

Import-Module $env:SyncroModule -WarningAction SilentlyContinue

Write-Host "Beginning Admin Password Reset script, ran by $Tech for $Ticket at $Today."

$Username = "Admin"
$group = "Administrators"
[String]$AdminPass = $AdminPass

Write-Host "System Restore Point requested."
Checkpoint-Computer -Description "Admin-Password-Reset" -RestorePointType "MODIFY_SETTINGS"

if ($AdminPass -eq "") {
    Write-Host "Admin Password was not specified.  Exiting script."
    Exit 1
} else {
    $adsi = [ADSI]"WinNT://$env:COMPUTERNAME"
    $existing = $adsi.Children | where {$_.SchemaClassName -eq 'user' -and $_.Name -eq $Username }
 
    if ($existing -eq $null) {
        Write-Host "Local Admin account does not already exist.  Please run On-Boarding script.  Exiting script."
        Exit 1
    } else {
        Write-Host "Setting password for existing local user $Username."
        $existing.SetPassword("$AdminPass")
    }
    Write-Host "Ensuring password for $Username never expires."
    & WMIC USERACCOUNT WHERE "Name='$Username'" SET PasswordExpires=FALSE
}

#Ticket notations
Write-Host "Adding Ticket info notations."
Create-Syncro-Ticket-Comment -TicketIdOrNumber $Ticket -Subject "Admin Password Reset" -Body "$AssetName : Created System Restore Point, Reset Admin password" -Hidden "true" -DoNotEmail "true"

Log-Activity -Message "Created System Restore Point & reset Admin password" -EventName "Admin Password Reset"

Write-Host "Script completed."

This kicks out the following error:

error> System.Net.WebException: The remote server returned an error: (401) Unauthorized.
error> HTTP Status: 401 'Unauthorized'
error> Content-Type: 'application/json; charset=utf-8'
error> Response: '{"error":"No ticket"}'
error> Stack:
error>   at Invoke-WebRequest20, C:\ProgramData\Syncro\bin\module.psm1: line 326
error>   at Call-SyncroApiEx, C:\ProgramData\Syncro\bin\module.psm1: line 253
error>   at Call-SyncroApi, C:\ProgramData\Syncro\bin\module.psm1: line 228
error>   at Create-Syncro-Ticket-Comment, C:\ProgramData\Syncro\bin\module.psm1: line 174
error>   at <ScriptBlock>, C:\ProgramData\Syncro\bin\ec90c69b-3df5-4e97-83ab-0c9cb454a4ad.ps1: line 82
error>   at <ScriptBlock>, <No file>: line 1
error>   at <ScriptBlock>, <No file>: line 1
error> Call-SyncroApi: failure
error> System.Net.WebException: The remote server returned an error: (401) Unauthorized.
error> HTTP Status: 401 'Unauthorized'
error> Content-Type: 'application/json; charset=utf-8'
error> Response: '{"error":"No ticket"}'
error> Stack:
error>   at Invoke-WebRequest20, C:\ProgramData\Syncro\bin\module.psm1: line 326
error>   at Call-SyncroApiEx, C:\ProgramData\Syncro\bin\module.psm1: line 253
error>   at Call-SyncroApi, C:\ProgramData\Syncro\bin\module.psm1: line 231
error>   at Create-Syncro-Ticket-Comment, C:\ProgramData\Syncro\bin\module.psm1: line 174
error>   at <ScriptBlock>, C:\ProgramData\Syncro\bin\ec90c69b-3df5-4e97-83ab-0c9cb454a4ad.ps1: line 82
error>   at <ScriptBlock>, <No file>: line 1
error>   at <ScriptBlock>, <No file>: line 1
error> Call-SyncroApi: failure
Call-SyncroApi: success
Script completed.

As I said, the script worked last week, but doesn’t work today. I have initiated it from Edge and from Chrome. I would think it would not matter, as it most likely depends on the machine that is running the script.

Any help would be greatly appreciated! Thanks!

1 Like

If you haven’t gotten this resolved yet, one thing comes to mind. I’ve had mixed results with strings embed with a variable in PowerShell in general.

Formatting this way seems to usually work:
“$($AssetName) : Created System Restore Point, Reset Admin password”

I changed $AssetName to $($AssetName) per your suggestion. Still get the exact same error.

It is almost like the call itself with the ticket number isn’t working. But even when I don’t use $Ticket and instead hard code a ticket number, it still fails.

Okay… Try this:

$ticketNo = [convert]::ToInt32($Ticket, 10)
Create-Syncro-Ticket-Comment -TicketIdOrNumber $ticketNo -Subject "Admin Password Reset" -Body "$AssetName : Created System Restore Point, Reset Admin password" -Hidden $True -DoNotEmail $True

This will convert the string variable to an Int32 and also uses Boolean instead of string “Trues.”

I tried that, but still get the same errors. See below:

Import-Module $env:SyncroModule

$TicketNum = [convert]::ToInt32($Ticket, 10)
$Today = Get-Date -Format "yyyy-MM-dd_HHmmss"

if ($TicketNum -eq "") {
    Write-Host "Beginning RDP-Disable script, ran by $Tech at $Today."
} else {
    Write-Host "Beginning RDP-Disable script, ran by $Tech for $TicketNum at $Today."
}

Write-Host "Enabling RDP with firewall configured and requiring NLA."
#Set-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Control\Terminal Server'-name "fDenyTSConnections" -Value 0
#Enable-NetFirewallRule -DisplayGroup "Remote Desktop"

#Ticket notations
if ($TicketNum -eq "") {
    Write-Host "Ticket number not provided."
} else {
    Write-Host "Adding Ticket info notations."
    Create-Syncro-Ticket-Comment -TicketIdOrNumber $TicketNum -Subject "RDP" -Body "$($AssetName) : RDP Enabled" -Hidden "true" -DoNotEmail "true"
}

Log-Activity -EventName "RDP"-Message "RDP Enabled"
Write-Host "Script completed."

Slightly different script as I use this to standardize my ticket documentation. If you are willing to try the script, does it work for you? The actual commands are commented out.

The Trues are still strings… That might matter?

From the examples that are at the bottom of the Script pages:

`# This just needs the ticketid or ticket number and you can add a comment. You can have it be "public" or "private", and email or not, and combine those.
# For example you can make a Public comment (shows on PDF/etc) and have it NOT email the customer.
Create-Syncro-Ticket-Comment -TicketIdOrNumber 123 -Subject "Contacted" -Body "This is the comment body here" -Hidden "true/false" -DoNotEmail "true/false"`

This tells me that I should use “true” or “false”, so I believe they should be strings. Any other thoughts? :slight_smile:

This is what Create-Syncro-Ticket-Comment looks like.

function Create-Syncro-Ticket-Comment ($Subdomain, $TicketIdOrNumber, $Subject, $Body, $Hidden, $DoNotEmail) {
  $Hidden     = Parse-Bool -Value $Hidden     -Default $true
  $DoNotEmail = Parse-Bool -Value $DoNotEmail -Default $true

  $result = Call-SyncroApi `
    -Subdomain $Subdomain `
    -Path "/api/syncro_device/tickets/$TicketIdOrNumber/add_comment" `
    -Data @{
      uuid = $UUID;
      subject = $Subject;
      body = $Body;
      hidden = if ($Hidden) {"1"} else {"0"};
      do_not_email = if ($DoNotEmail) {"1"} else {"0"};
    }
  $result
}

Parse-Bool is a function that essentially tries to parse -Value from a string into a boolean $true or $false and then returns that, and if it won’t parse - returns -Default

C:\> [bool]::Parse('truE')
True
C:\> [bool]::Parse('false')
False
C:\> [bool]::Parse('shoop')
ERROR  # In Parse-Bool, this will return -Default which is $true
C:\> [bool]::Parse($False)
False  # Somewhat interestingly, this is taking $False, converting it to the string 'False' and then parsing it back to $False
C:\> [bool]::Parse('0')
ERROR # In Parse-Bool, this will return -Default which is $true
C:> [bool]::Parse(1)
ERROR # In Parse-Bool, this will return -Default which is $true

Somewhat interestingly, this is different from how it would have behaved if they had specified Hidden and DoNotEmail as [bool] types in the powershell function, because then it would have used the implicit typecasting, which operates somewhat counter-intuitively

C:\> [bool]'truE'
True #This seems like it recognizes the word 'true', but  
C:\> [bool]'false'
True  #Then this would surely be returning False? 
C:\> [bool]'shoop'
True #These next couple examples start to show what is happening
C:\> [bool]'0'
True #Essentially any 'string' value will yield 'True'
C:\> [bool]0
False #Powershell does know how to correctly do 0 => False 
C:\> [bool]1
True # and 1=> True
C:\> [bool]564
True  #OK. Now this is slightly ridiculous! Is every Value "True" unless you know it is "False"
C:\> [bool]$null 
False  #Ahh! Now things make somewhat more sense. No Value ($null) generated False. 
C:\> [bool]$ThisVariableHasNotBeenDefined
False #Ahah!!! Confirmed the $null versus "some value" argument. 

Long story short - Use Strings for $Hidden and DoNotEmail - or $True and $False will basically always work too

John,
Does something like this throw a warning for you still?

Create-Syncro-Ticket-Comment -TicketIdOrNumber 123 -Subject “Contacted”
-Body "TestValue - RDP Enabled"
-Hidden “true/false” -DoNotEmail “true/false”

your second line has a backtick at the end, but I assume that’s just a small formatting mistake

-DoNotEmail "true/false"`

Interestingly (based on the above Function pulled from the current Module on my computer) - it looks like the endpoint it uses is at /api/syncro_device/tickets/$TicketIdOrNumber/add_comment - which is not listed on the public API Documentation. The closest I see is this one.
https://api-docs.syncromsp.com/#/Ticket/post_tickets__id__comment

but being that it is …/syncro_device/tickets/{id}/add_comment and not just /tickets/{id}/comment - maybe the ticket has to be associated to the current device running it?

So, my brain has been fried from a very long week that is continuing into next week… What should I be using instead then?

“True”
‘True’
$True
True

Sorry, I am just not processing tonight.

Thanks for your help though. Or makes sense once I understand which is the correct syntax.

oop - sorry - I accidentally posted mid-response, but that first message about strings was mainly aimed at Jeremy.

any standard powershell string formats should work great for Hidden and DoNotEmail
$True and $False should also work, but because PowerShell converts them to Strings where needed

So all of these would be examples that would work fine (for that part of the function anyway)

'True'
'false'
"True"
"False" 
$True
$false

I am curious if there might be a quirk of how -Body is processed though, causing it to have problems in certain cases.

If you have a moment try this post for me and let me know how it goes.

1 Like

@john.nelson did you get this resolved? I have the same issue.

The asset has to be on the ticket indicated. So, when I would try and reference a ticket that I was working on, and the asset had not been attached to the ticket previously, it would not write to the ticket and just kick out the error.

I need to see if there is a way I can script adding the asset to the ticket prior to writing the comment.

1 Like

Aha! Looks like the API being tied off /device/ was important!

I think if you wanted to add a device to a Ticket from inside a script - you would probably need to use a “real” Syncro REST API key and methods - I don’t see anything aimed around adding devices to tickets in the module.

You could make a new ticketand then maybe merge that into your main ticket somewhere else shortly afterward, but I don’t think you could add the device to a given ticket from inside the “Syncro Script”

Yeah, I have not seen anything yet on how I can do that.

Is there a way to add assets in mass to a ticket instead of trying to add 50 assets one at a time? It doesnt have to be automated though that wouldnt be a bad thing.

Having it create 50 different tickets and then having to manually merge those would be just as tedious.

Thanks for your input. :slight_smile:

Yeah, the only thing that I was thinking with create different tickets and then merge would be if that might be able to be scripted / automated from the technician side.