Was this helpful? Share It!
  • System Center: Orchestrator Engineering Team Blog

    Quick Tip: Enabling Link Text But Getting Rid of “Link”

    • 1 Comments

    If you're like me, you like to put descriptive text in a link to describe what it does. Perhaps it's to indicate the conditions of a branching structure, like this:

    image_thumb2

    But what’s annoying is that when you turn on the Link text, every link has the word “Link” on it (as if you didn’t know it was a link). Not only is that annoying but it clutters up the display with text you don’t want to see. So how can you get rid of that? Well, there are actually a few ways to do this.

    Inserting a Blank Space

    You’ve probably already tried and discovered that if you open the properties of the link and just delete the “Link” text and save it, the text is right back there. Likewise, if you just enter a space character, it does the same thing. This is because by default the code that sets the link values ignores null values and values that are nothing but spaces and just returns the link to its previous value (whatever that it).

    But you can fool the link into putting a space in there by entering a special ASCII character. Open the link properties, go to the General tab, delete the Link text, and then insert this ASCII character by holding down the ALT key and then typing 0160 (using the number pad – they number keys above the letters won’t work). The result is that there’s a tiny little break in the line where that character was inserted:

    image_thumb4

    Changing the Default Links to No “Link” Text

    So modifying the links on the fly is great, but how can you avoid having the “Link” text appear in the first place? Well that’s pretty simple too, but it requires creating an XML file. Now this advice is a bit different than the advice I gave for Opalis. In Opalis, all of the strings were contained in XML files. In Orchestrator, we’ve converted most of the strings to resource DLL files to make it easier for localization. However, we will still load strings from XML if they are there, and more importantly, if it finds an XML file with the string it needs first, it doesn’t try to load the one in the DLL. So knowing that fact is an advantage here because we can create an XML file containing the string we want for the Link text and it will override the value in the DLL!

    Strings in the Runbook Designer are managed by XML and DLL files located here:

    • (32-bit systems) C:\Program Files\Common Files\Microsoft System Center 2012\Orchestrator\Strings
    • (64-bit systems) C:\Program Files (x86)\Common Files\Microsoft System Center 2012\Orchestrator\Strings

    In the appropriate directory above, create a new file named OrchestratorMain.Strings.xml

    Enter the following XML into the file (making sure there is a space in the “str_Link: value:

    <Strings>
    <str_Link> </str_Link>
    </Strings>

    Save the file and open the Runbook Designer (close and reopen if it was already open). Now when you drag new between activities, they default to no text at all (not even the space), like this:

    image_thumb6

    Getting Dangerous: Modifying Existing Link Text via SQL Query

    Now that you’ve seen how to modify the link text on the fly and to modify the default link text, what about those hundreds of existing runbooks you have that all have “Link” everywhere? How do you fix those?

    The title of this post sounds a bit scary, right? Well, it's intended to be scary because I'm going to show you something to make you dangerous. This is not something that you should do without a thorough understanding of SQL queries and a complete backup of your Orchestrator database before continuing!

    IMPORTANT:

    The process described in this article involves editing the Orchestrator SQL database. If you are not comfortable with this, then do not do it.

    You should always back up your database before making any manual changes like this. I have only done minimal testing in a limited environment that probably doesn’t come close to your own environment’s configuration.

    Neither I nor Microsoft, nor any other person, animal, vegetable or mineral assumes responsibility for the process demonstrated here. USE AT YOUR OWN RISK!

    All activities in your runbooks are stored in the Orchestrator database in the OBJECTS table. Within the table is a field called NAME which contains the display name of the activity. It just so happens that links are activities too, and it's easy to find all of the links on all your workflows that have the default text of "Link" using a simple query:

    SELECT [UniqueID]
    ,[Name]
    ,[ObjectType]
    FROM [Orchestrator].[dbo].[OBJECTS]
    WHERE Name = 'Link'

    Now you've probably got a LOT fewer runbooks than I do in my database, because when I ran this query, it returned 4,036 rows. That's 4,036 different links that have the default text. I'd have to have a LOT of free time if I wanted to go modify these individually! By the way, I included the "ObjectType" field in the query just so I could confirm that all of these were links and not some other object. To be sure, I re-ran the query and added another condition in the where clause to exclude objects of the ObjectType I saw, and nothing was returned, so I know they were all Links.

    Now the dangerous part… to convert this to an UPDATE query.

    Since the Name field cannot be null, we'll replace the "Link" with just a space and see what happens.

    UPDATE [Orchestrator].[dbo].[OBJECTS]
    SET Name = ' '
    WHERE Name = 'Link'

    I run this and it says 4,036 rows affected. That's reassuring…

    Now I close and re-open the Runbook Designer … and all my links that had "Link" text are now solid lines! Woo Hoo!

    I hope you find this useful in visually cleaning up your workflows. Enjoy!

  • System Center: Orchestrator Engineering Team Blog

    Want to Use .NET 4.0 with Orchestrator Toolkit IPs? Here’s How!

    • 0 Comments

    One of our most awesome test guys on the Orchestrator Team, Zhenhua Yao, who has delivered such goodies as the TFS IP and a PowerShell IP on our CodePlex site, has done it again!

    Anyone who has built an IP using the Orchestrator SDK knows that you need to set your project to .NET 3.5 or it won’t work. Well, Yao figured out that you can make a couple of registry changes and a .config file and enable .NET 4.0 assemblies to work just fine! This is a great relief to those who already had their own tools that were compiled as .NET 4 assemblies and were not going to be able to use them with Orchestrator.

    For the full scoop on how to enable this functionality, see Yao’s blog here:  Enable .NET 4 in Orchestrator Integration Toolkit

    Happy Coding!

  • System Center: Orchestrator Engineering Team Blog

    More Fun with COM: Importing Integration Packs via PowerShell

    • 0 Comments

    Around the office, we have more and more internal teams that are latching on to Orchestrator and wanting to use it for building all sorts of integrations and automations, but one of the things that comes up from time to time is how to get the ability to have some sort of complete installation process that doesn’t require a separate step for installing Integration Packs or runbooks. In this case, enabling the automatic registering and deployment of an Integration Pack would really enable a streamlined installation process.

    Note from the legal dept: The process described here is not officially supported by Microsoft and are provided only as an example to the community.

    Neither I nor Microsoft, nor any other person, animal, vegetable or mineral assumes responsibility for the process demonstrated here. USE AT YOUR OWN RISK!

    Before I start, here are links to the previous parts of the “COM” series:

    Going back into the COM interface for Orchestrator, I can see that there is an “AddIntegrationPack” method available, and it takes a “Variant” type (which is usually XML for the Orchestrator Interface). The only thing is I don’t know what that XML looks like. However, luckily enough, there is also a “GetIntegrationPacks” method that I can use to return XML and I can figure out the format needed! As it turns out, the XML format looks like this:

    <IntegrationPacks>
      <IntegrationPack>
        <UniqueID datatype="string">{7A17B8D2-D916-4397-B774-26D9EDE3D9F1}</UniqueID>
        <Name datatype="string">System Center Configuration Manager</Name>
        <Description datatype="string">Workflow Activities for System Center Configuration Manager</Description>
        <Version datatype="int64">1</Version>
        <Library datatype="string">SCCMClientServerExtension.dll</Library>
        <ProductName datatype="string">IP_SYSTEMCENTERCONFIGURATIONMANAGER_1.0.OIP</ProductName>
        <ProductID datatype="string">{FD5A9BAC-E55F-4F35-AB26-381EE1D85B23}</ProductID>
      </IntegrationPack>
    </IntegrationPacks>

    So now I know that if I use this format when adding an Integration Pack, I should be fine. But where do I get this information, and what does this really get me?

    First of all, it’s useful to know how the whole process of registering and deploying Integration Packs works. If you missed the earlier post on the topic, you should see it here:

    Understanding IP Installation: What Does Register/Unregister/Deploy/Undeploy Really Mean?

    As it turns out, the format of the XML is actually the format of the .CAP file located inside the .OIP file. What this process of "AddIntegrationPack” does is the registration part. It doesn’t cover the rest of the stuff that Deployment manager does like copying the files to the right places or deploying the MSI to make the IP functional. It’s really just adding info to the database. However, this is a crucial part to getting an IP working. So in addition to the COM interface stuff, I will have to add some other stuff to be fully functional. Here’s the whole process in a nutshell:

    1. Crack open the OIP file and extract the files within to a subdirectory
    2. Copy the MSI File to %Common Files%\Microsoft System Center 2012\Orchestrator\Management Server\Components\Objects
    3. Read the MSI database info to get the product name and product code (since those are only in the MSI)
    4. Read the .CAP file into an XML object and update the ProductName and ProductID elements to be the product code from #3.
    5. Use AddIntegrationPack to import the CAP file info into the database
    6. Rename the OIP file to be {ProductCode}.OIP and copy to %Common Files%\Microsoft System Center 2012\Orchestrator\Management Server\Components\Packs
    7. Run msiexec.exe to install the MSI file

    In order to do all of this from PowerShell, I relied on some cool code provided on Rikard Ronnkvist’s blog that allowed me to read properties from within an MSI file, including loading another COM object (WindowsInstaller.Installer) and some new type definitions that I load dynamically in my script.

    Here is the script:




    Function LoadTypeData()
    {
    $contents = @"
    <!--Copied from: Abhishek's PowerShell Blog - http://abhishek225.spaces.live.com/blog/
        Original post: http://abhishek225.spaces.live.com/blog/cns!13469C7B7CE6E911!165.entry-->

    <Types>
      <Type>
        <Name>System.__ComObject</Name>
        <Members>
          <ScriptMethod>
            <Name>GetProperty</Name>
            <Script>
              $type = $this.gettype();
              $type.invokeMember($args[0],[System.Reflection.BindingFlags]::GetProperty,$null,$this,$null)
            </Script>
          </ScriptMethod>
          <ScriptMethod>
            <Name>SetProperty</Name>
            <Script>
               $type = $this.gettype();
               $type.invokeMember($args[0],[System.Reflection.BindingFlags]::GetProperty,$null,$this,@($args[1]))
             </Script>
          </ScriptMethod>
          <ScriptMethod>
            <Name>InvokeParamProperty</Name>
            <Script>
              $type = $this.gettype();
              $index = $args.count -1 ;
              $methodargs=$args[1..$index]
              $type.invokeMember($args[0],[System.Reflection.BindingFlags]::GetProperty,$null,$this,$methodargs)
            </Script>
          </ScriptMethod>
          <ScriptMethod>
            <Name>InvokeMethod</Name>
            <Script>
              $type = $this.gettype();
              $index = $args.count -1 ;
              $methodargs=$args[1..$index]
              $type.invokeMember($args[0],[System.Reflection.BindingFlags]::InvokeMethod,$null,$this,$methodargs)
            </Script>
          </ScriptMethod>
        </Members>
      </Type>
    </Types>
    "@
    $contents | Out-File -FilePath $(Join-Path $(Get-Location) "comObject.types.ps1xml")  -Force
    Update-TypeData -AppendPath $(Join-Path $(Get-Location) "comObject.types.ps1xml") -ErrorAction SilentlyContinue
    }

    function global:Get-MsiProperty
    {    
        PARAM (        
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true,ValueFromPipeline=$true)]
        [String]$Filename,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true,ValueFromPipeline=$true)]
        [String]$Propertyname
        )
        
        # A quick check to see if the file exist    
        if(!(Test-Path $Filename))
        {        
            throw "Could not find " + $Filename    
        }     

        # Create an empty hashtable to store properties in    
        $msiProp = ""
        # Creating WI object and load MSI database    
        $wiObject = New-Object -com WindowsInstaller.Installer    
        $wiDatabase = $wiObject.InvokeMethod("OpenDatabase", (Resolve-Path $Filename).Path, 0)     
        # Open the Property-view    
        $view = $wiDatabase.InvokeMethod("OpenView", "SELECT * FROM Property")    
        $view.InvokeMethod("Execute")     
        # Loop thru the table    
        $r = $view.InvokeMethod("Fetch")    
        while($r -ne $null)
        {        
            # Add property and value to hash table        
            $prop = $r.InvokeParamProperty("StringData",1)
            $value = $r.InvokeParamProperty("StringData",2)
            if ($prop -eq $PropertyName)
            {
                $msiProp = $value
            }
            # Fetch the next row        
            $r = $view.InvokeMethod("Fetch")    
        }     
        $view.InvokeMethod("Close")     
        
        return $msiProp
    }


    function Connect-SCOServer{
    <#
    .SYNOPSIS
       Establishes a connection handle to the Orchestrator COM interface

    .DESCRIPTION
        Establishes a connection handle to the Orchestrator COM interface that can be used
        with other functions that require authentication to succeed. This script must
        be run from the Orchestrator Management Server.

    .PARAMETER UserName
        A valid user account with rights to perform actions against Orchestrator
        objects such as runbooks, folders, etc. Must be entered in the form of:
        DOMAIN\USERNAME
        
    .PARAMETER Password
        The password associated with the provided user account.
        
    .EXAMPLE
        $ConnectionHandle = Connect-SCOServer -Username "domain\user" -Password "Password"
        
    .OUTPUTS
        System.Int32

    #>

    [CmdletBinding()]
        PARAM (
            [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true, ParameterSetName="SpecifyUser")]
            [ValidateNotNullOrEmpty()]
            [String] $UserName = $(throw "Provide a valid user account (domain\username)"),
            
            [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true, ParameterSetName="SpecifyUser")]
            [ValidateNotNullOrEmpty()]
            [String] $password = $(throw "Provide a password for the user account)")
        )
        
        PROCESS
        {
            try
            {
                $oismgr = new-object -com OpalisManagementService.OpalisManager
                $ohandle = New-Object object
                $handle = $handle = New-Object Runtime.InteropServices.VariantWrapper($ohandle)
                $retval = $oismgr.Connect($UserName, $password, [ref]$handle)
                
                if ($handle.GetType().FullName -eq "System.Int32")
                {
                    return $handle
                }
                else
                {
                    Write-Error "Unable to get a valid connection handle to Orchestrator!" -ErrorAction Stop
                }
            }
            catch
            {
                Write-Error "Exception occurred in $($MyInvocation.MyCommand): `n$($_.Exception)"
                throw new-object system.formatexception
            }
        }
    }


    function Install-SCOIntegrationPack{
    <#
    .SYNOPSIS
      Registers and optionally deploys an Integration Pack to the current computer.
      Assumes the current computer is a Management Server (and a Designer/Runbook Server
      in the case of deploying the IP)

    .DESCRIPTION
        
    .PARAMETER Handle
      The handle to the COM interface created using New-SCOConnection

    .PARAMETER Filename
      The path and filename of the OIP file to be imported

    .PARAMETER Deploy
      Switch parameter used when you want to also deploy the IP.
          
    .EXAMPLE
      Install-SCOIntegrationPack -OIPFile "C:\Files\Test.OIP" -Deploy
        

    .OUTPUTS
       
    #>
        [CmdletBinding()]
        PARAM (
            [Parameter(Mandatory=$true)]
            [Int] $Handle,

            [Parameter(Mandatory=$true)]
            [String] $Filename,
                           
            [Parameter(Mandatory=$false)]
            [Switch] $Deploy
            
            
        )
        BEGIN
        {
            $oismgr = new-object -com OpalisManagementService.OpalisManager
            $sh = new-object -com shell.application
            LoadTypeData
        }
        PROCESS
        {
            try
            {

                if ($(Test-Path $filename) -eq $false)
                {
                    Write-Error "File Not Found!"
                    return
                }
                [System.IO.FileInfo]$oipFile = gi $filename
                
                $extractDir = $(Join-Path -Path $oipFile.DirectoryName -ChildPath $oipFile.BaseName)
                if (Test-Path $extractDir)
                {
                    ri $extractDir -Recurse -Force
                }

                $ipSourceDirObj = $sh.namespace($oipFile.DirectoryName)
                $ipSourceDirObj.NewFolder($oipFile.BaseName)
                $extractDirObj = $sh.namespace($extractDir)

                Write-Debug "`n`nExtracting files from the OIP"
                $zipFileName = Join-Path $oipFile.DirectoryName "$($oipFile.BaseName).zip"
                if (Test-Path $zipFileName)
                {
                    ri $zipFileName -Force
                }
                $zipFile = $oipFile.CopyTo($zipFileName)
                $zipFileObj = $sh.namespace($zipFile.FullName)

                
                $extractDirObj.CopyHere($zipFileObj.Items(),8 -and 16 -and 256)

                $commonFiles = ${Env:CommonProgramFiles(x86)}
                if ($null -eq $commonFiles)
                {
                    $commonFiles = ${Env:CommonProgramFiles}
                }
                $PacksDir = Join-Path $commonFiles "Microsoft System Center 2012\Orchestrator\Management Server\Components\Packs"
                $ObjectsDir = Join-Path $commonFiles "Microsoft System Center 2012\Orchestrator\Management Server\Components\Objects"

                if ($(Test-Path $PacksDir) -eq $false)
                {
                    Write-Error "Could not find $($PacksDir)"
                    return
                }
                if ($(Test-Path $ObjectsDir) -eq $false)
                {
                    Write-Error "Could not find $($ObjectsDir)"
                    return
                }

               

                # Copy the MSI File to %Common Files%\Microsoft System Center 2012\Orchestrator\Management Server\Components\Objects
                $msiFile = $extractDirObj.self | gci | Where {$_.extension -eq ".msi"}
                

                $newMSIfile = $(Join-Path $ObjectsDir $msiFile.Name)
                if (Test-Path $newMSIfile)
                {
                    ri $newMSIfile -Force
                }
                $msiFile.CopyTo($newMSIfile)
                $productName = Get-MSIProperty -Filename $msiFile.FullName -Propertyname "ProductName"
                $productCode =  Get-MSIProperty -Filename $msiFile.FullName -Propertyname "ProductCode"


                #now use the MgmtService to install the IP
                [System.IO.FileInfo]$capfile = $extractDirObj.self | gci | Where {$_.extension -eq ".cap"}
                if ($capfile)
                {
                    Write-Host "     Extracting $($capFile)"
                    $capXml = New-Object XML
                    $capXml.Load($capfile.Fullname)

                
                    # Need to modify the CAP file to add Product ID and Product Name because Deployment Manager
                    # reads the MSI file for this and inserts it into the DB so it displays in the UI. The COM
                    # interface does not do this, so it needs to be done manually if you want it displayed.
                    #
                    #     <ProductName datatype="string">IP_SYSTEMCENTERDATAPROTECTIONMANAGER_1.0.OIP</ProductName>
                    #    <ProductID datatype="string">{9422FCC6-11C4-4827-AC49-C5FD352C8AA0}</ProductID>
                    

                    [Xml]$prodName = "<ProductName datatype=`"string`">$($ProductName)</ProductName>"
                    [Xml]$prodID = "<ProductID datatype=`"string`">$($ProductCode)</ProductID>"
                    
                    $c = $capXml.ImportNode($prodName.ProductName, $true)
                    $d = $capXml.ImportNode($prodID.ProductID, $true)
               
                    $capXml.Cap.AppendChild($c)
                    $capXml.Cap.AppendChild($d)

                    $oIPinfo = new-object object
                    [ref]$ipinfo = $ipinfo = New-Object Runtime.InteropServices.VariantWrapper($capXml.get_innerxml())
                    Write-Host "     Importing Integration Pack $($capFile)"
                    $retval = $oismgr.AddIntegrationPack($Handle, $ipinfo)
                }

                # Copy the OIP File to the %Common Files%\Microsoft System Center 2012\Orchestrator\Management Server\Components\Packs
                # directory and change the name to the GUID of the IP
                $productCodeOipFilename = "$($ProductCode).OIP"

                $newOIPfile = $(Join-Path $PacksDir $productCodeOipFilename)
                if (Test-Path $newOIPfile)
                {
                    ri $newOIPfile -Force
                }
                $oipFile.CopyTo($newOIPfile)



                if ($PSBoundParameters.ContainsKey('Deploy') -eq $false)
                {
                    return
                }

                if ($(Test-Path $newMSIfile) -eq $false)
                {
                    Write-Error "Could not find $($newMSIfile)"
                    return
                }

                Write-Verbose "Running msiexec to install  $($newMSIfile)"

                $proc = New-Object System.Diagnostics.Process
                $proc.StartInfo.FileName = "msiexec.exe"
                $proc.StartInfo.Arguments =  "/i `"$($newMSIfile)`" /qn"
                $proc.Start() | out-null
                $proc.WaitForExit()

            }
            catch
            {
                Write-Error "Exception occurred in $($MyInvocation.MyCommand): `n$($_.Exception)"
                
            }
            
        }    
            
    }

    To run the script, open a PowerShell(x86) console on the Management Server using Run As Administrator (required to access the Common Files directories), and then just do the following:

    1. Create a connection to the COM interface :

           $conn = Connect-SCOServer –username <domain\user> -password <password>
    2. Register the IP:

          Install-SCOIntegrationPack –handle $conn –filename <path and filename of OIP>

      if you also want to deploy the IP to the local machine (assuming it’s a Runbook Designer or Runbook Server):

          Install-SCOIntegrationPack –handle $conn –filename <path and filename of OIP> –Deploy
    3. You’re done!

    You can see how this process can enable you do incorporate IP installation and deployment into the actual installation (like via an MSI) of an application. Keep watching for more fun and exciting articles on automating administration of Orchestrator.

    The script shown above is also attached to the article. Enjoy!

     

  • System Center: Orchestrator Engineering Team Blog

    Understanding IP Installation: What Does Register/Unregister/Deploy/Undeploy Really Mean?

    • 0 Comments

    One of the most foundational activities an Orchestrator admin does is installing Integration Packs. After all, Integration Packs provide the real value to Orchestrator because they allow you to extend its capabilities and let you connect to virtually anything so you can automate and orchestrator across many different platforms. However, just because it’s one of the more common activities doesn’t mean most admins really understand it. In fact, it’s one of the more misunderstood parts of the platform. Hopefully here I can shed a little light on how it all works (and why it works the way it does, even if it might not be the way you expected).

    Installing an IP

    When you install a new IP, the process involves two distinct steps:

    1. Register the IP

    Deployment Manager opens up the OIP file (which is actually just a renamed ZIP file) and extracts several things – a .CAP file, an .MSI file, and some other things like the EULA. The .CAP file is an XML file that the Deployment Manager uses to import the right data into the CAPS table in the Orchestrator database. The CAPS table simply defines the Integration Packs’ names and IDs so they can be located for further actions. The CAP file also contains information that defines other tables where the activities themselves are defined, along with SQL scripts to effect the appropriate database changes. Deployment Manager then renames the OIP file to the product ID and saves it to the “C:\Program Files (x86)\Common Files\Microsoft System Center 2012\Orchestrator\Management Server\Components\Packs” directory, and saves the MSI file to the “C:\Program Files (x86)\Common Files\Microsoft System Center 2012\Orchestrator\Management Server\Components\Objects” directory.

    2. Deploy the IP

    Once the IP has been registered, it has to be deployed to every Runbook Designer and Runbook Server that needs to have it. Deploying the IP involves Deployment Manager copying the file to the remote computer (if not the current computer) and using msiexec.exe to install the MSI file. This would be essentially the same as you copying the file to the machine and double-clicking on the MSI file. When the MSI installs, it verifies that the computer it’s installing on is a Runbook Designer or Runbook Server (it won’t install anywhere else). The installer creates a registry key here: “HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\SystemCenter2012\Orchestrator\IPs”. This is used by the Deployment Manager to quickly determine which machines have the IP installed. An XML file in the MSI is copied to “C:\Program Files (x86)\Common Files\Microsoft System Center 2012\Orchestrator\Extensions\”. This MSI contains definitions for the IP and activities used by the Runbook Designer to know how to display the category and activities. The remaining files in the MSI, including the assemblies and dependent files, are copied to “C:\Program Files (x86)\Common Files\Microsoft System Center 2012\Orchestrator\Extensions\Support\Integration Toolkit” into a subdirectory named with the product ID guid.

    Upgrading an IP

    When you upgrade an existing IP, you have to first uninstall, or un-deploy, the IP from the Runbook Designers and Runbook Servers where it is installed. This is because if any files from an IP are in use when the new version is installed, installation will fail or cause a reboot of the computer. It could leave your server in a bad state or worse, reboot a runbook server at the most inappropriate time.

    Once you uninstall, you do not unregister. IPs have built-in knowledge on how to upgrade an existing version (this code was enhanced for Orchestrator 2012 to fix issues and limitations with Opalis 6.3’s upgrade process). However, if you unregister the IP, you can end up defeating the upgrade logic and wind up with a bad installation. The proper course of action is to simply register the new IP with the previous version still registered. Then you simply deploy the IP out to the Runbook Designers and Runbook Servers again.

    Uninstalling an IP

    So what happens when you just want to get rid of an IP? Maybe you created a brand new version of an IP that doesn’t upgrade from the old version – it is a new IP. You want to remove the old IP, so you uninstall the IP from the Runbook Designers and Runbook Servers, and you unregister the IP. SO what happens when you do that? Well when you uninstall, it’s pretty simple. It just uninstalls the MSI from the appropriate computers. When you unregister the IP, all it does it remove the OIP file from the “Packs” directory mentioned above. That’s all. I know, right now you’re saying “WHAT???” Why doesn’t it remove the information from the database too?

    When we were planning Orchestrator 2012, we also questioned this and wondered why we wouldn’t clean out the database to put it back the way is was before the IP was installed. Basically, this would have left the DB in a cleaned-up state. The thing was, we decided that it wasn’t appropriate for us to determine arbitrarily to delete information from a customer’s database. After all the data associated with the IP and its activities includes runtime data, can include valuable published data and auditing information, and if we simply deleted that data, we would make some customers very unhappy! So, we eventually decided to not change the behavior that existed in Opalis 6.3 so that the data would be retained. Now this decision had repercussions in the other direction in that leaving all this data in the database could lead to issues with re-installations of the IP or future versions of the IP, but those would likely be few.

    The biggest issue with leaving deleted activity and IP information in the database is simply that the DB can potentially bloat with data that is no longer used and not readily accessible. In a future post, I’ll show you a tool I created for helping remove this bloat. The key is that you control what gets removed rather than it being arbitrarily removed during IP unregistration.

    By the way… since you know that unregistering an IP simply removes the OIP file, if you ever accidentally unregister an IP, all you need to do is replace the guid-named OIP file back in the “Packs” directory and it will appear as registered again!

    Hopefully this has helped shed some light on the potentially confusing process of IP installation and uninstallation in Orchestrator 2012. As always, keep the comments and suggestions coming!

  • System Center: Orchestrator Engineering Team Blog

    Private Cloud Demo Extravaganza Videos!

    • 0 Comments

    I just noticed that all of these cool demo videos were posted to TechNet Video earlier this month.  Check them out to see how System Center 2012 can make managing your private cloud a whole lot easier and better!

     

    Private Cloud Demo Extravaganza 1: Deploy Bare Metal Servers to Hyper-V with System Center 2012

    http://technet.microsoft.com/en-us/video/video/private-cloud-demo-extravaganza-1-deploy-bare-metal-servers-to-hyper-v-with-system-center-2012

     

    Private Cloud Demo Extravaganza 2: Multiple Hypervisors for Cloud Resources & Adding ESX Servers with System Center 2012

    http://technet.microsoft.com/en-us/video/video/private-cloud-demo-extravaganza-2-multiple-hypervisors-for-cloud-resources-and-adding-esx-servers-with-system-center-2012

     

    Private Cloud Demo Extravaganza 3: Add Resources to a Failover Cluster with System Center 2012

    http://technet.microsoft.com/en-us/video/video/private-cloud-demo-extravaganza-3-add-resources-to-a-failover-cluster-with-system-center-2012

     

    Private Cloud Demo Extravaganza 4: Service Template Creation & Deployment with System Center 2012

    http://technet.microsoft.com/en-us/video/video/private-cloud-demo-extravaganza-4-service-template-creation-deployment-with-system-center-2012

     

    Private Cloud Demo Extravaganza 5: Standardized Service Updating with System Center 2012

    http://technet.microsoft.com/en-us/video/video/private-cloud-demo-extravaganza-5-tandardized-service-updating-with-system-center-2012

     

    Private Cloud Demo Extravaganza 6: Monitor Network Devices with System Center 2012

    http://technet.microsoft.com/en-us/video/video/private-cloud-demo-extravaganza-6-monitor-network-devices-with-system-center-2012

     

    Private Cloud Demo Extravaganza 7: Monitor and Automatically Resolve Issues in the Fabric with System Center 2012

    http://technet.microsoft.com/en-us/video/video/private-cloud-demo-extravaganza-7-monitor-and-automatically-resolve-issues-in-the-fabric-with-system-center-2012

     

    Private Cloud Demo Extravaganza 8: Create an Orchestrator Runbook and Integrate with Service Manager with System Center 2012

    http://technet.microsoft.com/en-us/video/video/private-cloud-demo-extravaganza-8-create-an-orchestrator-runbook-and-integrate-with-service-manager-with-system-center-2012

     

    Private Cloud Demo Extravaganza 9: Create Self-Service Request Offerings using the Service Catalog with System Center 2012

    http://technet.microsoft.com/en-us/video/video/private-cloud-demo-extravaganza-9-create-self-service-request-offerings-using-the-service-catalog-with-system-center-2012

     

    Private Cloud Demo Extravaganza 10: Deliver Self-Service Request Offerings using the Service Catalog with System Center 2012

    http://technet.microsoft.com/en-us/video/video/private-cloud-demo-extravaganza-10-deliver-self-service-request-offerings-using-the-service-catalog-with-system-center-2012

     

    Private Cloud Demo Extravaganza 11: Gain Insight & Visibility through Service Manager Reporting with System Center 2012

    http://technet.microsoft.com/en-us/video/video/private-cloud-demo-extravaganza-11-gain-insight-and-visibility-through-service-manager-reporting-with-system-center-2012

     

    Private Cloud Demo Extravaganza 12: Enabling Application Performance Monitoring with System Center 2012

    http://technet.microsoft.com/en-us/video/video/private-cloud-demo-extravaganza-12-enabling-application-performance-monitoring-with-system-center-2012

     

    Private Cloud Demo Extravaganza 13: Creating an Application Performance Monitoring Dashboard with System Center 2012

    http://technet.microsoft.com/en-us/video/video/private-cloud-demo-extravaganza-13-creating-an-application-performance-monitoring-dashboard-with-system-center-2012

     

    Private Cloud Demo Extravaganza 14: Deep Application Diagnostics & Insight with System Center 2012

    http://technet.microsoft.com/en-us/video/private-cloud-demo-extravaganza-14-deep-application-diagnostics-and-insight-with-system-center-2012.aspx

     

    Private Cloud Demo Extravaganza 15: Managing Applications Across Private & Public Clouds with System Center 2012

    http://technet.microsoft.com/en-us/video/private-cloud-demo-extravaganza-15-managing-applications-across-private-and-public-clouds-with-system-center-2012.aspx

     

    Private Cloud Demo Extravaganza 16: Managing Application Resources Across Private & Public Clouds with System Center 2012

    http://technet.microsoft.com/en-us/video/private-cloud-demo-extravaganza-16-managing-application-resources-across-private-and-public-clouds-with-system-center-2012.aspx

     

    Private Cloud Demo Extravaganza 17: Self-Service Application Deployment with System Center 2012

    http://technet.microsoft.com/en-us/video/private-cloud-demo-extravaganza-17-self-service-application-deployment-with-system-center-2012.aspx

  • System Center: Orchestrator Engineering Team Blog

    Upcoming Webcast Series: Bare Metal to Private Cloud

    • 0 Comments

    I’ve been spending quite a bit of time with customers over the last 6-12 months helping them plan out and deploy their first private clouds managed by System Center 2012.  To help people get started faster I headed into the Enterprise Engineering Center (EEC) on the Redmond campus, arranged for some really nice hardware, and set up a System Center managed private cloud from bare metal all the way up.  All along the way I recorded everything I did.  In this 8 part webcast series I will show you some of the best practices and process for getting start with your System Center 2012 managed private cloud.  We will deploy a Hyper-V host cluster, Virtual Machine Manager, Operations Manager, Service Manager, Orchestrator, the Cloud Service Process Management Pack, integrate them all together and do so in a high performance and high availability configuration.

    The web cast series starts next week and will be every Tuesday and Thursday at 11:00 AM Redmond time from May 29th through June 28th.  We will take the week of TechEd North America off.  All of the web casts will be available on demand after the initial showing.

    Please register for the sessions, add them to your calendar, and join me over the next few weeks as we go from Bare Metal to Private Cloud!

    -Travis

     

    5/29/2012 11:00:00 AM - Bare Metal to Private Cloud (Part 1 of 8): Beginning with the End in Mind

    http://go.microsoft.com/?linkid=9809577  or  http://bit.ly/JTGtJK

    Abstract:

    In this session, we take a look at the end state of managing a private cloud with Microsoft System Center, including the Cloud Services management pack. The sessions that follow this session describe how to go from bare metal to a private cloud managed by System Center.
    _____________

    5/31/2012 11:00:00 AM - Bare Metal to Private Cloud (Part 2 of 8): Hardware and Prerequisite Software Platform

    http://go.microsoft.com/?linkid=9809578  or  http://bit.ly/KJc41E

    Abstract:

    In this session, we take a look at the hardware used for these sessions as examples of the kind of hardware that you can use to run a private cloud. We’ll also discuss how to install and configure the prerequisite software, such as the Windows Server operating system, SQL Server data management software, and Active Directory Domain Services.
    _____________

    6/5/2012 11:00:00 AM - Bare Metal to Private Cloud (Part 3 of 8): Clustering Hyper-V and Installing a Highly Available Virtual Machine Manager Cluster

    http://go.microsoft.com/?linkid=9809579  or http://bit.ly/KvgVAM

    Abstract:

    In this session, we take a look at how to create a Hyper-V host cluster and install a highly available cluster by using Virtual Machine Manager, a component of Microsoft System Center 2012.

    _____________

    6/7/2012 11:00:00 AM - Bare Metal to Private Cloud (Part 4 of 8): Configuring System Center 2012 - Virtual Machine Manager

    http://go.microsoft.com/?linkid=9809580   or  http://bit.ly/KlsCYU

    Abstract:

    In this session, we talk about how to configure Virtual Machine Manager, a component of Microsoft System Center 2012. We explore how to deploy agents, create a host group, create a cloud, and create virtual networks.

    _____________

    6/19/2012 11:00:00 AM - Bare Metal to Private Cloud (Part 5 of 8): Installing and Configuring System Center 2012 - Operations Manager

    http://go.microsoft.com/?linkid=9809581  or http://bit.ly/J2WDgE

    Abstract:

    In this session, we show how to install a highly available Microsoft System Center 2012 - Operations Manager and deploy agents to manage the private cloud.

    _____________

    6/21/2012 11:00:00 AM - Bare Metal to Private Cloud (Part 6 of 8): Installing and Configuring System Center 2012 - Service Manager

    http://go.microsoft.com/?linkid=9809582   or http://bit.ly/Ms8GtP

    Abstract: 

    In this session, we show how to install a highly available Microsoft System Center 2012 Service Manager, including the configuration management database (CMDB), data warehouse, reporting, self-service portal, and service catalog.

    _____________

    6/26/2012 11:00:00 AM - Bare Metal to Private Cloud (Part 7 of 8): Installing and Configuring System Center 2012 - Orchestrator

    http://go.microsoft.com/?linkid=9809583  or http://bit.ly/JXQgPA

    Abstract:

    In this session, we show how to install a highly available Microsoft System Center 2012 - Orchestrator and installing the System Center and other integration packs for automated administration of the private cloud.

    _____________

    6/28/2012 11:00:00 AM - Bare Metal to Private Cloud (Part 8 of 8): Integrating System Center 2012

    http://go.microsoft.com/?linkid=9809584  or http://bit.ly/JcGHxd

    Abstract:

    In this session, we configure the many integration points between the Microsoft System Center components and also between System Center and Active Directory Domain Services.

  • System Center: Orchestrator Engineering Team Blog

    Working With Relationships in the SCSM Orchestrator Integration Pack

    • 0 Comments

    Working with relationships in the SCSM integration pack can be a bit tricky so this blog post is intended to provide some tips.

    First of all it is really important when working with Service Manager to understand the data model.  Have a look at the data model diagram that is included in the SM Job Aids package (more info) for details on what classes, properties and relationships exist in the out of box model.  Keep in mind that the Orchestrator integration pack reflects this data model when you are configuring activities in a runbook.  Another useful way to explore the data model is to use PowerShell (more info).

    Secondly, if you haven’t already watched them I highly recommend watching these two demo videos that will provide you needed background info on automating service request fulfillment with SCSM and Orchestrator:

    Demo: Automating Service Request Fulfillment from the SCSM Service Catalog with Orchestrator

    Demo: Automating Service Request Fulfillment from the SCSM Service Catalog with Orchestrator–Real World Examples

    For the purposes of this blog post we will deal with a fairly common scenario when you are trying to automate service request fulfillment using SCSM (Service Catalog and Service Requests) and Orchestrator (runbooks).  The scenario is adding the requesting user to a particular group in Active Directory.

    The relevant part of the data model look like this (simplified):

    image

    The Runbook activity is going to kick off the Orchestrator runbook and it is going to pass a single piece of data to the runbook via the Initialize Data activity – the Runbook Activity Work Item GUID:

     

    Configuration in Orchestrator:

    image

    Configuration in SCSM:

    image

    So – now when the runbook starts out it starts from the context of knowing exactly which Runbook Activity Work item triggered it.  From there we can figure out which Group is related to it (i.e. the group that the requesting user should be added to).

    image

    We can also figure out the parent service request (see hyperlink above) and then we can traverse from the service request over to the Affected User.

     

    So – our runbook looks like this at a high level:

    image

    This is what each activity does:

    Initialize Data – takes in the runbook activity work item GUID as described above.

    Get Group Relationship – this activity finds all the objects of a specific class that are related to the runbook activity work item – in this case the Active Directory Group class.  The runbook activity work item GUID that is passed in via the Initialize Data activity is used as the starting point.

    Get Group Object – this takes the output of the Get Group Relationship activity and actually gets the Group object itself using the related object GUID that is returned by the Get Group Relationship activity.

    Let’s recap where we are….

    image

    image

    image

     

    Now we are going to do essentially the same thing to get the parent service request.

    Get Parent SR Relationship  - this activity gets the relationship between the Runbook Activity Work Item and the Service Request.

    Get Parent SR – this activity actually gets the SR object using the output from the Get Parent SR Relationship activity.

    image

    image

    OK – so let’s pause here and take a look at the configuration of each of these activities so far:

    image

    image

    image

    image

     

    So far this should seem pretty straightforward.  Now we are going to get a little bit tricky.  The next thing we are going to do is traverse from the service request over to the affected user and get that object.

    Get User Relationship – This activity gets the relationship between the service request and the affected user.

    Get User Object – This activity gets the actual user object.

    image

    image

    And the configuration dialogs:

    image

    image

     

     

    Seems the same right?  Not quite!  There is a catch here.

    Notice how in the Get Group Relationship configuration I pointed to the Active Directory Group class.

    image

    And in the Get User Relationship activity I pointed to the Active Directory User or Group class.

    image

     

    It’s really only conceivable for purposes of this scenario that the only Active Directory Groups that will be related to the Runbook Activity Work Item will be those which are related by the Work Item About Config Item relationship type.

    In the case of the Service Request being related to the User class there are actually multiple relationship types between those two classes.  In fact there are three in the out of the box data model:

    image

    Keep in mind that in the Get User Relationship activity the only configuration that I am providing is the source class (Service Request), source object GUID (Service Request GUID), and the target class (User).  If the Created By User relationship points to Bob, the Assigned to Relationship points to Sally, and the Affected User points to Donna, how does Orchestrator know that I am looking for the Affected User Donna??

    Here’s what happens.  Orchestrator will grab all of the related objects that are of the User class that are related to the Service Request and put them on the databus as published data. If you open up the Runbook Tester and run this runbook you will see this in the output:

    image

    Those … mean that there is a collection of property values there not just one.  If we double click on the … we can see the output in a table format:

    image

    So you can see in this case by looking at the Related Object GUID that the Affected User and the Created By User are the same user and the Assigned To User is a different user.  Now – what we want to do is filter the list of objects that are passed along on the databus such that only the Affected User is passed along and everything else is dropped.

    To do this we right click on the link coming out of the Get User Relationship activity and choose Properties:

    image

    Then click the Exclude tab and the Add button to add an Exclude filter.  Click the first link and set it to Relationship Class, change the operator to ‘Does Not Equal’ and then click the last link and type in ‘Affected User’ (exactly as you see it above in the table).

    This will now filter out the Assigned To User and Created By User and pass along only the Affected User on the databus.

    That’s the trick!  The rest is easy.

    image

    image

    image

    That’s it!

    One more tip.  As I showed you above you need to use the Display Name of the relationship type in question.  You can discover the relationship type display name by using SMLets.  First – look up the internal name in the Visio diagram of the data model linked to at the beginning of this blog post.  For example the relationship type with the display name of ‘Affected User’ is called System.WorkItemAffectedUser.  Then you can run a command in SMLets like this:

    image

    If you aren’t sure of the exact internal name of a relationship but you might have some idea of the word(s) that might be included you can do a quick search using part of the name using SMLets too:

    image 

  • System Center: Orchestrator Engineering Team Blog

    Quick Tip: Using the “Read Text Log” Activity

    • 0 Comments

    I had someone contact me recently with some confusion about the Read Text Log activity in Orchestrator. It seems that it wasn’t quite working the way they expected and they were left scratching their head. So I put together a quick demo runbook and tested it out. I thought I’d share my experience just to help any others out there that might be sharing the same confusion.

    First, I created a simple log file with a few entries.

    image

    I configured my activity like this:

    clip_image002[5]

    The time set for getting log lines “more recent than” was the second entry in the log. I put in the custom timestamp format so it would know how to interpret the time, and then I ran the activity in the Runbook  Tester. Here’s what came out:

    image

    You can see from this that when you use “lines more recent than”, it will actually return “lines equal to or more recent than”. So plan for that in your definition of the activity.

    I then changed the settings of the activity to get log entries between two dates:

    image

    And here you can see that once again, the matching lines were inclusive of the dates and times I specified:

    image

     

    One interesting thing I found that is sure to cause confusion if it happens to you: If the last line in your log file does not have a carriage return (if the cursor doesn’t go to the next line), the last line will not be returned by the activity. It apparently doesn’t see that as a complete line and therefore doesn’t match it and return it.

    So hopefully this little lesson on the Read Text Log activity will help you better understand how to use it. Until next time…

     

    By the way…You can find the documentation for the Read Text Log activity on Technet:  http://technet.microsoft.com/en-us/library/hh206063.aspx

  • System Center: Orchestrator Engineering Team Blog

    New Exchange Integration Pack On the TechNet Gallery

    • 0 Comments

    Bart Timmermans (blog, @Bart_Inovativ) , a consultant at Inovativ, has just released an integration pack for Exchange!  Here is a graphic of the activities included.  You can read more about the integratio pack on his blog or download it from the TechNet Gallery.  Nice work Bart! 

    I’m really looking forward to setting up some automated self-service provisioning scenarios with the Service Manager service catalog + Orchestrator on the backend with this integration pack!

    image 

  • System Center: Orchestrator Engineering Team Blog

    Make Your PowerShell Script Activities Go “Splat”!

    • 0 Comments

    There are always interesting shortcuts and magical techniques to discover in PowerShell, and “splatting” is one of them. Splatting allows you to bundle a set of parameters into a hashtable and then simply using it as single parameter to a PowerShell function or cmdlet. For example, instead of specifying a command line with a bunch of parameters in a long command line like this (which could get longer):

    Get-WmiObject –computername SERVER-R2 –class Win32_LogicalDisk –filter "DriveType=3" –credential "Administrator"

    You can use a hashtable to define parametername – value pairs like this:

    $params = @{'class'='Win32_BIOS'; 
               'computername'='SERVER-R2'; 
               'filter'='drivetype=3';
               'credential'='Administrator' }

    And then all you need to do is specify a command line like this:

    Get-WMIObject @params

    While initially this may not seem like such a magical solution, the more parameters you have to a script, function or cmdlet, the more elegant this becomes. Now take this concept and apply it to activities in a runbook, either using the Run .NET Script activity or using custom activities built using the Command Line Activity Wizard in the Toolkit. You can imagine that having to create 10 or 20 input parameters or the same number of outputs for an activity can be kind of cumbersome.

    Here’s what a custom command-line activity would look like if you called it with 10 parameters:

    image

    You can’t even see all of the command line or the parameters in the same screen!

    Or, here is what the Run .Net Script activity would look like with 10 output parameters:

    image

    Now imagine having to map individual published data items to and from these inputs and outputs across several activities. Well that’s how many people build runbooks with PowerShell. Believe me when I tell you that splatting is WAY easier!

    Here’s an example of using splatting. First of all, I’ll start the runbook with an Initialize Data activity in order to gather the 10 parameters I need:

    image

    Next I need to convert those 10 individual inputs into a “here-string”, which is essentially a multi-line string:

    image

    Now that’s the hardest you’ll have to work in the whole runbook, because from now on, you can really simplify by using splatting. In the next activity I have a function that uses these parameters.In order to use these parameters, I will need to wrap the string that comes from Published Data in a “here-string” again, because when it’s created in the first activity, it’s actually an object type and gets output to string for the databus (but it retains the line breaks). When transferred on the databus it loses it’s “object-like” nature, so it needs to be put into an object again. I then use the “ConvertFrom-StringData” cmdlet to convert the string into a hashtable.

    image

    At the end of this script, I just call the function with the following command line:

    Test-MyCode @params

    Now you might be saying this simple example doesn’t really show me how I would save time with splatting, because I still had to create an Initialize Data activity with 10 parameters, and I had to put in an extra activity to create the here-string before I got to my script. OK, well, you’re right. Sort of. What I *didn’t* have to do was to create 10 special PowerShell input or output parameters like I showed above. I’ve also set myself up for an easier time if I decide to re-user this script activity in a number of other runbooks. I know that whenever I need to re-use it, I can just send it a single parameter as a here-string and it will take care of all the parameters it needs.

    I also know that if I need to pass data from one Run .Net Script activity to another, I don’t have to transfer anything other than one parameter, and simply do it as a here-string and then convert to a hashtable for splatting. Now passing data across multiple script activities gets a LOT easier and less time consuming (and less chance for error too).

    So be sure to try this out and use it across your own scripting activities!

Page 1 of 9 (82 items) 12345»
Was this helpful? Share it!