Aug
31

Get-FileAttachments.ps1 – Retrieve file attachments from Service Manager

By

A couple of days ago Anders Bengtsson over at contoso.se asked me if I could help out and create a solution that could be used to help automate the task of saving file attachments to the file system. After spending some time messing around with memory streams in PowerShell I’ve managed to come up with a script that can be used to save all files “attached” to a work item or configuration item in Service Manager.

#
#Author: Patrik Sundqvist, www.litware.se
#Description: Can be used to archive attached files
#
 
param([Guid] $Id = $(throw "Parameter `$Id is required. This should be the internal id of a work item or config item which attached files you want to archive."),
[string]$ArchiveRootPath = $(throw "Parameter `$ArchiveRootPath is required. A folder containing all file attachments will be created in this folder."),
[string]$ComputerName = "localhost")
 
$WIhasAttachMent = "aa8c26dc-3a12-5f88-d9c7-753e5a8a55b4"
$CIhasAttachMent = "095ebf2a-ee83-b956-7176-ab09eded6784"
 
#Adjust path
$ArchiveRootPath = $ArchiveRootPath.TrimEnd("\")
 
#Make sure path exists
if(!(Test-Path $ArchiveRootPath))
{
    Write-Error "Provided archive path $ArchiveRootPath doesn't exists" -ErrorAction Stop
}
 
#Making sure smlets is loaded
if(!(get-module smlets))
{
    import-module smlets -Force -ErrorAction Stop    
}
 
#Get Emo
$Emo = Get-SCSMObject -Id $Id -ComputerName $ComputerName
 
 
#Check if this is a work item or config item
$WIhasAttachMentClass = Get-SCSMRelationshipClass -Id $WIhasAttachMent -ComputerName $ComputerName
$WIClass = Get-SCSMClass System.WorkItem$ -ComputerName $ComputerName
#Figure out if this is a work item or a config item to make sure we use the correct relationship
if($Emo.IsInstanceOf($WIClass))
{
    $files = Get-SCSMRelatedObject -SMObject $Emo -Relationship $WIhasAttachMentClass -ComputerName $ComputerName
}
else
{
    $CIhasAttachMentClass = Get-SCSMRelationshipClass -Id $CIhasAttachMent -ComputerName $ComputerName
    $CIClass = Get-SCSMClass System.ConfigItem$ -ComputerName $ComputerName
    if($Emo.IsInstanceOf($CIClass))
    {
        $files = Get-SCSMRelatedObject -SMObject $Emo -Relationship $CIhasAttachMentClass -ComputerName $ComputerName
    }
    else
    {
        Write-Error "Instance isn't of supported type" -ErrorAction Stop
    }
}
 
#For each file, archive to entity folder
if($files -ne $Null)
{
    #Create archive folder
    $nArchivePath = $ArchiveRootPath + "\" + $Emo.Id
    New-Item -Path ($nArchivePath) -ItemType "directory" -Force|Out-Null
 
    $files|%{
            Try
            {
                $_.DisplayName
                $fs = [IO.File]::OpenWrite(($nArchivePath + "\" + $_.DisplayName))
                $memoryStream = New-Object IO.MemoryStream
                $buffer = New-Object byte[] 8192
                [int]$bytesRead|Out-Null
                while (($bytesRead = $_.Content.Read($buffer, 0, $buffer.Length)) -gt 0)
                {
                    $memoryStream.Write($buffer, 0, $bytesRead)
                }        
                $memoryStream.WriteTo($fs)
            }
            Finally
            {
                $fs.Close()
                $memoryStream.Close()
            }
    }
}

Get-FileAttachments.ps1 requires “smlets” which can be downloaded at smlets.codeplex.com.

Remember to unblock the script after downloading, if you want to be able to run it that is :)

Using smlets you can simply search for configuration items or work items and pass on their internal ids to the script to have all their attachments archived nice and easy in a folder of your choice. In the example below I’m searching for all incidents in Service Manager that has a title containing the word “computer”. I pass on their internal id, a folder to use for archiving and the computer name of my Service Manager management server to the script. The script then checks for attachments and, in the case of finding attachments, creates a folder for each incident that has attachments and save the files in them.

?View Code POWERSHELL
Import-module smlets
$class = get-scsmclass system.workitem.incident$ -ComputerName sm2
$incidents = Get-SCSMObject -Class $class -Filter "DisplayName -like '*test*'" -computerName sm2
foreach ($incident in $incidents)
{
    .\Get-FileAttachments.ps1 -Id $incident.Get_Id() -ArchiveRootPath "C:\SCSM\Archive" -computername sm2    
}

Comments

  1. [...] (7) RSS FeedsHere are some System Center news:Get-FileAttachments.ps1 – Retrieve file attachments from Service Manager (Litware)System Center 2012 Self-Study Guide – Orchestrator and Service Manager (System Center: [...]

  2. [...] Patrik Sundqvist a System Center Cloud and Datacenter Management MVP developed a script that can download SCSM attachments to save them as archive. Read more about this solution and get the script from here. [...]

  3. EdShep says:

    Excellent… thanks for this, I can see this coming in very handy. I had been looking for a way to get the attachments into the DW, but was not really very happy with this due to sizing issues – and the fact it’s not really the right place to store this kind of information, but this should do the trick nicely. Thanks again!

  4. German says:

    Thanks, Patrik! This is great!
    Some times I need activities to include attachments, so I’m planning on uploading them into SharePoint and just put the link in a notification.

  5. Rob says:

    Question – Qucik question…so will this do any and all attachments…so incidents, change requests? Just wanted to make sure.

  6. Patrik Sundqvist says:

    Yes, any Work Item or Configuration Item should work.

  7. Rob says:

    Last question Patrik – Sorry Patrik but how would I get the $ID info? I am trying to use get-scsmenumeration to get the workitem GUID but am having problems. Just need to get all requests with attachments in the system.

    Thanks

  8. Rob says:

    Thanks again Patrik. This helped me so much.

  9. Kenneth Andersen says:

    Hello Patrik,

    Thanks for all the articles regarding SCSM 2012, use them alot :-)

    I have a big problem – we have a old beta version af SCSM 2012, that we upgraded to RTM, but there is some unknow errors, that we thing is regarding to the old code from beta.
    So I looking for a solution to Export all Incident, Servicerequest and Problems with attachment, and then Import all in a brand new system (Windows 2012, SQL 2012 SP1 and SCSM 2012 SP1).

    Is there a way? I know that its a big assignment, and we will like to pay for a solution.

Leave a Reply