ocs Archives - Tales of a Code Monkey https://cymbeline.ch/tag/ocs/ ... the adventures of a guy making software. Sat, 22 Feb 2014 23:00:44 +0000 en-US hourly 1 https://wordpress.org/?v=5.9.3 PowerShell Script to trace OCS Components https://cymbeline.ch/2009/12/11/powershell-script-to-trace-ocs-components/?utm_source=rss&utm_medium=rss&utm_campaign=powershell-script-to-trace-ocs-components Fri, 11 Dec 2009 13:13:00 +0000 /post/2009/12/11/PowerShell-Script-to-trace-OCS-Components.aspx Tracing OCS components may be vital in troubleshooting various issues you may face in your deployment. On machines where you have OCS components installed, you’ll typically find a tool called OCSLogger.exe which allows you to start/stop/view traces of OCS components. However, sometimes this is not enough, for instance when you see problems at the startup … Continue reading "PowerShell Script to trace OCS Components"

The post PowerShell Script to trace OCS Components appeared first on Tales of a Code Monkey.

]]>
Tracing OCS components may be vital in troubleshooting various issues you may face in your deployment. On machines where you have OCS components installed, you’ll typically find a tool called OCSLogger.exe which allows you to start/stop/view traces of OCS components. However, sometimes this is not enough, for instance when you see problems at the startup of a machine. It’s kind of hard to run the GUI if you cannot logon yet. But you can typically run a scheduled task. Or maybe you are — just like me — more like the console guy and thus want to have a script/cmdline tool for everything.

Let’s start with the config file used by the script (TraceConfig.xml) which defines the components you want to trace, to what level the traces are supposed to be and some more things. The sample given here traces mostly the components which are useful in troubleshooting issues related to the Response Group Service of OCS.

<?xml version="1.0" encoding="utf-8"?>
<Config>
    <!--
        Levels:
            TL_FATAL        1
            TL_ERROR        2
            TL_WARN         3
            TL_INFO         4
            TL_VERBOSE      5
            TL_NOISE        6

        Flags:
            TF_COMPONENT    0x00000001
            TF_PROTOCOL     0x00000002
            TF_CONNECTION   0x00000004
            TF_SECURITY     0x00000008
            TF_DIAG         0x00000010
            TF_AUTH         0x00000020
            TF_PARSE        0x00000040
            TF_NETWORK      0x00000080
            TF_STACKTRACE   0x00000100
    -->
    <Default Level="6" Flags="0xffff" />
    <Paths Tracer="C:\Program Files\Common Files\Microsoft Communications Server 2007 R2\Tracing"
           Etl="D:\Tracing"
           Log="D:\Tracing"
           TmfSearchPath="C:\Program Files\Common Files\Microsoft Communications Server 2007 R2\Tracing">
    </Paths>
    <Components>
        <Component Name="LcsWMI" Enabled="no" />
        <Component Name="LcsWMIUserServices" Enabled="no" />

        <Component Name="PowerShell" Enabled="yes" />

        <Component Name="ApplicationServer" Enabled="yes" />

        <Component Name="RgsClientsLib" Enabled="yes" />
        <Component Name="RgsCommonLibrary" Enabled="yes" />
        <Component Name="RgsDatastores" Enabled="yes" />
        <Component Name="RgsDeploymentApi" Enabled="yes" />
        <Component Name="RgsDeploymentLibrary" Enabled="yes" />
        <Component Name="RgsDiagnostics" Enabled="yes" />
        <Component Name="RgsHostingFramework" Enabled="yes" />
        <Component Name="RgsMatchMakingService" Enabled="yes" />
    </Components>
</Config>

I added the most importan trace levels and flags in the comment. Right now, the Default element defines the levels and flags for all components, but there’s no reason why you shouldn’t be able to do that per component you want to trace.

The PS1 script itself (Tracer.ps1) heavily relies on the OcsTracer.exe tool which also comes with OCS and is typically installed in the same place as OcsLogger.exe. It has four main actions:

  1. Start tracing components
  2. Stop tracing components and format the traces
  3. Format traces of ETL files (e.g. from a different machine)
  4. Show the configuration details from a particular config XML file
<#
.SYNOPSIS
        Starts or Stops tracing of Office Communications Server components.
.DESCRIPTION
        Starts or Stops tracing of Office Communications Server components.
.PARAMETER Action
        The action to perform. Must be one of 'Start', 'Stop', 'Config' or
        'Format'.
.PARAMETER ConfigPath
        The path to the configuration XML file. If not specified,
        "TraceConfig.xml" is used.
.LINK
        This script was originally posted to
        http://www.cymbeline.ch/post/2009/12/11/PowerShell-Script-to-trace-OCS-Components.aspx
.EXAMPLE
        .\Tracer.ps1 Start

        Starts tracing all the enabled components from the "TraceConfig.xml" file.
.EXAMPLE
        .\Tracer.ps1 Stop

        Stops tracing all the enabled components from the "TraceConfig.xml" file
        and formats the traces.
.EXAMPLE
        .\Tracer.ps1 Format "MyOtherConfig.xml"

        Formats the traces of the enabled components from the "MyOtherConfig.xml"
        file with all the settings from the "MyOtherConfig.xml" file.
.EXAMPLE
        .\Tracer.ps1 Config

        Shows the configuration of the "TraceConfig.xml" file.
#>
param(
    [Parameter(Mandatory=$true)]
    [ValidateSet("Start", "Stop", "Config", "Format", IgnoreCase=$true)]
    [String] $Action,
    [String] $ConfigPath = "TraceConfig.xml"
)

$configXml = ((Get-Content $ConfigPath))
$tracerPath = $configXml.Config.Paths.Tracer
$etlDir = $configXml.Config.Paths.Etl
$logDir = $configXml.Config.Paths.Log
$tmfSearchPath = $configXml.Config.Paths.TmfSearchPath

# Construct the parameters for the 'Start' command to OcsTracer.exe
function getStartParams()
{
    $ret = @()

    $configXml.Config.Components.Component |
        ? {$_.Enabled -eq "yes"} |
        foreach {
            $ret = $ret +
                ("/Component:" + $_.Name + "," + $configXml.Config.Default.Level +
                    "," + $configXml.Config.Default.Flags + " ")
        }

    return $ret
}

# Construct the parameters for the 'Stop' command to OcsTracer.exe
function getStopParams()
{
    $ret = @()

    $configXml.Config.Components.Component |
        ? {$_.Enabled -eq "yes"} |
        foreach { $ret = $ret + ("/Component:" + $_.Name) }

    return $ret
}

# Format the ETL files for enabled components to a human readable format
function formatFiles(
    [Parameter(Mandatory=$true)]
    [String] $Timestamp
)
{
    md $logDir\$timestamp -ea silentlycontinue | Out-Null

    $configXml.Config.Components.Component |
        ? {$_.Enabled -eq "yes"} |
        foreach {
            $etlFile = $_.Name + ".etl";

            if (Test-Path $etlFile)
            {
                $logFile = $Timestamp + "\" + $Timestamp + "_" + $_.Name + ".log";

                & "$tracerPath\OcsTracer.exe" Format /LogFilePath:"$etlDir\$etlFile" /OutputFile:"$logDir\$logFile" /TmfSearchPath:"$tmfSearchPath" | Write-Verbose
            }
            else
            {
                Write-Warning "File $etlFile not found.";
            }
        }
}

Write-Host "Using Config File: $ConfigPath"
$timestamp = Get-Date -format "yyyy-MM-dd_HH.mm.ss"

if ($Action -eq "start")
{
    Write-Host "Removing all .etl files ..."
    ls $etlDir *.etl | ri

    Write-Host "Start tracing components ..."
    $params = getStartParams

    & "$tracerPath\OcsTracer.exe" Start $params /LogFileFolder:"$etlDir" | Write-Verbose
}
elseif ($Action -eq "stop")
{
    Write-Host "Stop tracing components ..."
    $params = getStopParams

    md $logDir\$timestamp | Out-Null

    & "$tracerPath\OcsTracer.exe" Stop $params /OutputFile:"$logDir\$timestamp\$($timestamp)_All.log" /TmfSearchPath:"$tmfSearchPath" | Write-Verbose

    if (!$?)
    {
        rd $logDir\$timestamp | Out-Null
    }
    else
    {
        Write-Host "Sessions stopped. Start formatting ..."
        formatFiles $timestamp
    }
}
elseif ($Action -eq "format")
{
    Write-Host "Formatting traces from ETL files ..."
    formatFiles $timestamp
}
elseif ($Action -eq "config")
{
    Write-Host "Default values"
    Write-Host "--------------"
    $configXml.Config.Default | ft Level,Flags

    Write-Host "Paths"
    Write-Host "-----"
    $configXml.Config.Paths | fl

    Write-Host "Components"
    Write-Host "----------"
    $configXml.Config.Components.Component | ft Name,Enabled
}
else
{
    Write-Error "Unknown action."
}

For samples on how to run the script, please run man .\Tracer.ps1 -Examples
Have fun 🙂

The post PowerShell Script to trace OCS Components appeared first on Tales of a Code Monkey.

]]>
Finding the Private Key File of Certificates https://cymbeline.ch/2009/11/30/finding-the-private-key-file-of-certificates/?utm_source=rss&utm_medium=rss&utm_campaign=finding-the-private-key-file-of-certificates Mon, 30 Nov 2009 18:54:00 +0000 /post/2009/11/30/Finding-the-Private-Key-File-of-Certificates.aspx At work, I have created multiple tools which we used to analyse and fix issues related to certificates that we use with Office Communications Server and their respective private key files. To summarize, a user/service who wants to use the certificate for authentication needs to have read access on the private key. If it doesn’t, … Continue reading "Finding the Private Key File of Certificates"

The post Finding the Private Key File of Certificates appeared first on Tales of a Code Monkey.

]]>
At work, I have created multiple tools which we used to analyse and fix issues related to certificates that we use with Office Communications Server and their respective private key files. To summarize, a user/service who wants to use the certificate for authentication needs to have read access on the private key. If it doesn’t, you’ll typically see a strange error which many people don’t relate to missing ACLs on the private key file.

Now these days, you don’t need to write such tools anymore. PowerShell allows you to pretty much do everything you need in this area. Let’s look at the following PS script (let’s call it FindPrivateKey.ps1) which accepts a parameter of type System.Security.Cryptography.X509Certificates.X509Certificate2, i.e. a reference to the certificate you want to analyze.

param(
    [Parameter(Mandatory=$true)]
    [System.Security.Cryptography.X509Certificates.X509Certificate2]
    $Certificate
)

echo "Looking for private key file of certificate"
echo $Certificate
echo ""
echo "The private key file is '$($Certificate.PrivateKey.CspKeyContainerInfo.UniqueKeyContainerName)'"
echo ""

$file = ls $env:userprofile -Filter $Certificate.PrivateKey.CspKeyContainerInfo.UniqueKeyContainerName -Recurse -Force -EA SilentlyContinue
echo "It is located at '$($file.FullName)'."

I guess I do not need to mention that you can easily find the certificate you’re interested in by running something like

pushd cert:\CurrentUser\My
ls
$cert = gci 0DAC31905AEB722D8561BFAF3F3BFD2F551AA197
popd
.\FindPrivateKey.ps1 $cert

where ‘0DAC31905AEB722D8561BFAF3F3BFD2F551AA197’ is simply the thumbprint of the certificate we’re interested in. From here on it should be easy to check what ACLs the file has (run $file.GetAccessControl()) and to modify them (run $file.SetAccessControl()).

The post Finding the Private Key File of Certificates appeared first on Tales of a Code Monkey.

]]>
Retrieving Agent’s Sign-in Information in RGS https://cymbeline.ch/2009/08/18/retrieving-agents-sign-in-information-in-rgs/?utm_source=rss&utm_medium=rss&utm_campaign=retrieving-agents-sign-in-information-in-rgs Tue, 18 Aug 2009 13:05:00 +0000 /post/2009/08/18/Retrieving-Agents-Sign-in-Information-in-RGS.aspx Animated by a recent comment I decided to give some more insight into the Agent Sign-in logic of the Response Group Service of Office Communications Server 2007 R2. We keep the sign-in states of agents in formal agent groups in a dedicated table called ‘AgentGroupSignInStates’ in the backend database (called ‘acddyn’) for each pool. The … Continue reading "Retrieving Agent’s Sign-in Information in RGS"

The post Retrieving Agent’s Sign-in Information in RGS appeared first on Tales of a Code Monkey.

]]>
Animated by a recent comment I decided to give some more insight into the Agent Sign-in logic of the Response Group Service of Office Communications Server 2007 R2.

We keep the sign-in states of agents in formal agent groups in a dedicated table called ‘AgentGroupSignInStates’ in the backend database (called ‘acddyn’) for each pool. The table is kept very simple. It consists only of three fields:

  • AgentId (uniqueidentifier)
  • GroupId (uniqueidentifier)
  • State (tinyint)

The first two fields, AgentId and GroupId, make up the primary key for the table, so they have to be unique. In other words, an agent can only have one sign-in state for every group he’s a member of. The State field indicates the current sign-in state for the agent with the given AgentId in the group with the given GroupId. A value of 0 means that the agent is not signed in, 1 means that the agent is signed in. If a record does not exist for an agent in a formal group, then the agent has never signed in yet (so he’s signed out). The AgentId and GroupId values should match the values of existing agents and groups in the RGS system (in WMI), though this is not enforced.

You should not modify records in the ‘AgentGroupSignInStates’ table, because the table is only kept as a reference in case of data-loss in the MatchMaking component of the Response Group Service. However, MatchMaking always keeps this table up-to-date, so reading from it should give you the most recent view on the sign-in states of the agents.

The post Retrieving Agent’s Sign-in Information in RGS appeared first on Tales of a Code Monkey.

]]>
Troubleshooting Authentication Issues with RGS Agent Tab https://cymbeline.ch/2009/07/29/troubleshooting-authentication-issues-with-rgs-agent-tab/?utm_source=rss&utm_medium=rss&utm_campaign=troubleshooting-authentication-issues-with-rgs-agent-tab Wed, 29 Jul 2009 19:08:00 +0000 /post/2009/07/29/Troubleshooting-Authentication-Issues-with-RGS-Agent-Tab.aspx Sometimes – especially in lab environments – you’ll see issues around user authentication with the RGS Agent Tab of Office Communications Server 2007 R2. This post should help you in determining what could be the issue and how to work around it. First of all, when the OCS 2007 R2 WebComponents get installed on a … Continue reading "Troubleshooting Authentication Issues with RGS Agent Tab"

The post Troubleshooting Authentication Issues with RGS Agent Tab appeared first on Tales of a Code Monkey.

]]>
Sometimes – especially in lab environments – you’ll see issues around user authentication with the RGS Agent Tab of Office Communications Server 2007 R2. This post should help you in determining what could be the issue and how to work around it.

First of all, when the OCS 2007 R2 WebComponents get installed on a machine, by default Integrated Windows Authenticated (IWA) for the RGS parts of WebComponents are enabled. We don’t require IWA, but this is the recommended setting; anything but Anonymous Authentication should work. If Anonymous Authentication is set for the RGS virtual directory in IIS, you’ll find a warning in NT event log about that. In that case, you should turn back on authentication for the virtual directory.

Another problem I’ve seen a couple of times was as follows: Agent A’s credentials are used to sign in with Office Communicator, but the Agent Tab in OC shows the RGS Agent Group memberships of Agent B, or it shows that the “Current User is not an Agent”. In this case, you should start tracing the RgsClientsLib component and either wait until the Agent Tab in OC refreshes automatically (this should happen within 30 – 60 seconds) or you can open the tab URL in IE; it’s typically something like https://pool-1.contoso.com/Rgs/Clients/Tab.aspx. Then, stop tracing and check out the captured traces for RgsClientsLib. You should now find something along the lines of

Authentication type: [Negotiate]
Authenticated user: [CONTOSO\AgentB]
Authenticated user's SID: [S-1-5-21-2278291046-1170081271-1450921830-1285]
Authenticated user's SID maps to: [efa2cabd-462c-49e4-a021-4dd71bd97ce4]

Please note that I left out the less important information like timestamps etc. here. What you see is that instead of AgentA, AgentB is being authenticated. Usually, this happens when the credentials you pass in to OC are different from the credentials you used to log in to Windows. OC uses the IE engine to render the tabs and thus also leaves the authentication for IE. Then, IE performs the authentication based on the “User Authentication” / “Logon” settings for the zone the Agent Tab is in. The default setting for the “Local Intranet Zone” in IE is to automatically try loggin on with the current user’s credentials – i.e. AgentB’s credentials in this case, because AgentB is the currently logged on (Windows) user. Only if authentication for this user fails, IE is going to prompt you for a different set of credentials. To change this behavior, you can set the security settings in IE accordingly:

IeSecurityZoneUserAuth

Setting it to “Prompt for user name and password” will always prompt you for sites in the intranet zone. Once you’ve done that, exit OC and start it again. Now you should be prompted for the credentials to the Agent Tab and you can provide AgentA’s credentials. You then should see the correct list of groups AgentA is a member of.

The post Troubleshooting Authentication Issues with RGS Agent Tab appeared first on Tales of a Code Monkey.

]]>
Agent Communications Panel for Microsoft Dynamics CRM 4.0 Released https://cymbeline.ch/2009/04/13/agent-communications-panel-for-microsoft-dynamics-crm-4-0-released/?utm_source=rss&utm_medium=rss&utm_campaign=agent-communications-panel-for-microsoft-dynamics-crm-4-0-released Mon, 13 Apr 2009 08:29:00 +0000 /post/2009/04/13/Agent-Communications-Panel-for-Microsoft-Dynamics-CRM-40-Released.aspx Last week the Agent Communications Panel for Microsoft Dynamics CRM 4.0 has been released and is now available from the Microsoft Download Center. It allows a certain amount of customization such as integration with the Response Group Service of Office Communications Server 2007 R2. That said, it uses the Agent WebService of RGS to determine … Continue reading "Agent Communications Panel for Microsoft Dynamics CRM 4.0 Released"

The post Agent Communications Panel for Microsoft Dynamics CRM 4.0 Released appeared first on Tales of a Code Monkey.

]]>
Last week the Agent Communications Panel for Microsoft Dynamics CRM 4.0 has been released and is now available from the Microsoft Download Center. It allows a certain amount of customization such as integration with the Response Group Service of Office Communications Server 2007 R2. That said, it uses the Agent WebService of RGS to determine the agent group memberships. And given the title, it of course also integrates with Dynamics CRM 4.0.

The post Agent Communications Panel for Microsoft Dynamics CRM 4.0 Released appeared first on Tales of a Code Monkey.

]]>
RGS Web Components Language Pack https://cymbeline.ch/2009/03/29/rgs-web-components-language-pack/?utm_source=rss&utm_medium=rss&utm_campaign=rgs-web-components-language-pack Sun, 29 Mar 2009 10:21:00 +0000 /post/2009/03/29/RGS-Web-Components-Language-Pack.aspx Finally, also the Response Group Service Language Pack is available. As of last Thursday, it can be downloaded from http://www.microsoft.com/downloads/details.aspx?FamilyID=b49b7671-3a3a-4bca-bd97-1566ffb1413a. It installs additional resources for the Response Group Configuration Tool and the Response Group Agent Tab in 9 additional languages, so users get the user interface in their preferred language. The languages which are contained … Continue reading "RGS Web Components Language Pack"

The post RGS Web Components Language Pack appeared first on Tales of a Code Monkey.

]]>
Finally, also the Response Group Service Language Pack is available. As of last Thursday, it can be downloaded from http://www.microsoft.com/downloads/details.aspx?FamilyID=b49b7671-3a3a-4bca-bd97-1566ffb1413a. It installs additional resources for the Response Group Configuration Tool and the Response Group Agent Tab in 9 additional languages, so users get the user interface in their preferred language. The languages which are contained in the Language Pack are

  • Chinese (Simplified)
  • Chinese (Traditional)
  • English
  • French
  • German
  • Italian
  • Japanese
  • Korean
  • Portuguese
  • Spanish

Install and enjoy.

The post RGS Web Components Language Pack appeared first on Tales of a Code Monkey.

]]>
RGS Agent OC Tab with Silverlight https://cymbeline.ch/2009/03/22/rgs-agent-oc-tab-with-silverlight/?utm_source=rss&utm_medium=rss&utm_campaign=rgs-agent-oc-tab-with-silverlight https://cymbeline.ch/2009/03/22/rgs-agent-oc-tab-with-silverlight/#comments Sun, 22 Mar 2009 11:23:00 +0000 /post/2009/03/22/RGS-Agent-OC-Tab-with-Silverlight.aspx I’ve already described how you would create your own client using the RGS Agent WebService. Now what if you want to keep the tab in OC but make it look more fancy? Silverlight of course is your friend here. This post describes how you can create your own Silverlight based Agent tab, which will look … Continue reading "RGS Agent OC Tab with Silverlight"

The post RGS Agent OC Tab with Silverlight appeared first on Tales of a Code Monkey.

]]>
I’ve already described how you would create your own client using the RGS Agent WebService. Now what if you want to keep the tab in OC but make it look more fancy? Silverlight of course is your friend here. This post describes how you can create your own Silverlight based Agent tab, which will look like following. Btw, I am using Visual Studio 2008 to build this entire solution.

AgentTab

All the code for this can be found in AgentTabSl.zip (45.3 KB).

Getting Started

First I created a new Silverlight Application project and named it ‘AgentTabSl’. The project template already comes with the basic structure which we need for this Silverlight control. I added another Silverlight user control which I use to show one Agent Group, named ‘Group.xaml’. Its XAML looks like following.

<UserControl x:Class="AgentTabSl.Group"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Grid x:Name="LayoutRoot" Background="White">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>

        <Rectangle Width="Auto" Height="Auto" Stroke="Black" RadiusX="4" RadiusY="4"
                   Grid.ColumnSpan="3" Grid.RowSpan="2" Name="Back" />

        <CheckBox Grid.RowSpan="2" Content="" VerticalAlignment="Center" Name="SignedIn"
                  Margin="2" Cursor="Hand" Checked="OnSignedInChanged" Unchecked="OnSignedInChanged" />

        <TextBlock Grid.Column="1" Grid.ColumnSpan="2" Name="GroupName" Margin="0,2"
                   FontWeight="Bold" />

        <TextBlock Grid.Column="1" Grid.Row="1" Margin="0,2">Number of Agents</TextBlock>

        <TextBlock Grid.Column="2" Grid.Row="1" TextAlignment="Right" Name="AgentCount"
                   Margin="2,2,4,2" />
    </Grid>
</UserControl>

I also added some code to the Group class to allow setting the agent group name, whether or not it’s a formal agent group, if the user is currently signed in and the number of agents. On top of this, I added a static method which return a new instance of Group created based on the required parameters.

Retrieving the data from the Web Service

Unfortunately, because of the limitations of the Silverlight runtime, we cannot use the client proxy generated from wsdl.exe here. But you can still add a reference to the web service, e.g. through the ‘Add Service Reference …’ command in Visual Studio. Simply enter the url to a deployed RGS Agent WebService (e.g. https://ocs-pool-01.contoso.com/Rgs/Clients/ProxyService.asmx) and everything else will be done for you. It is worthwhile to note that all methods of the web service will be asynchronous, but that’s not a problem. I’ve added an event handler for the Loaded event of the Silverlight application:

private void OnLoaded(object sender, RoutedEventArgs e)
{
    _service = new ProxyServiceSoapClient();

    _service.Endpoint.Address = new EndpointAddress(
        "https://ocs-pool-01.contoso.com/Rgs/Clients/ProxyService.asmx");

    _service.GetGroupsCompleted += OnGetGroupsCompleted;
    _service.GetAgentCompleted += OnGetAgentCompleted;
    _service.SignInCompleted += OnSignInCompleted;
    _service.SignOutCompleted += OnSignOutCompleted;

    _service.GetAgentAsync();

    _timer = new Timer(OnTimer, null, 0, 60 * 1000);
}

Timer is from System.Threading and I use it to periodically (every 60 seconds) refresh the data from the web service. This is required because else the Silverlight application won’t figure out if groups have been added / removed / modified. You should not make it refresh in less than 60 seconds, but in the end, it is your decision (and your servers).

Please keep in mind that if you want to deploy this Silverlight application on a web server different than the OCS WebComponents, you’ll need to allow Silverlight to access to that server. Please read the HTTP Communication and Security with Silverlight topic on MSDN for more information.

Retrieving the agent group memberships

The following code snippet shows the event handler for the GetGroupsCompleted event generated for us through the service reference. The first thing I am doing is to check whether or not we’re on the UI thread. If we’re not, we have to use the Dispatcher to invoke the method on the UI thread. The actual code to add the groups is then as simple as going through all groups and creating a new instance of the Group control which we’ll add to the Children collection of the StackPanel which holds the groups.

private void OnGetGroupsCompleted(object sender, GetGroupsCompletedEventArgs e)
{
    if (!Dispatcher.CheckAccess())
    {
        Dispatcher.BeginInvoke(() => OnGetGroupsCompleted(sender, e));
    }
    else
    {
        IEnumerable<AcdGroup> groups = e.Result.OrderBy(group => group.Name);

        Groups.Children.Clear();

        foreach (AcdGroup group in groups)
        {
            Group ctrl = Group.Create(group.Id, group.CanSignIn, group.IsSignedIn,
                                      group.Name, group.NumberOfAgents);

            ctrl.SignedInChanged += OnSignedInChanged;

            Groups.Children.Add(ctrl);
        }

        SetStatus("Ready.");
    }
}

Sign in / Sign out

Now what’s left is basically to let the user sign in / out throug a click on the checkbox for the corresponding group. As you can see in the code (when you downloaded it), I also added an event to the Group control which is fired when the sign-in state for the group is changed. In the code above you see that we’re subscribing to that event on line 18. So all we need to do is to actually call the corresponding method on the web service when the event is fired.

private void OnSignedInChanged(object sender, EventArgs e)
{
    Group group = sender as Group;

    SetStatus("Please wait while the operation is performed ...");

    if (group.IsSignedIn)
    {
        _service.SignInAsync(group.Id);
    }
    else
    {
        _service.SignOutAsync(group.Id);
    }
}

What’s missing?

If you look at the interface of the web service again, you see that it also allows you to sign in / out with multiple groups at the same time. I’ll leave it to you to implement that in this Silverlight application as well as it does not really involve anything which I haven’t discussed here. Also, you may want to highlight groups which have just been added by using a different gradient for the box.

If you’re planning on actually deploying a Silverlight Agent OC Tab, you most likely also want to make sure that the users get the static strings in their preferred language. The article Deployment and Localization on MSDN should give you all the information required to do that.

The post RGS Agent OC Tab with Silverlight appeared first on Tales of a Code Monkey.

]]>
https://cymbeline.ch/2009/03/22/rgs-agent-oc-tab-with-silverlight/feed/ 4
Using the Agent WebService of the Response Group Service https://cymbeline.ch/2009/03/19/using-the-agent-webservice-of-the-response-group-service/?utm_source=rss&utm_medium=rss&utm_campaign=using-the-agent-webservice-of-the-response-group-service Thu, 19 Mar 2009 22:25:00 +0000 /post/2009/03/19/Using-the-Agent-WebService-of-the-Response-Group-Service.aspx Your Office Communications Server 2007 R2, Response Group Service deployment comes with a tiny but nice little addition: the Agent WebService. It basically offers exactly the same data and functionality as the Agent OC tab but does this through a SOAP interface. If you have RGS deployed on a pool with the FQDN ‘ocs-pool-01.contoso.com’, you’ll … Continue reading "Using the Agent WebService of the Response Group Service"

The post Using the Agent WebService of the Response Group Service appeared first on Tales of a Code Monkey.

]]>
Your Office Communications Server 2007 R2, Response Group Service deployment comes with a tiny but nice little addition: the Agent WebService. It basically offers exactly the same data and functionality as the Agent OC tab but does this through a SOAP interface. If you have RGS deployed on a pool with the FQDN ‘ocs-pool-01.contoso.com’, you’ll find the Agent OC tab at https://ocs-pool-01.contoso.com/Rgs/Clients/Tab.aspx. The Agent WebService is then located at https://ocs-pool-01.contoso.com/Rgs/Clients/ProxyService.asmx. If you are running the OCS WebComponents on other machines than the front ends, then the host name is the FQDN of the WebComponents machine/farm. So here’s how you can write your own client to sign in/out with RGS Agent Groups. The TechNet article Deploying Response Group Clients gives more information about deploying RGS Clients, with focus on the Agent OC Tab.

Generating the Client Proxy

The first thing you typically want to do is to actually generate the proxy code which you will compile into your own client. You do so by calling

wsdl.exe /namespace:RgsAgentService /language:cs /out:RgsAgentService.cs https://ocs-pool-01.contoso.com/Rgs/Clients/ProxyService.asmx?wsdl

This will generate the RgsAgentService.cs file which you can include into your project and use right away. Web Services Description Language Tool (Wsdl.exe) on MSDN has more info on wsdl.exe if needed.

Using the Web Service

Now you’re already good to go and use the web service. The code below shows a sample console application which does the following.

  • Create a new instance of ProxyService (the generated class from the step above) which points to the service on the pool you’re interested in.
  • Query the web service if the current user is an agent or not. This requires you to authenticate with the user’s credentials.
  • If the current user is an agent
    • Determine some basic information (e.g. the name and SIP address of the agent).
    • Retrieve the list of agent groups the agent is a member of in the connected pool.
    • If there are formal agent groups to which the agent is not signed in, the user is asked if he wants to sign in.
      • If he choses to sign in, tries to sign the agent in to those formal groups.
using System;
using System.Collections.Generic;

using RgsAgentService;

namespace RgsClient
{
    class Program
    {
        static void Main(string[] args)
        {
            string poolFqdn = "ocs-pool-01.contoso.com";

            if (args.Length > 0)
            {
                poolFqdn = args[0];
            }

            ProxyService service = ConnectToPool(poolFqdn);

            // First, figure out if the current user is an Agent.
            if (!service.IsAgent())
            {
                Console.WriteLine("You are not an agent in Pool '{0}'.", poolFqdn);
                return;
            }

            // Now get some information about the Agent (i.e. the current User).
            AcdAgent self = service.GetAgent();

            Console.WriteLine("You were authenticated as agent '{0}' ('{1}') in pool '{2}'.",
                self.DisplayName, self.SipAddress, poolFqdn);
            Console.WriteLine();

            // Finally, determine which Agent Groups this Agent belongs to.
            AcdGroup[] agentGroups = service.GetGroups();

            Console.WriteLine("Agent Group Name                  Formal?   Signed In?  # Agents");
            Console.WriteLine("----------------------------------------------------------------");

            Dictionary<string, Guid> agentGroupIdsForSignIn = new Dictionary<string, Guid>();

            for (int i = 0; i < agentGroups.Length; i++)
            {
                Console.WriteLine("{0,-32}  {1,-8}  {2,-10}  {3,8}",
                    agentGroups[i].Name, agentGroups[i].CanSignIn,
                    agentGroups[i].IsSignedIn, agentGroups[i].NumberOfAgents);

                if (agentGroups[i].CanSignIn &&
                    !agentGroups[i].IsSignedIn)
                {
                    agentGroupIdsForSignIn.Add(agentGroups[i].Name, agentGroups[i].Id);
                }
            }

            // If the Agent is not signed in to all his formal groups, then offer
            // him to do so now.
            if (agentGroupIdsForSignIn.Count > 0)
            {
                Console.WriteLine();
                Console.WriteLine("You are not currently signed in to {0} agent group(s):",
                    agentGroupIdsForSignIn.Count);

                foreach (string agentGroupName in agentGroupIdsForSignIn.Keys)
                {
                    Console.WriteLine("    {0}", agentGroupName);
                }

                Console.WriteLine();
                Console.Write("Do you want to sign in to these groups now? [y/n] ");

                ConsoleKeyInfo key = Console.ReadKey();
                while (key.KeyChar != 'y' && key.KeyChar != 'n')
                {
                    key = Console.ReadKey();
                }

                if (key.KeyChar == 'n')
                {
                    return;
                }

                Console.WriteLine();

                if (service.SignInMultiple(agentGroupIdsForSignIn.Values.ToArray()))
                {
                    Console.WriteLine("You have successfully signed in.");
                }
                else
                {
                    Console.WriteLine("Sign-in to at leat one agent group has failed.");
                }
            }
        }

        private static ProxyService ConnectToPool(string poolFqdn)
        {
            ProxyService service = new ProxyService();

            service.Url = String.Format("https://{0}/Rgs/Clients/ProxyService.asmx", poolFqdn);
            service.UseDefaultCredentials = true;

            return service;
        }
    }
}

Running this program will yield something similar to the following.

You were authenticated as agent 'Bob' ('bob@contoso.com') in pool 'rgs-pool-01.contoso.com'.

Agent Group Name                  Formal?   Signed In?  # Agents
----------------------------------------------------------------
Payroll Questions                 False     True               5
General HR Questions              True      False              8

You are not currently signed in to 1 agent group(s):
    General HR Questions

Do you want to sign in to these groups now? [y/n] y
You have successfully signed in.

More Methods

The WebService has a few more methods. These are in particular

  • SignIn(Guid groupId) – Tries to sign the current agent in to the agent group with the given ID
  • SignOut(Guid groupId) – Tries to sign the current agent out of the agent group with the given ID
  • SignOutMultiple(Guid[] groupIds) – Tries to sign the current agent out of all the groups identified with their respective IDs

These methods all return a boolean which indicates success (true) or failure (false).

Summary

You can integrate the RGS Agent Services into your own application by using the corresponding web service which is installed with the Response Group Service. This allows you to offer the same information and functionality as the RGS Agent OC Tab in a customizable manner.

The post Using the Agent WebService of the Response Group Service appeared first on Tales of a Code Monkey.

]]>
OCS 2007 R2 Launch Teaser Videos https://cymbeline.ch/2009/01/31/ocs-2007-r2-launch-teaser-videos/?utm_source=rss&utm_medium=rss&utm_campaign=ocs-2007-r2-launch-teaser-videos Sat, 31 Jan 2009 12:58:00 +0000 /post/2009/01/31/OCS-2007-R2-Launch-Teaser-Videos.aspx Right on time for the upcoming launch of Office Communications Server 2007 R2 next Tuesday, a couple of videos were posted to youtube. There are also two videos for the products developed in the Zürich Development Center. Attendant Console: http://www.youtube.com/watch?v=caMPdEXDIDk&feature=channel_pageResponse Group Service: http://www.youtube.com/watch?v=1ietEAruOUM&feature=channel_page Btw, it’s nice to see that as of now the video about … Continue reading "OCS 2007 R2 Launch Teaser Videos"

The post OCS 2007 R2 Launch Teaser Videos appeared first on Tales of a Code Monkey.

]]>
Right on time for the upcoming launch of Office Communications Server 2007 R2 next Tuesday, a couple of videos were posted to youtube. There are also two videos for the products developed in the Zürich Development Center.

Attendant Console: http://www.youtube.com/watch?v=caMPdEXDIDk&feature=channel_page
Response Group Service: http://www.youtube.com/watch?v=1ietEAruOUM&feature=channel_page

Btw, it’s nice to see that as of now the video about the Response Group Service has been viewed the most out of all the videos in the channel.

The post OCS 2007 R2 Launch Teaser Videos appeared first on Tales of a Code Monkey.

]]>
Microsoft Office Communications Server 2007 R2 Resource Kit Book https://cymbeline.ch/2009/01/29/microsoft-office-communications-server-2007-r2-resource-kit-book/?utm_source=rss&utm_medium=rss&utm_campaign=microsoft-office-communications-server-2007-r2-resource-kit-book Thu, 29 Jan 2009 08:27:00 +0000 /post/2009/01/29/Microsoft-Office-Communications-Server-2007-R2-Resource-Kit-Book.aspx Yesterday, Microsoft Press announced the new Microsoft Office Communications Server 2007 R2 Resource Kit book, available by February 4. This book holds much of the information about the new OCS 2007 R2 release which comes with the Response Group Service. IIRC, there's also a huge amount of information if not an entire chapter about RGS … Continue reading "Microsoft Office Communications Server 2007 R2 Resource Kit Book"

The post Microsoft Office Communications Server 2007 R2 Resource Kit Book appeared first on Tales of a Code Monkey.

]]>
Yesterday, Microsoft Press announced the new Microsoft Office Communications Server 2007 R2 Resource Kit book, available by February 4. This book holds much of the information about the new OCS 2007 R2 release which comes with the Response Group Service. IIRC, there's also a huge amount of information if not an entire chapter about RGS to which many people from the product development teams have contributed.

The post Microsoft Office Communications Server 2007 R2 Resource Kit Book appeared first on Tales of a Code Monkey.

]]>