Powershell errors in ASP.NET

I have written a custom webapp to collect information from an ASP web form and execute a powershell script asyncronously to create a useraccount in AD based on the information collected.

What I want to achieve is some form of error handling in the powershell script, if a user account exists in AD store the error and display it on the asp page.

Below is the verification.aspx.cs file;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using System.Management.Automation.Host;
using System.Text;
using System.IO;
using System.Diagnostics;
using System.Net.Mail;

public partial class Account_Registration : System.Web.UI.Page
{
    Runspace runspace = RunspaceFactory.CreateRunspace();
    Pipeline pipe;

    void Output_DataReady(object sender, EventArgs e)
    {
        PipelineReader<PSObject> reader = (PipelineReader<PSObject>)sender;
        String strPowershellTrace = reader.Read().ToString();
        Session["PowerTrace"] += strPowershellTrace + "\r\n";
    }

    private void executePowerShellCode(string code)
    {
        runspace.Open();
        pipe = runspace.CreatePipeline(code);
        pipe.Input.Close();
        // Call output_DataReady when data arrived in the pipe
        pipe.Output.DataReady += new EventHandler(Output_DataReady);
        // Call pipe_StateChanged
        pipe.StateChanged += new EventHandler<PipelineStateEventArgs>(pipe_StateChanged);
        pipe.InvokeAsync();
    }

    void pipe_StateChanged(object sender, PipelineStateEventArgs e)
    {
        if (pipe.PipelineStateInfo.State == PipelineState.Completed)
        {
            runspace.Close();
            while ((Session["PowerTrace"] != null) && (Session["PowerTrace"].ToString().Length > 0))
            {
            }
            Session.Remove("PowerTrace");
        }
    }

    protected void Page_Load(object sender, EventArgs e)
    {

    }

    protected void ExecuteCode_Click(object sender, EventArgs e)
    {

        //Create GUID
        string activationCode = Guid.NewGuid().ToString();

        // Initialize PowerShell engine
        var shell = PowerShell.Create();

        //script modification before execution
        string strcontents = null;
        using (StreamReader objReader = new StreamReader(Server.MapPath("~/scripts/verification.ps1")))
        {
            strcontents = objReader.ReadToEnd();
        }
        strcontents = strcontents.Replace("*StudentID*", StudentID.Text);
        strcontents = strcontents.Replace("*email*", ConfirmEmailAddress.Text);
        strcontents = strcontents.Replace("*Password*", ConfirmPassword.Text);
        strcontents = strcontents.Replace("*GUID*", activationCode);

        this.executePowerShellCode(strcontents);

        MailMessage message = new MailMessage();
       
        message.From = new MailAddress("foo@bar.com");
        message.To.Add(new MailAddress(ConfirmEmailAddress.Text));
        message.Subject = "Self Service Portal Registration Verification";

        string mailbody = "To confirm your account, please verify your account by clicking the link below";
        mailbody += "<Br /> <a href= 'http://verify.someURL/confirm.aspx?userid=" + StudentID.Text + "&guid=" + activationCode + "'> Click here to activate your account.</a>";
       
        message.IsBodyHtml = true;
        message.Body = mailbody;
        SmtpClient client = new SmtpClient();
        client.Send(message);

 

         // Clean Input TextBoxes
        StudentID.Text = string.Empty;
        EmailAddress.Text = string.Empty;
        ConfirmEmailAddress.Text = string.Empty;
        Password.Text = string.Empty;
        ConfirmPassword.Text = string.Empty;

        Response.Write("<script>alert('Email Verification Sent. Please check your email account to complete registration.'); self.close();</script>");
    }
}

below is verification.ps1;

$PW= "*Password*"
$user= "*StudentID*"
$GUID= "*GUID*"
$emailaddress = "*email*"
$date = get-date
$expiration = $date.addmonths(6)

import-module activedirectory

$domainUsersDN= (Get-ADGroup "domain users").distinguishedname
$TestGroupDN= (Get-ADGroup "SEC_StudentONLY").distinguishedname
$TestGroupSID = "2722"

#Convert password to secure String
$SecurePW=CONVERTTO-Securestring $PW -asplaintext -force

#Create User
New-ADUser $user -UserPrincipalName "$($user)@student.external" -Description $GUID -AccountPassword $SecurePW -emailaddress $emailaddress -AccountexpirationDate $expiration -Path 'OU=STUDENTS,DC=contoso,DC=com' -Enabled $false
Add-ADprincipalGroupMembership -identity $user -memberof $TestGroupDN
get-aduser $user -Properties * | Set-ADUser -Replace @{primaryGroupID= $TestGroupSID}
Remove-ADprincipalGroupMembership -identity $user -memberof $domainUsersDN -Confirm:$false
LVL 1
David McIntoshAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

David Johnson, CD, MVPOwnerCommented:
code blocks
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using System.Management.Automation.Host;
using System.Text;
using System.IO;
using System.Diagnostics;
using System.Net.Mail;

public partial class Account_Registration : System.Web.UI.Page
{
    Runspace runspace = RunspaceFactory.CreateRunspace();
    Pipeline pipe;

    void Output_DataReady(object sender, EventArgs e)
    {
        PipelineReader<PSObject> reader = (PipelineReader<PSObject>)sender;
        String strPowershellTrace = reader.Read().ToString();
        Session["PowerTrace"] += strPowershellTrace + "\r\n";
    }

    private void executePowerShellCode(string code)
    {
        runspace.Open();
        pipe = runspace.CreatePipeline(code);
        pipe.Input.Close();
        // Call output_DataReady when data arrived in the pipe
        pipe.Output.DataReady += new EventHandler(Output_DataReady);
        // Call pipe_StateChanged
        pipe.StateChanged += new EventHandler<PipelineStateEventArgs>(pipe_StateChanged);
        pipe.InvokeAsync();
    }

    void pipe_StateChanged(object sender, PipelineStateEventArgs e)
    {
        if (pipe.PipelineStateInfo.State == PipelineState.Completed)
        {
            runspace.Close();
            while ((Session["PowerTrace"] != null) && (Session["PowerTrace"].ToString().Length > 0))
            {
            }
            Session.Remove("PowerTrace");
        }
    }

    protected void Page_Load(object sender, EventArgs e)
    {

    }

    protected void ExecuteCode_Click(object sender, EventArgs e)
    {

        //Create GUID
        string activationCode = Guid.NewGuid().ToString();

        // Initialize PowerShell engine
        var shell = PowerShell.Create();

        //script modification before execution
        string strcontents = null;
        using (StreamReader objReader = new StreamReader(Server.MapPath("~/scripts/verification.ps1")))
        {
            strcontents = objReader.ReadToEnd();
        }
        strcontents = strcontents.Replace("*StudentID*", StudentID.Text);
        strcontents = strcontents.Replace("*email*", ConfirmEmailAddress.Text);
        strcontents = strcontents.Replace("*Password*", ConfirmPassword.Text);
        strcontents = strcontents.Replace("*GUID*", activationCode);

        this.executePowerShellCode(strcontents);

        MailMessage message = new MailMessage();
       
        message.From = new MailAddress("foo@bar.com");
        message.To.Add(new MailAddress(ConfirmEmailAddress.Text));
        message.Subject = "Self Service Portal Registration Verification";

        string mailbody = "To confirm your account, please verify your account by clicking the link below";
        mailbody += "<Br /> <a href= 'http://verify.someURL/confirm.aspx?userid=" + StudentID.Text + "&guid=" + activationCode + "'> Click here to activate your account.</a>";
       
        message.IsBodyHtml = true;
        message.Body = mailbody;
        SmtpClient client = new SmtpClient();
        client.Send(message);

 

         // Clean Input TextBoxes
        StudentID.Text = string.Empty;
        EmailAddress.Text = string.Empty;
        ConfirmEmailAddress.Text = string.Empty;
        Password.Text = string.Empty;
        ConfirmPassword.Text = string.Empty;

        Response.Write("<script>alert('Email Verification Sent. Please check your email account to complete registration.'); self.close();</script>");
    }
}

Open in new window


below is verification.ps1;

$PW= "*Password*"
$user= "*StudentID*"
$GUID= "*GUID*"
$emailaddress = "*email*"
$date = get-date
$expiration = $date.addmonths(6)

import-module activedirectory

$domainUsersDN= (Get-ADGroup "domain users").distinguishedname
$TestGroupDN= (Get-ADGroup "SEC_StudentONLY").distinguishedname
$TestGroupSID = "2722"

#Convert password to secure String
$SecurePW=CONVERTTO-Securestring $PW -asplaintext -force

Open in new window

#Create User
New-ADUser $user -UserPrincipalName "$($user)@student.external" -Description $GUID -AccountPassword $SecurePW -emailaddress $emailaddress -AccountexpirationDate $expiration -Path 'OU=STUDENTS,DC=contoso,DC=com' -Enabled $false
Add-ADprincipalGroupMembership -identity $user -memberof $TestGroupDN
get-aduser $user -Properties * | Set-ADUser -Replace @{primaryGroupID= $TestGroupSID}
Remove-ADprincipalGroupMembership -identity $user -memberof $domainUsersDN -Confirm:$false 

Open in new window

0
David Johnson, CD, MVPOwnerCommented:
add try/catch blocks to check for errors and have some way of dealing with the errors
0
David McIntoshAuthor Commented:
I had been playing with try/catch but had been unable to find a way to output the error synchronously back to the page to throw the error
0
Chris DentPowerShell DeveloperCommented:
Non-terminating errors are returned to shell.Streams.Error (as a collection of System.Management.Automation.ErrorRecord).

Terminating errors require handling with try / catch. Given that you're running a script it might be best to handle everything in PowerShell such that only non-terminating errors are returned.

Chris
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
David McIntoshAuthor Commented:
Thank you this lead me in the right direct now running with a try/catch and parsing PSErrorOutput back to a text box.

ASPX.CS
try

           {

               PSErrorOutput = pipe.InvokeAsync();

           }

           catch (Exception ex) { PSErrorOutput = "Error: " + ex.Message; }

           finally { pipe.Dispose(); }

           return PSOutput;

       }

ASPX-
PSErrorOutput.Text = exCmdletResult;
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
ASP.NET

From novice to tech pro — start learning today.