websitepanel/WebsitePanel/Sources/WebsitePanel.Providers.TerminalServices.Windows2012/Windows2012.cs
2015-05-15 02:17:47 -07:00

3144 lines
127 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Copyright (c) 2015, 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.Generic;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Runtime.Remoting;
using System.Text;
using System.Reflection;
using Microsoft.Win32;
using WebsitePanel.Providers.HostedSolution;
using WebsitePanel.Server.Utils;
using WebsitePanel.Providers.Utils;
using WebsitePanel.Providers.OS;
using WebsitePanel.Providers.Common;
using System.Management;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using System.Collections.ObjectModel;
using System.DirectoryServices;
using System.Security.Cryptography.X509Certificates;
using System.Collections;
using System.Xml;
using WebsitePanel.EnterpriseServer.Base.RDS;
namespace WebsitePanel.Providers.RemoteDesktopServices
{
public class Windows2012 : HostingServiceProviderBase, IRemoteDesktopServices
{
#region Constants
private const string CapPath = @"RDS:\GatewayServer\CAP";
private const string RapPath = @"RDS:\GatewayServer\RAP";
private const string Computers = "Computers";
private const string AdDcComputers = "Domain Controllers";
private const string Users = "users";
private const string Admins = "Admins";
private const string RdsGroupFormat = "rds-{0}-{1}";
private const string RdsModuleName = "RemoteDesktopServices";
private const string AddNpsString = "netsh nps add np name=\"\"{0}\"\" policysource=\"1\" processingorder=\"{1}\" conditionid=\"0x3d\" conditiondata=\"^5$\" conditionid=\"0x1fb5\" conditiondata=\"{2}\" conditionid=\"0x1e\" conditiondata=\"UserAuthType:(PW|CA)\" profileid=\"0x1005\" profiledata=\"TRUE\" profileid=\"0x100f\" profiledata=\"TRUE\" profileid=\"0x1009\" profiledata=\"0x7\" profileid=\"0x1fe6\" profiledata=\"0x40000000\"";
private const string WspAdministratorsGroupDescription = "WSP RDS Collection Adminstrators";
private const string RdsCollectionUsersGroupDescription = "WSP RDS Collection Users";
private const string RdsCollectionComputersGroupDescription = "WSP RDS Collection Computers";
private const string RdsServersOU = "RDSServersOU";
private const string RdsServersRootOU = "RDSRootServersOU";
private const string RDSHelpDeskComputerGroup = "Websitepanel-RDSHelpDesk-Computer";
private const string RDSHelpDeskGroup = "WSP-HelpDeskAdministrators";
private const string RDSHelpDeskGroupDescription = "WSP Help Desk Administrators";
private const string LocalAdministratorsGroupName = "Administrators";
private const string RDSHelpDeskRdRapPolicyName = "RDS-HelpDesk-RDRAP";
private const string RDSHelpDeskRdCapPolicyName = "RDS-HelpDesk-RDCAP";
private const string ScreenSaverGpoKey = @"HKCU\Software\Policies\Microsoft\Windows\Control Panel\Desktop";
private const string ScreenSaverValueName = "ScreenSaveActive";
private const string ScreenSaverTimeoutGpoKey = @"HKCU\Software\Policies\Microsoft\Windows\Control Panel\Desktop";
private const string ScreenSaverTimeoutValueName = "ScreenSaveTimeout";
private const string RemoveRestartGpoKey = @"HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer";
private const string RemoveRestartGpoValueName = "NoClose";
private const string RemoveRunGpoKey = @"HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer";
private const string RemoveRunGpoValueName = "NoRun";
private const string DisableTaskManagerGpoKey = @"HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\System";
private const string DisableTaskManagerGpoValueName = "DisableTaskMgr";
private const string HideCDriveGpoKey = @"HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer";
private const string HideCDriveGpoValueName = "NoDrives";
private const string RDSSessionGpoKey = @"HKCU\Software\Policies\Microsoft\Windows NT\Terminal Services";
private const string RDSSessionGpoValueName = "Shadow";
private const string DisableCmdGpoKey = @"HKCU\Software\Policies\Microsoft\Windows\System";
private const string DisableCmdGpoValueName = "DisableCMD";
private const string DisallowRunParentKey = @"HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer";
private const string DisallowRunKey = @"HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer\DisallowRun";
private const string DisallowRunValueName = "DisallowRun";
#endregion
#region Properties
internal string PrimaryDomainController
{
get
{
return ProviderSettings["PrimaryDomainController"];
}
}
private string RootOU
{
get
{
return ProviderSettings["RootOU"];
}
}
private string ComputersRootOU
{
get
{
return ProviderSettings["ComputersRootOU"];
}
}
private string CentralNpsHost
{
get
{
return ProviderSettings["CentralNPS"];
}
}
private IEnumerable<string> Gateways
{
get
{
return ProviderSettings["GWServrsList"].Split(';').Select(x => string.IsNullOrEmpty(x) ? x : x.Trim());
}
}
private bool CentralNps
{
get
{
return Convert.ToBoolean(ProviderSettings["UseCentralNPS"]);
}
}
private string RootDomain
{
get
{
return ServerSettings.ADRootDomain;
}
}
private string ConnectionBroker
{
get
{
return ProviderSettings["ConnectionBroker"];
}
}
#endregion
#region HostingServiceProvider methods
public override bool IsInstalled()
{
Server.Utils.OS.WindowsVersion version = WebsitePanel.Server.Utils.OS.GetVersion();
return version == WebsitePanel.Server.Utils.OS.WindowsVersion.WindowsServer2012 || version == WebsitePanel.Server.Utils.OS.WindowsVersion.WindowsServer2012R2;
}
public override string[] Install()
{
Runspace runSpace = null;
PSObject feature = null;
try
{
runSpace = OpenRunspace();
if (!IsFeatureInstalled("Desktop-Experience", runSpace))
{
feature = AddFeature(runSpace, "Desktop-Experience", true, false);
}
if (!IsFeatureInstalled("NET-Framework-Core", runSpace))
{
feature = AddFeature(runSpace, "NET-Framework-Core", true, false);
}
if (!IsFeatureInstalled("NET-Framework-45-Core", runSpace))
{
feature = AddFeature(runSpace, "NET-Framework-45-Core", true, false);
}
}
finally
{
CloseRunspace(runSpace);
}
return new string[]{};
}
public bool CheckRDSServerAvaliable(string hostname)
{
bool result = false;
var ping = new Ping();
var reply = ping.Send(hostname, 1000);
if (reply.Status == IPStatus.Success)
{
result = true;
}
return result;
}
#endregion
#region RDS Collections
public List<string> GetRdsCollectionSessionHosts(string collectionName)
{
var result = new List<string>();
Runspace runspace = null;
try
{
runspace = OpenRunspace();
Command cmd = new Command("Get-RDSessionHost");
cmd.Parameters.Add("CollectionName", collectionName);
cmd.Parameters.Add("ConnectionBroker", ConnectionBroker);
object[] errors;
var hosts = ExecuteShellCommand(runspace, cmd, false, out errors);
foreach (var host in hosts)
{
result.Add(GetPSObjectProperty(host, "SessionHost").ToString());
}
}
finally
{
CloseRunspace(runspace);
}
return result;
}
public bool AddRdsServersToDeployment(RdsServer[] servers)
{
var result = true;
Runspace runSpace = null;
try
{
runSpace = OpenRunspace();
foreach (var server in servers)
{
if (!ExistRdsServerInDeployment(runSpace, server))
{
AddRdsServerToDeployment(runSpace, server);
}
}
}
catch (Exception e)
{
result = false;
}
finally
{
CloseRunspace(runSpace);
}
return result;
}
public bool CreateCollection(string organizationId, RdsCollection collection)
{
var result = true;
Runspace runSpace = null;
try
{
runSpace = OpenRunspace();
var existingServers = GetServersExistingInCollections(runSpace);
existingServers = existingServers.Select(x => x.ToUpper()).Intersect(collection.Servers.Select(x => x.FqdName.ToUpper())).ToList();
if (existingServers.Any())
{
throw new Exception(string.Format("Server{0} {1} already added to another collection", existingServers.Count == 1 ? "" : "s", string.Join(" ,", existingServers.ToArray())));
}
foreach (var server in collection.Servers)
{
//If server will restart it will not be added to collection
//Do not install feature here
if (!ExistRdsServerInDeployment(runSpace, server))
{
AddRdsServerToDeployment(runSpace, server);
}
}
Command cmd = new Command("New-RDSessionCollection");
cmd.Parameters.Add("CollectionName", collection.Name);
cmd.Parameters.Add("SessionHost", collection.Servers.Select(x => x.FqdName).ToArray());
cmd.Parameters.Add("ConnectionBroker", ConnectionBroker);
if (!string.IsNullOrEmpty(collection.Description))
{
cmd.Parameters.Add("CollectionDescription", collection.Description);
}
var collectionPs = ExecuteShellCommand(runSpace, cmd, false).FirstOrDefault();
if (collectionPs == null)
{
throw new Exception("Collection not created");
}
EditRdsCollectionSettingsInternal(collection, runSpace);
var orgPath = GetOrganizationPath(organizationId);
CheckOrCreateAdGroup(GetComputerGroupPath(organizationId, collection.Name), orgPath, GetComputersGroupName(collection.Name), RdsCollectionComputersGroupDescription);
CheckOrCreateHelpDeskComputerGroup();
string helpDeskGroupSamAccountName = CheckOrCreateAdGroup(GetHelpDeskGroupPath(RDSHelpDeskGroup), GetRootOUPath(), RDSHelpDeskGroup, RDSHelpDeskGroupDescription);
string groupName = GetLocalAdminsGroupName(collection.Name);
string groupPath = GetGroupPath(organizationId, collection.Name, groupName);
string localAdminsGroupSamAccountName = CheckOrCreateAdGroup(groupPath, GetOrganizationPath(organizationId), groupName, WspAdministratorsGroupDescription);
CheckOrCreateAdGroup(GetUsersGroupPath(organizationId, collection.Name), orgPath, GetUsersGroupName(collection.Name), RdsCollectionUsersGroupDescription);
var capPolicyName = GetPolicyName(organizationId, collection.Name, RdsPolicyTypes.RdCap);
var rapPolicyName = GetPolicyName(organizationId, collection.Name, RdsPolicyTypes.RdRap);
foreach (var gateway in Gateways)
{
CreateHelpDeskRdCapForce(runSpace, gateway);
CreateHelpDeskRdRapForce(runSpace, gateway);
if (!CentralNps)
{
CreateRdCapForce(runSpace, gateway, capPolicyName, collection.Name, new List<string> { GetUsersGroupName(collection.Name) });
}
CreateRdRapForce(runSpace, gateway, rapPolicyName, collection.Name, new List<string> { GetUsersGroupName(collection.Name) });
}
if (CentralNps)
{
CreateCentralNpsPolicy(runSpace, CentralNpsHost, capPolicyName, collection.Name, organizationId);
}
//add user group to collection
AddUserGroupsToCollection(runSpace, collection.Name, new List<string> { GetUsersGroupName(collection.Name) });
//add session servers to group
foreach (var rdsServer in collection.Servers)
{
MoveSessionHostToCollectionOU(rdsServer.Name, collection.Name, organizationId);
AddAdGroupToLocalAdmins(runSpace, rdsServer.FqdName, helpDeskGroupSamAccountName);
AddAdGroupToLocalAdmins(runSpace, rdsServer.FqdName, localAdminsGroupSamAccountName);
AddComputerToCollectionAdComputerGroup(organizationId, collection.Name, rdsServer);
}
string collectionComputersPath = GetComputerGroupPath(organizationId, collection.Name);
CreatePolicy(runSpace, organizationId, string.Format("{0}-administrators", collection.Name),
new DirectoryEntry(GetGroupPath(organizationId, collection.Name, GetLocalAdminsGroupName(collection.Name))), new DirectoryEntry(collectionComputersPath), collection.Name);
CreatePolicy(runSpace, organizationId, string.Format("{0}-users", collection.Name), new DirectoryEntry(GetUsersGroupPath(organizationId, collection.Name))
, new DirectoryEntry(collectionComputersPath), collection.Name);
CreateHelpDeskPolicy(runSpace, new DirectoryEntry(GetHelpDeskGroupPath(RDSHelpDeskGroup)), new DirectoryEntry(collectionComputersPath), organizationId, collection.Name);
}
finally
{
CloseRunspace(runSpace);
}
return result;
}
public void EditRdsCollectionSettings(RdsCollection collection)
{
Runspace runSpace = null;
try
{
runSpace = OpenRunspace();
if (collection.Settings != null)
{
var errors = EditRdsCollectionSettingsInternal(collection, runSpace);
if (errors.Count > 0)
{
throw new Exception(string.Format("Settings not setted:\r\n{0}", string.Join("r\\n\\", errors.ToArray())));
}
}
}
finally
{
CloseRunspace(runSpace);
}
}
public List<RdsUserSession> GetRdsUserSessions(string collectionName)
{
Runspace runSpace = null;
var result = new List<RdsUserSession>();
try
{
runSpace = OpenRunspace();
result = GetRdsUserSessionsInternal(collectionName, runSpace);
}
finally
{
CloseRunspace(runSpace);
}
return result;
}
public void LogOffRdsUser(string unifiedSessionId, string hostServer)
{
Runspace runSpace = null;
try
{
runSpace = OpenRunspace();
object[] errors;
Command cmd = new Command("Invoke-RDUserLogoff");
cmd.Parameters.Add("HostServer", hostServer);
cmd.Parameters.Add("UnifiedSessionID", unifiedSessionId);
cmd.Parameters.Add("Force", true);
ExecuteShellCommand(runSpace, cmd, false, out errors);
if (errors != null && errors.Length > 0)
{
throw new Exception(string.Join("r\\n\\", errors.Select(e => e.ToString()).ToArray()));
}
}
finally
{
CloseRunspace(runSpace);
}
}
public List<string> GetServersExistingInCollections()
{
Runspace runSpace = null;
List<string> existingServers = new List<string>();
try
{
runSpace = OpenRunspace();
existingServers = GetServersExistingInCollections(runSpace);
}
finally
{
CloseRunspace(runSpace);
}
return existingServers;
}
public RdsCollection GetCollection(string collectionName)
{
RdsCollection collection =null;
Runspace runSpace = null;
try
{
runSpace = OpenRunspace();
collection = runSpace.GetCollection(collectionName, ConnectionBroker, PrimaryDomainController);
}
finally
{
CloseRunspace(runSpace);
}
return collection;
}
public bool RemoveCollection(string organizationId, string collectionName, List<RdsServer> servers)
{
var result = true;
Runspace runSpace = null;
try
{
runSpace = OpenRunspace();
Command cmd = new Command("Remove-RDSessionCollection");
cmd.Parameters.Add("CollectionName", collectionName);
cmd.Parameters.Add("ConnectionBroker", ConnectionBroker);
cmd.Parameters.Add("Force", true);
ExecuteShellCommand(runSpace, cmd, false);
DeleteGpo(runSpace, string.Format("{0}-administrators", collectionName));
DeleteGpo(runSpace, string.Format("{0}-users", collectionName));
DeleteHelpDeskPolicy(runSpace, collectionName);
var capPolicyName = GetPolicyName(organizationId, collectionName, RdsPolicyTypes.RdCap);
var rapPolicyName = GetPolicyName(organizationId, collectionName, RdsPolicyTypes.RdRap);
foreach (var gateway in Gateways)
{
if (!CentralNps)
{
RemoveRdCap(runSpace, gateway, capPolicyName);
}
RemoveRdRap(runSpace, gateway, rapPolicyName);
}
if (CentralNps)
{
RemoveNpsPolicy(runSpace, CentralNpsHost, capPolicyName);
}
foreach(var server in servers)
{
RemoveGroupFromLocalAdmin(server.FqdName, server.Name, GetLocalAdminsGroupName(collectionName), runSpace);
RemoveComputerFromCollectionAdComputerGroup(organizationId, collectionName, server);
MoveRdsServerToTenantOU(server.Name, organizationId);
}
ActiveDirectoryUtils.DeleteADObject(GetComputerGroupPath(organizationId, collectionName));
ActiveDirectoryUtils.DeleteADObject(GetUsersGroupPath(organizationId, collectionName));
ActiveDirectoryUtils.DeleteADObject(GetGroupPath(organizationId, collectionName, GetLocalAdminsGroupName(collectionName)));
ActiveDirectoryUtils.DeleteADObject(GetCollectionOUPath(organizationId, string.Format("{0}-OU", collectionName)));
}
catch (Exception e)
{
result = false;
}
finally
{
CloseRunspace(runSpace);
}
return result;
}
public bool SetUsersInCollection(string organizationId, string collectionName, List<string> users)
{
var result = true;
try
{
var usersGroupName = GetUsersGroupName(collectionName);
var usersGroupPath = GetUsersGroupPath(organizationId, collectionName);
SetUsersToCollectionAdGroup(collectionName, organizationId, users, usersGroupName, usersGroupPath);
}
catch (Exception e)
{
result = false;
Log.WriteWarning(e.ToString());
}
return result;
}
public void AddSessionHostServerToCollection(string organizationId, string collectionName, RdsServer server)
{
Runspace runSpace = null;
try
{
runSpace = OpenRunspace();
if (!ExistRdsServerInDeployment(runSpace, server))
{
AddRdsServerToDeployment(runSpace, server);
}
Command cmd = new Command("Add-RDSessionHost");
cmd.Parameters.Add("CollectionName", collectionName);
cmd.Parameters.Add("SessionHost", server.FqdName);
cmd.Parameters.Add("ConnectionBroker", ConnectionBroker);
ExecuteShellCommand(runSpace, cmd, false);
CheckOrCreateHelpDeskComputerGroup();
foreach(var gateway in Gateways)
{
CreateHelpDeskRdCapForce(runSpace, gateway);
CreateHelpDeskRdRapForce(runSpace, gateway);
}
string helpDeskGroupSamAccountName = CheckOrCreateAdGroup(GetHelpDeskGroupPath(RDSHelpDeskGroup), GetRootOUPath(), RDSHelpDeskGroup, RDSHelpDeskGroupDescription);
string groupName = GetLocalAdminsGroupName(collectionName);
string groupPath = GetGroupPath(organizationId, collectionName, groupName);
string localAdminsGroupSamAccountName = CheckOrCreateAdGroup(groupPath, GetOrganizationPath(organizationId), groupName, WspAdministratorsGroupDescription);
AddAdGroupToLocalAdmins(runSpace, server.FqdName, LocalAdministratorsGroupName);
AddAdGroupToLocalAdmins(runSpace, server.FqdName, helpDeskGroupSamAccountName);
AddComputerToCollectionAdComputerGroup(organizationId, collectionName, server);
}
finally
{
CloseRunspace(runSpace);
}
}
public void AddSessionHostServersToCollection(string organizationId, string collectionName, List<RdsServer> servers)
{
foreach (var server in servers)
{
AddSessionHostServerToCollection(organizationId, collectionName, server);
}
}
public void MoveSessionHostsToCollectionOU(List<RdsServer> servers, string collectionName, string organizationId)
{
foreach(var server in servers)
{
MoveSessionHostToCollectionOU(server.Name, collectionName, organizationId);
}
}
public void RemoveSessionHostServerFromCollection(string organizationId, string collectionName, RdsServer server)
{
Runspace runSpace = null;
try
{
runSpace = OpenRunspace();
Command cmd = new Command("Remove-RDSessionHost");
cmd.Parameters.Add("ConnectionBroker", ConnectionBroker);
cmd.Parameters.Add("SessionHost", server.FqdName);
cmd.Parameters.Add("Force", true);
ExecuteShellCommand(runSpace, cmd, false);
RemoveGroupFromLocalAdmin(server.FqdName, server.Name, GetLocalAdminsGroupName(collectionName), runSpace);
RemoveComputerFromCollectionAdComputerGroup(organizationId, collectionName, server);
MoveRdsServerToTenantOU(server.Name, organizationId);
}
finally
{
CloseRunspace(runSpace);
}
}
public void RemoveSessionHostServersFromCollection(string organizationId, string collectionName, List<RdsServer> servers)
{
foreach (var server in servers)
{
RemoveSessionHostServerFromCollection(organizationId, collectionName, server);
}
}
#endregion
public void SetRDServerNewConnectionAllowed(bool newConnectionAllowed, RdsServer server)
{
Runspace runSpace = null;
try
{
runSpace = OpenRunspace();
Command cmd = new Command("Set-RDSessionHost");
cmd.Parameters.Add("SessionHost", server.FqdName);
cmd.Parameters.Add("NewConnectionAllowed", string.Format("${0}", newConnectionAllowed.ToString()));
ExecuteShellCommand(runSpace, cmd, false);
}
catch (Exception e)
{
}
finally
{
CloseRunspace(runSpace);
}
}
#region Remote Applications
public string[] GetApplicationUsers(string collectionName, string applicationName)
{
Runspace runspace = null;
List<string> result = new List<string>();
try
{
runspace = OpenRunspace();
Command cmd = new Command("Get-RDRemoteApp");
cmd.Parameters.Add("CollectionName", collectionName);
cmd.Parameters.Add("ConnectionBroker", ConnectionBroker);
cmd.Parameters.Add("Alias", applicationName);
var application = ExecuteShellCommand(runspace, cmd, false).FirstOrDefault();
if (application != null)
{
var users = (string[])(GetPSObjectProperty(application, "UserGroups"));
if (users != null)
{
result.AddRange(users);
}
}
}
finally
{
CloseRunspace(runspace);
}
return result.ToArray();
}
public bool SetApplicationUsers(string collectionName, RemoteApplication remoteApp, string[] users)
{
Runspace runspace = null;
bool result = true;
try
{
Log.WriteWarning(string.Format("App alias: {0}\r\nCollection Name:{2}\r\nUsers: {1}", remoteApp.Alias, string.Join("; ", users), collectionName));
runspace = OpenRunspace();
Command cmd = new Command("Set-RDRemoteApp");
cmd.Parameters.Add("CollectionName", collectionName);
cmd.Parameters.Add("ConnectionBroker", ConnectionBroker);
cmd.Parameters.Add("DisplayName", remoteApp.DisplayName);
cmd.Parameters.Add("UserGroups", users);
cmd.Parameters.Add("Alias", remoteApp.Alias);
object[] errors;
ExecuteShellCommand(runspace, cmd, false, out errors).FirstOrDefault();
if (errors.Any())
{
Log.WriteWarning(string.Format("{0} adding users errors: {1}", remoteApp.DisplayName, string.Join("\r\n", errors.Select(e => e.ToString()).ToArray())));
}
else
{
Log.WriteWarning(string.Format("{0} users added successfully", remoteApp.DisplayName));
}
}
catch(Exception)
{
result = false;
}
finally
{
CloseRunspace(runspace);
}
return result;
}
public List<StartMenuApp> GetAvailableRemoteApplications(string collectionName)
{
var startApps = new List<StartMenuApp>();
Runspace runSpace = null;
try
{
runSpace = OpenRunspace();
Command cmd = new Command("Get-RDAvailableApp");
cmd.Parameters.Add("CollectionName", collectionName);
cmd.Parameters.Add("ConnectionBroker", ConnectionBroker);
var remoteApplicationsPS = ExecuteShellCommand(runSpace, cmd, false);
if (remoteApplicationsPS != null)
{
startApps.AddRange(remoteApplicationsPS.Select(CreateStartMenuAppFromPsObject));
}
}
finally
{
CloseRunspace(runSpace);
}
return startApps;
}
public List<RemoteApplication> GetCollectionRemoteApplications(string collectionName)
{
var remoteApps = new List<RemoteApplication>();
Runspace runSpace = null;
try
{
runSpace = OpenRunspace();
Command cmd = new Command("Get-RDRemoteApp");
cmd.Parameters.Add("CollectionName", collectionName);
cmd.Parameters.Add("ConnectionBroker", ConnectionBroker);
var remoteAppsPs = ExecuteShellCommand(runSpace, cmd, false);
if (remoteAppsPs != null)
{
remoteApps.AddRange(remoteAppsPs.Select(CreateRemoteApplicationFromPsObject));
}
}
finally
{
CloseRunspace(runSpace);
}
return remoteApps;
}
public bool AddRemoteApplication(string collectionName, RemoteApplication remoteApp)
{
var result = false;
Runspace runSpace = null;
try
{
runSpace = OpenRunspace();
Command cmd = new Command("New-RDRemoteApp");
cmd.Parameters.Add("CollectionName", collectionName);
cmd.Parameters.Add("ConnectionBroker", ConnectionBroker);
cmd.Parameters.Add("Alias", remoteApp.Alias);
cmd.Parameters.Add("DisplayName", remoteApp.DisplayName);
cmd.Parameters.Add("FilePath", remoteApp.FilePath);
cmd.Parameters.Add("ShowInWebAccess", remoteApp.ShowInWebAccess);
if (!string.IsNullOrEmpty(remoteApp.RequiredCommandLine))
{
cmd.Parameters.Add("CommandLineSetting", "Require");
cmd.Parameters.Add("RequiredCommandLine", remoteApp.RequiredCommandLine);
}
ExecuteShellCommand(runSpace, cmd, false);
result = true;
}
finally
{
CloseRunspace(runSpace);
}
return result;
}
public bool AddRemoteApplications(string collectionName, List<RemoteApplication> remoteApps)
{
var result = true;
foreach (var remoteApp in remoteApps)
{
result = AddRemoteApplication(collectionName, remoteApp) && result;
}
return result;
}
public bool RemoveRemoteApplication(string collectionName, RemoteApplication remoteApp)
{
var result = false;
Runspace runSpace = null;
try
{
runSpace = OpenRunspace();
Command cmd = new Command("Remove-RDRemoteApp");
cmd.Parameters.Add("CollectionName", collectionName);
cmd.Parameters.Add("ConnectionBroker", ConnectionBroker);
cmd.Parameters.Add("Alias", remoteApp.Alias);
cmd.Parameters.Add("Force", true);
ExecuteShellCommand(runSpace, cmd, false);
}
finally
{
CloseRunspace(runSpace);
}
return result;
}
#endregion
#region Gateaway (RD CAP | RD RAP)
internal void CreateCentralNpsPolicy(Runspace runSpace, string centralNpshost, string policyName, string collectionName, string organizationId)
{
var showCmd = new Command("netsh nps show np");
var showResult = ExecuteRemoteShellCommand(runSpace, centralNpshost, showCmd);
var processingOrders = showResult.Where(x => Convert.ToString(x).ToLower().Contains("processing order")).Select(x => Convert.ToString(x));
var count = 0;
foreach(var processingOrder in processingOrders)
{
var order = Convert.ToInt32(processingOrder.Remove(0, processingOrder.LastIndexOf("=") + 1).Replace(" ", ""));
if (order > count)
{
count = order;
}
}
var userGroupAd = ActiveDirectoryUtils.GetADObject(GetUsersGroupPath(organizationId, collectionName));
var userGroupSid = (byte[])ActiveDirectoryUtils.GetADObjectProperty(userGroupAd, "objectSid");
var addCmdString = string.Format(AddNpsString, policyName.Replace(" ", "_"), count + 1, ConvertByteToStringSid(userGroupSid));
Command addCmd = new Command(addCmdString);
var result = ExecuteRemoteShellCommand(runSpace, centralNpshost, addCmd);
}
internal void RemoveNpsPolicy(Runspace runSpace, string centralNpshost, string policyName)
{
var removeCmd = new Command(string.Format("netsh nps delete np {0}", policyName.Replace(" ", "_")));
var removeResult = ExecuteRemoteShellCommand(runSpace, centralNpshost, removeCmd);
}
internal void CreateRdCapForce(Runspace runSpace, string gatewayHost, string policyName, string collectionName, List<string> groups)
{
//New-Item -Path "RDS:\GatewayServer\CAP" -Name "Allow Admins" -UserGroups "Administrators@." -AuthMethod 1
//Set-Item -Path "RDS:\GatewayServer\CAP\Allow Admins\SessionTimeout" -Value 480 -SessionTimeoutAction 0
if (ItemExistsRemote(runSpace, gatewayHost, Path.Combine(CapPath, policyName)))
{
RemoveRdCap(runSpace, gatewayHost, policyName);
}
var userGroupParametr = string.Format("@({0})",string.Join(",", groups.Select(x => string.Format("\"{0}@{1}\"", x, RootDomain)).ToArray()));
Command rdCapCommand = new Command("New-Item");
rdCapCommand.Parameters.Add("Path", string.Format("\"{0}\"", CapPath));
rdCapCommand.Parameters.Add("Name", string.Format("\"{0}\"", policyName));
rdCapCommand.Parameters.Add("UserGroups", userGroupParametr);
rdCapCommand.Parameters.Add("AuthMethod", 1);
ExecuteRemoteShellCommand(runSpace, gatewayHost, rdCapCommand, RdsModuleName);
}
private void CreateHelpDeskRdCapForce(Runspace runSpace, string gatewayHost)
{
if (ItemExistsRemote(runSpace, gatewayHost, Path.Combine(CapPath, RDSHelpDeskRdCapPolicyName)))
{
return;
}
var userGroupParameter = string.Format("@({0})", string.Format("\"{0}@{1}\"", RDSHelpDeskGroup, RootDomain));
Command rdCapCommand = new Command("New-Item");
rdCapCommand.Parameters.Add("Path", string.Format("\"{0}\"", CapPath));
rdCapCommand.Parameters.Add("Name", string.Format("\"{0}\"", RDSHelpDeskRdCapPolicyName));
rdCapCommand.Parameters.Add("UserGroups", userGroupParameter);
rdCapCommand.Parameters.Add("AuthMethod", 1);
ExecuteRemoteShellCommand(runSpace, gatewayHost, rdCapCommand, RdsModuleName);
}
private void CreateHelpDeskRdRapForce(Runspace runSpace, string gatewayHost)
{
if (ItemExistsRemote(runSpace, gatewayHost, Path.Combine(RapPath, RDSHelpDeskRdRapPolicyName)))
{
return;
}
var userGroupParameter = string.Format("@({0})", string.Format("\"{0}@{1}\"", RDSHelpDeskGroup, RootDomain));
var computerGroupParameter = string.Format("\"{0}@{1}\"", RDSHelpDeskComputerGroup, RootDomain);
Command rdRapCommand = new Command("New-Item");
rdRapCommand.Parameters.Add("Path", string.Format("\"{0}\"", RapPath));
rdRapCommand.Parameters.Add("Name", string.Format("\"{0}\"", RDSHelpDeskRdRapPolicyName));
rdRapCommand.Parameters.Add("UserGroups", userGroupParameter);
rdRapCommand.Parameters.Add("ComputerGroupType", 1);
rdRapCommand.Parameters.Add("ComputerGroup", computerGroupParameter);
object[] errors;
for (int i = 0; i < 3; i++)
{
ExecuteRemoteShellCommand(runSpace, gatewayHost, rdRapCommand, out errors, RdsModuleName);
if (errors == null || !errors.Any())
{
Log.WriteWarning("RD RAP Added Successfully");
break;
}
else
{
Log.WriteWarning(string.Join("\r\n", errors.Select(e => e.ToString()).ToArray()));
}
}
}
internal void RemoveRdCap(Runspace runSpace, string gatewayHost, string name)
{
RemoveItemRemote(runSpace, gatewayHost, string.Format(@"{0}\{1}", CapPath, name), RdsModuleName);
}
internal void CreateRdRapForce(Runspace runSpace, string gatewayHost, string policyName, string collectionName, List<string> groups)
{
//New-Item -Path "RDS:\GatewayServer\RAP" -Name "Allow Connections To Everywhere" -UserGroups "Administrators@." -ComputerGroupType 1
//Set-Item -Path "RDS:\GatewayServer\RAP\Allow Connections To Everywhere\PortNumbers" -Value 3389,3390
if (ItemExistsRemote(runSpace, gatewayHost, Path.Combine(RapPath, policyName)))
{
RemoveRdRap(runSpace, gatewayHost, policyName);
}
var userGroupParametr = string.Format("@({0})", string.Join(",", groups.Select(x => string.Format("\"{0}@{1}\"", x, RootDomain)).ToArray()));
var computerGroupParametr = string.Format("\"{0}@{1}\"", GetComputersGroupName(collectionName), RootDomain);
Command rdRapCommand = new Command("New-Item");
rdRapCommand.Parameters.Add("Path", string.Format("\"{0}\"", RapPath));
rdRapCommand.Parameters.Add("Name", string.Format("\"{0}\"", policyName));
rdRapCommand.Parameters.Add("UserGroups", userGroupParametr);
rdRapCommand.Parameters.Add("ComputerGroupType", 1);
rdRapCommand.Parameters.Add("ComputerGroup", computerGroupParametr);
object[] errors;
for (int i = 0; i < 3; i++)
{
Log.WriteWarning(string.Format("Adding RD RAP ... {0}\r\nGateway Host\t{1}\r\nUser Group\t{2}\r\nComputer Group\t{3}", i + 1, gatewayHost, userGroupParametr, computerGroupParametr));
ExecuteRemoteShellCommand(runSpace, gatewayHost, rdRapCommand, out errors, RdsModuleName);
if (errors == null || !errors.Any())
{
Log.WriteWarning("RD RAP Added Successfully");
break;
}
else
{
Log.WriteWarning(string.Join("\r\n", errors.Select(e => e.ToString()).ToArray()));
}
}
}
internal void RemoveRdRap(Runspace runSpace, string gatewayHost, string name)
{
RemoveItemRemote(runSpace, gatewayHost, string.Format(@"{0}\{1}", RapPath, name), RdsModuleName);
}
#endregion
#region Local Admins
public void SaveRdsCollectionLocalAdmins(List<string> users, List<string> hosts, string collectionName, string organizationId)
{
Runspace runspace = null;
try
{
runspace = OpenRunspace();
var index = ServerSettings.ADRootDomain.LastIndexOf(".");
var domainName = ServerSettings.ADRootDomain;
string groupName = GetLocalAdminsGroupName(collectionName);
string groupPath = GetGroupPath(organizationId, collectionName, groupName);
string helpDeskGroupSamAccountName = CheckOrCreateAdGroup(GetHelpDeskGroupPath(RDSHelpDeskGroup), GetRootOUPath(), RDSHelpDeskGroup, RDSHelpDeskGroupDescription);
string localAdminsGroupSamAccountName = CheckOrCreateAdGroup(groupPath, GetOrganizationPath(organizationId), groupName, WspAdministratorsGroupDescription);
if (index > 0)
{
domainName = ServerSettings.ADRootDomain.Substring(0, index);
}
foreach (var hostName in hosts)
{
AddAdGroupToLocalAdmins(runspace, hostName, helpDeskGroupSamAccountName);
AddAdGroupToLocalAdmins(runspace, hostName, localAdminsGroupSamAccountName);
SetUsersToCollectionAdGroup(collectionName, organizationId, users, GetLocalAdminsGroupName(collectionName), groupPath);
}
}
finally
{
CloseRunspace(runspace);
}
}
public List<string> GetRdsCollectionLocalAdmins(string organizationId, string collectionName)
{
string groupName = GetLocalAdminsGroupName(collectionName);
return GetUsersToCollectionAdGroup(collectionName, groupName, organizationId);
}
private void RemoveGroupFromLocalAdmin(string fqdnName, string hostName, string groupName, Runspace runspace)
{
var scripts = new List<string>
{
string.Format("$GroupObj = [ADSI]\"WinNT://{0}/{1}\"", hostName, LocalAdministratorsGroupName),
string.Format("$GroupObj.Remove(\"WinNT://{0}/{1}\")", ServerSettings.ADRootDomain, RDSHelpDeskGroup),
string.Format("$GroupObj.Remove(\"WinNT://{0}/{1}\")", ServerSettings.ADRootDomain, groupName)
};
object[] errors = null;
ExecuteRemoteShellCommand(runspace, fqdnName, scripts, out errors);
}
#endregion
#region GPO
public void ApplyGPO(string organizationId, string collectionName, RdsServerSettings serverSettings)
{
string administratorsGpo = string.Format("{0}-administrators", collectionName);
string usersGpo = string.Format("{0}-users", collectionName);
Runspace runspace = null;
try
{
runspace = OpenRunspace();
string collectionComputersPath = GetComputerGroupPath(organizationId, collectionName);
CreatePolicy(runspace, organizationId, string.Format("{0}-administrators", collectionName),
new DirectoryEntry(GetGroupPath(organizationId, collectionName, GetLocalAdminsGroupName(collectionName))), new DirectoryEntry(collectionComputersPath), collectionName);
CreatePolicy(runspace, organizationId, string.Format("{0}-users", collectionName),
new DirectoryEntry(GetUsersGroupPath(organizationId, collectionName)), new DirectoryEntry(collectionComputersPath), collectionName);
CreateHelpDeskPolicy(runspace, new DirectoryEntry(GetHelpDeskGroupPath(RDSHelpDeskGroup)), new DirectoryEntry(collectionComputersPath), organizationId, collectionName);
RemoveRegistryValue(runspace, ScreenSaverGpoKey, administratorsGpo);
RemoveRegistryValue(runspace, ScreenSaverGpoKey, usersGpo);
RemoveRegistryValue(runspace, RemoveRestartGpoKey, administratorsGpo);
RemoveRegistryValue(runspace, RemoveRestartGpoKey, usersGpo);
RemoveRegistryValue(runspace, DisableTaskManagerGpoKey, administratorsGpo);
RemoveRegistryValue(runspace, DisableTaskManagerGpoKey, usersGpo);
RemoveRegistryValue(runspace, DisableCmdGpoKey, usersGpo);
RemoveRegistryValue(runspace, DisableCmdGpoKey, administratorsGpo);
RemoveRegistryValue(runspace, DisallowRunKey, usersGpo);
RemoveRegistryValue(runspace, DisallowRunParentKey, usersGpo);
RemoveRegistryValue(runspace, DisallowRunKey, administratorsGpo);
RemoveRegistryValue(runspace, DisallowRunParentKey, administratorsGpo);
var setting = serverSettings.Settings.FirstOrDefault(s => s.PropertyName.Equals(RdsServerSettings.SCREEN_SAVER_DISABLED));
SetRegistryValue(setting, runspace, ScreenSaverGpoKey, administratorsGpo, usersGpo, ScreenSaverValueName, "0", "string");
setting = serverSettings.Settings.FirstOrDefault(s => s.PropertyName.Equals(RdsServerSettings.REMOVE_SHUTDOWN_RESTART));
SetRegistryValue(setting, runspace, RemoveRestartGpoKey, administratorsGpo, usersGpo, RemoveRestartGpoValueName, "1", "DWord");
setting = serverSettings.Settings.FirstOrDefault(s => s.PropertyName.Equals(RdsServerSettings.REMOVE_RUN_COMMAND));
SetRegistryValue(setting, runspace, RemoveRunGpoKey, administratorsGpo, usersGpo, RemoveRunGpoValueName, "1", "DWord");
setting = serverSettings.Settings.FirstOrDefault(s => s.PropertyName.Equals(RdsServerSettings.DISABLE_TASK_MANAGER));
SetRegistryValue(setting, runspace, DisableTaskManagerGpoKey, administratorsGpo, usersGpo, DisableTaskManagerGpoValueName, "1", "DWord");
setting = serverSettings.Settings.FirstOrDefault(s => s.PropertyName.Equals(RdsServerSettings.HIDE_C_DRIVE));
SetRegistryValue(setting, runspace, HideCDriveGpoKey, administratorsGpo, usersGpo, HideCDriveGpoValueName, "4", "DWord");
setting = serverSettings.Settings.FirstOrDefault(s => s.PropertyName.Equals(RdsServerSettings.DISABLE_CMD));
SetRegistryValue(setting, runspace, DisableCmdGpoKey, administratorsGpo, usersGpo, DisableCmdGpoValueName, "1", "DWord");
setting = serverSettings.Settings.FirstOrDefault(s => s.PropertyName.Equals(RdsServerSettings.LOCK_SCREEN_TIMEOUT));
double result;
if (setting != null && !string.IsNullOrEmpty(setting.PropertyValue) && double.TryParse(setting.PropertyValue, out result))
{
SetRegistryValue(setting, runspace, ScreenSaverTimeoutGpoKey, administratorsGpo, usersGpo, ScreenSaverTimeoutValueName, setting.PropertyValue, "string");
}
SetRdsSessionHostPermissions(runspace, serverSettings, usersGpo, administratorsGpo);
SetPowershellPermissions(runspace, serverSettings.Settings.FirstOrDefault(s => s.PropertyName.Equals(RdsServerSettings.REMOVE_POWERSHELL_COMMAND)), usersGpo, administratorsGpo);
}
finally
{
CloseRunspace(runspace);
}
}
private void CheckPolicySecurityFiltering(Runspace runspace, string gpoName, DirectoryEntry collectionComputersEntry)
{
var scripts = new List<string>{
string.Format("Get-GPPermissions -Name {0} -TargetName {1} -TargetType group", gpoName, string.Format("'{0}'", ActiveDirectoryUtils.GetADObjectProperty(collectionComputersEntry, "sAMAccountName").ToString()))
};
object[] errors = null;
ExecuteRemoteShellCommand(runspace, PrimaryDomainController, scripts, out errors);
if (errors != null && errors.Any())
{
scripts = new List<string>{
string.Format("Set-GPPermissions -Name {0} -PermissionLevel gpoapply -TargetName {1} -TargetType group", gpoName, string.Format("'{0}'", ActiveDirectoryUtils.GetADObjectProperty(collectionComputersEntry, "sAMAccountName").ToString()))
};
}
ExecuteRemoteShellCommand(runspace, PrimaryDomainController, scripts, out errors);
}
private void SetPowershellPermissions(Runspace runspace, RdsServerSetting setting, string usersGpo, string administratorsGpo)
{
if (setting != null)
{
SetRegistryValue(setting, runspace, DisallowRunParentKey, administratorsGpo, usersGpo, DisallowRunValueName, "1", "Dword");
if (setting.ApplyAdministrators)
{
SetRegistryValue(runspace, DisallowRunKey, administratorsGpo, "powershell.exe", "string");
}
if (setting.ApplyUsers)
{
SetRegistryValue(runspace, DisallowRunKey, usersGpo, "powershell.exe", "string");
}
}
}
private void SetRdsSessionHostPermissions(Runspace runspace, RdsServerSettings settings, string usersGpo, string administratorsGpo)
{
var viewSetting = settings.Settings.FirstOrDefault(s => s.PropertyName.Equals(RdsServerSettings.RDS_VIEW_WITHOUT_PERMISSION));
var controlSetting = settings.Settings.FirstOrDefault(s => s.PropertyName.Equals(RdsServerSettings.RDS_CONTROL_WITHOUT_PERMISSION));
if (viewSetting == null || controlSetting == null)
{
return;
}
if (controlSetting.ApplyUsers)
{
SetRegistryValue(runspace, RDSSessionGpoKey, usersGpo, "2", RDSSessionGpoValueName, "DWord");
}
else if (viewSetting.ApplyUsers)
{
SetRegistryValue(runspace, RDSSessionGpoKey, usersGpo, "4", RDSSessionGpoValueName, "DWord");
}
else
{
SetRegistryValue(runspace, RDSSessionGpoKey, usersGpo, "3", RDSSessionGpoValueName, "DWord");
}
if (controlSetting.ApplyAdministrators)
{
SetRegistryValue(runspace, RDSSessionGpoKey, administratorsGpo, "2", RDSSessionGpoValueName, "DWord");
}
else if (viewSetting.ApplyAdministrators)
{
SetRegistryValue(runspace, RDSSessionGpoKey, administratorsGpo, "4", RDSSessionGpoValueName, "DWord");
}
else
{
SetRegistryValue(runspace, RDSSessionGpoKey, administratorsGpo, "3", RDSSessionGpoValueName, "DWord");
}
}
private void RemoveRegistryValue(Runspace runspace, string key, string gpoName)
{
Command cmd = new Command("Remove-GPRegistryValue");
cmd.Parameters.Add("Name", gpoName);
cmd.Parameters.Add("Key", string.Format("\"{0}\"", key));
Collection<PSObject> result = ExecuteRemoteShellCommand(runspace, PrimaryDomainController, cmd);
}
private void SetRegistryValue(RdsServerSetting setting, Runspace runspace, string key, string administratorsGpo, string usersGpo, string valueName, string value, string type)
{
if (setting == null)
{
return;
}
if (setting.ApplyAdministrators)
{
SetRegistryValue(runspace, key, administratorsGpo, value, valueName, type);
}
if (setting.ApplyUsers)
{
SetRegistryValue(runspace, key, usersGpo, value, valueName, type);
}
}
private void SetRegistryValue(Runspace runspace, string key, string gpoName, string value, string type)
{
Command cmd = new Command("Set-GPRegistryValue");
cmd.Parameters.Add("Name", gpoName);
cmd.Parameters.Add("Key", string.Format("\"{0}\"", key));
cmd.Parameters.Add("Value", value);
cmd.Parameters.Add("Type", type);
Collection<PSObject> result = ExecuteRemoteShellCommand(runspace, PrimaryDomainController, cmd);
}
private void SetRegistryValue(Runspace runspace, string key, string gpoName, string value, string valueName, string type)
{
Command cmd = new Command("Set-GPRegistryValue");
cmd.Parameters.Add("Name", gpoName);
cmd.Parameters.Add("Key", string.Format("\"{0}\"", key));
cmd.Parameters.Add("Value", value);
cmd.Parameters.Add("ValueName", valueName);
cmd.Parameters.Add("Type", type);
Collection<PSObject> result = ExecuteRemoteShellCommand(runspace, PrimaryDomainController, cmd);
}
private void CreateHelpDeskPolicy(Runspace runspace, DirectoryEntry entry, DirectoryEntry collectionComputersEntry, string organizationId, string collectionName)
{
string gpoName = string.Format("{0}-HelpDesk", collectionName);
string gpoId = GetPolicyId(runspace, gpoName);
if (string.IsNullOrEmpty(gpoId))
{
gpoId = CreateAndLinkPolicy(runspace, gpoName, organizationId, collectionName);
SetPolicyPermissions(runspace, gpoName, entry, collectionComputersEntry);
SetRegistryValue(runspace, RDSSessionGpoKey, gpoName, "2", RDSSessionGpoValueName, "DWord");
}
else
{
CheckPolicySecurityFiltering(runspace, gpoName, collectionComputersEntry);
}
}
private string CreatePolicy(Runspace runspace, string organizationId, string gpoName, DirectoryEntry entry, DirectoryEntry collectionComputersEntry, string collectionName)
{
string gpoId = GetPolicyId(runspace, gpoName);
if (string.IsNullOrEmpty(gpoId))
{
gpoId = CreateAndLinkPolicy(runspace, gpoName, organizationId, collectionName);
SetPolicyPermissions(runspace, gpoName, entry, collectionComputersEntry);
}
else
{
CheckPolicySecurityFiltering(runspace, gpoName, collectionComputersEntry);
}
return gpoId;
}
private void DeleteHelpDeskPolicy(Runspace runspace, string collectionName)
{
string gpoName = string.Format("{0}-HelpDesk", collectionName);
DeleteGpo(runspace, gpoName);
}
private void DeleteGpo(Runspace runspace, string gpoName)
{
Command cmd = new Command("Remove-GPO");
cmd.Parameters.Add("Name", gpoName);
Collection<PSObject> result = ExecuteRemoteShellCommand(runspace, PrimaryDomainController, cmd);
}
private void SetPolicyPermissions(Runspace runspace, string gpoName, DirectoryEntry entry, DirectoryEntry collectionComputersEntry)
{
var scripts = new List<string>
{
string.Format("Set-GPPermissions -Name {0} -Replace -PermissionLevel None -TargetName 'Authenticated Users' -TargetType group", gpoName),
string.Format("Set-GPPermissions -Name {0} -PermissionLevel gpoapply -TargetName {1} -TargetType group", gpoName, string.Format("'{0}'", ActiveDirectoryUtils.GetADObjectProperty(entry, "sAMAccountName").ToString())),
string.Format("Set-GPPermissions -Name {0} -PermissionLevel gpoapply -TargetName {1} -TargetType group", gpoName, string.Format("'{0}'", ActiveDirectoryUtils.GetADObjectProperty(collectionComputersEntry, "sAMAccountName").ToString()))
};
object[] errors = null;
ExecuteRemoteShellCommand(runspace, PrimaryDomainController, scripts, out errors);
}
private string CreateAndLinkPolicy(Runspace runspace, string gpoName, string organizationId, string collectionName)
{
string gpoId = null;
try
{
var entry = new DirectoryEntry(GetOrganizationPath(organizationId));
var distinguishedName = string.Format("\"{0}\"", ActiveDirectoryUtils.GetADObjectProperty(entry, "DistinguishedName"));
Command cmd = new Command("New-GPO");
cmd.Parameters.Add("Name", gpoName);
Collection<PSObject> result = ExecuteRemoteShellCommand(runspace, PrimaryDomainController, cmd);
if (result != null && result.Count > 0)
{
PSObject gpo = result[0];
gpoId = ((Guid)GetPSObjectProperty(gpo, "Id")).ToString("B");
}
cmd = new Command("New-GPLink");
cmd.Parameters.Add("Name", gpoName);
cmd.Parameters.Add("Target", distinguishedName);
ExecuteRemoteShellCommand(runspace, PrimaryDomainController, cmd);
}
catch (Exception)
{
gpoId = null;
throw;
}
return gpoId;
}
private string GetPolicyId(Runspace runspace, string gpoName)
{
string gpoId = null;
try
{
Command cmd = new Command("Get-GPO");
cmd.Parameters.Add("Name", gpoName);
Collection<PSObject> result = ExecuteRemoteShellCommand(runspace, PrimaryDomainController, cmd);
if (result != null && result.Count > 0)
{
PSObject gpo = result[0];
gpoId = ((Guid)GetPSObjectProperty(gpo, "Id")).ToString("B");
}
}
catch (Exception)
{
gpoId = null;
throw;
}
return gpoId;
}
#endregion
#region Shadow Session
public void ShadowSession(string sessionId, bool control)
{
Runspace runspace = null;
try
{
runspace = OpenRunspace();
var scripts = new List<string>
{
string.Format("mstsc /Shadow:{0}{1}", sessionId, control ? " /Control" : "")
};
object[] errors = null;
ExecuteShellCommand(runspace, scripts, out errors);
}
finally
{
CloseRunspace(runspace);
}
}
#endregion
#region RDS Help Desk
private string GetHelpDeskGroupPath(string groupName)
{
StringBuilder sb = new StringBuilder();
AppendProtocol(sb);
AppendDomainController(sb);
AppendCNPath(sb, groupName);
AppendOUPath(sb, RootOU);
AppendDomainPath(sb, RootDomain);
return sb.ToString();
}
private void CheckOrCreateHelpDeskComputerGroup()
{
if (!ActiveDirectoryUtils.AdObjectExists(GetHelpDeskGroupPath(RDSHelpDeskComputerGroup)))
{
ActiveDirectoryUtils.CreateGroup(GetRootOUPath(), RDSHelpDeskComputerGroup);
}
}
private string CheckOrCreateAdGroup(string groupPath, string rootPath, string groupName, string description)
{
DirectoryEntry groupEntry = null;
if (!ActiveDirectoryUtils.AdObjectExists(groupPath))
{
ActiveDirectoryUtils.CreateGroup(rootPath, groupName);
groupEntry = ActiveDirectoryUtils.GetADObject(groupPath);
if (groupEntry.Properties.Contains("Description"))
{
groupEntry.Properties["Description"][0] = description;
}
else
{
groupEntry.Properties["Description"].Add(description);
}
groupEntry.CommitChanges();
}
if (groupEntry == null)
{
groupEntry = ActiveDirectoryUtils.GetADObject(groupPath);
}
return ActiveDirectoryUtils.GetADObjectProperty(groupEntry, "sAMAccountName").ToString();
}
private void AddAdGroupToLocalAdmins(Runspace runspace, string hostName, string samAccountName)
{
var scripts = new List<string>
{
string.Format("$GroupObj = [ADSI]\"WinNT://{0}/{1}\"", hostName, LocalAdministratorsGroupName),
string.Format("$GroupObj.Add(\"WinNT://{0}/{1}\")", ServerSettings.ADRootDomain, samAccountName)
};
object[] errors = null;
ExecuteRemoteShellCommand(runspace, hostName, scripts, out errors);
}
#endregion
#region SSL
public void InstallCertificate(byte[] certificate, string password, List<string> hostNames)
{
Runspace runspace = null;
try
{
var guid = Guid.NewGuid();
var x509Cert = new X509Certificate2(certificate, password, X509KeyStorageFlags.Exportable);
var filePath = SaveCertificate(certificate, guid);
runspace = OpenRunspace();
foreach (var hostName in hostNames)
{
var destinationPath = string.Format("\\\\{0}\\c$\\{1}.pfx", hostName, guid);
var errors = CopyCertificateFile(runspace, filePath, destinationPath);
if (!errors.Any())
{
RemoveCertificate(runspace, hostName, x509Cert.Thumbprint);
errors = ImportCertificate(runspace, hostName, password, string.Format("c:\\{0}.pfx", guid), x509Cert.Thumbprint);
}
DeleteCertificateFile(destinationPath, runspace);
if (errors.Any())
{
Log.WriteWarning(string.Join("\r\n", errors.Select(e => e.ToString()).ToArray()));
throw new Exception(string.Join("\r\n", errors.Select(e => e.ToString()).ToArray()));
}
}
if (File.Exists(filePath))
{
File.Delete(filePath);
}
}
finally
{
CloseRunspace(runspace);
}
}
private void RemoveCertificate(Runspace runspace, string hostName, string thumbprint)
{
var scripts = new List<string>
{
string.Format("Remove-Item -Path cert:\\LocalMachine\\My\\{0}", thumbprint)
};
object[] errors = null;
ExecuteRemoteShellCommand(runspace, hostName, scripts, out errors);
}
private object[] ImportCertificate(Runspace runspace, string hostName, string password, string certificatePath, string thumbprint)
{
var scripts = new List<string>
{
string.Format("$mypwd = ConvertTo-SecureString -String {0} -Force AsPlainText", password),
string.Format("Import-PfxCertificate FilePath \"{0}\" cert:\\localMachine\\my -Password $mypwd", certificatePath),
string.Format("$cert = Get-Item cert:\\LocalMachine\\My\\{0}", thumbprint),
string.Format("$path = (Get-WmiObject -class \"Win32_TSGeneralSetting\" -Namespace root\\cimv2\\terminalservices -Filter \"TerminalName='RDP-tcp'\").__path"),
string.Format("Set-WmiInstance -Path $path -argument @{0}", string.Format("{{SSLCertificateSHA1Hash=\"{0}\"}}", thumbprint))
};
object[] errors = null;
ExecuteRemoteShellCommand(runspace, hostName, scripts, out errors);
return errors;
}
private string SaveCertificate(byte[] certificate, Guid guid)
{
var filePath = string.Format("{0}{1}.pfx", Path.GetTempPath(), guid);
if (File.Exists(filePath))
{
File.Delete(filePath);
}
File.WriteAllBytes(filePath, certificate);
return filePath;
}
private object[] CopyCertificateFile(Runspace runspace, string filePath, string destinationPath)
{
var scripts = new List<string>
{
string.Format("Copy-Item \"{0}\" -Destination \"{1}\" -Force", filePath, destinationPath)
};
object[] errors = null;
ExecuteShellCommand(runspace, scripts, out errors);
return errors;
}
private object[] DeleteCertificateFile(string destinationPath, Runspace runspace)
{
var scripts = new List<string>
{
string.Format("Remove-Item -Path \"{0}\" -Force", destinationPath)
};
object[] errors = null;
ExecuteShellCommand(runspace, scripts, out errors);
return errors;
}
#endregion
#region Import Collection
public ImportedRdsCollection GetExistingCollection(string collectionName)
{
Runspace runspace = null;
ImportedRdsCollection result;
try
{
runspace = OpenRunspace();
var collection = runspace.GetCollection(collectionName, ConnectionBroker, PrimaryDomainController);
result = new ImportedRdsCollection
{
CollectionName = collection.Name,
Description = collection.Description
};
if (collection == null)
{
throw new NullReferenceException(string.Format("Collection \"{0}\" not found", collectionName));
}
object[] errors;
result.CollectionSettings = runspace.GetCollectionSettings(collectionName, ConnectionBroker, PrimaryDomainController, out errors).ToList();
if (errors.Any())
{
throw new Exception(string.Format("Collection not imported:\r\n{0}", string.Join("r\\n\\", errors.Select(e => e.ToString()).ToArray())));
}
result.SessionHosts = runspace.GetSessionHosts(collectionName, ConnectionBroker, PrimaryDomainController, out errors);
if (errors.Any())
{
throw new Exception(string.Format("Collection not imported:\r\n{0}", string.Join("r\\n\\", errors.Select(e => e.ToString()).ToArray())));
}
result.UserGroups = runspace.GetCollectionUserGroups(collectionName, ConnectionBroker, PrimaryDomainController, out errors).ToList();
if (errors.Any())
{
throw new Exception(string.Format("Collection not imported:\r\n{0}", string.Join("r\\n\\", errors.Select(e => e.ToString()).ToArray())));
}
}
finally
{
CloseRunspace(runspace);
}
return result;
}
public void ImportCollection(string organizationId, RdsCollection collection, List<string> users)
{
Runspace runSpace = null;
try
{
runSpace = OpenRunspace();
var orgPath = GetOrganizationPath(organizationId);
CheckOrCreateAdGroup(GetComputerGroupPath(organizationId, collection.Name), orgPath, GetComputersGroupName(collection.Name), RdsCollectionComputersGroupDescription);
CheckOrCreateHelpDeskComputerGroup();
string helpDeskGroupSamAccountName = CheckOrCreateAdGroup(GetHelpDeskGroupPath(RDSHelpDeskGroup), GetRootOUPath(), RDSHelpDeskGroup, RDSHelpDeskGroupDescription);
string groupName = GetLocalAdminsGroupName(collection.Name);
string groupPath = GetGroupPath(organizationId, collection.Name, groupName);
string localAdminsGroupSamAccountName = CheckOrCreateAdGroup(groupPath, GetOrganizationPath(organizationId), groupName, WspAdministratorsGroupDescription);
CheckOrCreateAdGroup(GetUsersGroupPath(organizationId, collection.Name), orgPath, GetUsersGroupName(collection.Name), RdsCollectionUsersGroupDescription);
var capPolicyName = GetPolicyName(organizationId, collection.Name, RdsPolicyTypes.RdCap);
var rapPolicyName = GetPolicyName(organizationId, collection.Name, RdsPolicyTypes.RdRap);
foreach (var gateway in Gateways)
{
CreateHelpDeskRdCapForce(runSpace, gateway);
CreateHelpDeskRdRapForce(runSpace, gateway);
if (!CentralNps)
{
CreateRdCapForce(runSpace, gateway, capPolicyName, collection.Name, new List<string> { GetUsersGroupName(collection.Name) });
}
CreateRdRapForce(runSpace, gateway, rapPolicyName, collection.Name, new List<string> { GetUsersGroupName(collection.Name) });
}
if (CentralNps)
{
CreateCentralNpsPolicy(runSpace, CentralNpsHost, capPolicyName, collection.Name, organizationId);
}
//add user group to collection
AddUserGroupsToCollection(runSpace, collection.Name, new List<string> { GetUsersGroupName(collection.Name) });
//add session servers to group
foreach (var rdsServer in collection.Servers)
{
MoveSessionHostToCollectionOU(rdsServer.Name, collection.Name, organizationId);
AddAdGroupToLocalAdmins(runSpace, rdsServer.FqdName, helpDeskGroupSamAccountName);
AddAdGroupToLocalAdmins(runSpace, rdsServer.FqdName, localAdminsGroupSamAccountName);
AddComputerToCollectionAdComputerGroup(organizationId, collection.Name, rdsServer);
}
string collectionComputersPath = GetComputerGroupPath(organizationId, collection.Name);
CreatePolicy(runSpace, organizationId, string.Format("{0}-administrators", collection.Name),
new DirectoryEntry(GetGroupPath(organizationId, collection.Name, GetLocalAdminsGroupName(collection.Name))), new DirectoryEntry(collectionComputersPath), collection.Name);
CreatePolicy(runSpace, organizationId, string.Format("{0}-users", collection.Name), new DirectoryEntry(GetUsersGroupPath(organizationId, collection.Name))
, new DirectoryEntry(collectionComputersPath), collection.Name);
CreateHelpDeskPolicy(runSpace, new DirectoryEntry(GetHelpDeskGroupPath(RDSHelpDeskGroup)), new DirectoryEntry(collectionComputersPath), organizationId, collection.Name);
SetUsersInCollection(organizationId, collection.Name, users);
}
finally
{
CloseRunspace(runSpace);
}
}
#endregion
private void AddRdsServerToDeployment(Runspace runSpace, RdsServer server)
{
Command cmd = new Command("Add-RDserver");
cmd.Parameters.Add("Server", server.FqdName);
cmd.Parameters.Add("Role", "RDS-RD-SERVER");
cmd.Parameters.Add("ConnectionBroker", ConnectionBroker);
ExecuteShellCommand(runSpace, cmd, false);
}
private bool ExistRdsServerInDeployment(Runspace runSpace, RdsServer server)
{
Command cmd = new Command("Get-RDserver");
cmd.Parameters.Add("Role", "RDS-RD-SERVER");
cmd.Parameters.Add("ConnectionBroker", ConnectionBroker);
var serversPs = ExecuteShellCommand(runSpace, cmd, false);
if (serversPs != null)
{
foreach (var serverPs in serversPs)
{
var serverName = Convert.ToString( GetPSObjectProperty(serverPs, "Server"));
if (string.Compare(serverName, server.FqdName, StringComparison.InvariantCultureIgnoreCase) == 0)
{
return true;
}
}
}
return false;
}
private void SetUsersToCollectionAdGroup(string collectionName, string organizationId, IEnumerable<string> users, string groupName, string groupPath)
{
var orgPath = GetOrganizationPath(organizationId);
var orgEntry = ActiveDirectoryUtils.GetADObject(orgPath);
var groupUsers = ActiveDirectoryUtils.GetGroupObjects(groupName, "user", orgEntry);
foreach (string userPath in groupUsers)
{
ActiveDirectoryUtils.RemoveObjectFromGroup(userPath, groupPath);
}
foreach (var user in users)
{
var userPath = GetUserPath(organizationId, user);
if (ActiveDirectoryUtils.AdObjectExists(userPath))
{
var userObject = ActiveDirectoryUtils.GetADObject(userPath);
var samName = (string)ActiveDirectoryUtils.GetADObjectProperty(userObject, "sAMAccountName");
ActiveDirectoryUtils.AddObjectToGroup(userPath, groupPath);
}
}
}
private List<string> GetUsersToCollectionAdGroup(string collectionName, string groupName, string organizationId)
{
var users = new List<string>();
var orgPath = GetOrganizationPath(organizationId);
var orgEntry = ActiveDirectoryUtils.GetADObject(orgPath);
foreach (string userPath in ActiveDirectoryUtils.GetGroupObjects(groupName, "user", orgEntry))
{
var userObject = ActiveDirectoryUtils.GetADObject(userPath);
var samName = (string)ActiveDirectoryUtils.GetADObjectProperty(userObject, "sAMAccountName");
users.Add(samName);
}
return users;
}
private void AddUserGroupsToCollection(Runspace runSpace, string collectionName, List<string> groups)
{
Command cmd = new Command("Set-RDSessionCollectionConfiguration");
cmd.Parameters.Add("CollectionName", collectionName);
cmd.Parameters.Add("UserGroup", groups);
cmd.Parameters.Add("ConnectionBroker", ConnectionBroker);
ExecuteShellCommand(runSpace, cmd, false).FirstOrDefault();
}
private void AddComputerToCollectionAdComputerGroup(string organizationId, string collectionName, RdsServer server)
{
var computerGroupName = GetComputersGroupName( collectionName);
var computerObject = GetComputerObject(server.Name);
if (computerObject != null)
{
var samName = (string)ActiveDirectoryUtils.GetADObjectProperty(computerObject, "sAMAccountName");
if (!ActiveDirectoryUtils.IsComputerInGroup(samName, computerGroupName))
{
ActiveDirectoryUtils.AddObjectToGroup(computerObject.Path, GetComputerGroupPath(organizationId, collectionName));
}
if (!ActiveDirectoryUtils.IsComputerInGroup(samName, RDSHelpDeskComputerGroup))
{
ActiveDirectoryUtils.AddObjectToGroup(computerObject.Path, GetHelpDeskGroupPath(RDSHelpDeskComputerGroup));
}
}
SetRDServerNewConnectionAllowed(false, server);
}
private void RemoveComputerFromCollectionAdComputerGroup(string organizationId, string collectionName, RdsServer server)
{
var computerGroupName = GetComputersGroupName(collectionName);
var computerObject = GetComputerObject(server.Name);
if (computerObject != null)
{
var samName = (string)ActiveDirectoryUtils.GetADObjectProperty(computerObject, "sAMAccountName");
if (ActiveDirectoryUtils.IsComputerInGroup(samName, computerGroupName))
{
ActiveDirectoryUtils.RemoveObjectFromGroup(computerObject.Path, GetComputerGroupPath(organizationId, collectionName));
}
if (ActiveDirectoryUtils.AdObjectExists(GetHelpDeskGroupPath(RDSHelpDeskComputerGroup)))
{
if (ActiveDirectoryUtils.IsComputerInGroup(samName, RDSHelpDeskComputerGroup))
{
ActiveDirectoryUtils.RemoveObjectFromGroup(computerObject.Path, GetHelpDeskGroupPath(RDSHelpDeskComputerGroup));
}
}
}
}
public bool AddSessionHostFeatureToServer(string hostName)
{
bool installationResult = false;
Runspace runSpace = null;
try
{
runSpace = OpenRunspace();
var feature = AddFeature(runSpace, hostName, "RDS-RD-Server", true, true);
installationResult = (bool)GetPSObjectProperty(feature, "Success");
if (!IsFeatureInstalled(hostName, "Desktop-Experience", runSpace))
{
feature = AddFeature(runSpace, hostName, "Desktop-Experience", true, false);
}
if (!IsFeatureInstalled(hostName, "NET-Framework-Core", runSpace))
{
feature = AddFeature(runSpace, hostName, "NET-Framework-Core", true, false);
}
}
finally
{
CloseRunspace(runSpace);
}
return installationResult;
}
private void CheckOrCreateComputersRoot(string computersRootPath)
{
if (ActiveDirectoryUtils.AdObjectExists(computersRootPath) && !ActiveDirectoryUtils.AdObjectExists(GetRdsServersGroupPath()))
{
//ActiveDirectoryUtils.CreateGroup(computersRootPath, RdsServersRootOU);
ActiveDirectoryUtils.CreateOrganizationalUnit(RdsServersRootOU, computersRootPath);
}
}
public void MoveSessionHostToRdsOU(string hostName)
{
if (!string.IsNullOrEmpty(ComputersRootOU))
{
CheckOrCreateComputersRoot(GetComputersRootPath());
}
var computerObject = GetComputerObject(hostName);
if (computerObject != null)
{
var samName = (string)ActiveDirectoryUtils.GetADObjectProperty(computerObject, "sAMAccountName");
if (!ActiveDirectoryUtils.IsComputerInGroup(samName, RdsServersRootOU))
{
DirectoryEntry group = new DirectoryEntry(GetRdsServersGroupPath());
computerObject.MoveTo(group);
}
}
}
public void MoveSessionHostToCollectionOU(string hostName, string collectionName, string organizationId)
{
if (!string.IsNullOrEmpty(ComputersRootOU))
{
CheckOrCreateComputersRoot(GetComputersRootPath());
}
var computerObject = GetComputerObject(hostName);
string collectionOUName = string.Format("{0}-OU", collectionName);
string collectionOUPath = GetCollectionOUPath(organizationId, collectionOUName);
if (!ActiveDirectoryUtils.AdObjectExists(collectionOUPath))
{
ActiveDirectoryUtils.CreateOrganizationalUnit(collectionOUName, GetOrganizationPath(organizationId));
}
if (computerObject != null)
{
var samName = (string)ActiveDirectoryUtils.GetADObjectProperty(computerObject, "sAMAccountName");
if (!ActiveDirectoryUtils.IsComputerInGroup(samName, collectionOUName))
{
DirectoryEntry group = new DirectoryEntry(collectionOUPath);
computerObject.MoveTo(group);
}
}
}
public void MoveRdsServerToTenantOU(string hostName, string organizationId)
{
var tenantComputerGroupPath = GetTenantComputerGroupPath(organizationId);
if (!ActiveDirectoryUtils.AdObjectExists(tenantComputerGroupPath))
{
ActiveDirectoryUtils.CreateOrganizationalUnit(RdsServersOU, GetOrganizationPath(organizationId));
}
hostName = hostName.ToLower().Replace(string.Format(".{0}", ServerSettings.ADRootDomain.ToLower()), "");
var rootComputerPath = GetRdsServerPath(hostName);
var tenantComputerPath = GetTenantComputerPath(hostName, organizationId);
if (!string.IsNullOrEmpty(ComputersRootOU))
{
CheckOrCreateComputersRoot(GetComputersRootPath());
}
var computerObject = GetComputerObject(hostName);
if (computerObject != null)
{
var samName = (string)ActiveDirectoryUtils.GetADObjectProperty(computerObject, "sAMAccountName");
if (!ActiveDirectoryUtils.IsComputerInGroup(samName, RdsServersOU))
{
DirectoryEntry group = new DirectoryEntry(tenantComputerGroupPath);
computerObject.MoveTo(group);
}
}
}
public void RemoveRdsServerFromTenantOU(string hostName, string organizationId)
{
var tenantComputerGroupPath = GetTenantComputerGroupPath(organizationId);
hostName = hostName.ToLower().Replace(string.Format(".{0}", ServerSettings.ADRootDomain.ToLower()), "");
if (!string.IsNullOrEmpty(ComputersRootOU))
{
CheckOrCreateComputersRoot(GetComputersRootPath());
}
if (!ActiveDirectoryUtils.AdObjectExists(tenantComputerGroupPath))
{
ActiveDirectoryUtils.CreateOrganizationalUnit(RdsServersOU, GetOrganizationPath(organizationId));
}
var computerObject = GetComputerObject(hostName);
if (computerObject != null)
{
var samName = (string)ActiveDirectoryUtils.GetADObjectProperty(computerObject, "sAMAccountName");
if (ActiveDirectoryUtils.AdObjectExists(GetComputersRootPath()) && !string.IsNullOrEmpty(ComputersRootOU) && !ActiveDirectoryUtils.IsComputerInGroup(samName, RdsServersRootOU))
{
DirectoryEntry group = new DirectoryEntry(GetRdsServersGroupPath());
computerObject.MoveTo(group);
}
}
}
public bool CheckSessionHostFeatureInstallation(string hostName)
{
bool isInstalled = false;
Runspace runSpace = null;
try
{
runSpace = OpenRunspace();
Command cmd = new Command("Get-WindowsFeature");
cmd.Parameters.Add("Name", "RDS-RD-Server");
var feature = ExecuteRemoteShellCommand(runSpace, hostName, cmd).FirstOrDefault();
if (feature != null)
{
isInstalled = (bool) GetPSObjectProperty(feature, "Installed");
}
}
finally
{
CloseRunspace(runSpace);
}
return isInstalled;
}
public bool CheckServerAvailability(string hostName)
{
var ping = new Ping();
var ipAddress = GetServerIp(hostName);
var reply = ping.Send(ipAddress, 3000);
return reply != null && reply.Status == IPStatus.Success;
}
#region Helpers
private static string ConvertByteToStringSid(Byte[] sidBytes)
{
StringBuilder strSid = new StringBuilder();
strSid.Append("S-");
try
{
// Add SID revision.
strSid.Append(sidBytes[0].ToString());
// Next six bytes are SID authority value.
if (sidBytes[6] != 0 || sidBytes[5] != 0)
{
string strAuth = String.Format
("0x{0:2x}{1:2x}{2:2x}{3:2x}{4:2x}{5:2x}",
(Int16)sidBytes[1],
(Int16)sidBytes[2],
(Int16)sidBytes[3],
(Int16)sidBytes[4],
(Int16)sidBytes[5],
(Int16)sidBytes[6]);
strSid.Append("-");
strSid.Append(strAuth);
}
else
{
Int64 iVal = (Int32)(sidBytes[1]) +
(Int32)(sidBytes[2] << 8) +
(Int32)(sidBytes[3] << 16) +
(Int32)(sidBytes[4] << 24);
strSid.Append("-");
strSid.Append(iVal.ToString());
}
// Get sub authority count...
int iSubCount = Convert.ToInt32(sidBytes[7]);
int idxAuth = 0;
for (int i = 0; i < iSubCount; i++)
{
idxAuth = 8 + i * 4;
UInt32 iSubAuth = BitConverter.ToUInt32(sidBytes, idxAuth);
strSid.Append("-");
strSid.Append(iSubAuth.ToString());
}
}
catch
{
return "";
}
return strSid.ToString();
}
private StartMenuApp CreateStartMenuAppFromPsObject(PSObject psObject)
{
var remoteApp = new StartMenuApp
{
DisplayName = Convert.ToString(GetPSObjectProperty(psObject, "DisplayName")),
FilePath = Convert.ToString(GetPSObjectProperty(psObject, "FilePath")),
FileVirtualPath = Convert.ToString(GetPSObjectProperty(psObject, "FileVirtualPath"))
};
remoteApp.Alias = remoteApp.DisplayName;
return remoteApp;
}
private RemoteApplication CreateRemoteApplicationFromPsObject(PSObject psObject)
{
var remoteApp = new RemoteApplication
{
DisplayName = Convert.ToString(GetPSObjectProperty(psObject, "DisplayName")),
FilePath = Convert.ToString(GetPSObjectProperty(psObject, "FilePath")),
Alias = Convert.ToString(GetPSObjectProperty(psObject, "Alias")),
ShowInWebAccess = Convert.ToBoolean(GetPSObjectProperty(psObject, "ShowInWebAccess")),
Users = null
};
var requiredCommandLine = GetPSObjectProperty(psObject, "RequiredCommandLine");
remoteApp.RequiredCommandLine = requiredCommandLine == null ? null : requiredCommandLine.ToString();
var users = (string[])(GetPSObjectProperty(psObject, "UserGroups"));
if (users != null && users.Any())
{
remoteApp.Users = users;
}
else
{
remoteApp.Users = null;
}
return remoteApp;
}
internal IPAddress GetServerIp(string hostname, AddressFamily addressFamily = AddressFamily.InterNetwork)
{
var address = GetServerIps(hostname);
return address.FirstOrDefault(x => x.AddressFamily == addressFamily);
}
internal IEnumerable<IPAddress> GetServerIps(string hostname)
{
var address = Dns.GetHostAddresses(hostname);
return address;
}
internal void RemoveItem(Runspace runSpace, string path)
{
Command rdRapCommand = new Command("Remove-Item");
rdRapCommand.Parameters.Add("Path", path);
rdRapCommand.Parameters.Add("Force", true);
rdRapCommand.Parameters.Add("Recurse", true);
ExecuteShellCommand(runSpace, rdRapCommand, false);
}
internal void RemoveItemRemote(Runspace runSpace, string hostname, string path, params string[] imports)
{
Command rdRapCommand = new Command("Remove-Item");
rdRapCommand.Parameters.Add("Path", string.Format("\"{0}\"", path));
rdRapCommand.Parameters.Add("Force", "");
rdRapCommand.Parameters.Add("Recurse", "");
ExecuteRemoteShellCommand(runSpace, hostname, rdRapCommand, imports);
}
private string GetPolicyName(string organizationId, string collectionName, RdsPolicyTypes policyType)
{
string policyName = string.Format("{0}-", collectionName);
switch (policyType)
{
case RdsPolicyTypes.RdCap:
{
policyName += "RDCAP";
break;
}
case RdsPolicyTypes.RdRap:
{
policyName += "RDRAP";
break;
}
}
return policyName;
}
private string GetComputersGroupName(string collectionName)
{
return string.Format(RdsGroupFormat, collectionName, Computers.ToLowerInvariant());
}
private string GetUsersGroupName(string collectionName)
{
return string.Format(RdsGroupFormat, collectionName, Users.ToLowerInvariant());
}
private string GetLocalAdminsGroupName(string collectionName)
{
return string.Format(RdsGroupFormat, collectionName, Admins.ToLowerInvariant());
}
internal string GetComputerGroupPath(string organizationId, string collection)
{
StringBuilder sb = new StringBuilder();
AppendProtocol(sb);
AppendDomainController(sb);
AppendCNPath(sb, GetComputersGroupName(collection));
AppendOUPath(sb, organizationId);
AppendOUPath(sb, RootOU);
AppendDomainPath(sb, RootDomain);
return sb.ToString();
}
internal string GetUsersGroupPath(string organizationId, string collection)
{
StringBuilder sb = new StringBuilder();
AppendProtocol(sb);
AppendDomainController(sb);
AppendCNPath(sb, GetUsersGroupName(collection));
AppendOUPath(sb, organizationId);
AppendOUPath(sb, RootOU);
AppendDomainPath(sb, RootDomain);
return sb.ToString();
}
private string GetGroupPath(string organizationId, string collectionName, string groupName)
{
StringBuilder sb = new StringBuilder();
AppendProtocol(sb);
AppendDomainController(sb);
AppendCNPath(sb, groupName);
AppendOUPath(sb, organizationId);
AppendOUPath(sb, RootOU);
AppendDomainPath(sb, RootDomain);
return sb.ToString();
}
private string GetCollectionOUPath(string organizationId, string collectionName)
{
StringBuilder sb = new StringBuilder();
AppendProtocol(sb);
AppendDomainController(sb);
AppendOUPath(sb, collectionName);
AppendOUPath(sb, organizationId);
AppendOUPath(sb, RootOU);
AppendDomainPath(sb, RootDomain);
return sb.ToString();
}
private string GetUserPath(string organizationId, string loginName)
{
StringBuilder sb = new StringBuilder();
// append provider
AppendProtocol(sb);
AppendDomainController(sb);
AppendCNPath(sb, loginName);
AppendOUPath(sb, organizationId);
AppendOUPath(sb, RootOU);
AppendDomainPath(sb, RootDomain);
return sb.ToString();
}
private string GetRootOUPath()
{
StringBuilder sb = new StringBuilder();
// append provider
AppendProtocol(sb);
AppendDomainController(sb);
AppendOUPath(sb, RootOU);
AppendDomainPath(sb, RootDomain);
return sb.ToString();
}
private string GetOrganizationPath(string organizationId)
{
StringBuilder sb = new StringBuilder();
// append provider
AppendProtocol(sb);
AppendDomainController(sb);
AppendOUPath(sb, organizationId);
AppendOUPath(sb, RootOU);
AppendDomainPath(sb, RootDomain);
return sb.ToString();
}
private DirectoryEntry GetComputerObject(string computerName)
{
DirectorySearcher deSearch = new DirectorySearcher
{
Filter = string.Format("(&(objectCategory=computer)(name={0}))", computerName)
};
SearchResult results = deSearch.FindOne();
return results.GetDirectoryEntry();
}
private string GetTenantComputerPath(string objName, string organizationId)
{
StringBuilder sb = new StringBuilder();
AppendProtocol(sb);
AppendDomainController(sb);
AppendCNPath(sb, objName);
AppendOUPath(sb, RdsServersOU);
AppendOUPath(sb, organizationId);
AppendOUPath(sb, RootOU);
AppendDomainPath(sb, RootDomain);
return sb.ToString();
}
private string GetComputersRootPath()
{
StringBuilder sb = new StringBuilder();
AppendProtocol(sb);
AppendDomainController(sb);
AppendOUPath(sb, ComputersRootOU);
AppendDomainPath(sb, RootDomain);
return sb.ToString();
}
private string GetRdsServersGroupPath()
{
StringBuilder sb = new StringBuilder();
AppendProtocol(sb);
AppendDomainController(sb);
AppendOUPath(sb, RdsServersRootOU);
AppendOUPath(sb, ComputersRootOU);
AppendDomainPath(sb, RootDomain);
return sb.ToString();
}
private string GetRdsServerPath(string name)
{
StringBuilder sb = new StringBuilder();
AppendProtocol(sb);
AppendDomainController(sb);
AppendCNPath(sb, name);
AppendOUPath(sb, RdsServersRootOU);
AppendOUPath(sb, ComputersRootOU);
AppendDomainPath(sb, RootDomain);
return sb.ToString();
}
private string GetRootPath()
{
StringBuilder sb = new StringBuilder();
AppendProtocol(sb);
AppendDomainController(sb);
AppendDomainPath(sb, RootDomain);
return sb.ToString();
}
internal string GetTenantComputerGroupPath(string organizationId)
{
StringBuilder sb = new StringBuilder();
AppendProtocol(sb);
AppendDomainController(sb);
AppendOUPath(sb, RdsServersOU);
AppendOUPath(sb, organizationId);
AppendOUPath(sb, RootOU);
AppendDomainPath(sb, RootDomain);
return sb.ToString();
}
private static void AppendCNPath(StringBuilder sb, string organizationId)
{
if (string.IsNullOrEmpty(organizationId))
return;
sb.Append("CN=").Append(organizationId).Append(",");
}
private void AppendDomainController(StringBuilder sb)
{
sb.Append(PrimaryDomainController + "/");
}
private static void AppendProtocol(StringBuilder sb)
{
sb.Append("LDAP://");
}
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(",");
}
}
#endregion
#region Windows Feature PowerShell
internal bool IsFeatureInstalled(string featureName, Runspace runSpace)
{
bool isInstalled = false;
Command cmd = new Command("Get-WindowsFeature");
cmd.Parameters.Add("Name", featureName);
var feature = ExecuteShellCommand(runSpace, cmd, false).FirstOrDefault();
if (feature != null)
{
isInstalled = (bool)GetPSObjectProperty(feature, "Installed");
}
return isInstalled;
}
internal bool IsFeatureInstalled(string hostName, string featureName, Runspace runSpace)
{
bool isInstalled = false;
Command cmd = new Command("Get-WindowsFeature");
cmd.Parameters.Add("Name", featureName);
var feature = ExecuteRemoteShellCommand(runSpace, hostName, cmd).FirstOrDefault();
if (feature != null)
{
isInstalled = (bool) GetPSObjectProperty(feature, "Installed");
}
return isInstalled;
}
internal PSObject AddFeature(Runspace runSpace, string featureName, bool includeAllSubFeature = true, bool restart = false)
{
Command cmd = new Command("Add-WindowsFeature");
cmd.Parameters.Add("Name", featureName);
if (includeAllSubFeature)
{
cmd.Parameters.Add("IncludeAllSubFeature", true);
}
if (restart)
{
cmd.Parameters.Add("Restart", true);
}
return ExecuteShellCommand(runSpace, cmd, false).FirstOrDefault();
}
internal PSObject AddFeature(Runspace runSpace, string hostName, string featureName, bool includeAllSubFeature = true, bool restart = false)
{
Command cmd = new Command("Add-WindowsFeature");
cmd.Parameters.Add("Name", featureName);
if (includeAllSubFeature)
{
cmd.Parameters.Add("IncludeAllSubFeature", "");
}
if (restart)
{
cmd.Parameters.Add("Restart", "");
}
return ExecuteRemoteShellCommand(runSpace, hostName, cmd).FirstOrDefault();
}
#endregion
#region PowerShell integration
private static InitialSessionState session = null;
internal virtual Runspace OpenRunspace()
{
Log.WriteStart("OpenRunspace");
if (session == null)
{
session = InitialSessionState.CreateDefault();
session.ImportPSModule(new string[] { "ServerManager", "RemoteDesktop", "RemoteDesktopServices" });
}
Runspace runSpace = RunspaceFactory.CreateRunspace(session);
//
runSpace.Open();
//
runSpace.SessionStateProxy.SetVariable("ConfirmPreference", "none");
Log.WriteEnd("OpenRunspace");
return runSpace;
}
internal void CloseRunspace(Runspace runspace)
{
try
{
if (runspace != null && runspace.RunspaceStateInfo.State == RunspaceState.Opened)
{
runspace.Close();
}
}
catch (Exception ex)
{
Log.WriteError("Runspace error", ex);
}
}
internal Collection<PSObject> ExecuteRemoteShellCommand(Runspace runSpace, string hostName, Command cmd, params string[] moduleImports)
{
object[] errors;
return ExecuteRemoteShellCommand(runSpace, hostName, cmd, out errors, moduleImports);
}
internal Collection<PSObject> ExecuteRemoteShellCommand(Runspace runSpace, string hostName, Command cmd, out object[] errors, params string[] moduleImports)
{
Command invokeCommand = new Command("Invoke-Command");
invokeCommand.Parameters.Add("ComputerName", hostName);
RunspaceInvoke invoke = new RunspaceInvoke();
string commandString = moduleImports.Any() ? string.Format("import-module {0};", string.Join(",", moduleImports)) : string.Empty;
commandString += cmd.CommandText;
if (cmd.Parameters != null && cmd.Parameters.Any())
{
commandString += " " +
string.Join(" ",
cmd.Parameters.Select(x => string.Format("-{0} {1}", x.Name, x.Value)).ToArray());
}
ScriptBlock sb = invoke.Invoke(string.Format("{{{0}}}", commandString))[0].BaseObject as ScriptBlock;
invokeCommand.Parameters.Add("ScriptBlock", sb);
return ExecuteShellCommand(runSpace, invokeCommand, false, out errors);
}
internal Collection<PSObject> ExecuteRemoteShellCommand(Runspace runSpace, string hostName, List<string> scripts, out object[] errors, params string[] moduleImports)
{
Command invokeCommand = new Command("Invoke-Command");
invokeCommand.Parameters.Add("ComputerName", hostName);
RunspaceInvoke invoke = new RunspaceInvoke();
string commandString = moduleImports.Any() ? string.Format("import-module {0};", string.Join(",", moduleImports)) : string.Empty;
commandString = string.Format("{0};{1}", commandString, string.Join(";", scripts.ToArray()));
ScriptBlock sb = invoke.Invoke(string.Format("{{{0}}}", commandString))[0].BaseObject as ScriptBlock;
invokeCommand.Parameters.Add("ScriptBlock", sb);
return ExecuteShellCommand(runSpace, invokeCommand, false, out errors);
}
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, List<string> scripts, out object[] errors)
{
Log.WriteStart("ExecuteShellCommand");
var errorList = new List<object>();
Collection<PSObject> results;
using (Pipeline pipeLine = runspace.CreatePipeline())
{
foreach (string script in scripts)
{
pipeLine.Commands.AddScript(script);
}
results = pipeLine.Invoke();
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);
Log.WriteWarning(errorMessage);
}
}
}
errors = errorList.ToArray();
Log.WriteEnd("ExecuteShellCommand");
return results;
}
internal Collection<PSObject> ExecuteShellCommand(Runspace runSpace, Command cmd, bool useDomainController,
out object[] errors)
{
Log.WriteStart("ExecuteShellCommand");
List<object> errorList = new List<object>();
if (useDomainController)
{
CommandParameter dc = new CommandParameter("DomainController", PrimaryDomainController);
if (!cmd.Parameters.Contains(dc))
{
cmd.Parameters.Add(dc);
}
}
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);
Log.WriteWarning(errorMessage);
}
}
}
pipeLine = null;
errors = errorList.ToArray();
Log.WriteEnd("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)
{
Log.WriteStart("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();
Log.WriteEnd("GetResultObjectIdentity");
return ret;
}
internal string GetResultObjectDN(Collection<PSObject> result)
{
Log.WriteStart("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();
Log.WriteEnd("GetResultObjectDN");
return ret;
}
internal bool ItemExists(Runspace runSpace, string path)
{
Command testPathCommand = new Command("Test-Path");
testPathCommand.Parameters.Add("Path", path);
var testPathResult = ExecuteShellCommand(runSpace, testPathCommand, false).First();
var result = Convert.ToBoolean(testPathResult.ToString());
return result;
}
internal bool ItemExistsRemote(Runspace runSpace, string hostname,string path)
{
Command testPathCommand = new Command("Test-Path");
testPathCommand.Parameters.Add("Path", string.Format("\"{0}\"", path));
var testPathResult = ExecuteRemoteShellCommand(runSpace, hostname, testPathCommand, RdsModuleName).First();
var result = Convert.ToBoolean(testPathResult.ToString());
return result;
}
internal List<string> GetServersExistingInCollections(Runspace runSpace)
{
var existingHosts = new List<string>();
//var scripts = new List<string>();
//scripts.Add(string.Format("$sessions = Get-RDSessionCollection -ConnectionBroker {0}", ConnectionBroker));
//scripts.Add(string.Format("foreach($session in $sessions){{Get-RDSessionHost $session.CollectionName -ConnectionBroker {0}|Select SessionHost}}", ConnectionBroker));
//object[] errors;
//var sessionHosts = ExecuteShellCommand(runSpace, scripts, out errors);
//foreach(var host in sessionHosts)
//{
// var sessionHost = GetPSObjectProperty(host, "SessionHost");
// if (sessionHost != null)
// {
// existingHosts.Add(sessionHost.ToString());
// }
//}
return existingHosts;
}
internal List<string> EditRdsCollectionSettingsInternal(RdsCollection collection, Runspace runspace)
{
object[] errors;
Command cmd = new Command("Set-RDSessionCollectionConfiguration");
cmd.Parameters.Add("CollectionName", collection.Name);
cmd.Parameters.Add("ConnectionBroker", ConnectionBroker);
if (string.IsNullOrEmpty(collection.Settings.ClientDeviceRedirectionOptions))
{
collection.Settings.ClientDeviceRedirectionOptions = "None";
}
var properties = collection.Settings.GetType().GetProperties();
foreach(var prop in properties)
{
if (prop.Name.ToLower() != "id" && prop.Name.ToLower() != "rdscollectionid")
{
var value = prop.GetValue(collection.Settings, null);
if (value != null)
{
cmd.Parameters.Add(prop.Name, value);
}
}
}
ExecuteShellCommand(runspace, cmd, false, out errors);
if (errors != null)
{
return errors.Select(e => e.ToString()).ToList();
}
return new List<string>();
}
internal List<RdsUserSession> GetRdsUserSessionsInternal(string collectionName, Runspace runSpace)
{
var result = new List<RdsUserSession>();
var scripts = new List<string>();
scripts.Add(string.Format("Get-RDUserSession -ConnectionBroker {0} - CollectionName {1} | ft CollectionName, Username, UnifiedSessionId, SessionState, HostServer", ConnectionBroker, collectionName));
object[] errors;
Command cmd = new Command("Get-RDUserSession");
cmd.Parameters.Add("CollectionName", collectionName);
cmd.Parameters.Add("ConnectionBroker", ConnectionBroker);
var userSessions = ExecuteShellCommand(runSpace, cmd, false, out errors);
var properties = typeof(RdsUserSession).GetProperties();
foreach(var userSession in userSessions)
{
var session = new RdsUserSession
{
CollectionName = GetPSObjectProperty(userSession, "CollectionName").ToString(),
DomainName = GetPSObjectProperty(userSession, "DomainName").ToString(),
HostServer = GetPSObjectProperty(userSession, "HostServer").ToString(),
SessionState = GetPSObjectProperty(userSession, "SessionState").ToString(),
UnifiedSessionId = GetPSObjectProperty(userSession, "UnifiedSessionId").ToString(),
SamAccountName = GetPSObjectProperty(userSession, "UserName").ToString(),
};
session.IsVip = false;
session.UserName = GetUserFullName(session.DomainName, session.SamAccountName, runSpace);
result.Add(session);
}
return result;
}
private string GetUserFullName(string domain, string userName, Runspace runspace)
{
Command cmd = new Command("Get-WmiObject");
cmd.Parameters.Add("Class", "win32_useraccount");
cmd.Parameters.Add("Filter", string.Format("Domain = '{0}' AND Name = '{1}'", domain, userName));
var names = ExecuteShellCommand(runspace, cmd, false);
if (names.Any())
{
return names.First().Members["FullName"].Value.ToString();
}
return "";
}
#endregion
#region Server Info
public RdsServerInfo GetRdsServerInfo(string serverName)
{
var result = new RdsServerInfo();
Runspace runspace = null;
try
{
runspace = OpenRunspace();
result = GetServerInfo(runspace, serverName);
result.Status = GetRdsServerStatus(runspace, serverName);
}
finally
{
CloseRunspace(runspace);
}
return result;
}
public string GetRdsServerStatus(string serverName)
{
string result = "";
Runspace runspace = null;
try
{
runspace = OpenRunspace();
result = GetRdsServerStatus(runspace, serverName);
}
finally
{
CloseRunspace(runspace);
}
return result;
}
public void ShutDownRdsServer(string serverName)
{
Runspace runspace = null;
try
{
runspace = OpenRunspace();
var command = new Command("Stop-Computer");
command.Parameters.Add("ComputerName", serverName);
command.Parameters.Add("Force", true);
object[] errors = null;
ExecuteShellCommand(runspace, command, false, out errors);
if (errors.Any())
{
Log.WriteWarning(string.Join("\r\n", errors.Select(e => e.ToString()).ToArray()));
throw new Exception(string.Join("\r\n", errors.Select(e => e.ToString()).ToArray()));
}
}
finally
{
CloseRunspace(runspace);
}
}
public void RestartRdsServer(string serverName)
{
Runspace runspace = null;
try
{
runspace = OpenRunspace();
var command = new Command("Restart-Computer");
command.Parameters.Add("ComputerName", serverName);
command.Parameters.Add("Force", true);
object[] errors = null;
ExecuteShellCommand(runspace, command, false, out errors);
if (errors.Any())
{
Log.WriteWarning(string.Join("\r\n", errors.Select(e => e.ToString()).ToArray()));
throw new Exception(string.Join("\r\n", errors.Select(e => e.ToString()).ToArray()));
}
}
finally
{
CloseRunspace(runspace);
}
}
private RdsServerInfo GetServerInfo(Runspace runspace, string serverName)
{
var result = new RdsServerInfo();
Command cmd = new Command("Get-WmiObject");
cmd.Parameters.Add("Class", "Win32_Processor");
cmd.Parameters.Add("ComputerName", serverName);
object[] errors = null;
var psProcInfo = ExecuteShellCommand(runspace, cmd, false, out errors).First();
if (errors.Any())
{
Log.WriteWarning(string.Join("\r\n", errors.Select(e => e.ToString()).ToArray()));
return result;
}
cmd = new Command("Get-WmiObject");
cmd.Parameters.Add("Class", "Win32_OperatingSystem");
cmd.Parameters.Add("ComputerName", serverName);
var psMemoryInfo = ExecuteShellCommand(runspace, cmd, false, out errors).First();
if (errors.Any())
{
Log.WriteWarning(string.Join("\r\n", errors.Select(e => e.ToString()).ToArray()));
return result;
}
result.NumberOfCores = Convert.ToInt32(GetPSObjectProperty(psProcInfo, "NumberOfCores"));
result.MaxClockSpeed = Convert.ToInt32(GetPSObjectProperty(psProcInfo, "MaxClockSpeed"));
result.LoadPercentage = Convert.ToInt32(GetPSObjectProperty(psProcInfo, "LoadPercentage"));
result.MemoryAllocatedMb = Math.Round(Convert.ToDouble(GetPSObjectProperty(psMemoryInfo, "TotalVisibleMemorySize")) / 1024, 1);
result.FreeMemoryMb = Math.Round(Convert.ToDouble(GetPSObjectProperty(psMemoryInfo, "FreePhysicalMemory")) / 1024, 1);
result.Drives = GetRdsServerDriveInfo(runspace, serverName).ToArray();
return result;
}
private string GetRdsServerStatus (Runspace runspace, string serverName)
{
if (CheckServerAvailability(serverName))
{
if (CheckPendingReboot(runspace, serverName))
{
return "Online - Pending Reboot";
}
return "Online";
}
else
{
return "Unavailable";
}
}
private List<RdsServerDriveInfo> GetRdsServerDriveInfo(Runspace runspace, string serverName)
{
var result = new List<RdsServerDriveInfo>();
Command cmd = new Command("Get-WmiObject");
cmd.Parameters.Add("Class", "Win32_LogicalDisk");
cmd.Parameters.Add("Filter", "DriveType=3");
cmd.Parameters.Add("ComputerName", serverName);
object[] errors = null;
var psDrives = ExecuteShellCommand(runspace, cmd, false, out errors);
if (errors.Any())
{
Log.WriteWarning(string.Join("\r\n", errors.Select(e => e.ToString()).ToArray()));
return result;
}
foreach (var psDrive in psDrives)
{
var driveInfo = new RdsServerDriveInfo()
{
VolumeName = GetPSObjectProperty(psDrive, "VolumeName").ToString(),
DeviceId = GetPSObjectProperty(psDrive, "DeviceId").ToString(),
SizeMb = Math.Round(Convert.ToDouble(GetPSObjectProperty(psDrive, "Size"))/1024/1024, 1),
FreeSpaceMb = Math.Round(Convert.ToDouble(GetPSObjectProperty(psDrive, "FreeSpace"))/1024/1024, 1)
};
result.Add(driveInfo);
}
return result;
}
private bool CheckRDSServerAvaliability(string serverName)
{
var ping = new Ping();
var reply = ping.Send(serverName, 1000);
if (reply.Status == IPStatus.Success)
{
return true;
}
return false;
}
private bool CheckPendingReboot(Runspace runspace, string serverName)
{
if (CheckPendingReboot(runspace, serverName, @"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing", "RebootPending"))
{
return true;
}
if (CheckPendingReboot(runspace, serverName, @"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update", "RebootRequired"))
{
return true;
}
if (CheckPendingReboot(runspace, serverName, @"HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager", "PendingFileRenameOperations"))
{
return true;
}
return false;
}
private bool CheckPendingReboot(Runspace runspace, string serverName, string registryPath, string registryKey)
{
Command cmd = new Command("Get-ItemProperty");
cmd.Parameters.Add("Path", registryPath);
cmd.Parameters.Add("Name", registryKey);
cmd.Parameters.Add("ErrorAction", "SilentlyContinue");
var feature = ExecuteRemoteShellCommand(runspace, serverName, cmd).FirstOrDefault();
if (feature != null)
{
return true;
}
return false;
}
#endregion
}
}