Can not execute Powershell Script in .Net MVC Application - c#

I have a .Net MVC application which need to check and get some information from another server via powershell command with code shown below. But app can not get information
try
{
string un = #"domainA\domainUserName";
System.Security.SecureString pw = new System.Security.SecureString();
string password = "";
string exchangeServerName = "ServerAdress/powershell";
foreach (char ch in password)
{
pw.AppendChar(ch);
}
using (PowerShell _powerShell = PowerShell.Create())
{
var credential = new PSCredential(un, pw);
_powerShell.Runspace.SessionStateProxy.SetVariable("Credential", credential);
_powerShell.AddScript($"$Session = New-PSSession –ConfigurationName Microsoft.Exchange -ConnectionUri {exchangeServerName} -Credential $Credential -Authentication Kerberos -AllowRedirection");
_powerShell.AddScript("Import-PSSession $Session");
_powerShell.Invoke();
_powerShell.AddScript(#"get-mailbox -identity " + mail + " | Select-Object ProhibitSendReceiveQuota");
var results = _powerShell.Invoke();
string size = "";
string used = "";
string size2 = "";
foreach (PSObject obj in results)
{
size = (obj.Properties["ProhibitSendReceiveQuota"].Value.ToString());
}
_powerShell.AddScript(#"Get-MailboxStatistics -Identity " + mail + " | Select-Object Totalitemsize,DatabaseProhibitSendQuota");
var results2 = _powerShell.Invoke();
_powerShell.AddScript("Remove-PSSession $Session");
_powerShell.Invoke();
//
}
}
Target server and source server are in different domains.
In local running app wroks perfectly. What can be cause this issue and how can I resolve issue.
Thank you.

Related

quser (query user) no result in powershell c#

I've been searching the solution of this problem for weeks now and still blocked...
I need to use the program "quser" in powershell but in my C# program.
If I run "quser" just in the powershell console I have a result.
But when I execute a powershell script with "quser", it returns nothing... That's weird.
Runspace runspace = RunspaceFactory.CreateRunspace();
runspace.Open();
PowerShell ps = PowerShell.Create();
ps.Runspace = runspace;
String script = "$re = '(\\S+)\\s+?(\\S*)\\s+?(\\d+)\\s+(\\S+)\\s+(\\S+)\\s+(\\d+\\/\\d+\\/\\d+\\s+\\d+:\\d+)'\n"
+ "query user /server:"+machine+" | Where-Object { $_ -match $re } | ForEach-Object {\n"
+ "New-Object -Type PSCustomObject -Property #{"
+ "'Username' = $matches[1]\n"
+ "'LogonTime' = $matches[6]\n"
+ "}\n"
+ "} | Select-Object Username, LogonTime | ForEach-Object { Write-Output (\"{0} is connected from {1}\" -f $_.Username, $_.LogonTime) }";
ps.AddScript(script);
Collection<PSObject> result = ps.Invoke();
ps.Dispose();
runspace.Close();
runspace.Dispose();
Console.WriteLine(result.Count);
The result of the ps.Invoke() is empty.
But when I run this code from a powershell console it works.
Also another weird thing, it works in remote powershell :
String script = "$re = '(\\S+)\\s+?(\\S*)\\s+?(\\d+)\\s+(\\S+)\\s+(\\S+)\\s+(\\d+\\/\\d+\\/\\d+\\s+\\d+:\\d+)'\n"
+ "query user | Where-Object { $_ -match $re } | ForEach-Object {\n"
+ "New-Object -Type PSCustomObject -Property #{"
+ "'Username' = $matches[1]\n"
+ "'LogonTime' = $matches[6]\n"
+ "}\n"
+ "} | Select-Object Username, LogonTime | ForEach-Object { Write-Output (\"{0} is connected from {1}\" -f $_.Username, $_.LogonTime) }";
string shellUri = "http://schemas.microsoft.com/powershell/Microsoft.PowerShell";
System.Security.SecureString sString = new System.Security.SecureString();
foreach (char passwordChar in password.ToCharArray())
{
sString.AppendChar(passwordChar);
}
PSCredential credential = new PSCredential(username, sString);
WSManConnectionInfo connectionInfo = new WSManConnectionInfo(false, machine, 5985, "/wsman", shellUri, credential);
List<String> scriptOutput = new List<String>();
using (Runspace runspace = RunspaceFactory.CreateRunspace(connectionInfo))
{
runspace.Open();
Pipeline pipe = runspace.CreatePipeline();
pipe.Commands.AddScript(script);
Collection<PSObject> result = pipe.Invoke();
foreach (PSObject line in result)
{
scriptOutput.Add(line.ToString());
}
pipe.Dispose();
runspace.Close();
}
foreach(String line in scriptOutput)
{
Console.WriteLine(line);
}
It returns the connected user.
The fact is that I don't want to logged into the machine in order to see the conncted users. (because it works in the powershell console)
If someone could help me please.
Thanks.

Powershell remote commandlet from c# for cim-session

using (PowerShell pInst=PowerShell.Create()) // implements Idisposable
{
string username = Console.ReadLine();
System.Security.SecureString pwd = getPassword();
PSCredential credential = new PSCredential(username, pwd);
pInst.Runspace.SessionStateProxy.SetVariable("cred", credential);
//pInst.AddScript("$cred;");
//pInst.AddScript("$session= New-CimSession -ComputerName anksahawin8a $cred");
//pInst.AddScript("$session;");
//pInst.AddScript("param($param1) $d = get-date;"+"$d; $s; $param1; get-service");
//.AddParameter("param1","Ankit");
//pInst.Invoke(); // Synchronous Invocation
pInst.AddScript("$session= New-CimSession -ComputerName anksahawin8a -Credential $cred;");
//psOutput = pInst.Invoke();
pInst.AddScript("$session;");
Collection<PSObject> psOutput = pInst.Invoke();
//psOutput = pInst.Invoke();
if(pInst.Streams.Error.Count>0) // Errors
{
}
foreach(PSObject pso in psOutput)
{
Console.WriteLine(pso);
if (pso != null)
{
//String result=pso.Members["Value"].Value.ToString();
Console.WriteLine(pso.BaseObject.GetType().FullName);
Console.WriteLine(pso.BaseObject.ToString() + "\n");
}
}
Console.WriteLine("Hello");
}
This code is not working. Whereas
pInst.AddScript("$session= New-CimSession");
for local computer works...

Using C# To Return Data From PowerShell

I am trying to return a PrimarySMTPAddress to a variable, in Powershell the code I run is this:
Get-Mailbox -identity UserName | select PrimarySMTPAddress
And it returns the correct value, I want to get this in my C# Code, I have done the following:
string getPrimarySMTP = "Get-Mailbox -identity " + username + "| select PrimarySMTPAddress";
var runSpace = RunspaceFactory.CreateRunspace(Utility.CreateConnectionInfo());
runSpace.Open();
var pipeline = runSpace.CreatePipeline();
pipeline.Commands.AddScript(getPrimarySMTP);
var primarySmtp = pipeline.Invoke();
runSpace.Dispose();
I would Expect this to return the same data, but it doesn't. I just get an exception:
The term 'select' 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.
Is this the way to return values from a powershell command?
For what version of Exchange ? for 2010 up you need to use Remote Powershell see https://msdn.microsoft.com/en-us/library/office/ff326159%28v=exchg.150%29.aspx . (even in 2007 your code would work because you haven't loaded the snapin).
Cheers
Glen
You may need to add an additional space character before the pipe. It' being concatenated to the username, with the resulting string becoming ... -identity UserName| select ..."
Here's the corrected statement:
string getPrimarySMTP = "Get-Mailbox -identity " + username + " | select PrimarySMTPAddress";
Thanks for asking this question, it helped me to lead to the answer I needed. My code resulted in the following using RemoteRunspace to an Exchange 2013 environment:
try
{
var target = new Uri(Uri);
SecureString PSPassword = new SecureString();
foreach (char c in ConfigurationManager.AppSettings["Password"])
{
PSPassword.AppendChar(c);
}
//var cred = (PSCredential)null;
PSCredential cred = new PSCredential(ConfigurationManager.AppSettings["Username"], PSPassword);
WSManConnectionInfo connectionInfo = new WSManConnectionInfo(target, shell, cred);
connectionInfo.AuthenticationMechanism = AuthenticationMechanism.Default;
connectionInfo.OperationTimeout = 1 * 60 * 1000; // 4 minutes.
connectionInfo.OpenTimeout = 1 * 30 * 1000; // 1 minute.
using (Runspace remoteRunspace = RunspaceFactory.CreateRunspace(connectionInfo))
{
remoteRunspace.Open();
using (PowerShell powershell = PowerShell.Create())
{
powershell.Runspace = remoteRunspace;
powershell.AddScript(PSSnapin);
powershell.Invoke();
powershell.Streams.ClearStreams();
powershell.Commands.Clear();
Pipeline pipeline = remoteRunspace.CreatePipeline();
Command getMailBox = new Command("Get-Mailbox");
getMailBox.Parameters.Add("Identity", Username);
Command cmd = new Command("Select-Object");
string[] Parameter = new string[] { "PrimarySMTPAddress" };
cmd.Parameters.Add("Property", Parameter);
pipeline.Commands.Add(getMailBox);
pipeline.Commands.Add(cmd);
Collection<PSObject> results = pipeline.Invoke();
primarySMTPAddress = results[0].ToString();
primarySMTPAddress = primarySMTPAddress.ToUpper().Replace("#{PRIMARYSMTPADDRESS=", "");
primarySMTPAddress = primarySMTPAddress.ToUpper().Replace("}", "");
}
remoteRunspace.Close();
}
return primarySMTPAddress;
}
catch
{
return "Error";
}
Hope this helps anyone in future.

Error message when running a c# powershell code

When I run the code below I get the following error at Response.Write( result.Properties["name"].Value);. "use the 'new' keyword to create and object instance."
I can't figure out how to fix this problem.
String sEmailAddress;
String sPassword;
sEmailAddress = Request.QueryString["value1"];
sPassword = Request.QueryString["value2"];
lbl1.Text = sEmailAddress + " " + sPassword;
SecureString sSecurePW = new SecureString();
foreach (char c in sPassword.ToCharArray())
sSecurePW.AppendChar(c);
PSCredential Credential = new PSCredential(sEmailAddress, sSecurePW);
PowerShell powershell = PowerShell.Create();
powershell.Runspace.SessionStateProxy.SetVariable("cred", Credential);
powershell.AddScript("$s = New-PSSession -ComputerName ExchDC01 -Credential $cred -Authentication Kerberos");
powershell.AddScript("invoke-command -session $s -scriptblock {Get-ADOrganizationalUnit -LDAPFilter '(name=*)' -SearchBase 'OU=TENANTS,DC=lab,DC=local' -SearchScope OneLevel | ft Name}");
// Collection<PSObject> results = powershell.Invoke();
foreach (PSObject result in powershell.Invoke())
{
Response.Write(result.Properties["name"].Value); //<-- Error:use the 'new' keyword to create and object instance.
}
}
Thanks in advance

Problems with accessing AD Information (PowerShell Script works, C# code dont)

I found this PowerShell Script that searches for Exchange Servers in the Domain.
Function Get-ExchangeServerInSite {
$ADSite = [System.DirectoryServices.ActiveDirectory.ActiveDirectorySite]
$siteDN = $ADSite::GetComputerSite().GetDirectoryEntry().distinguishedName
$configNC=([ADSI]"LDAP://RootDse").configurationNamingContext
$search = new-object DirectoryServices.DirectorySearcher([ADSI]"LDAP://$configNC")
$objectClass = "objectClass=msExchExchangeServer"
$site = "msExchServerSite=$siteDN"
$search.Filter = "(&($objectClass)($site))"
$search.PageSize=1000
[void] $search.PropertiesToLoad.Add("name")
[void] $search.PropertiesToLoad.Add("msexchcurrentserverroles")
[void] $search.PropertiesToLoad.Add("networkaddress")
$search.FindAll() | %{
New-Object PSObject -Property #{
Name = $_.Properties.name[0]
FQDN = $_.Properties.networkaddress |
%{if ($_ -match "ncacn_ip_tcp") {$_.split(":")[1]}}
Roles = $_.Properties.msexchcurrentserverroles[0]
}
}
}
$role = #{
2 = "MB"
4 = "CAS"
16 = "UM"
32 = "HT"
64 = "ET"
}
foreach ($server in Get-ExchangeServerinSite) {
$roles = ($role.keys | ?{$_ -band $server.roles} | %{$role.Get_Item($_)}) -join ", "
$server | select Name, #{n="Roles";e={$roles}},FQDN
}
Because I need the same task in C# code without using PowerShell. I tried using the .Net classes the same way and even debuged both scripts and the info is the same.
Now my problem. The PowerShell script correctly displays the server and the C# code returns an empty collection.
Here is the C#
string siteDN = ActiveDirectorySite.GetComputerSite().GetDirectoryEntry().Properties["distinguishedName"].Value.ToString();
DirectoryEntry RootDSE = new DirectoryEntry( #"LDAP://RootDSE" );
string baseStr = #"LDAP://" + RootDSE.Properties["configurationNamingContext"].Value ;
DirectorySearcher searcher = new DirectorySearcher(baseStr );
string classObj = "objectClass=msExchExchangeServer";
string site = "msExchServerSite="+siteDN;
searcher.Filter = string.Format("(&({0})({1}))",classObj,site);
searcher.PropertiesToLoad.Add( "name" );
searcher.PageSize = 1000;
searcher.ServerTimeLimit = new TimeSpan(0,1,0);
searcher.CacheResults = false;
SearchResultCollection coll = searcher.FindAll();
The only difference I could find was the [ADSI] tag in the PowerShell code but I couldn't find out what the C# part is from that.

Categories

Resources