1248 lines
No EOL
48 KiB
C#
1248 lines
No EOL
48 KiB
C#
// Copyright (c) 2012, Outercurve Foundation.
|
|
// All rights reserved.
|
|
//
|
|
// Redistribution and use in source and binary forms, with or without modification,
|
|
// are permitted provided that the following conditions are met:
|
|
//
|
|
// - Redistributions of source code must retain the above copyright notice, this
|
|
// list of conditions and the following disclaimer.
|
|
//
|
|
// - Redistributions in binary form must reproduce the above copyright notice,
|
|
// this list of conditions and the following disclaimer in the documentation
|
|
// and/or other materials provided with the distribution.
|
|
//
|
|
// - Neither the name of the Outercurve Foundation nor the names of its
|
|
// contributors may be used to endorse or promote products derived from this
|
|
// software without specific prior written permission.
|
|
//
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
using System;
|
|
using System.IO;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Collections.ObjectModel;
|
|
using System.Text;
|
|
using System.Reflection;
|
|
using System.Globalization;
|
|
using System.DirectoryServices;
|
|
|
|
using Microsoft.Win32;
|
|
|
|
using WebsitePanel.Providers;
|
|
using WebsitePanel.Providers.HostedSolution;
|
|
using WebsitePanel.Providers.Utils;
|
|
using WebsitePanel.Server.Utils;
|
|
|
|
using System.Management;
|
|
using System.Management.Automation;
|
|
using System.Management.Automation.Runspaces;
|
|
|
|
using Microsoft.Rtc.Management.Hosted;
|
|
using Microsoft.Rtc.Management.WritableConfig.Settings.Edge;
|
|
using Microsoft.Rtc.Management.WritableConfig.Settings.SimpleUrl;
|
|
|
|
|
|
namespace WebsitePanel.Providers.HostedSolution
|
|
{
|
|
public class Lync2010 : HostingServiceProviderBase, ILyncServer
|
|
{
|
|
|
|
#region Static constructor
|
|
static Lync2010()
|
|
{
|
|
LyncRegistryPath = "SOFTWARE\\Microsoft\\Real-Time Communications";
|
|
}
|
|
|
|
internal static string LyncRegistryPath
|
|
{
|
|
get;
|
|
set;
|
|
}
|
|
|
|
#endregion
|
|
|
|
|
|
#region Properties
|
|
|
|
/// <summary>
|
|
/// Pool FQDN
|
|
/// </summary>
|
|
private string PoolFQDN
|
|
{
|
|
get { return ProviderSettings[LyncConstants.PoolFQDN]; }
|
|
}
|
|
|
|
private string SimpleUrlRoot
|
|
{
|
|
get { return ProviderSettings[LyncConstants.SimpleUrlRoot]; }
|
|
}
|
|
|
|
internal string PrimaryDomainController
|
|
{
|
|
get { return ProviderSettings["PrimaryDomainController"]; }
|
|
}
|
|
|
|
private string RootOU
|
|
{
|
|
get { return ProviderSettings["RootOU"]; }
|
|
}
|
|
|
|
private string RootDomain
|
|
{
|
|
get { return ServerSettings.ADRootDomain; }
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
#region ILyncServer implementation
|
|
|
|
public string CreateOrganization(string organizationId, string sipDomain, bool enableConferencing, bool enableConferencingVideo, int maxConferenceSize, bool enabledFederation, bool enabledEnterpriseVoice)
|
|
{
|
|
return CreateOrganizationInternal(organizationId, sipDomain, enableConferencing, enableConferencingVideo, maxConferenceSize, enabledFederation, enabledEnterpriseVoice);
|
|
}
|
|
|
|
public bool DeleteOrganization(string organizationId, string sipDomain)
|
|
{
|
|
return DeleteOrganizationInternal(organizationId, sipDomain);
|
|
}
|
|
|
|
public bool CreateUser(string organizationId, string userUpn, LyncUserPlan plan)
|
|
{
|
|
return CreateUserInternal(organizationId, userUpn, plan);
|
|
}
|
|
|
|
public LyncUser GetLyncUserGeneralSettings(string organizationId, string userUpn)
|
|
{
|
|
return GetLyncUserGeneralSettingsInternal(organizationId, userUpn);
|
|
}
|
|
|
|
public bool SetLyncUserPlan(string organizationId, string userUpn, LyncUserPlan plan)
|
|
{
|
|
return SetLyncUserPlanInternal(organizationId, userUpn, plan, null);
|
|
}
|
|
|
|
public bool DeleteUser(string userUpn)
|
|
{
|
|
return DeleteUserInternal(userUpn);
|
|
}
|
|
|
|
public LyncFederationDomain[] GetFederationDomains(string organizationId)
|
|
{
|
|
return GetFederationDomainsInternal(organizationId);
|
|
}
|
|
|
|
public bool AddFederationDomain(string organizationId, string domainName, string proxyFqdn)
|
|
{
|
|
return AddFederationDomainInternal(organizationId, domainName, proxyFqdn);
|
|
}
|
|
|
|
public bool RemoveFederationDomain(string organizationId, string domainName)
|
|
{
|
|
return RemoveFederationDomainInternal(organizationId, domainName);
|
|
}
|
|
|
|
public void ReloadConfiguration()
|
|
{
|
|
ReloadConfigurationInternal();
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region organization
|
|
private string CreateOrganizationInternal(string organizationId, string sipDomain, bool enableConferencing, bool enableConferencingVideo, int maxConferenceSize, bool enabledFederation, bool enabledEnterpriseVoice)
|
|
{
|
|
HostedSolutionLog.LogStart("CreateOrganizationInternal");
|
|
HostedSolutionLog.DebugInfo("organizationId: {0}", organizationId);
|
|
HostedSolutionLog.DebugInfo("sipDomain: {0}", sipDomain);
|
|
|
|
string TenantId = string.Empty;
|
|
|
|
LyncTransaction transaction = StartTransaction();
|
|
|
|
Runspace runSpace = null;
|
|
try
|
|
{
|
|
runSpace = OpenRunspace();
|
|
|
|
// create sip domain
|
|
Command cmd = new Command("New-CsSipDomain");
|
|
cmd.Parameters.Add("Identity", sipDomain);
|
|
ExecuteShellCommand(runSpace, cmd, false);
|
|
|
|
transaction.RegisterNewSipDomain(sipDomain);
|
|
|
|
//set the msRTCSIP-Domains, TenantID, ObjectID
|
|
Guid id = Guid.NewGuid();
|
|
|
|
string path = AddADPrefix(GetOrganizationPath(organizationId));
|
|
DirectoryEntry ou = ActiveDirectoryUtils.GetADObject(path);
|
|
ActiveDirectoryUtils.SetADObjectPropertyValue(ou, "msRTCSIP-Domains", sipDomain);
|
|
ActiveDirectoryUtils.SetADObjectPropertyValue(ou, "msRTCSIP-TenantId", id);
|
|
ActiveDirectoryUtils.SetADObjectPropertyValue(ou, "msRTCSIP-ObjectId", id);
|
|
ou.CommitChanges();
|
|
|
|
//Create simpleurls
|
|
CreateSimpleUrl(runSpace, sipDomain, id);
|
|
transaction.RegisterNewSimpleUrl(sipDomain, id.ToString());
|
|
|
|
//create conferencing policy
|
|
cmd = new Command("New-CsConferencingPolicy");
|
|
cmd.Parameters.Add("Identity", organizationId);
|
|
cmd.Parameters.Add("MaxMeetingSize", maxConferenceSize);
|
|
cmd.Parameters.Add("AllowIPVideo", enableConferencingVideo);
|
|
ExecuteShellCommand(runSpace, cmd, false);
|
|
transaction.RegisterNewConferencingPolicy(organizationId);
|
|
|
|
//create external access policy
|
|
cmd = new Command("New-CsExternalAccessPolicy");
|
|
cmd.Parameters.Add("Identity", organizationId);
|
|
cmd.Parameters.Add("EnableFederationAccess", true);
|
|
cmd.Parameters.Add("EnableOutsideAccess", true);
|
|
cmd.Parameters.Add("EnablePublicCloudAccess", false);
|
|
cmd.Parameters.Add("EnablePublicCloudAudioVideoAccess", false);
|
|
ExecuteShellCommand(runSpace, cmd, false);
|
|
transaction.RegisterNewCsExternalAccessPolicy(organizationId);
|
|
|
|
//Enable for federation
|
|
AllowList allowList = new AllowList();
|
|
DomainPattern domain = new DomainPattern(sipDomain);
|
|
allowList.AllowedDomain.Add(domain);
|
|
|
|
cmd = new Command("Set-CsTenantFederationConfiguration");
|
|
cmd.Parameters.Add("Tenant", id);
|
|
cmd.Parameters.Add("AllowFederatedUsers", true);
|
|
cmd.Parameters.Add("AllowedDomains", allowList);
|
|
ExecuteShellCommand(runSpace, cmd, false);
|
|
|
|
//create mobility policy
|
|
cmd = new Command("New-CsMobilityPolicy");
|
|
cmd.Parameters.Add("Identity", organizationId + " EnableOutSideVoice");
|
|
cmd.Parameters.Add("EnableMobility", true);
|
|
cmd.Parameters.Add("EnableOutsideVoice", true);
|
|
ExecuteShellCommand(runSpace, cmd, false);
|
|
transaction.RegisterNewCsMobilityPolicy(organizationId + " EnableOutSideVoice");
|
|
|
|
cmd = new Command("New-CsMobilityPolicy");
|
|
cmd.Parameters.Add("Identity", organizationId + " DisableOutSideVoice");
|
|
cmd.Parameters.Add("EnableMobility", true);
|
|
cmd.Parameters.Add("EnableOutsideVoice", false);
|
|
ExecuteShellCommand(runSpace, cmd, false);
|
|
transaction.RegisterNewCsMobilityPolicy(organizationId + " DisableOutSideVoice");
|
|
|
|
cmd = new Command("Invoke-CsManagementStoreReplication");
|
|
ExecuteShellCommand(runSpace, cmd, false);
|
|
|
|
|
|
TenantId = id.ToString();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
HostedSolutionLog.LogError("CreateOrganizationInternal", ex);
|
|
RollbackTransaction(transaction);
|
|
throw;
|
|
}
|
|
finally
|
|
{
|
|
|
|
CloseRunspace(runSpace);
|
|
}
|
|
|
|
HostedSolutionLog.LogEnd("CreateOrganizationInternal");
|
|
|
|
return TenantId;
|
|
}
|
|
|
|
|
|
|
|
private bool DeleteOrganizationInternal(string organizationId, string sipDomain)
|
|
{
|
|
HostedSolutionLog.LogStart("DeleteOrganizationInternal");
|
|
HostedSolutionLog.DebugInfo("organizationId: {0}", organizationId);
|
|
HostedSolutionLog.DebugInfo("sipDomain: {0}", sipDomain);
|
|
|
|
bool ret = true;
|
|
|
|
Runspace runSpace = null;
|
|
try
|
|
{
|
|
runSpace = OpenRunspace();
|
|
|
|
Command cmd = new Command("Get-CsTenant");
|
|
cmd.Parameters.Add("Identity", GetOrganizationPath(organizationId));
|
|
Collection<PSObject> result = ExecuteShellCommand(runSpace, cmd, false);
|
|
if ((result != null) && (result.Count > 0))
|
|
{
|
|
Guid tenantId = (Guid)GetPSObjectProperty(result[0], "TenantId");
|
|
|
|
// create sip domain
|
|
DeleteSipDomain(runSpace, sipDomain);
|
|
|
|
//clear the msRTCSIP-Domains, TenantID, ObjectID
|
|
string path = AddADPrefix(GetOrganizationPath(organizationId));
|
|
DirectoryEntry ou = ActiveDirectoryUtils.GetADObject(path);
|
|
ActiveDirectoryUtils.ClearADObjectPropertyValue(ou, "msRTCSIP-Domains");
|
|
ActiveDirectoryUtils.ClearADObjectPropertyValue(ou, "msRTCSIP-TenantId");
|
|
ActiveDirectoryUtils.ClearADObjectPropertyValue(ou, "msRTCSIP-ObjectId");
|
|
ou.CommitChanges();
|
|
|
|
try
|
|
{
|
|
DeleteConferencingPolicy(runSpace, organizationId);
|
|
}
|
|
catch (Exception)
|
|
{
|
|
}
|
|
|
|
try
|
|
{
|
|
DeleteExternalAccessPolicy(runSpace, organizationId);
|
|
}
|
|
catch (Exception)
|
|
{
|
|
}
|
|
|
|
try
|
|
{
|
|
DeleteMobilityPolicy(runSpace, organizationId + " EnableOutSideVoice");
|
|
}
|
|
catch (Exception)
|
|
{
|
|
}
|
|
|
|
try
|
|
{
|
|
DeleteMobilityPolicy(runSpace, organizationId + " DisableOutSideVoice");
|
|
}
|
|
catch (Exception)
|
|
{
|
|
}
|
|
|
|
try
|
|
{
|
|
DeleteSimpleUrl(runSpace, sipDomain, tenantId);
|
|
}
|
|
catch (Exception)
|
|
{
|
|
}
|
|
}
|
|
|
|
cmd = new Command("Invoke-CsManagementStoreReplication");
|
|
ExecuteShellCommand(runSpace, cmd, false);
|
|
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
ret = false;
|
|
HostedSolutionLog.LogError("DeleteOrganizationInternal", ex);
|
|
throw;
|
|
}
|
|
finally
|
|
{
|
|
|
|
CloseRunspace(runSpace);
|
|
}
|
|
HostedSolutionLog.LogEnd("DeleteOrganizationInternal");
|
|
return ret;
|
|
}
|
|
#endregion
|
|
|
|
#region Users
|
|
private bool CreateUserInternal(string organizationId, string userUpn, LyncUserPlan plan)
|
|
{
|
|
HostedSolutionLog.LogStart("CreateUserInternal");
|
|
HostedSolutionLog.DebugInfo("organizationId: {0}", organizationId);
|
|
HostedSolutionLog.DebugInfo("userUpn: {0}", userUpn);
|
|
|
|
bool ret = true;
|
|
Guid tenantId = Guid.Empty;
|
|
|
|
LyncTransaction transaction = StartTransaction();
|
|
|
|
Runspace runSpace = null;
|
|
try
|
|
{
|
|
runSpace = OpenRunspace();
|
|
|
|
Command cmd = new Command("Get-CsTenant");
|
|
cmd.Parameters.Add("Identity", GetOrganizationPath(organizationId));
|
|
Collection<PSObject> result = ExecuteShellCommand(runSpace, cmd, false);
|
|
if ((result != null) && (result.Count > 0))
|
|
{
|
|
tenantId = (Guid)GetPSObjectProperty(result[0], "TenantId");
|
|
|
|
//enable for lync
|
|
cmd = new Command("Enable-CsUser");
|
|
cmd.Parameters.Add("Identity", userUpn);
|
|
cmd.Parameters.Add("RegistrarPool", PoolFQDN);
|
|
cmd.Parameters.Add("SipAddressType", "UserPrincipalName");
|
|
ExecuteShellCommand(runSpace, cmd);
|
|
|
|
transaction.RegisterNewCsUser(userUpn);
|
|
|
|
//set groupingID and tenantID
|
|
cmd = new Command("Get-CsAdUser");
|
|
cmd.Parameters.Add("Identity", userUpn);
|
|
result = ExecuteShellCommand(runSpace, cmd);
|
|
|
|
|
|
string path = AddADPrefix(GetResultObjectDN(result));
|
|
DirectoryEntry user = ActiveDirectoryUtils.GetADObject(path);
|
|
ActiveDirectoryUtils.SetADObjectPropertyValue(user, "msRTCSIP-GroupingID", tenantId);
|
|
ActiveDirectoryUtils.SetADObjectPropertyValue(user, "msRTCSIP-TenantId", tenantId);
|
|
|
|
string[] tmp = userUpn.Split('@');
|
|
if (tmp.Length > 0)
|
|
{
|
|
string Url = SimpleUrlRoot + tmp[1];
|
|
ActiveDirectoryUtils.SetADObjectPropertyValue(user, "msRTCSIP-BaseSimpleUrl", Url);
|
|
}
|
|
user.CommitChanges();
|
|
|
|
//set-plan
|
|
SetLyncUserPlanInternal(organizationId, userUpn, plan, runSpace);
|
|
|
|
//initiate addressbook generation
|
|
cmd = new Command("Update-CsAddressBook");
|
|
ExecuteShellCommand(runSpace, cmd, false);
|
|
|
|
//initiate user database replication
|
|
cmd = new Command("Update-CsUserDatabase");
|
|
ExecuteShellCommand(runSpace, cmd, false);
|
|
}
|
|
else
|
|
{
|
|
ret = false;
|
|
HostedSolutionLog.LogError("Failed to retrieve tenantID", null);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
ret = false;
|
|
HostedSolutionLog.LogError("CreateUserInternal", ex);
|
|
RollbackTransaction(transaction);
|
|
throw;
|
|
}
|
|
finally
|
|
{
|
|
|
|
CloseRunspace(runSpace);
|
|
}
|
|
HostedSolutionLog.LogEnd("CreateUserInternal");
|
|
return ret;
|
|
}
|
|
|
|
private LyncUser GetLyncUserGeneralSettingsInternal(string organizationId, string userUpn)
|
|
{
|
|
HostedSolutionLog.LogStart("GetLyncUserGeneralSettingsInternal");
|
|
HostedSolutionLog.DebugInfo("organizationId: {0}", organizationId);
|
|
HostedSolutionLog.DebugInfo("userUpn: {0}", userUpn);
|
|
|
|
LyncUser lyncUser = new LyncUser();
|
|
Runspace runSpace = null;
|
|
try
|
|
{
|
|
runSpace = OpenRunspace();
|
|
|
|
Command cmd = new Command("Get-CsUser");
|
|
cmd.Parameters.Add("Identity", userUpn);
|
|
Collection<PSObject> result = ExecuteShellCommand(runSpace, cmd);
|
|
PSObject user = result[0];
|
|
|
|
lyncUser.DisplayName = (string)GetPSObjectProperty(user, "DisplayName");
|
|
lyncUser.PrimaryUri = (string)GetPSObjectProperty(user, "SipAddress");
|
|
lyncUser.LineUri = (string)GetPSObjectProperty(user, "LineURI");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
HostedSolutionLog.LogError("GetLyncUserGeneralSettingsInternal", ex);
|
|
throw;
|
|
}
|
|
finally
|
|
{
|
|
CloseRunspace(runSpace);
|
|
}
|
|
HostedSolutionLog.LogEnd("GetLyncUserGeneralSettingsInternal");
|
|
return lyncUser;
|
|
}
|
|
|
|
|
|
private bool SetLyncUserPlanInternal(string organizationId, string userUpn, LyncUserPlan plan, Runspace runSpace)
|
|
{
|
|
HostedSolutionLog.LogStart("SetLyncUserPlanInternal");
|
|
HostedSolutionLog.DebugInfo("organizationId: {0}", organizationId);
|
|
HostedSolutionLog.DebugInfo("userUpn: {0}", userUpn);
|
|
bool ret = true;
|
|
bool bCloseRunSpace = false;
|
|
|
|
try
|
|
{
|
|
if (runSpace == null)
|
|
{
|
|
runSpace = OpenRunspace();
|
|
bCloseRunSpace = true;
|
|
}
|
|
|
|
//CsExternalAccessPolicy
|
|
Command cmd = new Command("Grant-CsExternalAccessPolicy");
|
|
cmd.Parameters.Add("Identity", userUpn);
|
|
cmd.Parameters.Add("PolicyName", plan.Federation ? organizationId : null);
|
|
ExecuteShellCommand(runSpace, cmd);
|
|
|
|
//CsConferencingPolicy
|
|
cmd = new Command("Grant-CsConferencingPolicy");
|
|
cmd.Parameters.Add("Identity", userUpn);
|
|
cmd.Parameters.Add("PolicyName", plan.Federation ? organizationId : null);
|
|
ExecuteShellCommand(runSpace, cmd);
|
|
|
|
//CsMobilityPolicy
|
|
cmd = new Command("Grant-CsMobilityPolicy");
|
|
cmd.Parameters.Add("Identity", userUpn);
|
|
if (plan.Mobility)
|
|
cmd.Parameters.Add("PolicyName", plan.MobilityEnableOutsideVoice ? organizationId + " EnableOutSideVoice" : organizationId + " DisableOutSideVoice");
|
|
else
|
|
cmd.Parameters.Add("PolicyName", null);
|
|
ExecuteShellCommand(runSpace, cmd);
|
|
|
|
//initiate user database replication
|
|
cmd = new Command("Update-CsUserDatabase");
|
|
ExecuteShellCommand(runSpace, cmd, false);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
ret = false;
|
|
HostedSolutionLog.LogError("SetLyncUserPlanInternal", ex);
|
|
throw;
|
|
}
|
|
finally
|
|
{
|
|
|
|
if (bCloseRunSpace) CloseRunspace(runSpace);
|
|
}
|
|
HostedSolutionLog.LogEnd("SetLyncUserPlanInternal");
|
|
return ret;
|
|
}
|
|
|
|
|
|
private bool DeleteUserInternal(string userUpn)
|
|
{
|
|
HostedSolutionLog.LogStart("DeleteUserInternal");
|
|
HostedSolutionLog.DebugInfo("userUpn: {0}", userUpn);
|
|
|
|
bool ret = true;
|
|
|
|
Runspace runSpace = null;
|
|
try
|
|
{
|
|
runSpace = OpenRunspace();
|
|
|
|
//Delete User
|
|
DeleteUser(runSpace, userUpn);
|
|
|
|
//Clear groupingID and tenantID
|
|
Command cmd = new Command("Get-CsAdUser");
|
|
cmd.Parameters.Add("Identity", userUpn);
|
|
Collection<PSObject> result = ExecuteShellCommand(runSpace, cmd);
|
|
|
|
string path = AddADPrefix(GetResultObjectDN(result));
|
|
DirectoryEntry user = ActiveDirectoryUtils.GetADObject(path);
|
|
ActiveDirectoryUtils.ClearADObjectPropertyValue(user, "msRTCSIP-GroupingID");
|
|
ActiveDirectoryUtils.ClearADObjectPropertyValue(user, "msRTCSIP-TenantId");
|
|
ActiveDirectoryUtils.ClearADObjectPropertyValue(user, "msRTCSIP-BaseSimpleUrl");
|
|
user.CommitChanges();
|
|
|
|
//initiate addressbook generation
|
|
cmd = new Command("Update-CsAddressBook");
|
|
ExecuteShellCommand(runSpace, cmd, false);
|
|
|
|
//initiate user database replication
|
|
cmd = new Command("Update-CsUserDatabase");
|
|
ExecuteShellCommand(runSpace, cmd, false);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
ret = false;
|
|
HostedSolutionLog.LogError("DeleteUserInternal", ex);
|
|
throw;
|
|
}
|
|
finally
|
|
{
|
|
|
|
CloseRunspace(runSpace);
|
|
}
|
|
HostedSolutionLog.LogEnd("DeleteUserInternal");
|
|
return ret;
|
|
}
|
|
|
|
internal void DeleteUser(Runspace runSpace, string userUpn)
|
|
{
|
|
HostedSolutionLog.LogStart("DeleteUser");
|
|
HostedSolutionLog.DebugInfo("userUpn : {0}", userUpn);
|
|
Command cmd = new Command("Disable-CsUser");
|
|
cmd.Parameters.Add("Identity", userUpn);
|
|
cmd.Parameters.Add("Confirm", false);
|
|
ExecuteShellCommand(runSpace, cmd, false);
|
|
HostedSolutionLog.LogEnd("DeleteUser");
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region SipDomains
|
|
internal void DeleteSipDomain(Runspace runSpace, string id)
|
|
{
|
|
HostedSolutionLog.LogStart("DeleteSipDomain");
|
|
HostedSolutionLog.DebugInfo("SipDomain : {0}", id);
|
|
Command cmd = new Command("Remove-CsSipDomain");
|
|
cmd.Parameters.Add("Identity", id);
|
|
cmd.Parameters.Add("Confirm", false);
|
|
cmd.Parameters.Add("Force", true);
|
|
ExecuteShellCommand(runSpace, cmd, false);
|
|
HostedSolutionLog.LogEnd("DeleteSipDomain");
|
|
}
|
|
|
|
private void CreateSimpleUrl(Runspace runSpace, string sipDomain, Guid id)
|
|
{
|
|
//Create the simpleUrlEntry
|
|
Command cmd = new Command("Get-CsSipDomain");
|
|
Collection<PSObject> sipDomains = ExecuteShellCommand(runSpace, cmd, false);
|
|
|
|
IList<PSObject> SimpleUrls = new List<PSObject>();
|
|
|
|
|
|
foreach (PSObject domain in sipDomains)
|
|
{
|
|
string d = (string)GetPSObjectProperty(domain, "Name");
|
|
string Url = SimpleUrlRoot + d;
|
|
|
|
|
|
//Create the simpleUrlEntry
|
|
cmd = new Command("New-CsSimpleUrlEntry");
|
|
cmd.Parameters.Add("Url", Url);
|
|
Collection<PSObject> simpleUrlEntry = ExecuteShellCommand(runSpace, cmd, false);
|
|
|
|
//Create the simpleUrl
|
|
cmd = new Command("New-CsSimpleUrl");
|
|
cmd.Parameters.Add("Component", "meet");
|
|
cmd.Parameters.Add("Domain", d);
|
|
cmd.Parameters.Add("SimpleUrl", simpleUrlEntry[0]);
|
|
cmd.Parameters.Add("ActiveUrl", Url);
|
|
Collection<PSObject> simpleUrl = ExecuteShellCommand(runSpace, cmd, false);
|
|
|
|
SimpleUrls.Add(simpleUrl[0]);
|
|
}
|
|
|
|
Hashtable properties = new Hashtable();
|
|
properties.Add("Add", SimpleUrls);
|
|
|
|
//PSListModifier
|
|
cmd = new Command("Set-CsSimpleUrlConfiguration");
|
|
cmd.Parameters.Add("Identity", "Global");
|
|
cmd.Parameters.Add("Tenant", id);
|
|
cmd.Parameters.Add("SimpleUrl", SimpleUrls);
|
|
ExecuteShellCommand(runSpace, cmd, false);
|
|
}
|
|
|
|
|
|
internal void DeleteSimpleUrl(Runspace runSpace, string sipDomain, Guid id)
|
|
{
|
|
/*
|
|
//build the url
|
|
string Url = SimpleUrlRoot + sipDomain;
|
|
|
|
//Create the simpleUrlEntry
|
|
Command cmd = new Command("New-CsSimpleUrlEntry");
|
|
cmd.Parameters.Add("Url", Url);
|
|
Collection<PSObject> simpleUrlEntry = ExecuteShellCommand(runSpace, cmd, false);
|
|
|
|
//Create the simpleUrl
|
|
cmd = new Command("New-CsSimpleUrl");
|
|
cmd.Parameters.Add("Component", "meet");
|
|
cmd.Parameters.Add("Domain", sipDomain);
|
|
cmd.Parameters.Add("SimpleUrl", simpleUrlEntry[0]);
|
|
cmd.Parameters.Add("ActiveUrl", Url);
|
|
Collection<PSObject> simpleUrl = ExecuteShellCommand(runSpace, cmd, false);
|
|
|
|
//PSListModifier
|
|
|
|
Hashtable properties = new Hashtable();
|
|
properties.Add("Remove", simpleUrl[0]);
|
|
|
|
cmd = new Command("Set-CsSimpleUrlConfiguration");
|
|
cmd.Parameters.Add("Identity", "Global");
|
|
cmd.Parameters.Add("Tenant", id);
|
|
cmd.Parameters.Add("SimpleUrl", properties);
|
|
ExecuteShellCommand(runSpace, cmd, false);
|
|
*/
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
#region Policies
|
|
|
|
internal void DeleteConferencingPolicy(Runspace runSpace, string policyName)
|
|
{
|
|
HostedSolutionLog.LogStart("DeleteConferencingPolicy");
|
|
HostedSolutionLog.DebugInfo("policyName : {0}", policyName);
|
|
Command cmd = new Command("Remove-CsConferencingPolicy");
|
|
cmd.Parameters.Add("Identity", policyName);
|
|
cmd.Parameters.Add("Confirm", false);
|
|
cmd.Parameters.Add("Force", true);
|
|
ExecuteShellCommand(runSpace, cmd, false);
|
|
HostedSolutionLog.LogEnd("DeleteConferencingPolicy");
|
|
}
|
|
|
|
internal void DeleteExternalAccessPolicy(Runspace runSpace, string policyName)
|
|
{
|
|
HostedSolutionLog.LogStart("DeleteExternalAccessPolicy");
|
|
HostedSolutionLog.DebugInfo("policyName : {0}", policyName);
|
|
Command cmd = new Command("Remove-CsExternalAccessPolicy");
|
|
cmd.Parameters.Add("Identity", policyName);
|
|
cmd.Parameters.Add("Confirm", false);
|
|
cmd.Parameters.Add("Force", true);
|
|
ExecuteShellCommand(runSpace, cmd, false);
|
|
HostedSolutionLog.LogEnd("DeleteExternalAccessPolicy");
|
|
}
|
|
|
|
internal void DeleteMobilityPolicy(Runspace runSpace, string policyName)
|
|
{
|
|
HostedSolutionLog.LogStart("DeleteMobilityPolicy");
|
|
HostedSolutionLog.DebugInfo("policyName : {0}", policyName);
|
|
Command cmd = new Command("Remove-CsMobilityPolicy");
|
|
cmd.Parameters.Add("Identity", policyName);
|
|
cmd.Parameters.Add("Confirm", false);
|
|
cmd.Parameters.Add("Force", true);
|
|
ExecuteShellCommand(runSpace, cmd, false);
|
|
HostedSolutionLog.LogEnd("DeleteMobilityPolicy");
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Sytsem Related Methods
|
|
private void ReloadConfigurationInternal()
|
|
{
|
|
HostedSolutionLog.LogStart("ReloadConfigurationInternal");
|
|
Runspace runSpace = null;
|
|
try
|
|
{
|
|
runSpace = OpenRunspace();
|
|
|
|
Command cmd = new Command("Enable-CsComputer");
|
|
ExecuteShellCommand(runSpace, cmd, false);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
HostedSolutionLog.LogError("ReloadConfigurationInternal", ex);
|
|
throw;
|
|
}
|
|
finally
|
|
{
|
|
|
|
CloseRunspace(runSpace);
|
|
}
|
|
HostedSolutionLog.LogEnd("ReloadConfigurationInternal");
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
#region Federation Domains
|
|
private LyncFederationDomain[] GetFederationDomainsInternal(string organizationId)
|
|
{
|
|
|
|
HostedSolutionLog.LogStart("GetFederationDomainsInternal");
|
|
HostedSolutionLog.DebugInfo("organizationId: {0}", organizationId);
|
|
|
|
|
|
LyncFederationDomain[] domains = null;
|
|
|
|
Runspace runSpace = null;
|
|
try
|
|
{
|
|
runSpace = OpenRunspace();
|
|
|
|
Guid tenantId = Guid.Empty;
|
|
|
|
domains = GetFederationDomainsInternal(runSpace, organizationId, ref tenantId);
|
|
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
HostedSolutionLog.LogError("GetFederationDomainsInternal", ex);
|
|
throw;
|
|
}
|
|
finally
|
|
{
|
|
|
|
CloseRunspace(runSpace);
|
|
}
|
|
HostedSolutionLog.LogEnd("GetFederationDomainsInternal");
|
|
|
|
return domains;
|
|
}
|
|
|
|
private LyncFederationDomain[] GetFederationDomainsInternal(Runspace runSpace, string organizationId, ref Guid tenantId)
|
|
{
|
|
//Get TenantID
|
|
List<LyncFederationDomain> domains = null;
|
|
Command cmd = new Command("Get-CsTenant");
|
|
cmd.Parameters.Add("Identity", GetOrganizationPath(organizationId));
|
|
Collection<PSObject> result = ExecuteShellCommand(runSpace, cmd, false);
|
|
if ((result != null) && (result.Count > 0))
|
|
{
|
|
tenantId = (Guid)GetPSObjectProperty(result[0], "TenantId");
|
|
|
|
//Get-CSTenantFederationConfiguration (AllowedDomains)
|
|
cmd = new Command("Get-CsTenantFederationConfiguration");
|
|
cmd.Parameters.Add("Tenant", tenantId);
|
|
result = ExecuteShellCommand(runSpace, cmd, false);
|
|
|
|
if ((result != null) && (result.Count > 0))
|
|
{
|
|
domains = new List<LyncFederationDomain>();
|
|
|
|
if (GetPSObjectProperty(result[0], "AllowedDomains").GetType().ToString() == "Microsoft.Rtc.Management.WritableConfig.Settings.Edge.AllowList")
|
|
{
|
|
AllowList allowList = (AllowList)GetPSObjectProperty(result[0], "AllowedDomains");
|
|
|
|
foreach (DomainPattern d in allowList.AllowedDomain)
|
|
{
|
|
LyncFederationDomain domain = new LyncFederationDomain();
|
|
domain.DomainName = d.Domain.ToString();
|
|
domains.Add(domain);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (domains != null)
|
|
return domains.ToArray();
|
|
else
|
|
return null;
|
|
}
|
|
|
|
|
|
private bool AddFederationDomainInternal(string organizationId, string domainName, string proxyFqdn)
|
|
{
|
|
HostedSolutionLog.LogStart("AddFederationDomainInternal");
|
|
HostedSolutionLog.DebugInfo("organizationId: {0}", organizationId);
|
|
HostedSolutionLog.DebugInfo("domainName: {0}", domainName);
|
|
|
|
Runspace runSpace = null;
|
|
try
|
|
{
|
|
runSpace = OpenRunspace();
|
|
|
|
Guid tenantId = Guid.Empty;
|
|
Command cmd = new Command("Get-CsTenant");
|
|
cmd.Parameters.Add("Identity", GetOrganizationPath(organizationId));
|
|
Collection<PSObject> result = ExecuteShellCommand(runSpace, cmd, false);
|
|
if ((result != null) && (result.Count > 0))
|
|
{
|
|
tenantId = (Guid)GetPSObjectProperty(result[0], "TenantId");
|
|
|
|
//Get-CSTenantFederationConfiguration (AllowedDomains)
|
|
cmd = new Command("Get-CsTenantFederationConfiguration");
|
|
cmd.Parameters.Add("Tenant", tenantId);
|
|
result = ExecuteShellCommand(runSpace, cmd, false);
|
|
|
|
if ((result != null) && (result.Count > 0))
|
|
{
|
|
AllowList allowList = null;
|
|
|
|
if (GetPSObjectProperty(result[0], "AllowedDomains").GetType().ToString() == "Microsoft.Rtc.Management.WritableConfig.Settings.Edge.AllowList")
|
|
{
|
|
allowList = (AllowList)GetPSObjectProperty(result[0], "AllowedDomains");
|
|
DomainPattern domain = new DomainPattern(domainName);
|
|
allowList.AllowedDomain.Add(domain);
|
|
}
|
|
else
|
|
{
|
|
allowList = new AllowList();
|
|
DomainPattern domain = new DomainPattern(domainName);
|
|
allowList.AllowedDomain.Add(domain);
|
|
}
|
|
|
|
cmd = new Command("Set-CsTenantFederationConfiguration");
|
|
cmd.Parameters.Add("Tenant", tenantId);
|
|
cmd.Parameters.Add("AllowedDomains", allowList);
|
|
ExecuteShellCommand(runSpace, cmd, false);
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
HostedSolutionLog.LogError("AddFederationDomainInternal", ex);
|
|
throw;
|
|
}
|
|
finally
|
|
{
|
|
|
|
CloseRunspace(runSpace);
|
|
}
|
|
HostedSolutionLog.LogEnd("AddFederationDomainInternal");
|
|
|
|
return true;
|
|
}
|
|
|
|
private bool RemoveFederationDomainInternal(string organizationId, string domainName)
|
|
{
|
|
HostedSolutionLog.LogStart("RemoveFederationDomainInternal");
|
|
HostedSolutionLog.DebugInfo("organizationId: {0}", organizationId);
|
|
HostedSolutionLog.DebugInfo("domainName: {0}", domainName);
|
|
|
|
Runspace runSpace = null;
|
|
try
|
|
{
|
|
runSpace = OpenRunspace();
|
|
|
|
Guid tenantId = Guid.Empty;
|
|
Command cmd = new Command("Get-CsTenant");
|
|
cmd.Parameters.Add("Identity", GetOrganizationPath(organizationId));
|
|
Collection<PSObject> result = ExecuteShellCommand(runSpace, cmd, false);
|
|
if ((result != null) && (result.Count > 0))
|
|
{
|
|
tenantId = (Guid)GetPSObjectProperty(result[0], "TenantId");
|
|
|
|
//Get-CSTenantFederationConfiguration (AllowedDomains)
|
|
cmd = new Command("Get-CsTenantFederationConfiguration");
|
|
cmd.Parameters.Add("Tenant", tenantId);
|
|
result = ExecuteShellCommand(runSpace, cmd, false);
|
|
|
|
if ((result != null) && (result.Count > 0))
|
|
{
|
|
AllowList allowList = null;
|
|
|
|
if (GetPSObjectProperty(result[0], "AllowedDomains").GetType().ToString() == "Microsoft.Rtc.Management.WritableConfig.Settings.Edge.AllowList")
|
|
{
|
|
allowList = (AllowList)GetPSObjectProperty(result[0], "AllowedDomains");
|
|
DomainPattern domain = new DomainPattern(domainName);
|
|
allowList.AllowedDomain.Remove(domain);
|
|
}
|
|
|
|
cmd = new Command("Set-CsTenantFederationConfiguration");
|
|
cmd.Parameters.Add("Tenant", tenantId);
|
|
cmd.Parameters.Add("AllowedDomains", allowList);
|
|
ExecuteShellCommand(runSpace, cmd, false);
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
HostedSolutionLog.LogError("RemoveFederationDomainInternal", ex);
|
|
throw;
|
|
}
|
|
finally
|
|
{
|
|
|
|
CloseRunspace(runSpace);
|
|
}
|
|
HostedSolutionLog.LogEnd("RemoveFederationDomainInternal");
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
#region PowerShell integration
|
|
private static InitialSessionState session = null;
|
|
|
|
internal virtual Runspace OpenRunspace()
|
|
{
|
|
HostedSolutionLog.LogStart("OpenRunspace");
|
|
|
|
if (session == null)
|
|
{
|
|
session = InitialSessionState.CreateDefault();
|
|
session.ImportPSModule(new string[] { "ActiveDirectory", "Lync", "LyncOnline" });
|
|
}
|
|
Runspace runSpace = RunspaceFactory.CreateRunspace(session);
|
|
//
|
|
runSpace.Open();
|
|
//
|
|
runSpace.SessionStateProxy.SetVariable("ConfirmPreference", "none");
|
|
HostedSolutionLog.LogEnd("OpenRunspace");
|
|
return runSpace;
|
|
}
|
|
|
|
internal void CloseRunspace(Runspace runspace)
|
|
{
|
|
try
|
|
{
|
|
if (runspace != null && runspace.RunspaceStateInfo.State == RunspaceState.Opened)
|
|
{
|
|
runspace.Close();
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
HostedSolutionLog.LogError("Runspace error", ex);
|
|
}
|
|
}
|
|
|
|
internal Collection<PSObject> ExecuteShellCommand(Runspace runSpace, Command cmd)
|
|
{
|
|
return ExecuteShellCommand(runSpace, cmd, true);
|
|
}
|
|
|
|
internal Collection<PSObject> ExecuteShellCommand(Runspace runSpace, Command cmd, bool useDomainController)
|
|
{
|
|
object[] errors;
|
|
return ExecuteShellCommand(runSpace, cmd, useDomainController, out errors);
|
|
}
|
|
|
|
internal Collection<PSObject> ExecuteShellCommand(Runspace runSpace, Command cmd, out object[] errors)
|
|
{
|
|
return ExecuteShellCommand(runSpace, cmd, true, out errors);
|
|
}
|
|
|
|
internal Collection<PSObject> ExecuteShellCommand(Runspace runSpace, Command cmd, bool useDomainController, out object[] errors)
|
|
{
|
|
HostedSolutionLog.LogStart("ExecuteShellCommand");
|
|
List<object> errorList = new List<object>();
|
|
|
|
if (useDomainController)
|
|
{
|
|
CommandParameter dc = new CommandParameter("DomainController", PrimaryDomainController);
|
|
if (!cmd.Parameters.Contains(dc))
|
|
{
|
|
cmd.Parameters.Add(dc);
|
|
}
|
|
}
|
|
|
|
HostedSolutionLog.DebugCommand(cmd);
|
|
Collection<PSObject> results = null;
|
|
// Create a pipeline
|
|
Pipeline pipeLine = runSpace.CreatePipeline();
|
|
using (pipeLine)
|
|
{
|
|
// Add the command
|
|
pipeLine.Commands.Add(cmd);
|
|
// Execute the pipeline and save the objects returned.
|
|
results = pipeLine.Invoke();
|
|
|
|
// Log out any errors in the pipeline execution
|
|
// NOTE: These errors are NOT thrown as exceptions!
|
|
// Be sure to check this to ensure that no errors
|
|
// happened while executing the command.
|
|
if (pipeLine.Error != null && pipeLine.Error.Count > 0)
|
|
{
|
|
foreach (object item in pipeLine.Error.ReadToEnd())
|
|
{
|
|
errorList.Add(item);
|
|
string errorMessage = string.Format("Invoke error: {0}", item);
|
|
HostedSolutionLog.LogWarning(errorMessage);
|
|
}
|
|
}
|
|
}
|
|
pipeLine = null;
|
|
errors = errorList.ToArray();
|
|
HostedSolutionLog.LogEnd("ExecuteShellCommand");
|
|
return results;
|
|
}
|
|
|
|
internal object GetPSObjectProperty(PSObject obj, string name)
|
|
{
|
|
return obj.Members[name].Value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the identity of the object from the shell execution result
|
|
/// </summary>
|
|
/// <param name="result"></param>
|
|
/// <returns></returns>
|
|
internal string GetResultObjectIdentity(Collection<PSObject> result)
|
|
{
|
|
HostedSolutionLog.LogStart("GetResultObjectIdentity");
|
|
if (result == null)
|
|
throw new ArgumentNullException("result", "Execution result is not specified");
|
|
|
|
if (result.Count < 1)
|
|
throw new ArgumentException("Execution result is empty", "result");
|
|
|
|
if (result.Count > 1)
|
|
throw new ArgumentException("Execution result contains more than one object", "result");
|
|
|
|
PSMemberInfo info = result[0].Members["Identity"];
|
|
if (info == null)
|
|
throw new ArgumentException("Execution result does not contain Identity property", "result");
|
|
|
|
string ret = info.Value.ToString();
|
|
HostedSolutionLog.LogEnd("GetResultObjectIdentity");
|
|
return ret;
|
|
}
|
|
|
|
internal string GetResultObjectDN(Collection<PSObject> result)
|
|
{
|
|
HostedSolutionLog.LogStart("GetResultObjectDN");
|
|
if (result == null)
|
|
throw new ArgumentNullException("result", "Execution result is not specified");
|
|
|
|
if (result.Count < 1)
|
|
throw new ArgumentException("Execution result does not contain any object");
|
|
|
|
if (result.Count > 1)
|
|
throw new ArgumentException("Execution result contains more than one object");
|
|
|
|
PSMemberInfo info = result[0].Members["DistinguishedName"];
|
|
if (info == null)
|
|
throw new ArgumentException("Execution result does not contain DistinguishedName property", "result");
|
|
|
|
string ret = info.Value.ToString();
|
|
HostedSolutionLog.LogEnd("GetResultObjectDN");
|
|
return ret;
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
#region Transactions
|
|
|
|
internal LyncTransaction StartTransaction()
|
|
{
|
|
return new LyncTransaction();
|
|
}
|
|
|
|
internal void RollbackTransaction(LyncTransaction transaction)
|
|
{
|
|
HostedSolutionLog.LogStart("RollbackTransaction");
|
|
Runspace runSpace = null;
|
|
try
|
|
{
|
|
runSpace = OpenRunspace();
|
|
|
|
|
|
for (int i = transaction.Actions.Count - 1; i > -1; i--)
|
|
{
|
|
//reverse order
|
|
try
|
|
{
|
|
RollbackAction(transaction.Actions[i], runSpace);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
HostedSolutionLog.LogError("Rollback error", ex);
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
HostedSolutionLog.LogError("Rollback error", ex);
|
|
}
|
|
finally
|
|
{
|
|
|
|
CloseRunspace(runSpace);
|
|
}
|
|
HostedSolutionLog.LogEnd("RollbackTransaction");
|
|
}
|
|
|
|
private void RollbackAction(TransactionAction action, Runspace runspace)
|
|
{
|
|
HostedSolutionLog.LogInfo("Rollback action: {0}", action.ActionType);
|
|
switch (action.ActionType)
|
|
{
|
|
case TransactionAction.TransactionActionTypes.LyncNewSipDomain:
|
|
DeleteSipDomain(runspace, action.Id);
|
|
break;
|
|
//case TransactionAction.TransactionActionTypes.LyncNewSimpleUrl:
|
|
//DeleteSimpleUrl(runspace, action.Id);
|
|
//break;
|
|
case TransactionAction.TransactionActionTypes.LyncNewUser:
|
|
DeleteUser(runspace, action.Id);
|
|
break;
|
|
case TransactionAction.TransactionActionTypes.LyncNewConferencingPolicy:
|
|
DeleteConferencingPolicy(runspace, action.Id);
|
|
break;
|
|
case TransactionAction.TransactionActionTypes.LyncNewExternalAccessPolicy:
|
|
DeleteExternalAccessPolicy(runspace, action.Id);
|
|
break;
|
|
case TransactionAction.TransactionActionTypes.LyncNewMobilityPolicy:
|
|
DeleteMobilityPolicy(runspace, action.Id);
|
|
break;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region helpers
|
|
private string GetOrganizationPath(string organizationId)
|
|
{
|
|
StringBuilder sb = new StringBuilder();
|
|
// append provider
|
|
AppendOUPath(sb, organizationId);
|
|
AppendOUPath(sb, RootOU);
|
|
AppendDomainPath(sb, RootDomain);
|
|
|
|
return sb.ToString();
|
|
}
|
|
|
|
private static void AppendOUPath(StringBuilder sb, string ou)
|
|
{
|
|
if (string.IsNullOrEmpty(ou))
|
|
return;
|
|
|
|
string path = ou.Replace("/", "\\");
|
|
string[] parts = path.Split('\\');
|
|
for (int i = parts.Length - 1; i != -1; i--)
|
|
sb.Append("OU=").Append(parts[i]).Append(",");
|
|
}
|
|
|
|
private static void AppendDomainPath(StringBuilder sb, string domain)
|
|
{
|
|
if (string.IsNullOrEmpty(domain))
|
|
return;
|
|
|
|
string[] parts = domain.Split('.');
|
|
for (int i = 0; i < parts.Length; i++)
|
|
{
|
|
sb.Append("DC=").Append(parts[i]);
|
|
|
|
if (i < (parts.Length - 1))
|
|
sb.Append(",");
|
|
}
|
|
}
|
|
|
|
internal string AddADPrefix(string path)
|
|
{
|
|
string dn = path;
|
|
if (!dn.ToUpper().StartsWith("LDAP://"))
|
|
{
|
|
dn = string.Format("LDAP://{0}/{1}", PrimaryDomainController, dn);
|
|
}
|
|
return dn;
|
|
}
|
|
|
|
#endregion
|
|
|
|
public override bool IsInstalled()
|
|
{
|
|
string value = "";
|
|
bool bResult = false;
|
|
RegistryKey root = Registry.LocalMachine;
|
|
RegistryKey rk = root.OpenSubKey(LyncRegistryPath);
|
|
if (rk != null)
|
|
{
|
|
value = (string)rk.GetValue("ProductVersion", null);
|
|
if (value == "4.0.7577.0")
|
|
bResult = true;
|
|
|
|
rk.Close();
|
|
}
|
|
return bResult;
|
|
}
|
|
}
|
|
} |