Get-VMMemory powershell return problems - c#

I am trying to use ASP.NET to return the total startup RAM on a VM on a Hyper-V server. The function I have is this:
public static double GetRamVM(string vm, string host)
{
string cmdToRun = "get-vmmemory -name " + vm + " -computername " + host + " | select Startup" ;
var shell = PowerShell.Create();
shell.Commands.AddScript(cmdToRun);
var mem = shell.Invoke();
foreach (PSObject obj in mem)
{
var startMem = obj.Members["Startup"].Value;
return (double)startMem;
}
return 9999.9999;
}
However, whenever I return it - it ALWAYS returns as 9999.9999. I know that the command works, as when I run it manually in a powershell window I get the result that I want.
Please help - as I am going out of my mind.
Edit:
The manual run of the script looks like this
PS C:\Users\mark> Get-VMMemory -vmname "test test" -computername "testhost" | select Startup
Startup
-------
536870912

You could try using the -ExpandProperty on the PowerShell Select cmdlet. This will return a number for the account of memory being used and not an PS-object, so you wont have to extract the value in your C code.
public static double GetRamVM(string vm, string host)
{
string cmdToRun = "get-vmmemory -name " + vm + " -computername " + host + " | select -ExpandProperty Startup" ;
var shell = PowerShell.Create();
shell.Commands.AddScript(cmdToRun);
var mem = shell.Invoke();
return (double)mem;
}

Related

Can not execute Powershell Script in .Net MVC Application

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.

Powershell scripts will always return zero result. while the same script will work well if i call it from the Powershell window

I have installed VMware PowerCLI inside ym application server, and if i directly write the following inside windows powershell i will get the resutl i am looking for :-
PS C:\Windows\system32> add-pssnapin VMware.VimAutomation.Core;
PS C:\Windows\system32> Connect-VIServer -Server ***** -User root -Password "*******"
PS C:\Windows\system32> Get-VMHOST
Name ConnectionState PowerState NumCpu CpuUsageMhz CpuTotalMhz MemoryUsageGB MemoryTotalGB Version
---- --------------- ---------- ------ ----------- ----------- ------------- ------------- -------
********** Connected PoweredOn 8 2733 18400 12.894 15.998 5.0.0
but if i try to run the command inside my asp.net mvc visual studio project , as follow:-
public ActionResult About(string vCenterIp = "****", string vCenterUsername = "****", string vCenterPassword = "****")
{
var shell = PowerShell.Create();
string PsCmd = "add-pssnapin VMware.VimAutomation.Core; $vCenterServer = '" + vCenterIp + "';$vCenterAdmin = '" + vCenterUsername + "' ;$vCenterPassword = '" + vCenterPassword + "';" + System.Environment.NewLine;
PsCmd = PsCmd + "$VIServer = Connect-VIServer -Server $vCenterServer -User $vCenterAdmin -Password $vCenterPassword;" + System.Environment.NewLine;
PsCmd = PsCmd + "$VMHosts = Get-VMHost" + System.Environment.NewLine;
shell.Commands.AddScript(PsCmd);
var results = shell.Invoke();
if (results.Count > 0)
then the result will always be zero .. can anyone adivce on this please?
How could there be results if you absorb them into a Powershell-local variable, and don't pass through to the pipeline? "$VMHosts = Get-VMHost" This command does not return anything (Get-VMHost is absorbed). Change it to plain Get-VMHost and there will be results.

Get-MsolUser command error from C#

I am trying to execute a piece of Azure script to check if the user object is synced from on-prem AD to Azure as below.
username follows the pattern of a UPN. example: john.Smith#ed.com
//Check Azure to see if user is synced to office 365
private static bool IsAccountSyncedToOffice365(string username)
{
StringBuilder cmd = CreateAzureConnectScript();
//cmd.AppendLine("Get-MsolUser -UserPrincipalName " + username + " -ErrorAction SilentlyContinue");
cmd.AppendLine("$global:res = \"false\"");
cmd.AppendLine("$global:user = \"false\"");
cmd.AppendLine("try{ if(($global:user=Get-MsolUser -UserPrincipalName " + username + " -ErrorAction Stop).ImmutableId -ne $null) { $global:res = \"true\"} } Catch { $global:errorMessage = $_.Exception.Message}");
try
{
Collection<PSObject> results;
string output, error, errorMessageAzureCnn = "";
do
{
results = null;
output = "";
error = "";
var rs = CreateAzureRunspace();
var pipe = rs.CreatePipeline();
pipe.Commands.AddScript(cmd.ToString());
results = pipe.Invoke();
output = (rs.SessionStateProxy.PSVariable.GetValue("res")) != null ? rs.SessionStateProxy.PSVariable.GetValue("res").ToString() : "false";
error = (rs.SessionStateProxy.PSVariable.GetValue("errorMessage")) != null ? rs.SessionStateProxy.PSVariable.GetValue("errorMessage").ToString() : "null";
errorMessageAzureCnn = (rs.SessionStateProxy.PSVariable.GetValue("errorMessageAzureCnn")) != null ? rs.SessionStateProxy.PSVariable.GetValue("errorMessageAzureCnn").ToString() : "null";
ExceptionManager.Publish(new Exception("LOG: Queried Azure at:" + DateTime.Now + " for user:" + username + " Result: " + output + " Error: " + error + " errorMessageAzureCnn: " + errorMessageAzureCnn));
Thread.Sleep(60000); //sleep for 60 seconds
pipe.Dispose();
rs.Close();
rs.Dispose();
} while (output.Trim().ToLower() != "true");
ExceptionManager.Publish(new Exception("LOG: " + username + " is found synced to Azure at: " + DateTime.Now));
cmd.Clear();
return true;
}
catch (Exception ex)
{
ExceptionManager.Publish(new Exception("Error checking Azure to see if the user is synced to office 365 or not.. " + ex.Message));
throw ex;
}
}
private static StringBuilder CreateAzureConnectScript()
{
StringBuilder ss = new StringBuilder();
MSCredential cred = new MSCredential();
var username = cred.username;
var pwd = cred.password;
try
{
ss.AppendLine("try {");
ss.AppendLine("$password = ConvertTo-SecureString \"" + pwd + "\" -AsPlainText –Force");
ss.AppendLine("$credential = New-Object System.Management.Automation.PsCredential(\"" + username + "\",$password)");
ss.AppendLine("$cred = Get-Credential -cred $credential");
ss.AppendLine("Import-Module MSOnline");
ss.AppendLine("Start-Sleep -s 10");
ss.AppendLine("Connect-Msolservice -cred $cred");
ss.AppendLine("} Catch { $global:errorMessageAzureCnn = $_.Exception.Message }");
//ExceptionManager.Publish(new Exception("LOG:pwd: " + pwd + " uname:" + username));
return ss;
}
catch (Exception ex)
{
ExceptionManager.Publish(new Exception("Error enabling the remote mailbox.. " + ex.Message));
throw ex;
}
}
While the script executes successfully through Powershell Window on the same server having got all the latest versions of the modules installed. When trying to execute the same command from C# code it throws the below exception collected from the powershell exception handling $global:errorMessage = $_.Exception.Message.
Show Details Exception (0): [] LOG: Queried Azure at:7/30/2015 12:00:55 PM for user:testuser0385#xxx.com Result: false Error: You must call the Connect-MsolService cmdlet before calling any other cmdlets. errorMessageAzureCnn: null
Worth mentioning that I have got the same code as below working in one server but it is throwing the below error on a production server (Windows Server 2008 R2 Datacenter) and only via the code it is happening. via the powershell window it works perfectly fine.
Good to know your thoughts about what looks wrong or needed to be looked into.
Thanks!
It suggests that the sign in is failing, but you're pushing on with the Get-MsolUser anyway. The Connect-MsolService cmdlet fails if it cannot communicate to the Microsoft Online Services Sign-In Assistant. Ref: https://community.office365.com/en-us/f/156/t/252201
Has the production server got all the pre-requisites installed: Microsoft Online Services Sign-In Assistant and .NET 3.5? We had a problem in production (Azure PAAS) where the guest OS image was automatically updated and was missing .NET 3.5, which broke our Azure AD PowerShell processes.

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.

DotCMIS connect to SharePoint Foundation 2013

I would like to connect DotCMIS.dll to my SharePoint but does not work correct.
I open the script in the SharePoint 2013 Management Shell.
I use my user permissions (This is not a Farm user)
Probably here's the problem with giving the correct link. org.apache.chemistry.dotcmis.binding.atompub.url=?
Have you got any idea where link in sharepoint have to go?
Website of example:
http://chemistry.apache.org/dotnet/powershell-example.html
Error
You cannot call a method on a null-valued expression.
At line:6 char:7
+ $b = $contentStream.Stream.Read($buffer, 0, 4096)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
Important part of my Script
$sp["org.apache.chemistry.dotcmis.binding.atompub.url"] = "http://localhost/_layouts/15/start.aspx#/SitePages/WebSite.aspx"
$sp["org.apache.chemistry.dotcmis.user"] = "mylogin"
$sp["org.apache.chemistry.dotcmis.password"] = "mypassword"
All Script
# load DotCMIS DLL
[Reflection.Assembly]::LoadFile("C:\dotCmisServer\DotCMIS.dll")
# -----------------------------------------------------------------
# helper functions
function New-GenericDictionary([type] $keyType, [type] $valueType) {
$base = [System.Collections.Generic.Dictionary``2]
$ct = $base.MakeGenericType(($keyType, $valueType))
New-Object $ct
}
function New-ContentStream([string] $file, [string] $mimetype) {
$fileinfo = ([System.IO.FileInfo]$file)
$contentStream = New-Object "DotCMIS.Data.Impl.ContentStream"
$contentStream.Filename = $fileinfo.Name
$contentStream.Length = $fileinfo.Length
$contentStream.MimeType = $mimetype
$contentStream.Stream = $fileinfo.OpenRead()
$contentStream
}
function Download-ContentStream([DotCMIS.Client.IDocument] $document, [string] $file) {
$contentStream = $document.GetContentStream()
$fileStream = [System.IO.File]::OpenWrite($file)
$buffer = New-Object byte[] 4096
do {
$b = $contentStream.Stream.Read($buffer, 0, 4096)
$fileStream.Write($buffer, 0, $b)
}
while ($b -ne 0)
$fileStream.Close()
$contentStream.Stream.Close()
}
# -----------------------------------------------------------------
# create session
$sp = New-GenericDictionary string string
$sp["org.apache.chemistry.dotcmis.binding.spi.type"] = "atompub"
$sp["org.apache.chemistry.dotcmis.binding.atompub.url"] = "http://localhost/_layouts/15/start.aspx#/SitePages/WebSite.aspx"
$sp["org.apache.chemistry.dotcmis.user"] = "mylogin"
$sp["org.apache.chemistry.dotcmis.password"] = "mypassword"
$factory = [DotCMIS.Client.Impl.SessionFactory]::NewInstance()
$session = $factory.GetRepositories($sp)[0].CreateSession()
# print the repository infos
$session.RepositoryInfo.Id
$session.RepositoryInfo.Name
$session.RepositoryInfo.Vendor
$session.RepositoryInfo.ProductName
$session.RepositoryInfo.ProductVersion
# get root folder
$root = $session.GetRootFolder()
# print root folder children
$children = $root.GetChildren()
foreach ($object in $children) {
$object.Name + " (" + $object.ObjectType.Id + ")"
}
# run a quick query
$queryresult = $session.Query("SELECT * FROM cmis:document", $false)
foreach ($object in $queryresult) {
foreach ($item in $object.Properties) {
$item.QueryName + ": " + $item.FirstValue
}
"----------------------------------"
}
# create a folder
$folderProperties = New-GenericDictionary string object
$folderProperties["cmis:name"] = "myNewFolder"
$folderProperties["cmis:objectTypeId"] = "cmis:folder"
$folder = $root.CreateFolder($folderProperties)
# create a document
$documentProperties = New-GenericDictionary string object
$documentProperties["cmis:name"] = "myNewDocument"
$documentProperties["cmis:objectTypeId"] = "cmis:document"
$source = $home + "\source.txt"
$mimetype = "text/plain"
$contentStream = New-ContentStream $source $mimetype
$doc = $folder.CreateDocument($documentProperties, $contentStream, $null)
# download a document
$target = $home + "\target.txt"
Download-ContentStream $doc $target
# clean up
$doc.Delete($true)
$folder.Delete($true)
Unfortunately in SharePoint Foundation 2013 I have to write own C# software.
SharePoint Foundation 2013 IMPORT\EXPORT dbo.allDocs file\files

Categories

Resources