Using the REST API in Manage Engine ServiceDesk Plus with PowerShell

It has been a while since my last post.  I have changed jobs and started focusing more on scripting and automation so I thought I would finally write a new post.  PowerShell is a very powerful scripting language and I have taken advantage of added tools in PowerShell 3.0 with regards to http web requests and Invoke-WebRequest.

ServiceDesk Plus by Manage Engine is a ticketing system with the ability to interact with it via their API.  By combining PowerShell Invoke-WebRequest and ServiceDesk’s REST API you can do all kinds of cool things like open and close tickets or even pull info out of a ticket and perform some automated tasks.  Interfacing with the API is pretty straight forward and easy to get started with but in order to do that you will need a few things to get started.

1.) You will need to get some information about your ServiceDesk Installation:
-You will need to get the IP or DNS name of your servicedesk server.
-You will also need to get the Port Number set for your ServiceDesk server.
-This could be 80 or 8080 or another port that you set.  If you are not sure when you start up ServiceDesk the command line interface should tell you the port number.

2.) You will need to get an API key from an active ServiceDesk Technician account:
goto Admin -> Technicicians -> find the technician -> edit the technician -> at the bottom click Generate API Key (Be sure to save after generating)

NOTE: That you cannot generate an API key for your own account so you will need to get another admin account to generate it for you or in my case I created a API service Account and made it a technician to use for my scripts

Once you have this information you are ready to start building a request! For this example we will build an Add Request  to generate a new ticket.

To start based on the ServiceDesk API documentation for the REST API we want to start by building the http request:

$inputData = @"
<requester>John Doe</requester>
<subject>Testing 123</subject>
<description>hello world!</description>
<requesttemplate>Default Request</requesttemplate>

Esseintially we are creating a block text with all our request details. These can easily be replaced with variables so you can dynamically generate a request.  Next we need to create the post parameters for the request:

$postParams = @{OPERATION_NAME='ADD_REQUEST';TECHNICIAN_KEY='<technician Key>';INPUT_DATA=$inputData}

This builds a post command for the request using the technician key from earlier to submit the request to ServiceDesk.  This allows you to submit requests with out ever passing any login credentials.

Finally we are ready to put it all together and submit the request:

Invoke-WebRequest -Uri $URI -Method POST -Body $postParams

This is the simplest way to submit a request and will return the http response from service desk which is a long list of properties.  Most of which is not important but what you will probably care about is the content property which is an XML response with details about your new ticket and looks like this:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<API version="1.0">
<operation name="ADD_REQUEST">
<message>Request added successfully</message>

This returns the details of a successful or unsuccessful request.  In this case the request status message was “Request added successfully” and it also returned the ticket ID number of 7300.  While this is great you probably want to do something usefull with this information such as make sure the request was successfull and maybe strore the ticket number some where.

In this case we can convert the content response to XML and reference specific property fields:

$response = Invoke-WebRequest -Uri $URI -Method POST -Body $postParams
[xml]$responseContent = $response.Content
if($responseContent.API.response.operation.result.status -eq "Success")
$reqID = [string]$responseContent.API.response.operation.Details.workorderid

Here we check to make sure the result of the request was a success and if so we grab the ticket ID number.

This is just an example of what you can do or the fields in a servicedesk ticket that you can update.  Pretty much any field in a request template can be updated as long as you reference the field name.  There is also alot more that you can do with the REST API such as update a ticket, get details of and existing ticket or even use ticket details to run an automated task such as create a new distribution list based on a request.  I will try and add some more posts on what you can do in the future.

Posted in Powershell | 6 Comments

Send Mail with inline embedded images with powershell

Its been a while but here is a quick tip for embedding inline images in SMTP emails with powershell.  Outlook will see these the attachments and embed them inline with the message.

create your message:

$smtpServer = ""
$msg = new-object Net.Mail.MailMessage
$smtp = new-object Net.Mail.SmtpClient($smtpServer)

Add your contact and subject to your message:

$msg.From = "<a href=""></a>"
$msg.ReplyTo = "<a href=""></a>"
$msg.To.Add("<a href=""></a>")
$msg.subject = "This is an email with inline images"

Makre sure the email is HTML enabled:

$msg.IsBodyHtml = $True

Add your Content to the body (note this can also be read in from an html file via get-content):

$body = @"
<img src="cid:image1.jpg">

Attach the image to your email: (note setting the images as inline and media type will make sure that outlook attaches the images as embedded and the email will not show as having attachments)

$attachment = New-Object System.Net.Mail.Attachment –ArgumentList "C:\image1.jpg"
$attachment.ContentDisposition.Inline = $True
$attachment.ContentDisposition.DispositionType = "Inline"
$attachment.ContentType.MediaType = "image/jpg"
$attachment.ContentId = 'image1.jpg'

Or for multiple images or attachments:

$path = C:\images
$files= Get-ChildItem $path

Foreach($file in $files)

$attachment = New-Object System.Net.Mail.Attachment –ArgumentList $Path\$file.ToString() #convert file-system object type to string
$attachment.ContentDisposition.Inline = $True
$attachment.ContentDisposition.DispositionType = "Inline"
$attachment.ContentType.MediaType = "image/jpg"
$attachment.ContentId = $file.ToString()


Just make sure that in your html email to referece each file with <image src=”cid:filename.extension”>

<img src="cid:image1.jpg">
<img src="cid:image2.jpg">
<img src="cid:image3.jpg">

When done adding attachments send your message adn clean up:


If you have inline image attachments of varying file formats you can also set the inline media type dynamically. In your attachment lool take the file type as a string and pipe it into the media type:

$fileType = $file.Substring(($file.IndexOf('.'))+1) #get image file extension
$attachment.MediaType = "image/$fileType" #set mediaType based on $file extension
Posted in Powershell | Tagged , , , , | 16 Comments

Distributing .apk files for android 2.3.x with IIS 7+

A project recently came across my desk to set up a web server for android application file distribution.

Setting up an IIS web server to distribute files is generally simple and straight forward. Though I recently discovered that with android its not that simple.

To handle .apk file types I created a MIME type map for android .apk ” application/”


This seemed to work and would server the .apk files for download via the android browser.  However I found that android devices running 2.3.x would get an error “cannot download. This content is not supported by this device.” It appeared that it did not recognize this as a .apk file when it tried to download the file.

I found a work around by creating a generic MIME type handler “application/octet-Stream”:


Adding this MIME type seems to work great and is able to properly serve the files on all versions of android.

Posted in IIS | Tagged , , | Leave a comment

Filtering a list of usernames based on OU or Container

Recently I was given a list of usernames and asked to find all the user who were in a specific OU in Active Directory.  This sounds complicated but is actually quite easy to do with powershell in 3 easy steps:

Step 1: I created a txt file with the list of usernames called userList.txt

Step 2: I then created a simple powershell script to read in username and return the users DN

Step 3: If the users DN contained the OU I was looking for I appended that users info to a new file called matchedUsers.txt

$userList = Get-Content "c:\fileLocation\userList.txt" #open the file and read the data in an array
write-host $userList.count total lines read from file #output total lines read
foreach ($user in $userList)#do this for each user read from file
$userDN = dsquery user -samID $user #does a dsquery using the read in samID and returns the userDN

if ($userDN.Contains("Name_Of_OU_or_Container")) #if the userDN contains the target OU or container
$lineOutToFile = $user + " " + $userDN #concatenate the user name and userDN
$lineOutToFile | Out-File "c:\fileLocation\matchedUsers.txt" -append #output the user+userDN to file

The result is you get a file output with all username and userDNs that are located in the container or OU you wanted to search for.

Posted in Active Directory, Powershell | Tagged , , | Leave a comment

Security Group Monitoring

A question I have seen come up is how do I monitor access to important security groups such as Domain Admin.  You always want to minimize access to this group but sometimes someone may give this access without you knowing and you want to know about it.  Here is a solution you can use to monitor security groups in a windows 2008 R2 environment.

When a user is added to a security group such as Domain Admins an event is triggered in the security event log on your domain controller.  By looking for this event you can easily trigger a notification. Continue reading

Posted in Active Directory | Tagged , , | Leave a comment

My new blog!

So I decided to start a new tech blog I’ll update when I can with tips and tricks from the IT world!

Posted in Active Directory | Leave a comment