*Problem
*Using the System.Management.Automation.Runspace namespace I can not
find any logical classes/methods for creating a remote runspace outside
of invoking a script to enter a PSSession.
Basically I want to Enter a Runspace/Session with the arguments;
username, password, uri, configuration, authentication. Essentially
creating the statement below using managed code (C#).
New-PSSession -ConfigurationName Microsoft.Exchange -Credentials $cred
-Uri $livedatacenter -Authentication Basic
Any help will be appreciated.
Thanks Anthony.
--
noli44
Using Reflector on System.Management.Automation.dll, I can see that
Enter-PSSession uses RemoteRunspace which is an internal class. I'm not
sure how far you'll get without taking a dependency on this internal class,
but it appears the entry point to it is
RunspaceFactory.CreateRunspace(RunspaceConnectionInfo, PSHost, TypeTable)
and it returns type Runspace, which is abstract.
I gotta say, I've dug into the guts of PowerShell and there's an assload of
internal classes and methods that really limit what you can do from C#. For
example, I've been trying to find an easy way from a cmdlet to use the
metadata produced by Format-Table (or the metadata used by Format-Table to
produce displays based on format xml files) and it's really hard to do
without running into internal methods.
Hell, even just invoking a ScriptBlock from C# that receives an automatic $_
variable...
Josh
"noli44" <gu...@unknown-email.com> wrote in message
news:0192c52188241952...@nntp-gateway.com...
Thanks for the reply. I agree when you say you feel limited by the
capabilities
of the powershell libraries used in C#.
I was really looking for a clean implementation,
but looks as though I may have to resort to hacks. Atleast until the
next RC.
Anthony
> "noli44" <gu...@xxxxxx-email.com> wrote in message
> news:0192c52188241952...@xxxxxx-gateway.com...> > >
> > >
> > > *Background*
> > > I am currently developing an automated API for my company to manage
> > > public email provisioning in ExchangeLabs (Outlook live).
> > >
> > > *Problem
> > > *Using the System.Management.Automation.Runspace namespace I can not
> > > find any logical classes/methods for creating a remote runspace
> > outside
> > > of invoking a script to enter a PSSession.
> > >
> > > Basically I want to Enter a Runspace/Session with the arguments;
> > > username, password, uri, configuration, authentication. Essentially
> > > creating the statement below using managed code (C#).
> > >
> > > New-PSSession -ConfigurationName Microsoft.Exchange -Credentials
> > $cred
> > > -Uri $livedatacenter -Authentication Basic
> > >
> > > Any help will be appreciated.
> > >
> > > Thanks Anthony.
> > >
> > >
> > > --
> > > noli44 > >
--
noli44
Not the nicest implementation, but after wrapping it in a custom
session object it does the job.
(This might be hard to make sense of without the complete
implementation)
Here's the underlying code:
public static PSObject GenerateSession(IPowershellSessionInformation
sessionInformation)
{
IDictionary<string,object> nameValuePairs = new
Dictionary<string, object>();
if
(!String.IsNullOrEmpty(sessionInformation.Configuration))
nameValuePairs["Configuration"] =
sessionInformation.Configuration;
if
(!String.IsNullOrEmpty(sessionInformation.Authentication))
nameValuePairs["Authentication"] =
sessionInformation.Authentication;
if (!String.IsNullOrEmpty(sessionInformation.Uri))
nameValuePairs["Uri"] = sessionInformation.Uri;
if (sessionInformation.Credential != null)
nameValuePairs["Credential"] =
sessionInformation.Credential;
if (!String.IsNullOrEmpty(sessionInformation.ComputerName))
nameValuePairs["Computer"] =
sessionInformation.ComputerName;
Command command =
TranslateToPowershellCommand("Create-Session", nameValuePairs); //
mapping is performed to translate pre-defined arguments/commands into
valid powershell Command Object.
// my implementation of a "Remote Runspace", takes argument of
IPowershellSessionInformation. // If default ctor invoked just uses
default runspace
IPowershellExtension extension = new
ExchangeLabsPowershellExtension();
ICollection<PSObject> collection =
extension.PerformInvokeCommand(command);
// return session object if it exists
if (collection.Count == 0)
throw new ConfigurationException("Session was not
created, revise Session parameters.");
return collection.SingleOrDefault();
}
// very important to remove the PSSession after use
public static bool CleanSession(IPowershellSessionInformation
sessionInformation)
{
if (sessionInformation == null)
return true;
IDictionary<string, object> nameValuePairs = new
Dictionary<string, object>();
nameValuePairs.Add("Session", sessionInformation.Session);
Command command =
ExchangeLabsProvisioningCommands.TranslateToPowershellCommand("Remove-Session",
nameValuePairs);
IPowershellExtension extension = new
ExchangeLabsPowershellExtension();
ICollection<PSObject> collection =
extension.PerformInvokeCommand(command);
return true;
}
If anyone is interested in the complete implementation please email me
at: fargnoli...@gmail.com
--
noli44
After the installation of WinRM ctpv3 and powershell ctpv3 you need to
reference the correct System.Management.Automation.dll.
First add a reference tag from within the csproj file that you wish to
use the Automation library. To do this open the csproj file with a text
editor and locate the starting tag; <ItemGroup>.
Inbetween these tags you should see a bunch of <Reference Include>
tags. Locate the last </ItemGroup> tag and on the line before it place
<Reference Include="System.Management.Automation />
This will give you access to the System.Management.Automation.Remoting
namespace.
You can now use the WSManConnectionInfo class which allows you create
Remote Runspaces.
Enjoy!
<Code>
WSManConnectionInfo connectionInfo = new WSManConnectionInfo(
new Uri(liveIdconnectionUri),
"http://schemas.microsoft.com/powershell/Microsoft.Exchange",
creds);
connectionInfo.AuthenticationMechanism =
AuthenticationMechanism.Basic;
// create a runspace on a remote path
// the returned instance must be of type RemoteRunspace
Runspace runspace =
System.Management.Automation.Runspaces.RunspaceFactory.CreateRunspace(connectionInfo);
</Code>
--
noli44
After creating the runspace, i tried with basic cmdlets like "dir" but
i have an exception "The term 'dir' is not recognized as a cmdlet,
function, operable program, or script file. Verify the term and try
again." , the same message with other cmdlets.
There is the code:
public void create_runspace(String uri, String shelluri, String
username, String pass)
{
SecureString ss = ConvertToSecureString(pass);
PSCredential creds = new PSCredential(username, ss);
WSManConnectionInfo connectionInfo = new
WSManConnectionInfo(
new
Uri("https://pod51002psh.outlook.com/PowerShell-LiveID\0"),
"http://schemas.microsoft.com/powershell/Microsoft.Exchange", creds);
connectionInfo.AuthenticationMechanism =
AuthenticationMechanism.Basic;
Runspace runspace =
RunspaceFactory.CreateRunspace(connectionInfo);
runspace.Open();
Pipeline pipl = runspace.CreatePipeline("dir");
Collection<PSObject> results = pipl.Invoke();
foreach (PSObject res in results)
{
Console.WriteLine("{0}",
res.Members["Name"].Value);
}
runspace.Close();
}
And the call:
create_runspace("https://pod51002psh.outlook.com/PowerShell-LiveID\0","http://schemas.microsoft.com/powershell/Microsoft.Exchange",adminusername,adminpass);
When i call the WSManConnectionInfo Constructor without parameters it
works.
I didn't find much documentation on the net, so i woud be very grateful
if someone could help me to find what's wrong.
Thanks a lot.
Eva
--
Eva2009
So you'd have to set an alias in your custom host if you wanted to use "dir"
specifically.
Marco
"Eva2009" <gu...@unknown-email.com> wrote in message
news:5839e9a9e860887a...@nntp-gateway.com...
Eva,
You will probably find that the command 'dir' is not a valid
command-let on the outlook live remote runspace.
Your best bet is to connect to outlook live via the powershell console
and run a 'Get-Command' in the remote runspace to see what is available
to you. This will give you the ability to experiment with the powershell
command-lets available. Once you figure out the command-let you would
like to run you can easily translate it into managed code.
btw if you create a runspace with the default constructor it will
connect to your local runspace (where you will be able to run 'dir').
Hope this helps
Anthony
--
noli44
I'm trying now to write into managed code the user add part from the
script csv_parser.ps1 :
%{Invoke-Command -Session $Script:RS {param
($name,$email,$firstName,$lastName,$displayName) new-mailuser -Name
$name -ExternalEmailAddress $email -FirstName $firstName -LastName
$lastName -DisplayName $displayName}-arg
$this_name,$this_email,$this_firstName,$this_lastName,$this_displayName}
> $results
i wrote this code for invoke-command:(i also tried with a basic command
to test, but i tested it in powershell, it works in remote)
Command myCommand = new Command("invoke-command");
myCommand.Parameters.Add(new CommandParameter("Computername",
"pod51002psh.outlook.com"));
myCommand.Parameters.Add(new CommandParameter("Credential", creds));
myCommand.Parameters.Add(new
CommandParameter("Scriptblock",@"{get-command}"));
i get this exception:
Cannot bind parameter 'ScriptBlock'. Cannot convert value
"{get-command}" to type "System.Management.Automation.ScriptBlock".
Error: "Invalid cast from 'System.String' to
'System.Management.Automation.ScriptBlock'."
the same exception when i replace with :
ScriptBlock sb=ScriptBlock.Create(@"{get-command}");
myCommand.Parameters.Add(new CommandParameter("Scriptblock",sb));
Does anyone have an idea how to deal with that? and is it the best way
to perform the user add?
thanks
Eva
--
Eva2009
The good news is you don't have to write script blocks or use the
invoke-command cmdlet. When you use the WSManConnectionInfo class to
create the runspace it is similar to using Enter-PSSession in a
powershell console. Therefore you can run commands directly within the
remote runspace without the need to invoke scripts.
eg. (assumes you have created the runspace)
Command myCommand = new Command("New-Mailbox");
myCommand.Parameters.Add("Name", mailbox_username);
myCommand.Parameters.Add("Password",
CreateSecureString(mailbox_password));
myCommand.Parameters.Add("WindowsLiveID", mailbox_emailaddress);
myCommand.Parameters.Add("FirstName", mailbox_firstname);
myCommand.Parameters.Add("LastName", mailbox_lastname);
myCommand.Parameters.Add("DisplayName", mailbox_displayname);
myCommand.Parameters.Add("Alias", mailbox_alias);
you can now run this command on a pipeline like so;
Pipeline pipl = runspace.CreatePipeline();
pipl.Commands.Add(myCommand);
Collection<PSObject> results = pipl.Invoke();
--
noli44
PSCredential credential = new PSCredential(admin_username,
CreateSecureString(password));
WSManConnectionInfo connectionInfo = new WSManConnectionInfo(new
Uri(liveIdconnectionUri1),
"http://schemas.microsoft.com/powershell/Microsoft.Exchange",
credential);
connectionInfo.AuthenticationMechanism = AuthenticationMechanism.Basic;
// create a runspace on a remote path
// the returned instance must be of type RemoteRunspace
using(Runspace runspace =
System.Management.Automation.Runspaces.RunspaceFactory.CreateRunspace(connectionInfo))
{
runspace.Open();
// get all mailboxes starting with 'a'
Pipeline pipeline = runspace.CreatePipeline();
Command command = new Command("Get-Mailbox");
command.Parameters.Add("Identity", "a*");
pipeline.Commands.Add(command);
IList<PSObject> list = pipeline.Invoke();
foreach (var psObj in list)
{
// cycle through returned objects
}
}
--
noli44
--
Eva2009