C# Remote Powershell Packet Privacy Problem

  • Thread starter Thread starter ThePenguinMaster
  • Start date Start date
T

ThePenguinMaster

Guest
I typically dont resort to asking questions on forums, but I am stumped with this problem.

I am trying to make a c# application that can change the number of desktops in an RDS pool. This works great from power-shell using the Add-RDVirtualDesktopToCollection command.

For those who do not know, this will create a new desktop in an RDS pool on windows server 2012. The power-shell command is as follows:



Add-RDVirtualDesktopToCollection -ConnectionBroker "cb.mydomain.com" -CollectionName "Desktop pool" -VirtualDesktopAllocation @{"hyperv1.mydomain.com"=1;}


This will add a single VM to the hyperv1 server. And now we get to the root of the problem and how it relates to C#. The problem is that this command uses the WMI namespace "root\cimv2\rdms" which requires packet privacy. In my c# application, I create a remote run-space, and power-shell object, then run his command.

I then receive an error:


Get-RDPersonalVirtualDesktopAssignment : A Remote Desktop Services deployment does not exist on cb.mydomain.com.
This operation can be performed after creating a deployment. For information about creating a deployment, run
"Get-Help Set-VDIDeployment" or "Get-Help Set-RDSHDeployment".
At line:1 char:1
+ Get-RDPersonalVirtualDesktopAssignment -ConnectionBroker "cb.mydomain.com" - ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Get-RDPersonalVirtualDesktopAssignment

This is due to the fact hat the namespace requires packet privacy to use the WMI namespace that the command accesses. This is verified by an event log message on the

Log Name: Application
Source: Microsoft-Windows-WMI
Date: 3/3/2013 1:20:05 PM
Event ID: 5605
Task Category: None
Level: Information
Keywords:
User: SYSTEM
Computer: ***********
Description:
The root\cimv2\rdms namespace is marked with the RequiresEncryption flag. Access to this namespace might be denied if the script or application does not have the appropriate authentication level. Change the authentication level to Pkt_Privacy and run the script or application again.
Event Xml:
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event
<System>
<Provider Name="Microsoft-Windows-WMI" Guid="{1EDEEE53-0AFE-4609-B846-D8C0B2075B1F}" />
<EventID>5605</EventID>
<Version>2</Version>
<Level>4</Level>
<Task>0</Task>
<Opcode>0</Opcode>
<Keywords>0x8000000000000000</Keywords>
<TimeCreated SystemTime="2013-03-03T18:20:05.288197500Z" />
<EventRecordID>587869</EventRecordID>
<Correlation ActivityID="{33C321D8-B3BE-0000-EC5B-1E34BEB3CD01}" />
<Execution ProcessID="820" ThreadID="3004" />
<Channel>Application</Channel>
<Computer>************</Computer>
<Security UserID="S******" />
</System>
<UserData>
<data_0x8000003F xmlns="http://manifests.microsoft.com/win/2006/windows/WMI
<Namespace>root\cimv2\rdms</Namespace>
</data_0x8000003F>
</UserData>
</Event>


As you can see, the power-shell command cannot function without the packet privacy. Now to the C#. In my program, I specify credentials to access the connection broker server. This application should be able to run from any machine on the domain by using power-shell to manage the system. Below is the code (with sensitive information masked or changed):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.Management;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using System.Threading;

using RLibrary.Logging;
using VMModerator.Config;

namespace VMModerator
{
/// <summary>
/// This class manages the creation, deletion,
/// </summary>
public class VMManager
{
LogManager _logger;
Runspace _Runspace;
PowerShell _PowerShell;

public void AddDesktop()
{
Uri remoteComputer = new Uri(String.Format("http://{0}:5985/wsman", "cb.mydomain.com");
System.Security.SecureString password = new System.Security.SecureString();

foreach (char c in ("MyPassword").ToCharArray())
{
password.AppendChar(c);
}
PSCredential psc = new PSCredential(@"mydomain.com\Administrator", password);

WSManConnectionInfo connectInfo = new WSManConnectionInfo( remoteComputer, @"http://schemas.microsoft.com/powershell/Microsoft.PowerShell", psc);
connectInfo.NoEncryption=false;

connectInfo.AuthenticationMechanism = AuthenticationMechanism.Kerberos ;
connectInfo.ProxyAuthentication = AuthenticationMechanism.Negotiate;
_Runspace = RunspaceFactory.CreateRunspace(connectInfo);
_Runspace.Open();

_PowerShell = PowerShell.Create();
_PowerShell.Runspace = _Runspace;

string testCommand = "Get-RDPersonalVirtualDesktopAssignment -ConnectionBroker \"cb.mydomain.com\" -CollectionName \"Developer Desktops\" ";

_PowerShell.AddScript(testCommand);
var results = _PowerShell.Invoke();

if (_PowerShell.Streams.Error.Count > 0) _logger.LogMessage(_PowerShell.Streams.Error[0].Exception.Message);

foreach (var output in results.Where(o => o != null))
{
_logger.LogMessage(output.ToString());
}
}
}
}

So my question is, How can I run the power-shell command specified from C# with packet privacy? I feel this is a C# question because i know how the power-shell part works, I just cannot get it to work from C#.

I have been struggling with this for two days now. Please help!

Continue reading...
 
Back
Top