Customise the system Exception instance to pass two parameters - c#

I need to customise the system exception without using the user defined exception classes.
Following is my requirement.
String ErrorMessage="";
Exception e= new Exception (ErrorMessage);
then I need to throw errorMessage string with one integer parameter for the upper layer in my project.
So can someone please let me know if I can customise the system Exception instance to pass two parameters (Integer value and errorMessage string)?

Some real example:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ExceptionExamples
{
public static class Error
{
[Serializable]
public class RegistryReadException : Exception
{
/// <summary>
/// Message template
/// </summary>
static string msg = "Can't parse value from Windows Registry.\nKey: {0}\nValue: {1}\nExpected type: {2}";
/// <summary>
/// Can't read value from registry
/// </summary>
/// <param name="message"></param>
public RegistryReadException(
string message)
: base(message) { }
/// <summary>
/// Can't read value from registry
/// </summary>
/// <param name="key">Key path</param>
/// <param name="value">Real value</param>
/// <param name="type">Expected type</param>
public RegistryReadException(
string key, string value, Type type)
: base( string.Format(msg, key, value, type.Name) ) { }
}
}
}

This is simply not possible.
Your only option is to create a new class that inherits from System.Exception or some other exception class and add whatever you need in there.
If you can't or won't do that, then you can't do what you want.

You can create some custom Exception classes and throw it using the same code TryCatch. But in the upper layer you can catch not by generic Exception, using your custom type.
Try
{
//Your try code Here
if(/*Something Happens*/)
{
throw new YourCustomExceptionClass("Message");
}
else
{
throw new AnotherCustomExceptionClass("Other Message");
}
}
Catch(YourCustomExceptionClass err)
{
//This will be a type of exception
}
Catch(AnotherCustomExceptionClass err)
{
//This will be another type of Exception
}

Related

How do I create an interactive Powershell instance from C#?

I have a Powershell script that requires user interaction. I can call powershell.exe from C# using System.Diagnostics.Process and pass the scripts path as a parameter but I would like the script to be an embedded resource of the project. I tried creating a Runspace (see below) and running the script but because the script requires user interaction I receive an exception.
var assembly = Assembly.GetExecutingAssembly();
var resourceName = "mynamespace.myscriptfile.ps1";
string result = "";
using (Stream stream = assembly.GetManifestResourceStream(resourceName))
using (StreamReader reader = new StreamReader(stream))
{
result = reader.ReadToEnd();
Console.WriteLine(result);
}
//Create Powershell Runspace
Runspace runspace = RunspaceFactory.CreateRunspace();
runspace.Open();
// Create pipeline and add commands
Pipeline pipeline = runspace.CreatePipeline();
pipeline.Commands.AddScript(result);
// Execute Script
Collection<PSObject> results = new Collection<PSObject>();
try
{
results = pipeline.Invoke();
}
catch (Exception ex)
{
results.Add(new PSObject((object)ex.Message));
}
runspace.Close();
Console.ReadKey();
Is there a way to either pass the embedded resource to powershell.exe using System.Diagnostics.Process or is there a way to Invoke the script from C# where the user can interact?
UPDATE:
It seems to me that I may be able to use an implementation of the abstract class PSHost along with using the PSHostUserInterface property correctly, I may be able to create a Runspace that takes the PSHost implementation as a parameter to use the native Powershell console. I have been trying to test the idea but I'm not quite sure how to implement the abstract class.
Below is a sample of code that I obtained from Microsoft. I am confused with a couple of things. If it matters I will be creating the Runspace in a console application with a namespace called: WebRequirements in the Program class.
private Host01 program; (Would Host01 be Program?)
PSHostUserInterface (Is this where I would dictate that I want to use a native Powershell host and if so how would I do that?)
internal class MyHost : PSHost
{
///
/// A reference to the PSHost implementation.
///
private Host01 program;
/// <summary>
/// The culture information of the thread that created
/// this object.
/// </summary>
private CultureInfo originalCultureInfo =
System.Threading.Thread.CurrentThread.CurrentCulture;
/// <summary>
/// The UI culture information of the thread that created
/// this object.
/// </summary>
private CultureInfo originalUICultureInfo =
System.Threading.Thread.CurrentThread.CurrentUICulture;
/// <summary>
/// The identifier of this PSHost implementation.
/// </summary>
private Guid myId = Guid.NewGuid();
/// <summary>
/// Initializes a new instance of the MyHost class. Keep
/// a reference to the host application object so that it
/// can be informed of when to exit.
/// </summary>
/// <param name="program">
/// A reference to the host application object.
/// </param>
public MyHost(Host01 program)
{
this.program = program;
}
/// <summary>
/// Return the culture information to use. This implementation
/// returns a snapshot of the culture information of the thread
/// that created this object.
/// </summary>
public override System.Globalization.CultureInfo CurrentCulture
{
get { return this.originalCultureInfo; }
}
/// <summary>
/// Return the UI culture information to use. This implementation
/// returns a snapshot of the UI culture information of the thread
/// that created this object.
/// </summary>
public override System.Globalization.CultureInfo CurrentUICulture
{
get { return this.originalUICultureInfo; }
}
/// <summary>
/// This implementation always returns the GUID allocated at
/// instantiation time.
/// </summary>
public override Guid InstanceId
{
get { return this.myId; }
}
/// <summary>
/// Return a string that contains the name of the host implementation.
/// Keep in mind that this string may be used by script writers to
/// identify when your host is being used.
/// </summary>
public override string Name
{
get { return "MySampleConsoleHostImplementation"; }
}
/// <summary>
/// This sample does not implement a PSHostUserInterface component so
/// this property simply returns null.
/// </summary>
public override PSHostUserInterface UI
{
get { return null; }
}
/// <summary>
/// Return the version object for this application. Typically this
/// should match the version resource in the application.
/// </summary>
public override Version Version
{
get { return new Version(1, 0, 0, 0); }
}
/// <summary>
/// Not implemented by this example class. The call fails with
/// a NotImplementedException exception.
/// </summary>
public override void EnterNestedPrompt()
{
throw new NotImplementedException(
"The method or operation is not implemented.");
}
/// <summary>
/// Not implemented by this example class. The call fails
/// with a NotImplementedException exception.
/// </summary>
public override void ExitNestedPrompt()
{
throw new NotImplementedException(
"The method or operation is not implemented.");
}
/// <summary>
/// This API is called before an external application process is
/// started. Typically it is used to save state so the parent can
/// restore state that has been modified by a child process (after
/// the child exits). In this example, this functionality is not
/// needed so the method returns nothing.
/// </summary>
public override void NotifyBeginApplication()
{
return;
}
/// <summary>
/// This API is called after an external application process finishes.
/// Typically it is used to restore state that a child process may
/// have altered. In this example, this functionality is not
/// needed so the method returns nothing.
/// </summary>
public override void NotifyEndApplication()
{
return;
}
/// <summary>
/// Indicate to the host application that exit has
/// been requested. Pass the exit code that the host
/// application should use when exiting the process.
/// </summary>
/// <param name="exitCode">The exit code to use.</param>
public override void SetShouldExit(int exitCode)
{
this.program.ShouldExit = true;
this.program.ExitCode = exitCode;
}
}

How to store multiple value types in a property?

I have an events class that I'm creating, that currently looks like the following:
public class SharePointOnErrorEventsArgs : EventArgs
{
public SharePointOnErrorEventsArgs(string message, bool showException, Exception exception)
{
Message = message;
Exception = exception;
ShowException = showException;
}
/// <summary>
/// Property to allow the storage of a more verbose and explainable error message
/// </summary>
public string Message { get; private set; }
/// <summary>
/// Object to store full exception information within
/// </summary>
public Exception Exception { get; private set; }
/// <summary>
/// Boolean value allows for verbose messages to be sent up the stack without
/// the need for displaying a full exception object, or stack trace.
/// </summary>
public bool ShowException { get; private set; }
}
Now, instead of sending true or false for showException I'd like to send one of three values Debug, Info or Error - how can I tackle something like this? I don't really want to use a string as I want to always restrict this to one of those three values, but I'm unsure how to approach this when using properties.
You can use an enum:
public enum ShowExceptionLevel
{
Debug,
Info,
Error
}
So your class will be:
public class SharePointOnErrorEventsArgs : EventArgs
{
public enum ShowExceptionLevel
{
Debug,
Info,
Error
}
public SharePointOnErrorEventsArgs(string message, ShowExceptionLevel showExceptionLevel, Exception exception)
{
Message = message;
Exception = exception;
ShowException = showException;
}
/// <summary>
/// Property to allow the storage of a more verbose and explainable error message
/// </summary>
public string Message { get; private set; }
/// <summary>
/// Object to store full exception information within
/// </summary>
public Exception Exception { get; private set; }
/// <summary>
/// Boolean value allows for verbose messages to be sent up the stack without
/// the need for displaying a full exception object, or stack trace.
/// </summary>
public ShowExceptionLevel ShowException { get; private set; }
}

Pass Exception and Subclasses over NamedPipe

I'm trying to pass objects of type Exception (or one of it's subclasses) over a NamedPipe.
ServiceContract:
[ServiceContract]
public interface IWCFCallback
{
[OperationContract]
void sendException(Exception e);
}
it works fine when i use it like this:
_pipeproxy.sendException(new Exception("bla bla 99"));
but as soon as I pass a subclass:
_pipeproxy.sendException(new ArgumentException("fridgemaster 3000"));
I get a Exception, saying deserialisation failed.
I already read about the KnownTypes Attribute, but i can't figure out how to use it for classes not implemented by myself.
Can someone give me a hint here?
One of the "Best practices" over WCF, is Do not serialize Exception.
If your ServiceHost is throwing exception, then you are suppose to use FaultException.
One of the reason why exception is not safe to transfer, is that Exception itself is serializable, but you can derive from it, and who guarantee that your custom derived exception will be serialable.
You could pass a Data contract object with the exception stack as string and type as enum, as a work-around.
This may not be according to the best practices but you can create a DataContract that represents the Exception - something like this:
/// <summary>
/// Represents errors that occur during application execution.
/// </summary>
[DataContract]
public class ExceptionInfo
{
/// <summary>
/// Gets the type of the exception.
/// </summary>
[DataMember]
public string ExceptionType
{
get;
set;
}
/// <summary>
/// Gets a message that describes the current exception.
/// </summary>
/// <returns>
/// The error message that explains the reason for the exception, or an empty string("").
/// </returns>
[DataMember]
public string Message
{
get;
set;
}
/// <summary>
/// Gets the <see cref="T:System.Exception"/> instance that caused the current exception.
/// </summary>
/// <returns>
/// An instance of Exception that describes the error that caused the current exception. The InnerException property returns the same value as was passed into the constructor, or a null reference (Nothing in Visual Basic) if the inner exception value was not supplied to the constructor. This property is read-only.
/// </returns>
[DataMember]
public ExceptionInfo InnerException
{
get;
set;
}
/// <summary>
/// Gets a string representation of the immediate frames on the call stack.
/// </summary>
/// <returns>
/// A string that describes the immediate frames of the call stack.
/// </returns>
[DataMember]
public string StackTrace
{
get;
set;
}
/// <summary>
/// Gets or sets a link to the help file associated with this exception.
/// </summary>
/// <returns>
/// The Uniform Resource Name (URN) or Uniform Resource Locator (URL).
/// </returns>
[DataMember]
public string HelpLink
{
get;
set;
}
/// <summary>
/// Gets or sets the name of the application or the object that causes the error.
/// </summary>
[DataMember]
public string Source
{
get;
set;
}
/// <summary>
/// Initializes a new instance of the <see cref="ExceptionInfo"/> class.
/// </summary>
/// <param name="exception">The exception.</param>
/// <exception cref="ArgumentNullException">exception</exception>
public ExceptionInfo(Exception exception)
{
if(exception == null)
throw new ArgumentNullException("exception");
ExceptionType = exception.GetType().FullName;
HelpLink = exception.HelpLink;
Message = exception.Message;
Source = exception.Source;
StackTrace = exception.StackTrace;
if(exception.InnerException != null)
{
InnerException = new ExceptionInfo(exception.InnerException);
}
}
}
Service Contract:
[ServiceContract]
public interface IWCFCallback
{
[OperationContract]
void sendException(ExceptionInfo e);
}
Usage:
try
{
// .....
}
catch (Exception ex)
{
var info = new ExceptionInfo(ex);
// do something....
}

I'm not sure if my game is working yet

My friend and I have been working on a game and we have a trace listener set up, here's some of the code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
namespace GuiGame {
/// <summary>
/// A type of Trace Listener that sends its output to a ListBox.
/// </summary>
public class ListBoxTraceListener : TraceListener {
private ListBox listBox; // A reference to the listbox that we're writing to.
private string stringToAddToListBox = "";
private const char NEW_LINE = '\n';
/// <summary>
/// Parameterless constructor.
/// Do not want the generic default constructor to be used
/// as there is no way to set the ListBoxTraceListener's data.
/// This replaces the compiler's generic default constructor.
/// Pre: none
/// Post: ALWAYS throws an ArgumentException.
/// </summary>
/// <remarks>NOT TO BE USED!</remarks>
public ListBoxTraceListener() {
throw new ArgumentException("Parameterless constructor invalid.");
} // end ListBoxTraceListener constructor
/// <summary>
/// Constructor with initialising parameters.
/// Pre: the existence of a ListBox on a GUI form.
/// Post: initialised object.
/// </summary>
/// <param name="listBox">The ListBox that we're writing to.</param>
public ListBoxTraceListener(ListBox listBox) {
this.listBox = listBox;
}
/// <summary>
/// Automatically collects the outputs from all Trace.WriteLine statements.
/// Pre: none.
/// Post: the string s is displayed in the listBox.
/// </summary>
/// <param name="s"></param>
public override void WriteLine(string s) {
Write(s + NEW_LINE);
} //end WriteLine
/// <summary>
/// Automatically collects the outputs from all Trace.Write statements.
/// Pre: none.
/// Post: the string s is displayed in the listBox, once we receive a NEW_LINE.
/// </summary>
/// <param name="s"></param>
public override void Write(string s) {
stringToAddToListBox += s;
// If we have one or more complete lines
if (stringToAddToListBox.Contains (NEW_LINE)) {
// Split the string into multiple lines.
// If NEW_LINE is found at the beginning or end of the string,
// then the corresponding array element contains an empty string.
string[] lines = stringToAddToListBox.Split(NEW_LINE);
// Add all the lines to the listbox, except for the last one.
// When stringToAddToListBox has a new-line at the end,
// the last element in lines[] will be an empty string.
int highestLineNumber = lines.Length - 1;
for (int i = 0; i < highestLineNumber; i++) {
AddToListBox(lines[i]);
}
// Reset stringToAddToListBox to what remains. (May be an empty string).
stringToAddToListBox = lines[highestLineNumber];
}
} // end Write
/// <summary>
/// Adds a complete output-line to the ListBox.
/// Pre: none.
/// Post: the string listBoxLine is displayed in the listBox .
/// </summary>
/// <param name="listBoxLine"></param>
private void AddToListBox(string listBoxLine) {
Debug.Assert(listBox != null, "listBox != null");
listBox.Items.Add(listBoxLine);
} // end AddToListBox
}
}
At this stage we are just trying to use the trace listener to output some text on in the ListBox so we know it is working, so we have an event handler setup:
private void RollDiceButton_Click(object sender, EventArgs e)
{
}
We haven't been able to get any output from the trace listener. The Add method as the trace listener is not set up for that. Can anyone provide some suggestions please? I think maybe we are doing something really stupid and obvious that we have missed.
The most probable cause of your issue is that your application is single threaded (as most simple Windows applications are). This means that although you are sending messages to the listview to append a new element to the list, the message is not yet handled just because your original handler hasn't returned yet (the RollDiceButton_Click).
To work this around, you should force the list to refresh itself from within the current handler:
private void AddToListBox(string listBoxLine) {
Debug.Assert(listBox != null, "listBox != null");
listBox.Items.Add(listBoxLine);
// this would help?
listBox.Refresh();
} // end
If this doesn't help, try temporarily switching to unconditional processing of all pending events with
private void AddToListBox(string listBoxLine) {
Debug.Assert(listBox != null, "listBox != null");
listBox.Items.Add(listBoxLine);
// this would help?
Application.DoEvents();
} // end
and report back.

What is the correct way to validate the arguments of a constructor

So I have a class with a single string parameter in its constructor:
public MyClass(string name)
{
this.Name = name;
}
but I never want to worry about some one initializing an instance of MyClass with name that is NULL or a zero length string. What is the best was to validate the parameter? With a property or method you can always just do nothing, return null, or not set anything if an invalid argument is provided. But once a constructor is called the instance of the object is already created regardless of whether it was passed valid arguments.
Is throwing an exception as shown below the best way? Or is there some other method that's more preferred?
public MyClass(string name)
{
if (name == null | name == "") throw new ArgumentException("Name can not be null or blank", "name");
this.Name = name;
}
Of course I could always set the name to some default like "Unnamed MyClass" if the argument is invalid, but in this case I'd rather just prevent an invalid name then trying to assume some alternate behavior.
Throw an ArgumentNullException
Document that the ctor throws ArgumentNullException if name is null
If you are using Code Contracts, add a Contract.EndContractBlock() line after your parameter validation.
Edit: Instead of this:
if (name == null || name == "")
Use this:
if (string.IsNullOrEmpty(name))
The preferred solution here is to throw an exception. Fail early, fail often. Document what the valid parameters are for your constructor and that it throws an ArgumentNullException or ArgumentOutOfRangeException on invalid parameters.
In my opinion, the salient point is that you don't want to silently absorb failures. Suppose the user typed in a name incorrectly (accidentally left it null, for example). Better to have the operation fail and return notification to the user than to swallow the failure (with, say, a default) and have the user unaware they mistyped their entry.
I asked a similar question awhile back to settle an argument with some colleagues.
"But once a constructor is called the instance of the object is already created regardless of whether it was passed valid arguments."
The object is created (i.e., non-null) only if the constructor returns normally.
You can either set the name to some default or throw an exception. Anything else is just plain wrong since it would create an object with a non-valid state.
If passing an empty or null name represents an error, throwing an exception is the reasonable thing to do. Ignoring the null name and doing some arbitrary recovery is just masking the error and becomes likely to lead to invalid state.
If not passing a name is a valid way to construct the object, offer a parameterless constructor.
There is a Guard utility class that you might find useful for validating arguments passed to any method.
The class is avaialable here
using System;
using System.Globalization;
namespace Microsoft.Practices.Mobile.CompositeUI.Utility
{
/// <summary>
/// Common guard clauses.
/// </summary>
public static class Guard
{
/// <summary>
/// Checks a string argument to ensure it isn't null or empty.
/// </summary>
/// <param name="argumentValue">The argument value to check.</param>
/// <param name="argumentName">The name of the argument.</param>
public static void ArgumentNotNullOrEmptyString(string argumentValue, string argumentName)
{
ArgumentNotNull(argumentValue, argumentName);
if (argumentValue.Trim().Length == 0)
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Properties.Resources.StringCannotBeEmpty, argumentName));
}
/// <summary>
/// Checks an argument to ensure it isn't null.
/// </summary>
/// <param name="argumentValue">The argument value to check.</param>
/// <param name="argumentName">The name of the argument.</param>
public static void ArgumentNotNull(object argumentValue, string argumentName)
{
if (argumentValue == null)
throw new ArgumentNullException(argumentName);
}
/// <summary>
/// Checks an Enum argument to ensure that its value is defined by the specified Enum type.
/// </summary>
/// <param name="enumType">The Enum type the value should correspond to.</param>
/// <param name="value">The value to check for.</param>
/// <param name="argumentName">The name of the argument holding the value.</param>
public static void EnumValueIsDefined(Type enumType, object value, string argumentName)
{
if (Enum.IsDefined(enumType, value) == false)
throw new ArgumentException(String.Format(CultureInfo.CurrentCulture,
Properties.Resources.InvalidEnumValue,
argumentName, enumType.ToString()));
}
/// <summary>
/// Verifies that an argument type is assignable from the provided type (meaning
/// interfaces are implemented, or classes exist in the base class hierarchy).
/// </summary>
/// <param name="assignee">The argument type.</param>
/// <param name="providedType">The type it must be assignable from.</param>
/// <param name="argumentName">The argument name.</param>
public static void TypeIsAssignableFromType(Type assignee, Type providedType, string argumentName)
{
if (!providedType.IsAssignableFrom(assignee))
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture,
Properties.Resources.TypeNotCompatible, assignee, providedType), argumentName);
}
}
}

Categories

Resources