locked
Help using SMLets in workflow powershell script RRS feed

  • Question

  • Hello,

    I have written a powershell script in a workflow to help me perform a process. The idea is this: We have an extended Incident class and a custom RMA class, users will sometimes need to launch an RMA from an incident, but never an incident from an RMA or an RMA by itself. Therefore, source cardinality I assume is 1 and target cardinality is 2 (unlimited). The RMA NEEDS TO BE ASSOCIATED (related) to the ID # of the Incident Request. So, if you click on the Incident and go to related items, you should see the RMA id # there, and when you go to the related items of the RMA, you should see the appropriate IR # there. The workflow is launched by trigger: when an object of the RMA class is created.

    The workflow contains the following powershell script:

    # Load the SMlets module

    Import-Module SMlets

    # Get Date

    $date = ((Get-Date).AddDays(-1));

    # Set ClassName

    $ClassName = Get-SCSMClass -Name Flexity.RMA.Class;

    # Get the RMA Class

    $RMAClass = Get-SCSMObject -Class $ClassName | where{$_.CreatedDate -gt $date};

    # Set DisplayName, Title and Description to RMAx

    foreach ($RMA in $RMAClass)

     {$RMANumber = $RMA.RMA_ID; $RMA | Set-SCSMObject -PropertyHashtable @{"DisplayName"  =  $RMANumber; “Title” =  $RMANumber; ”Description” =  $RMANumber;   }}

    So I can get the RMA objects created, and properly name them so they show up as RMA{#} but still have not figured out how to get the parent incident and relate it to the appropriate RMA #... Any help would be greatly appreciated!!!!!

    Sunday, July 27, 2014 9:54 PM

Answers

  • @Anders

    For Service Manager 2010, numbers larger than 1 in a cardinality statement are evaluated as “unlimited” when an MP is imported into Service Manager. This means that MaxCardenality=“2” is the same as MaxCardenality=“2147483647”. Has this changed from 2010 to 2012?

    @Thomas

    You are indeed correct but I didn't receive any response in there from my last post so I thought it was dead by now. I have also progressed MUCH further from when I had posted that question, so I figured I should just make it a new topic as the topic of the question has become much more specific. I will link this post in there to be used as reference.

    I actually ended up figuring this out, let me know what you guys think and if it can be optimized in any way, or if you see any error checking I should add in somewhere.

    Thank you all for your help, especially with your detailed responses Thomas

    My original idea was to have a workflow and that workflow got launched when an object of the RMA class was created, regardless of HOW it was launched through console task or custom control or whatever. However, I ended up using a console task, which when clicked launches my script :)

    Code:

    # Creates a variable called IncidentID and points Incident # to it for use within the script
    Param([string]$IncidentID)
    # Load the SMlets module
    Import-Module SMlets 
    # Get the Incident Class
    $IncClass = Get-SCSMClass -Name System.WorkItem.Incident$
    # Get the RMA Class
    $RMAClass = Get-SCSMClass -Name flexity.RMA.class
    # Build the Filter String
    $FilterStr = "ID -eq " + $IncidentID
    # Find the Incident we need to link to an RMA
    $Inc = Get-SCSMObject -Class $IncClass -Filter $FilterStr
    $RMAIncText = ["Linked to Incident " + $Inc.ID + ""]
    $RMADescription = $RMAIncText 
    New-SCSMObject -Class $RMAClass -PropertyHashtable (@{Title = $Inc.Title; Description = $RMADescription})
    # Find the new RMA to be linked
    $FilterStr = "Description -eq '$RMADescription'"
    $RMA = Get-SCSMObject -Class $RMAClass -Filter $FilterStr
    #Set RMA Number Variable
    $RMANumber = $RMA.RMA_ID; 
     
    #Clean up DisplayName, Title and Description  
    $RMA | Set-SCSMObject -PropertyHashtable @{"DisplayName"  =  $RMANumber; "Title" =  $RMANumber; "Description" =  $RMANumber;   }
    # Create the relationship between the two items
    $RWIClass = Get-SCSMRelationshipClass -Name System.WorkItemRelatesToWorkItem$
    New-SCSMRelationshipObject -Relationship $RWIClass -Source $Inc -Target $RMA -Bulk
    New-SCSMRelationshipObject -Relationship $RWIClass -Source $RMA -Target $Inc -Bulk
    # Unload the SMlets module
    Remove-Module SMlets


    • Marked as answer by SirLearnAlot Monday, July 28, 2014 7:26 PM
    • Edited by SirLearnAlot Monday, July 28, 2014 7:28 PM added codeblock
    Monday, July 28, 2014 7:25 PM

All replies

  • How do your users get about creating the RMA from an incident? This requires adding a custom control to the IR form.

    You got the cardinality wrong. 2 is not unlimited, it is... well 2. And it has nothing to do as such with where the RMA can be "created from". It defines the number of relationships between the IR and RMA. Can an IR have multiple RMAs? Can an RMA be related to more than one IR, etc.

    I wrote something on this subject a while back codebeaver.blogspot.dk/2014/04/nested-type-projections-in-scsm-review.html - and you can also sirlearnalot something about nested type projections.

    I dont get how your workflow works. When an RMA object is created. How? Clicking something on the IR form?

    With regards to the PS you can use New-SCSMRelationshipObject (depending on how your relationship is defined) to relate the RMA and IR.


    http://codebeaver.blogspot.dk/

    Monday, July 28, 2014 8:28 AM
  • Maybe these two scripts are helpful to see how relationships in SCSM with PowerShell (SMlets) work:

    Get All Incidents With File Attachments (get related object) 

    http://gallery.technet.microsoft.com/SCSM-Get-All-Incidents-861d1bdd

    Add a Implementer to Manual Activity via PowerShell (Create new relationship)

    http://gallery.technet.microsoft.com/SCSM-Add-a-Implementer-to-74443a8f


    Andreas Baumgarten | H&D International Group

    Monday, July 28, 2014 8:50 AM
  • is this related to your Previous Question? it seems like you have not solved how to store which IR should relate to which RMA, and are trying to hack it by getting all the RMAs created today (or yesterday? AddDays(-1) should be yesterday). you'll probably want to optimize your retrieval command  by using -Filter  (I.e. [Get-SCSMObject -Class $RMAClass -filter "CreatedDate -gt $Date"], YMMV)

    You'll need to create a relationship to relate the IR to the RMA. something like this:

    Import-Module SMLets
    
    $WItoWIRel = Get-SCSMRelationshipClass System.WorkItemRelatesToWorkItem #Check my work on this one, I don't know if this name is correct
    
    $IRClass = Get-SCSMClass System.WorkItem.Incident$ #Again with the work checking, not sure on this name either
    $RMAClass = Get-SCSMClass -Name Flexity.RMA.Class;
    
    $IR = Get-SCSMObject -Class $IRClass -Filter #Find the right IR Somehow?
    $RMA = Get-SCSMObject -Class $RMAClass -Filter #Identify the correct RMA to relate Somehow?
    
    New-SCSMRelationship -Relationship $WItoWIRel -Source $RMA -Target $IR -Bulk 
    #the -bulk option means to create the relationship directly. 
    
    
    

    Monday, July 28, 2014 3:45 PM
  • @Anders

    For Service Manager 2010, numbers larger than 1 in a cardinality statement are evaluated as “unlimited” when an MP is imported into Service Manager. This means that MaxCardenality=“2” is the same as MaxCardenality=“2147483647”. Has this changed from 2010 to 2012?

    @Thomas

    You are indeed correct but I didn't receive any response in there from my last post so I thought it was dead by now. I have also progressed MUCH further from when I had posted that question, so I figured I should just make it a new topic as the topic of the question has become much more specific. I will link this post in there to be used as reference.

    I actually ended up figuring this out, let me know what you guys think and if it can be optimized in any way, or if you see any error checking I should add in somewhere.

    Thank you all for your help, especially with your detailed responses Thomas

    My original idea was to have a workflow and that workflow got launched when an object of the RMA class was created, regardless of HOW it was launched through console task or custom control or whatever. However, I ended up using a console task, which when clicked launches my script :)

    Code:

    # Creates a variable called IncidentID and points Incident # to it for use within the script
    Param([string]$IncidentID)
    # Load the SMlets module
    Import-Module SMlets 
    # Get the Incident Class
    $IncClass = Get-SCSMClass -Name System.WorkItem.Incident$
    # Get the RMA Class
    $RMAClass = Get-SCSMClass -Name flexity.RMA.class
    # Build the Filter String
    $FilterStr = "ID -eq " + $IncidentID
    # Find the Incident we need to link to an RMA
    $Inc = Get-SCSMObject -Class $IncClass -Filter $FilterStr
    $RMAIncText = ["Linked to Incident " + $Inc.ID + ""]
    $RMADescription = $RMAIncText 
    New-SCSMObject -Class $RMAClass -PropertyHashtable (@{Title = $Inc.Title; Description = $RMADescription})
    # Find the new RMA to be linked
    $FilterStr = "Description -eq '$RMADescription'"
    $RMA = Get-SCSMObject -Class $RMAClass -Filter $FilterStr
    #Set RMA Number Variable
    $RMANumber = $RMA.RMA_ID; 
     
    #Clean up DisplayName, Title and Description  
    $RMA | Set-SCSMObject -PropertyHashtable @{"DisplayName"  =  $RMANumber; "Title" =  $RMANumber; "Description" =  $RMANumber;   }
    # Create the relationship between the two items
    $RWIClass = Get-SCSMRelationshipClass -Name System.WorkItemRelatesToWorkItem$
    New-SCSMRelationshipObject -Relationship $RWIClass -Source $Inc -Target $RMA -Bulk
    New-SCSMRelationshipObject -Relationship $RWIClass -Source $RMA -Target $Inc -Bulk
    # Unload the SMlets module
    Remove-Module SMlets


    • Marked as answer by SirLearnAlot Monday, July 28, 2014 7:26 PM
    • Edited by SirLearnAlot Monday, July 28, 2014 7:28 PM added codeblock
    Monday, July 28, 2014 7:25 PM
  • cool. looks like a good solution. you should only have to create one of those relationships thou, the console loads both directions and displays them in the same list, so regardless if the RMA is the source or the target, it will show up the same way in the Incident Related Work Items.
    Monday, July 28, 2014 7:30 PM
  • @Anders

    For Service Manager 2010, numbers larger than 1 in a cardinality statement are evaluated as “unlimited” when an MP is imported into Service Manager. This means that MaxCardenality=“2” is the same as MaxCardenality=“2147483647”. Has this changed from 2010 to 2012?

    this hasn't changed, but the standard is still defined as the maximum number of relationships, even if the current implementation only respects 1 and lots. If they fix the implementation, your relationship may break.
    Monday, July 28, 2014 7:35 PM
  • Ah ok thanks I wasn't 100% sure if I needed it or not so I just put it in anyways. And as for the cardinality, I'm not really worried that Microsoft will fix it as they didn't from 2010 still, and plus they aren't exactly keeping it updated anyways - service manager is FILLED with bugs that will never be addressed it seems. Thanks for everything Thomas!
    Monday, July 28, 2014 7:40 PM
  • Hello again Thomas,

    After performing some other modifications and implementing my script, I realize my script function is not completed. When an incident is open and my custom "Create linked RMA" task is run, it creates an rma and associates it with the incident correctly, but our analysts still have to manually save the incident and reopen it to see the newly created "RMA" in the related items tab, then open the correct RMA from there, or manually go to my RMA custom view and select the appropriate RMA to open. Is there a way to make the console task open the custom work item (RMA form) that it just created? I tried playing with the SMlets but couldn't find one to actually auto open a form (make it pop out so the analyst can proceed to fill in its details).

    From my research I discovered I could put the custom console task in my custom form assembly (I think), and launch the form from its guid. But I was hoping for a quicker fix either directly in my script or through passing parameters within the console task.

    Any guidance would be appreciated. Thanks in advance.

    Tuesday, August 5, 2014 5:25 PM
  • This is the expected behavior. The powershell script is "going around" the console and addressing the OMSDK on the server directly; essentially the console has no way of knowing it's item has been updated. 

    In order to correct this issue, you'd need to step up to a custom console task that runs inside the console SDK, and can call the commit and refresh functions on the form. 

    However, if you are going to go to the trouble of writing a custom console SDK, then you probably want to cut out the middle man and use the C# Console SDK directly to create the new RMA in the form's data context using CreateNewProjectionInstanceBindableItem(). This would enable the default Ok/Cancel/Apply behaviors on the parent form.

    Tuesday, August 5, 2014 6:53 PM
  • I appreciate the quick response. I am a big SCSM newbie and still learning this stuff as I go, so please forgive me for not understanding 100% and requiring you to be more specific.

    Your first suggestion was to create a custom console task that runs inside the console SDK. I am no expert, but I am assuming this means I have to edit my custom forms assembly in Visual Studio and add in references to the console SDK, then add my script directly in the assembly as well as call a function that opens the form? If so, I would like to avoid this if possible.

    The second option sounds more fitting to my situation but I am not fully clear on it. When you say use the C# Console SDK directly what are you referring to? Is this a written script? Is this in the C code of my assembly? Or is this code I can enter directly into the console task within the Script dialogue box? Again, sorry for my ignorance.

    What do you mean by create the RMA in the form's data context?

    CreateNewProjectionInsanceBindableItem() is a function to use in the C Code of my assembly?

    Tuesday, August 5, 2014 9:28 PM
  • they're both visual studio. i'm just suggesting that if you need to update the form, your going to have to go into visual studio and write custom C# code against the console SDK, and if you're going to do that, you might as well just do everything in the Console SDK rather then breaking out to powershell. 

    also, C# is pronounced "Sea Sharp", reference http://en.wikipedia.org/wiki/C_Sharp_(programming_language) 


    • Edited by Thomas Bianco Tuesday, August 5, 2014 9:47 PM explanation
    Tuesday, August 5, 2014 9:44 PM
  • Blah. I was hoping to avoid that. Thanks Thomas. I knew what C Sharp was I just was not clear as to where I had to add the code.

    I will refer to your linked post then and try to perform the necessary modifications. Will update here once complete or if any errors reached. Thanks again.
    Tuesday, August 5, 2014 9:59 PM