Exception occured when call cmldet powershell c# create New-mailBox - c#

trying to execute cmdlet exchange powershell new-mailBox failed in c# - remote access on exchange 2016 server
Add user account to the different group for access right execution
string connectionUri = "http://xxx.contosoe.com/powershell/";
string loginPassword = "password";
SecureString secpassword = new SecureString();
foreach (char c in loginPassword)
{
secpassword.AppendChar(c);
}
PSCredential credential = new PSCredential(#"doamin\user", secpassword);
Runspace runspace = RunspaceFactory.CreateRunspace(rsConfig);
PowerShell powershell = PowerShell.Create();
powershell.Commands.AddCommand("Import-Module").AddArgument("ActiveDirectory");
//
PSCommand command = new PSCommand();
command.AddCommand("New-PSSession");
command.AddParameter("ConfigurationName", "Microsoft.Exchange");
command.AddParameter("ConnectionUri", new Uri(connectionUri));
command.AddParameter("Credential", credential);
command.AddParameter("Authentication", "KerBeros");
powershell.Commands = command;
runspace.Open();
powershell.Runspace = runspace;
Collection<PSObject> result = powershell.Invoke();
if (powershell.Streams.Error.Count > 0 || result.Count != 1)
{
throw new Exception("Fail to establish the connection");
}
powershell = PowerShell.Create();
command = new PSCommand();
command.AddCommand("Set-Variable");
command.AddParameter("Name", "ra");
command.AddParameter("Value", result[0]);
powershell.Commands = command;
powershell.Runspace = runspace;
powershell.Invoke();
powershell = PowerShell.Create();
command = new PSCommand();
command.AddScript("Import-PSSession -Session $ra");
powershell.Commands = command;
powershell.Runspace = runspace;
powershell.Invoke();
Pipeline pipeLine = runspace.CreatePipeline();
var emailCreateCommand = CreateEmailCommand("name", "displayName", "alias");
pipeLine.Commands.Add(emailCreateCommand);
Collection<PSObject> result_ = pipeLine.Invoke();
stack trace....
System.TypeInitializationException: The type initializer for 'Microsoft.Exchange.Management.Common.NewUserBase'. --->
System.UnauthorizedAccessException: Access to the registry key 'Global' is denied.
Microsoft.Win32.RegistryKey.Win32Error(Int32 errorCode, String str)
Microsoft.Win32.RegistryKey.InternalGetValue(String name, Object defaultValue, Boolean doNotExpand, Boolean checkSecurity)
Microsoft.Win32.RegistryKey.GetValue(String name)
System.Diagnostics.PerformanceMonitor.GetData(String item)
System.Diagnostics.PerformanceCounterLib.GetPerformanceData(String item)
System.Diagnostics.PerformanceCounterLib.get_CategoryTable()
System.Diagnostics.PerformanceCounterLib.CategoryExists(String machine, String category)
System.Diagnostics.PerformanceCounterCategory.Exists(String categoryName, String machineName)
Microsoft.Exchange.Management.Common.NewUserBase..cctor()
Microsoft.Exchange.Management.Common.NewUserBase.InternalBeginProcessing()
Microsoft.Exchange.Management.RecipientTasks.NewMailboxBase.InternalBeginProcessing()
Microsoft.Exchange.Management.RecipientTasks.NewMailboxOrSyncMailbox.InternalBeginProcessing()
Microsoft.Exchange.Configuration.Tasks.Task.<BeginProcessing>b__83_1()
Microsoft.Exchange.Configuration.Tasks.Task.InvokeRetryableFunc(String funcName, Action func, Boolean terminatePipelineIfFailed)

Related

c# Can logged in credentials (non explicit) be used with wsmanconnectioninfo?

I have the function below with multiple threads, which was fine with explicit credentials when I was the only one using it, but I've been asked to put it into a powershell script where it will be plain text to leverage the multithread capability.
Is it possible to use the implied credentials of the account running the script with wsmanconnectioninfo? If not, is there a different way to create the Exchange shell connection without explicit credentials?
private Collection<PSObject> runPowerShellScript(object server)
{
Collection<PSObject> psobjs = new Collection<PSObject>();
string result = "";
string serverName = server.ToString();
string loginPassword = "xxx";
System.Security.SecureString secpassword = new SecureString();
foreach (char c in loginPassword)
{
secpassword.AppendChar(c);
}
PSCredential credential = new PSCredential(#"domain/samaccount", secpassword);
WSManConnectionInfo connectionInfo = new WSManConnectionInfo(new Uri("https://xxxxx/powershell"), "http://schemas.microsoft.com/powershell/Microsoft.Exchange", credential);
connectionInfo.AuthenticationMechanism = AuthenticationMechanism.Basic;
using (Runspace runspace = RunspaceFactory.CreateRunspace(connectionInfo))
{
PowerShell powershell = PowerShell.Create();
if (runspace.RunspaceStateInfo.State == RunspaceState.Opened)
{
// do nothing
}
else
{
runspace.Open();
powershell.Runspace = runspace;
}
try
{
PSCommand command = new PSCommand();
command.AddScript($#"get-mailboxdatabase -Server " + server + " -Status");
powershell.Commands = command;
psobjs = powershell.Invoke();
if (powershell.HadErrors == true)
{
result = "Failed - " + powershell.Streams.Error[0].ToString();
result = result.Replace("\"", "*");
}
}
catch (Exception ex)
{
string fail = ex.Message;
}
}
object serverNameO = server;
PSObject serverNameObj = new PSObject(serverNameO);
psobjs.Insert(0, serverNameObj);
return psobjs;
}
This is working
WSManConnectionInfo wmc = new WSManConnectionInfo(new Uri(`"http://xxx/powershell`"));
wmc.AuthenticationMechanism = AuthenticationMechanism.Kerberos;
wmc.ShellUri = `"http://schemas.microsoft.com/powershell/Microsoft.Exchange`";
using (Runspace runspace = RunspaceFactory.CreateRunspace(wmc))
{
}

c# The term 'Enable-Mailbox' is not recognized as the name of a cmdlet

All is working well on developer's computer from VS or from bin/release files of wpf app. But, when I run the same project from VS or bin/release files on another computer I'm receiving an error:"The term 'Enable-Mailbox' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again."
Here is the code where the error is happening:
public static class ManageMailBox
{
public static bool CreateMailBox(string strUserID, string admin_user, string pword) //, string str_upn)
{
try
{
string strExchangeServer = Constants.ExchangeServer;
Uri uri = new Uri(#"http://" + strExchangeServer + #"/powershell?serializationLevel=Full"); // orig works
/// must pass secure string
char[] passwordChars = pword.ToCharArray();
SecureString password = new SecureString();
foreach (char c in passwordChars)
{
password.AppendChar(c);
}
PSCredential credential = new PSCredential("DOMAIN\\" + admin_user, password);
Runspace runspace = RunspaceFactory.CreateRunspace();
PowerShell powershell = PowerShell.Create();
PSCommand command = new PSCommand();
command.AddCommand("New-PSSession");
command.AddParameter("ConfigurationName", "Microsoft.Exchange");
command.AddParameter("ConnectionUri", uri);
command.AddParameter("Credential", credential);
command.AddParameter("Authentication", "Default");
PSSessionOption sessionOption = new PSSessionOption();
sessionOption.SkipCACheck = true;
sessionOption.SkipCNCheck = true;
sessionOption.SkipRevocationCheck = true;
command.AddParameter("SessionOption", sessionOption);
powershell.Commands = command;
try
{
// open the remote runspace
runspace.Open();
// associate the runspace with powershell
powershell.Runspace = runspace;
// invoke the powershell to obtain the results
Collection<PSSession> result = powershell.Invoke<PSSession>();
foreach (ErrorRecord current in powershell.Streams.Error)
{
throw new Exception("Exception: " + current.Exception.ToString());
throw new Exception("Inner Exception: " + current.Exception.InnerException);
}
if (result.Count != 1)
throw new Exception("Unexpected number of Remote Runspace connections returned.");
// Set the runspace as a local variable on the runspace
powershell = PowerShell.Create();
command = new PSCommand();
command.AddCommand("Set-Variable");
command.AddParameter("Name", "ra");
command.AddParameter("Value", result[0]);
powershell.Commands = command;
powershell.Runspace = runspace;
powershell.Invoke();
// First import the cmdlets in the current runspace (using Import-PSSession)
powershell = PowerShell.Create();
command = new PSCommand();
//command.AddScript("Set-ExecutionPolicy -Unrestricted");
command.AddScript("Import-PSSession -Session $ra");
powershell.Commands = command;
powershell.Runspace = runspace;
powershell.Invoke();
// Now run get-ExchangeServer
powershell = PowerShell.Create();
command = new PSCommand();
command.AddCommand("Enable-Mailbox");
command.AddParameter("Identity", strUserID);
command.AddParameter("Alias", strUserID);
command.AddParameter("Database", "IAP Mailbox Database 0948752629");
powershell.Commands = command;
powershell.Runspace = runspace;
powershell.Invoke(); // ERROR !!! The term 'Enable-Mailbox' is not recognized as the name of a cmdlet, function
return true;
}
catch(Exception ex) {
throw new Exception(ex.Message.ToString()); }
finally
{
// dispose the runspace and enable garbage collection
runspace.Dispose();
runspace = null;
// Finally dispose the powershell and set all variables to null to free
// up any resources.
powershell.Dispose();
powershell = null;
}
}
catch (Exception argex)
{
throw new ArgumentException(argex.Message.ToString());
}
}
}

How to run Import-PSSessions from .Net program

I am trying to write code in C# that get mailbox details from user via Power Shell command.
The power shell command script is:
Import-PSSession -session (New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://myServer.myDomain.com/Powershell)
Get-Mailbox -Identity helpdesk
The script runs OK from PowerShell.
Now my goal is to run it using C#.
This is my function:
private void button1_Click(object sender, EventArgs e)
{
m_RunSpace = RunspaceFactory.CreateRunspace();
m_RunSpace.Open();
Pipeline pipeLine = m_RunSpace.CreatePipeline();
Command newSession = new Command("New-PSSession");
newSession.Parameters.Add("-ConfigurationName", "Microsoft.Exchange");
newSession.Parameters.Add("-ConnectionUri", "http://myServer.myDomain.com/Powershell");
Command createSessionForExch = new Command("Import-PSSession");
createSessionForExch.Parameters.Add("-Session", newSession);
Command getMailbox = new Command("Get-Mailbox");
getMailbox.Parameters.Add("-Identity", "helpdesk");
pipeLine.Commands.Add(createSessionForExch);
pipeLine.Commands.Add(getMailbox);
Collection<PSObject> commandResults = pipeLine.Invoke();
foreach (PSObject cmdlet in commandResults)
{
}
}
But I receive an error that the "Get-Mailbox" command is not recognize:
Probably because the Import-PSSessions wasn't invok correctly.
I need help how to run the command Import-PSSession correctly from C#
Hope, you have found the solution. If not, please give this code a try:
String url = "http://" + ExchangeServerName + "/powershell?serializationLevel=Full";
System.Uri uri = new Uri(url);
Console.WriteLine(url);
System.Security.SecureString securePassword = String2SecureString(password);
System.Management.Automation.PSCredential creds = new System.Management.Automation.PSCredential(userName, securePassword);
Runspace runspace = System.Management.Automation.Runspaces.RunspaceFactory.CreateRunspace();
PowerShell powershell = PowerShell.Create();
PSCommand command = new PSCommand();
command.AddCommand("New-PSSession");
command.AddParameter("ConfigurationName", "Microsoft.Exchange");
command.AddParameter("ConnectionUri", uri);
command.AddParameter("Credential", creds);
command.AddParameter("Authentication", Authentication);
//PSSessionOption sessionOption = new PSSessionOption();
//sessionOption.SkipCACheck = true;
//sessionOption.SkipCNCheck = true;
//sessionOption.SkipRevocationCheck = true;
//command.AddParameter("SessionOption", sessionOption);
powershell.Commands = command;
try
{
runspace.Open();
powershell.Runspace = runspace;
Collection<PSSession> result = powershell.Invoke<PSSession>();
foreach (ErrorRecord current in powershell.Streams.Error)
Console.WriteLine("The following Error happen when opening the remote Runspace: " + current.Exception.ToString() +
" | InnerException: " + current.Exception.InnerException);
if (result.Count != 1)
throw new System.Exception("Unexpected number of Remote Runspace connections returned.");
// Set the runspace as a local variable on the runspace
powershell = PowerShell.Create();
command = new PSCommand();
command.AddCommand("Set-Variable");
command.AddParameter("Name", "ra");
command.AddParameter("Value", result[0]);
powershell.Commands = command;
powershell.Runspace = runspace;
powershell.Invoke();
// First import the cmdlets in the current runspace (using Import-PSSession)
powershell = PowerShell.Create();
command = new PSCommand();
//command.AddScript("Import-PSSession $ra");
command.AddScript("Invoke-Command -ScriptBlock { Get-Mailbox -Identity:" + MailBoxName + " } -Session $ra");
powershell.Commands = command;
powershell.Runspace = runspace;
//powershell.Commands.AddCommand("Import-Module").AddArgument("activedirectory");
powershell.Invoke();
//command = new PSCommand();
//command.AddCommand("Get-Mailbox");
////Change the name of the database
//command.AddParameter("Identity", "");
//powershell.Commands = command;
//powershell.Runspace = runspace;
Collection<PSObject> results = new Collection<PSObject>();
results = powershell.Invoke();
Full an interesting tutorial about : Access Exchange Online by PowerShell in C#
Get-Mailbox example in step 3.
Use WSManConnectionInfo class to supply the uri,schema to open the remote runspace.Please find the code :
private static string CreateConnection()
{
Runspace remoteRunspace = null;
openRunspace(
"https://pod51057psh.outlook.com/powershell-liveid?PSVersion=3.0",
"http://schemas.microsoft.com/powershell/Microsoft.Exchange",
#"xxx#xxx.com",
"xxxxx",
ref remoteRunspace
);
// Command getLicenseCommand = new Command("Get-MsolAccountSku");
//Command activityCommand = new Command("Get-GroupActivityReport");
//activityCommand.Parameters.Add(new CommandParameter("ReportType", "Daily"));
//activityCommand.Parameters.Add(new CommandParameter("StartDate", "03/4/2014"));
//activityCommand.Parameters.Add(new CommandParameter("EndDate", "03/27/2014"));
Command activityCommand = new Command("Get-Mailbox");
activityCommand.Parameters.Add("-Identity", "xxx");
StringBuilder stringBuilder = new StringBuilder();
using (PowerShell powershell = PowerShell.Create())
{
powershell.Runspace = remoteRunspace;
powershell.Commands.AddCommand(activityCommand);
powershell.Invoke();
var results = powershell.Invoke();
remoteRunspace.Close();
foreach (PSObject obj in results)
{
stringBuilder.AppendLine(obj.ToString());
}
}
remoteRunspace.Close();
return stringBuilder.ToString();
}
public static void openRunspace(string uri, string schema, string username, string livePass, ref Runspace remoteRunspace)
{
System.Security.SecureString password = new System.Security.SecureString();
foreach (char c in livePass.ToCharArray())
{
password.AppendChar(c);
}
PSCredential psc = new PSCredential(username, password);
WSManConnectionInfo rri = new WSManConnectionInfo(new Uri(uri), schema, psc);
rri.AuthenticationMechanism = AuthenticationMechanism.Basic;
remoteRunspace = RunspaceFactory.CreateRunspace(rri);
remoteRunspace.Open();
}

How I can create a User in AD with Powershell in a ASP.NET Webapplication

I have a question to C# and Powershell in a ASP.NET Application.
I want to create a User in our Active Directory and I want/must use a powershell for this. I had built a Webapllication that could add a mailcontact in the Exchange Server one year ago. For this I used the System.Management.Automation Namespace with the Powershell Classes. But I don't know how I can do it for the Active Directory.
the ps command that I must use:
New-ADUser %prefix-%name
-SamAccountName "%name"
-UserPrincipalName "%name#test-company.com"
-GivenName "%text1"
-SurName "%text2"
-displayname "%name"
-enabled $true
-Path '%OU'
-AllowReversiblePasswordEncryption $true
-PasswordNeverExpires $true
-AccountPassword (ConvertTo-Securestring "%name" -asplaintext -Force)
and here my cs code:
public void CreateRemoteConnectionToActiveDirectory(string Username, string password//,...comming)
{
SecureString securePassword = new SecureString();
str_password = password;
str_username = Username;
foreach (char x in str_password)
{
securePassword.AppendChar(x);
}
PSCredential cred = new PSCredential(str_username, securePassword);
// connection?
}
My Old Code for the exchange Server:
public string CreateRemoteConnectionToExchange(string UserName, string Password, string Mailbox)
{
SecureString SecurePassword = new SecureString();
string str_password = Password;
string str_username = UserName;
foreach (char x in str_password)
{
SecurePassword.AppendChar(x);
}
PSCredential cred = new PSCredential(str_username, SecurePassword);
WSManConnectionInfo connectionInfo = new WSManConnectionInfo(new Uri(ExchangeServer), Schema, cred);
connectionInfo.AuthenticationMechanism = AuthenticationMechanism.Default;
Runspace runspace = RunspaceFactory.CreateRunspace(connectionInfo);
PowerShell powershell = PowerShell.Create();
PSCommand command = new PSCommand();
command.AddCommand("New-MailContact");
command.AddParameter("ExternalEmailAddress", "SMTP:" + Mailbox + MailExtension);
command.AddParameter("Name", Mailbox);
command.AddParameter("Alias", Mailbox);
command.AddParameter("FirstName", Mailbox);
command.AddParameter("Initials", "");
command.AddParameter("LastName", "");
command.AddParameter("OrganizationalUnit", OrganizationalUnit);
command.AddParameter("DomainController", configDC);
powershell.Commands = command;
try
{
runspace.Open();
powershell.Runspace = runspace;
powershell.Invoke();
return "Der Kontakt wurde Erfolgreich erstellt";
}
catch (Exception ex)
{
///...
}
finally
{
runspace.Dispose();
runspace = null;
powershell.Dispose();
powershell = null;
}
}
How I can do this. A Example,tutorial or a tipp would me help.
Looks like your connection just needs to connect to either your AD server or another server that can actually execute the command.

Powershell and exchange in C#

I have the following code in C# that I use to connect to exchange through powershell.
The following code works fine, however there is one more command that I need in order to use the exchange cmdlets.
Here is the code I have now.
Runspace runspace = System.Management.Automation.Runspaces.RunspaceFactory.CreateRunspace();
PowerShell powershell = PowerShell.Create();
PSCommand command = new PSCommand();
command.AddCommand("New-PSSession");
command.AddParameter("ConfigurationName", "Microsoft.Exchange");
command.AddParameter("ConnectionUri", new Uri("https://ps.outlook.com/powershell/"));
command.AddParameter("Credential", creds);
command.AddParameter("Authentication", "Basic");
command.AddParameter("AllowRedirection");
powershell.Commands = command;
try
{
runspace.Open();
powershell.Runspace = runspace;
Collection<PSObject> commandResults = powershell.Invoke();
StringBuilder sb = new StringBuilder();
foreach (PSObject ps in commandResults)
{
sb.AppendLine(ps.ToString());
}
sb.AppendLine();
lbl.Text += sb.ToString();
}
finally
{
// dispose the runspace and enable garbage collection
runspace.Dispose();
runspace = null;
// Finally dispose the powershell and set all variables to null to free
// up any resources.
powershell.Dispose();
powershell = null;
}
My problem is that I still need to run the command import-pssession $session where $session is the output of my first command. However I am not sure how I can declare that output as the variable $session or something like:
PSCommand command = new PSCommand();
command.AddCommand("Import-PSSession");
command.AddParameter("Session", #Not sure how to put session info which is what the first command produces into here.);
You can try using creating a Remote Runspace instead, an example is given below. You can reference the following article http://msdn.microsoft.com/en-us/library/windows/desktop/ee706560(v=vs.85).aspx.
string schemaURI = "http://schemas.microsoft.com/powershell/Microsoft.Exchange";
Uri connectTo = new Uri("https://ps.outlook.com/powershell/");
PSCredential credential = new PSCredential(user,secureStringPassword ); // the password must be of type SecureString
WSManConnectionInfo connectionInfo = new WSManConnectionInfo(connectTo,schemaURI, credential);
connectionInfo.MaximumConnectionRedirectionCount = 5;
connectionInfo.AuthenticationMechanism = AuthenticationMechanism.Basic;
try
{
Runspace remoteRunspace = RunspaceFactory.CreateRunspace(connectionInfo);
remoteRunspace.Open();
}
catch(Exception e)
{
//Handle error
}
try the section "Remote Request using a local run space (Scripting the remote class)" in the following technet blog
http://blogs.technet.com/b/exchange/archive/2009/11/02/3408653.aspx
I believe what you are trying to achieve is:
// Set the runspace as a local variable on the runspace
powershell = PowerShell.Create();
command = new PSCommand();
command.AddCommand("Set-Variable");
command.AddParameter("Name", "ra");
command.AddParameter("Value", result[0]);
powershell.Commands = command;
powershell.Runspace = runspace;
powershell.Invoke();
Where result[0] is the result of the first remote session created. Let me know if that helps.

Categories