Error when executing Get-SCSMClass in SMA Powershell script

Stephane_BouillonStephane_Bouillon Customer IT Monkey ✭
Hi,
Every now and then I get a weird error when executing a script in SMA that otherwise runs without issues. I'm suspecting an intermittent concurrency issue, but I have no idea how to circumvent it.
My script then fails on the instruction

$ActivityClass = Get-SCSMClass System.Workitem$ -ComputerName $ComputerName

The error i'm getting is:

Get-SCSMClass : Item has already been added. Key in dictionary: 'HQSCSMMS01.multi.be_ENU'  Key being added: 
'HQSCSMMS01.multi.be_ENU'
At line:11 char:18
+ ... vityClass = Get-SCSMClass System.Workitem$ -ComputerName $ComputerNam ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (HQSCSMMS01.multi.be:String) [Get-SCSMClass], ArgumentException
    + FullyQualifiedErrorId : GenericMessage,SMLets.GetSMClassCommand

I tried without the -Computername parameter, but then I get another error:

Get-SCSMClass : The Data Access service is either not running or not yet initialized. Check the event log for more information.

Best Answer

  • Stephane_BouillonStephane_Bouillon Customer IT Monkey ✭
    Accepted Answer
    This code seems to get around the problem:
    $ComputerName = 'myServer'
    Import-Module SMLets
    $incidentClass = Get-SCSMClass -Name "system.workitem.incident$" -ComputerName $ComputerName
    If(-not $incidentClass)
    {
        Write-Output "Problem with PS module"
        Import-Module SMLets
        $IncidentClass =  Get-SCSMClass -Name 'System.WorkItem.Incident$' -ComputerName $Computername
    }
    subsequent code in the script runs without further errors. In the automation logs I see that from time to time I get the PS module error message.

Answers

  • Tom_HendricksTom_Hendricks Customer Super IT Monkey ✭✭✭✭✭
    Just to state the obvious, this is a truly strange error message.  I have never run across it in years of using SMLets directly, or via Orchestrator and SMA.

    • What version of SCSM are you running, and what version of SMLets?  Same version of SMA as SCSM?
    • Do you receive this error if you specify the -Name parameter? (e.g.: Get-ScsmClass -ComputerName myScsmServer -Name System.WorkItem$)
    There are two issues here I am trying to either confirm or rule out:  1.) SMA does seem to behave strangely when parameters are supplied by position rather than by naming the parameter, even if the same command works perfectly well in a PS window, and 2.) the fact that your error message mentions trying to add something as part of a "get" command makes me suspect something fundamentally wrong such as a version incompatibility of some kind.

    You are right to specify the -ComputerName param.  Otherwise, it assumes the local machine is what you are trying to talk to, and on an SMA server or your own computer, it is likely not running the Service Manager DAS service as your error correctly indicates.

  • Stephane_BouillonStephane_Bouillon Customer IT Monkey ✭
    I doubt there is a coding error, because it only fails very occasionally as I can observe in the automation Dashboard. What I'm suspecting is that when multiple scripts are triggered simultaneously, and the Get-SCSMClass is called there is some data that is initialised on the management server which is not properly isolated and upon reentry for another instance of the workflow it tries to recreate the same data structure while it already exists.

    I'll add the -Name parameter to the command and see if that helps

    Regarding your question: I'm running System Center 2016 SCSM Version 7.5.7487.0
    SMLETS version 0.5.0.1
  • Tom_HendricksTom_Hendricks Customer Super IT Monkey ✭✭✭✭✭
    I also do not suspect a coding error.  Your versions for SCSM and SMLets are fine, so that only leaves SMA.  Are you also running 2016 for SMA?  Powershell 4.x, or higher?

    Triggering multiple scripts concurrently should not cause you any problems unless they are creating data in SCSM, and even then it should only be an issue if one instance expects data that has since been changed by another.  I do not think it is likely that this is your issue, but I suppose anything is possible.

    I have definitely had issues with cmdlets in SMA Scripts if the parameters aren't explicitly named for some reason, so I hope that is your problem.  There is a decent chance of it.  I have never determined why this matters, but it is repeatable, and simple enough to work with.
  • Justin_WorkmanJustin_Workman Cireson Support Ninja IT Monkey ✭✭✭✭
    I see that you're passing -ComputerName a variable called $ComputerName.  Is it a hashtable of computer names?  If you specify the computer name explicitly does the command work?  I'm making a couple of assumptions here.  #1: Your SCSM server is contained in the variable $ComputerName and its name is HQSCSMMS01.  #2: The part of the command that it's choking on is the ComputerName not actually fetching the Class.  Based on these assumptions, it looks to me like somehow the script is trying to add the computer name to the $ComputerName variable again, but it already exists.  Of course I realize that get-scsmclass shouldn't be assigning values at all, but this does seem to be what the error is indicating.
  • Stephane_BouillonStephane_Bouillon Customer IT Monkey ✭
    thanks Justin, this opens a few avenues for getting rid of this problem. I might have been a bit overzealous to make the server configurable, and if I have to hardcode the server name, that's no issue for the moment, as I have only one server ;)
  • Stephane_BouillonStephane_Bouillon Customer IT Monkey ✭
    So, I rewrote the command as follows
    $ActivityClass = Get-SCSMClass -Name System.Workitem$ -ComputerName "HQSCSMMS01.multi.be"
    Unfortunately I still get the same error.
  • Stephane_BouillonStephane_Bouillon Customer IT Monkey ✭
    I also added quotes around System.Workitem$ with limited hope of success ...


    What I noticed in the logs is that it usually fails when the same script was run shortly before it.(which finished successfully).


    I'm now looking more towards finding a workaround when it actually fails. Does anyone have suggestions ?
  • Justin_WorkmanJustin_Workman Cireson Support Ninja IT Monkey ✭✭✭✭
    What if you set $SMDefaultComputer early on in the script and avoid adding the -ComputerName parameter on a per-command basis?
  • Tom_HendricksTom_Hendricks Customer Super IT Monkey ✭✭✭✭✭
    edited July 12
    Well, you ruled out the issue that I most commonly encounter in SMA, which is not naming all params.  I was hopeful that would do it, since that simple action has fixed many scripts for me (which run perfectly fine without it, outside of SMA). 

    I am glad @Justin_Workman has jumped in here, because this might be beyond what I can help with.  One last suggestion though, and then a tip:

    Perhaps it is not the act of getting a class that is failing, but rather you are seeing the affects of another cmdlet in the same error stream?  This is a bit of a stretch, but I'll continue the thought just in case.  Are there any other parts of your script that create/modify objects or relationships, perhaps later in the script that actually cause this error to occur in the previous run?

    I can at least offer this (completely optional) tip based off of Justin's comment, which helps reduce re-typing:
    $conn = @{"ComputerName"="mycomputername";"Credential"=$aPSCredentialObject}
    
    $class = Get-ScsmClass -Name "System.WorkItem$" @conn
    $someObject = $class | Get-ScsmObject -Filter "Id -eq 'IR12345'" @conn

    This is an example of "splatting" which I use in most scripts that use SMLets, particularly when I have to also supply a credential in addition to the server name.  It's shorthand, but can also help prevent errors of omission.  It also cleans up the script a bit.
  • Adam_DzyackyAdam_Dzyacky Customer Contributor Monkey ✭✭✭✭✭
    Catching up on this and it looks like @Justin_Workman and @Tom_Hendricks have beat me to most observations. The question I have is if you're running this in SMA, could you describe how you're doing that? What I'm getting at is does the SMA runbook inline script over to an SCSM mgmt server?
  • Stephane_BouillonStephane_Bouillon Customer IT Monkey ✭
    I have an advanced Service Request and in the template that it is derived from I have an SMA Runbook Activity that parses and formats the form fields to place them in the description of the created Service Request. The activity points to a PowerShell script that runs on an SMA server different from the SCSM management server.
  • Adam_DzyackyAdam_Dzyacky Customer Contributor Monkey ✭✭✭✭✭
    So given that setup, does the SMA server in question have the SCSM console deployed on it?
  • Stephane_BouillonStephane_Bouillon Customer IT Monkey ✭
    No, the SCSM Console is not deployed on the SMA server.
  • Adam_DzyackyAdam_Dzyacky Customer Contributor Monkey ✭✭✭✭✭
    Unless the requirement has changed (which it absolutely could have), in my experience I've needed the SCSM Console deployed alongside SMlets as there are binaries references in the SCSM Console installed directory. Without it, i've generally had hit and miss results with cmd-lets.

    Short of this, if you could try inline scripting the SMA runbook against a management server (where the console and smlets are presumably installed by virtue of the Cireson Portal) I'd be interested to know the results.
  • Stephane_BouillonStephane_Bouillon Customer IT Monkey ✭
    Would you recommend I install the console on the SMA server ? If yes, how would that change the execution of the runbook ?
  • Adam_DzyackyAdam_Dzyacky Customer Contributor Monkey ✭✭✭✭✭
    edited July 12
    To expand on my line of thinking here/per your setup:

    • SCSM has a template that invokes an SMA runbook
    • SMA invokes that runbook against SCSM remotely (i.e. you aren't inline scripting)
    • In the past I've seen SMLets need the SCSM Console installed, because they reference dll's within the SCSM installer directory
    • If you aren't inlinescripting to the management server, then yes i'd reccomend getting the SCSM console deployed. I've seen errors when even starting SMLets without a console that "binaries could not be found"

    But In terms of how this changes the runbook execution, per what @Justin_Workman it sounds like the $computername is a hashtable instead of just a string. Whichever the case, I'd go back to using the -computername parameter followed by a string variable set near the beginning of your script. Here's an example of how I begin a lot of my scripts/runbooks with SMLets:

    $mgmtServer = "localhost"
    
    $irClass = get-scsmclass -name "system.workitem.incident$" -computername $mgmtServer
    $ir = get-scsmobject -class $irClass -filter 'Name -eq 'IR12324'" -computername $mgmtServer

    This also serves the purpose of making fairly adaptable/shareable scripts since there is now only one place folks need to actually set their management server.

    The alternative to this which wouldn't require using -computername at all is to create a runbook in SMA that has an inlinescript to your SCSM server. This approach is the same as running the powershell directly on the box hence you don't need the -computername parameter. In order to achieve this, you'll need to create an SMA Asset that contains the username/password of a user that has the rights to log into that box and perform SCSM actions. You could use the SCSM Service Account or create a wholly new service account that is a local admin on the scsm mgmt server and an admin within SCSM. The advantage of this being that when it comes to Work Item history logs there is a clear distinction of "what SMA did"
  • Tom_HendricksTom_Hendricks Customer Super IT Monkey ✭✭✭✭✭
    Just to offer alternatives (skip this if you intend to install the console--it's pretty much just FYI then), Adam is correct, but it is not strictly necessary to install the console to achieve this.  In my case, I had installed SMLets on my orchestrator server a long time ago, and as part of that original installation, it required grabbing the SCSM dll's and copying them to orchestrator.  Fast forward a bit, and I had installed SMA on the same servers, since there was plenty of capacity to spare.  Still no SCSM console installed, but SMA "just worked" when running scripts that had SMLets in them.
  • Stephane_BouillonStephane_Bouillon Customer IT Monkey ✭
    Yes, I don't mind installing the console if that will solve the issue. I'll get back to the forum in a couple of days.
    On the other hand, I'm curious as to know a method for converting a hashtable into a string or more strictly control how this error occurs if that is the cause ? Another question is if a try/catch approach would help ?
  • Tom_HendricksTom_Hendricks Customer Super IT Monkey ✭✭✭✭✭
    I somehow managed to miss that the $computername variable is a hashtable, before. Of course, I am always doing at least one other task while posting here--I'd never have time to use this forum otherwise.  Are you by any chance passing that hashtable into an input parameter of a runbook or function?  Particularly in the case of runbooks, SMA does not handle hashtables well in my experience.  Could that be it?  If so, I have examples of runbooks that accept an object parameter and the runbook converts the object into a proper hashtable before proceeding.  Let me know and I could quickly scrub and share an example.

    To answer your question more directly, you want to end up with an array of computer names that is provided to your -ComputerName param, not a hashtable  of them.  An array, in terms of text, is just a comma-separated list.  A hashtable is an array of key/value pairs, which is not what the cmdlet is expecting as input.  There are ways to split and join your hashtable to condition it.
  • Stephane_BouillonStephane_Bouillon Customer IT Monkey ✭
    Accepted Answer
    This code seems to get around the problem:
    $ComputerName = 'myServer'
    Import-Module SMLets
    $incidentClass = Get-SCSMClass -Name "system.workitem.incident$" -ComputerName $ComputerName
    If(-not $incidentClass)
    {
        Write-Output "Problem with PS module"
        Import-Module SMLets
        $IncidentClass =  Get-SCSMClass -Name 'System.WorkItem.Incident$' -ComputerName $Computername
    }
    subsequent code in the script runs without further errors. In the automation logs I see that from time to time I get the PS module error message.
Sign In or Register to comment.