I have the following script to schedule an event on an O365 calendar.
The goal is to run this script from an Asp.net C# page.
If I run it in WindowPowershell ISE, it works perfectly.
The problem is when I run it from the page.
It returns me the following error: "The term 'Connect-MgGraph' 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."
C# CODE
public static string SetEvent(string Subject, string Date, string StartHour, string EndHour, string Location, string[] Attendees, string Body)
{
string result = "";
try
{
//Subject
string strSubject = Subject;
//Param StartDateHour && EndDateHour
DateTime datDate = Convert.ToDateTime(Date);
string strStartDateHour = datDate.Year.ToString() + "-" + datDate.Month.ToString() + "-" + datDate.Day.ToString() + "T" + StartHour;
string strEndDateHour = datDate.Year.ToString() + "-" + datDate.Month.ToString() + "-" + datDate.Day.ToString() + "T" + EndHour;
// Location
string strLocation = Location;
// Attendees
string strAttendees = "#(";
foreach (string item in Attendees)
{
strAttendees += "#{EmailAddress = #{" +
"Address = ' + item.ToString() + ' " +
"} " +
"Type = 'Required'" +
"}";
}
strAttendees += ")";
// Body
string strBody = Body;
//Secrets!
string strAppID = HIDDEN;
string strTenantID = HIDDEN;
string strClientSecret = HIDDEN;
// create Powershell runspace
RunspaceConfiguration runspaceConfiguration = RunspaceConfiguration.Create();
Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfiguration);
runspace.Open();
RunspaceInvoke runSpaceInvoker = new RunspaceInvoke(runspace);
string scriptfile = HttpContext.Current.Server.MapPath(#"~/PowerShell/scripts/Calendar/SetEvent.ps1");
// create a pipeline and feed it the script text
Pipeline pipeline = runspace.CreatePipeline();
Command myCommand = new Command(scriptfile);
CommandParameter SubjectParam = new CommandParameter("subject", strSubject);
myCommand.Parameters.Add(SubjectParam);
CommandParameter StartDateHourParam = new CommandParameter("startdatehour", strStartDateHour);
myCommand.Parameters.Add(StartDateHourParam);
CommandParameter EndDateHourParam = new CommandParameter("enddatehour", strEndDateHour);
myCommand.Parameters.Add(EndDateHourParam);
CommandParameter LocationParam = new CommandParameter("location", strLocation);
myCommand.Parameters.Add(LocationParam);
CommandParameter AttendeesParam = new CommandParameter("attendees", strAttendees);
myCommand.Parameters.Add(AttendeesParam);
CommandParameter BodyParam = new CommandParameter("body", strBody);
myCommand.Parameters.Add(BodyParam);
CommandParameter AppIDParam = new CommandParameter("appid", strAppID);
myCommand.Parameters.Add(AppIDParam);
CommandParameter TenantIDParam = new CommandParameter("tenantid", strTenantID);
myCommand.Parameters.Add(TenantIDParam);
CommandParameter ClientSecretParam = new CommandParameter("clientsecret", strClientSecret);
myCommand.Parameters.Add(ClientSecretParam);
pipeline.Commands.Add(myCommand);
pipeline.Invoke();
runspace.Close();
}
catch (Exception ex)
{
result = ex.Message;
}
return result;
}
POWERSHELL CODE
[string]$subject,
[string]$startdatehour,
[string]$enddatehour,
[string]$location,
[string]$attendees,
[string]$appid,
[string]$tenantid,
[string]$clientsecret
)
Import-Module MSAL.PS
Import-Module Microsoft.Graph.Calendar
#Generate Access Token to use in the connection string to MSGraph
$AppId = $appid
$TenantId = $tenantid
$ClientSecret = $clientsecret
$MsalToken = Get-MsalToken -TenantId $TenantId -ClientId $AppId -ClientSecret ($ClientSecret | ConvertTo-SecureString -AsPlainText -Force)
#Connect to Graph using access token
Connect-MgGraph -AccessToken $MsalToken.AccessToken -Scopes "User.Read.All","Calendars.ReadWrite"
$params = #{
Subject = $subject
Start = #{
DateTime = $startdatehour
TimeZone = "GMT Standard Time"
}
End = #{
DateTime = $enddatehora
TimeZone = "GMT Standard Time"
}
Location = #{
DisplayName = $location
LocationType = "Default"
}
IsOnlineMeeting = $true
OnlineMeetingProvider = "teamsForBusiness"
Attendees = $attendees
}
# Create event
New-MgUserEvent -UserId "a#a.net" -BodyParameter $params´´´
Related
will appreciate any Help on this one.
I am trying to replace text in an email template using Mailkit. The issue is that in Mailkit there is at least a text part and and Html part.
I can get then set the text part using code such as:
var textPart = message.BodyParts.OfType<TextPart>().FirstOrDefault();
I can get the htmlbody using
var htmlPart = message.htmlBody
but once I modify it I do not know how to set the htmlpart to the message's htmlBody.
My code so far:
FileStream sr = new FileStream(fileLocation + "\\" + fileName, FileMode.Open, FileAccess.Read);
message = MimeMessage.Load(sr);
sr.Close();
//Get the text Part
var textPart = message.BodyParts.OfType<TextPart>().FirstOrDefault();
//Get the HtmlBody
var htmlPart = message.HtmlBody;
string regexPattern;
string regexReplacement;
Regex regexText;
foreach (var replaceSet in replaceArray)
{
regexPattern = "#" + replaceSet["Key"].ToString() + "#";
regexReplacement = (string)replaceSet["Value"].ToString();
//bool test = Regex.IsMatch(docText, regexPattern);
if (regexReplacement != "")
{
regexText = new Regex(regexPattern);
textPart.Text = regexText.Replace(textPart.Text, regexReplacement);
//Set, modify the text part
htmlPart = regexText.Replace(htmlPart, regexReplacement);
}
}
try
{
message.WriteTo(fileLocation + "\\output\\" + fileName);
}
catch (Exception Ex)
{
result = Ex.Message;
return BadRequest(result);
}```
Something like this will probably work:
// Get the text Part
var textPart = message.BodyParts.OfType<TextPart>().FirstOrDefault(x => x.IsPlain);
var htmlPart = message.BodyParts.OfType<TextPart>().FirstOrDefault(x => x.IsHtml);
string regexPattern;
string regexReplacement;
Regex regexText;
foreach (var replaceSet in replaceArray)
{
regexPattern = "#" + replaceSet["Key"].ToString() + "#";
regexReplacement = (string)replaceSet["Value"].ToString();
//bool test = Regex.IsMatch(docText, regexPattern);
if (regexReplacement != "")
{
regexText = new Regex(regexPattern);
textPart.Text = regexText.Replace(textPart.Text, regexReplacement);
//Set, modify the text part
htmlPart.Text = regexText.Replace(htmlPart.Text, regexReplacement);
}
}
I have a function that is able to send email by sending it through PowerShell.
Using the System.Management.Automation reference I am able to use the PowerShell class that allows me to add PowerShell script that will send the email.
If I were to type it directly into the PowerShell window it would look like this:
$password = ConvertTo-SecureString 'PASSWORD' -AsPlainText -Force
$Cred = New-Object System.Management.Automation.PSCredential('sender#email.com', $password)
Send-MailMessage -From 'sender#email.com' -To 'receiver#email.com' -Subject 'Heres the Email Subject' -Body 'This is what I want to say' -SmtpServer 'smtp.office365.com' -Port '587' -UseSsl -Credential $Cred –DeliveryNotificationOption OnSuccess
It is able to send an email but I how would I check if an email wasn't sent?
The function is below.
private void SendEmail()
{
string from = "sender#email.com";
string to = "receiver#email.com";
string subject = "Heres the Email Subject";
string body = "This is what I want to say";
string server = "smtp.office365.com";
string port = "587";
//Password goes here
string password = "PASSWORD";
string pw = "ConvertTo-SecureString '" + password + "' -AsPlainText -Force";
string cred = "New-Object System.Management.Automation.PSCredential('" + from + "', $password)";
string send = "Send-MailMessage -From '" + from + "' -To '" + to + "' -Subject '" + subject + "' -Body '" + body + "' -SmtpServer '" + server + "' -Port '" + port + "' -UseSsl -Credential $Cred -DeliveryNotificationOption OnSuccess";
string psScript = "$password = " + pw + System.Environment.NewLine +
"$Cred = " + cred + System.Environment.NewLine +
send;
using (PowerShell ps = PowerShell.Create())
{
ps.AddScript(psScript);
// invoke execution on the pipeline (collecting output)
Collection<PSObject> PSOutput = ps.Invoke();
// loop through each output object item
foreach (PSObject outputItem in PSOutput)
{
// if null object was dumped to the pipeline during the script then a null
// object may be present here. check for null to prevent potential NRE.
if (outputItem != null)
{
//TODO: do something with the output item
Console.WriteLine(outputItem.BaseObject.GetType().FullName);
Console.WriteLine(outputItem.BaseObject.ToString() + "\n");
}
}
}
}
I found a way to check for errors using ps.HadErrors
using (PowerShell ps = PowerShell.Create())
{
//Add the powershell script to the pipeline
ps.AddScript(psScript);
// invoke execution on the pipeline (collecting output)
Collection<PSObject> PSOutput = ps.Invoke();
//check for any errors
if (ps.HadErrors)
{
foreach (var errorRecord in ps.Streams.Error)
{
Console.WriteLine(errorRecord);
}
}
}
I have written a console application wherein I have called a powershell script from the console. In the powershell script I have written hello world as a return variable and it is running as expected but next time when I change the string from hello world to How are you it is not displaying the changed string. I cannot figure out myself what needs to be done to clear the pipeline or cache.
I have used the below namespace apart from default namespaces
using System.Management;
using System.Management.Automation;
using System.Collections.ObjectModel;
using System.Management.Automation.Runspaces;
static void Main(string[] args)
{
string _str = string.Empty;
_str= RunScript(#"C:\Powershell_Scripts\Test.ps1");
Console.WriteLine("Input String is =" + str);
Console.Read();
}
private static string RunScript(string scriptText)
{
// create Powershell runspace
Runspace runspace = RunspaceFactory.CreateRunspace();
// open it
runspace.Open();
// create a pipeline and feed it the script text
Pipeline pipeline = runspace.CreatePipeline();
pipeline.Commands.AddScript("Set-ExecutionPolicy -Scope Process -ExecutionPolicy Unrestricted");
pipeline.Commands.AddScript(scriptText);
// add an extra command to transform the script
// output objects into nicely formatted strings
// remove this line to get the actual objects
// that the script returns. For example, the script
// "Get-Process" returns a collection
// of System.Diagnostics.Process instances.
pipeline.Commands.Add("Out-String");
// execute the script
Collection <PSObject> results = pipeline.Invoke();
pipeline.Streams.ClearStreams();
// close the runspace
runspace.Close();
// convert the script result into a single string
StringBuilder stringBuilder = new StringBuilder();
foreach (PSObject obj in results)
{
stringBuilder.AppendLine(obj.ToString());
}
return stringBuilder.ToString();
}
Powershell Script i.e. Test1.ps1
sleep 3
$a=""
$a = "Hello word"
return $a
Here is a sample how to use the PowerShell in a Runspace
using System;
using System.Collections.Generic;
using System.Text;
using System.Management;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
// Create a runspace.
using (Runspace myRunSpace = RunspaceFactory.CreateRunspace())
{
myRunSpace.Open();
using (PowerShell powershell = PowerShell.Create())
{
// Create a pipeline with the Get-Command command.
powershell.AddScript("Set-ExecutionPolicy -Scope Process -ExecutionPolicy Unrestricted");
powershell.AddScript(#"C:\Users\you\Desktop\a.ps1");
// add an extra command to transform the script output objects into nicely formatted strings
// remove this line to get the actual objects
powershell.AddCommand("Out-String");
// execute the script
var results = powershell.Invoke();
powershell.Streams.ClearStreams();
powershell.Commands.Clear();
// convert the script result into a single string
StringBuilder stringBuilder = new StringBuilder();
foreach (PSObject obj in results)
{
stringBuilder.AppendLine(obj.ToString());
}
Console.WriteLine(stringBuilder.ToString());
}
}
}
}
}
Further reference: Creating a constrained runspace
Here is a code which runs as expected
enter code here
try
{
if (System.IO.File.Exists(#"c:\disk\op.txt") && (new FileInfo(#"c:\disk\op.txt").Length != 0))
{
System.IO.File.Move(#"c:\disk\op.txt", #"c:\disk\Previous_op_" + DateTime.Now.ToString("dd_MM_yyyy hh mm") + ".txt");
log.Info("Previous Output File Successfully Renamed");
}
// TODO: Add delete logic here
log.Info("Input ActionResult - Server " + Server);
log.Info("Input ActionResult - Volume " + Volume);
log.Info("Input ActionResult - Size " + size);
string userID = "dir\\" + Session["Uname"].ToString();
string userpassword = Session["Upwd"].ToString();
log.Info("username " + userID);
StringBuilder stringBuilder = new StringBuilder();
var con = new WSManConnectionInfo();
log.Info("Pushing username in PSCredential- " + userID.ToString().Trim());
con.Credential = new PSCredential(userID.ToString().Trim(), userpassword.ToString().Trim().ToSecureString());
Runspace runspace = RunspaceFactory.CreateRunspace(con);
runspace.Open();
Pipeline pipeline = runspace.CreatePipeline();
pipeline.Commands.AddScript("Set-ExecutionPolicy -Scope Process -ExecutionPolicy Unrestricted");
string _str = #"-Server " + Server + " -Volumeletter " + Volume + ": -deltasize " + size + " -Logfile c:\\disk\\op.txt -username " + userID + " -password " + userpassword;
log.Info("Parameter string format- " + _str.Substring(0, _str.IndexOf("-password") + 9));
pipeline.Commands.AddScript(#"C:\disk\diskerr.ps1 " + _str.ToString());
pipeline.Commands[0].MergeMyResults(PipelineResultTypes.Error, PipelineResultTypes.Output);
pipeline.Commands.Add("Out-String");
var results = pipeline.Invoke();
runspace.Close();
runspace.Dispose();
foreach (PSObject obj in results)
{
stringBuilder.AppendLine(obj.ToString());
log.Info("Output from powershell: " + obj.ToString());
}
if (System.IO.File.Exists(#"c:\disk\op.txt") && (new FileInfo(#"c:\disk\op.txt").Length != 0))
{
fileStream = new FileStream(#"c:\test\op.txt", FileMode.Open, FileAccess.Read);
using (var streamReader = new StreamReader(fileStream, Encoding.UTF8))
{
_consoleOutput = streamReader.ReadToEnd();
}
_output = Regex.Replace(_consoleOutput, #"\r\n?|\n", "<br />");
}
return Content(_output);
}
catch (Exception ex)
{
log.Info("Error stackTrace inside Input ActionResult " + ex.StackTrace.ToString());
log.Info("Error Message inside Input ActionResult " + ex.Message.ToString());
return View();
}
You need to change the directory path and the powershell file name.
The problem I am facing is that, payfort API should return me some json. But instead i get some html that has some hidden fields. and i see no error written inside there.
Here is my code
string access_code = string.Empty,
amount = string.Empty,
currency = string.Empty,
customer_email = string.Empty,
merchant_reference = string.Empty,
order_description = string.Empty,
language = string.Empty,
merchant_identifier = string.Empty,
signature = string.Empty,
command = string.Empty;
access_code = "X78979879h8h8h8";
amount = "1000";
command = "AUTHORIZATION";
currency = "AED";
customer_email = "zetawars#hotmail.com";
language = "en";
merchant_identifier = "RaskdQuCc";
merchant_reference = "ASASASASASADSS";
order_description = "Some order details";
signature = "";
string signature_string = "PASSaccess_code="+access_code+"amount="+amount+"command="+command+"currency="+currency+"customer_email"+customer_email+"language"+language+"merchant_identifier"+merchant_identifier+"merchant_reference"+merchant_reference+"order_description"+order_description+"PASS";
signature = getHashSha256(signature_string);
string url = "https://sbcheckout.payfort.com/FortAPI/paymentPage";
string param = "access_code" + access_code + "&amount=" + amount + "¤cy=" + currency +
"&customer_email=" + customer_email + "&merchant_reference=" + merchant_reference +
"&order_description=" + order_description + "&language=" + language + "merchant_identifier="
+ merchant_identifier + "&signature=" + signature + "&command=" + command;
using (WebClient wc = new WebClient())
{
wc.Headers[HttpRequestHeader.ContentType] = "application/json";
//wc.Headers.Add("Content-Type", "application/json");
string HtmlResult = wc.UploadString(url, param);
}
Try adding values for below header
wc.Headers[HttpRequestHeader.Authorization]
wc.Headers[HttpRequestHeader.TenantId]
wc.Headers[HttpRequestHeader.Client-Type]
wc.Headers[HttpRequestHeader.Protocol]
Works for me!!
First Encode the response
string responseString = Encoding.UTF8.GetString(response);
Use HtmlDocument (HtmlAgilityPack)
var html = new HtmlDocument();
var tokenValue = "";
html.LoadHtml(responseString);
After Loading This into html you can query fields and values.
var tokenFormIdElement =
html.DocumentNode.SelectSingleNode("//input[#name='token']");
tokenValue = tokenFormIdElement.GetAttributeValue("value", "");
I created a website that does remotely execute powershell to specific server. I would like to know how it work to pass 2 user selected values to commandline from dropdownlist on asp.net website along with powershell script file?
I already have working code with powershell script file but now adding 2 arguments in script file.The powershell arguments is,
[string]$ContainerIn=$args[0]
[int]$ips2get=$args[1]
Here a C# working codes,
//These 3 input varaibles will pass to powershell script to get specific results
string env = "";
string container = "";
string numIPs = "";
//assign dropdown selected value to variable to pass to script
container = DropDownListContainer.SelectedValue;
numIPs = DropDownListIP.SelectedValue;
if (container == "H02" || container == "H07" || container == "H08")
{
env = "Prod";
}
else
{
env = "NonProd";
}
// Create a Powershell
Runspace runSpace = RunspaceFactory.CreateRunspace();
runSpace.Open();
Pipeline pipeline = runSpace.CreatePipeline();
Command invokeScript = new Command("Invoke-Command");
RunspaceInvoke invoke = new RunspaceInvoke();
//Add powershell command/script functions into scriptblock
//Somewhere on this codes that it need to add command line to go with Get-FreeAddress.ps1 file script
ScriptBlock sb = invoke.Invoke(#"{D:\Scripts\Get-FreeAddress.ps1}")[0].BaseObject as ScriptBlock;
//ScriptBlock sb = invoke.Invoke("{" + PowerShellCodeBox.Text + "}")[0].BaseObject as ScriptBlock;
invokeScript.Parameters.Add("scriptBlock", sb);
invokeScript.Parameters.Add("computername", TextBoxServer.Text);
pipeline.Commands.Add(invokeScript);
Collection<PSObject> output = pipeline.Invoke();
//splitting results in new lines
foreach (PSObject psObject in output)
{
str = str + psObject + "\r\n";
//str = psObject + "\r\n";
//str += "\n" + psObject;
//str = str + Environment.NewLine + psObject;
}
if (str == "")
{
str = "Error";
ResultBox.ForeColor = System.Drawing.ColorTranslator.FromHtml("#FF0000");
}
//print out powershell output result
ResultBox.Text = str;
}
I finally made this work,
I just need to modify to
ScriptBlock sb = invoke.Invoke(#"{D:\Scripts\Get-FreeAddress.ps1 '"+container+"' "+numIPs+"}")[0].BaseObject as ScriptBlock;
The powershell script argument will get container and numIPs variables.