I need to convert a Kentico 7 web application to Kentico 8.0.21. The old code has a CMSModuleLoader file in the App_Code folder which has code for Authenticate_Execute event.
The init event suggested by kentico does not get fired
public partial class CMSModuleLoader
{
private class AuthenticationHandler : CMSLoaderAttribute
{
/// <summary>
/// Called automatically when the application starts
/// </summary>
public override void Init()
{
// Assigns a handler to the SecurityEvents.Authenticate.Execute event
// This event occurs when users attempt to log in on the website
SecurityEvents.Authenticate.Execute += OnAuthentication;
}
private void OnAuthentication(object sender, AuthenticationEventArgs args)
{
if (args.User != null) //the authenticate was successful
{
try
{
var accountFacade = WebContainer.Instance.Container.GetInstance<IAccountFacade>();
accountFacade.ReconcileOnLogin(args.UserName);
}
catch (Exception e)
{
var logger = LogManager.GetCurrentClassLogger();
var ex = new Exception("IAccountFacade.ReconcileOnLogin method throw an error communicating with dynamics, the issue is not resolvable from Kentico thus regardless of the permission level of the current user, the exception will be bubbled up and the user will be shown error details or the custom error page.", e);
logger.Fatal(x => x("The current exception is caused by dynamics/data problems and the user will not be allowed to login. A system admin with access to dynamics is required to resolve the problem.", e));
throw ex;
}
//ResetPasswordAttempts(args.User);
}
}
}
/// <summary>
/// Attribute class that ensures the loading of custom handlers
/// </summary>
private class CustomSecurityEventsAttribute : CMS.Base.CMSLoaderAttribute
{
/// <summary>
/// Called automatically when the application starts
/// </summary>
public override void Init()
{
SecurityEvents.Authenticate.Execute += new EventHandler<AuthenticationEventArgs>(Authenticate_Execute);
}
/// <summary>
/// called on every kentico authenticate attempt
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
All authentication-related events were moved to CMS.Membership.SecurityEvents in Kentico 8.0. The usage is as follows:
using System.Data;
using CMS.Base;
using CMS.Membership;
using CMS.DataEngine;
[AuthenticationHandler]
public partial class CMSModuleLoader
{
/// <summary>
/// Custom attribute class.
/// </summary>
private class AuthenticationHandler : CMSLoaderAttribute
{
/// <summary>
/// Called automatically when the application starts
/// </summary>
public override void Init()
{
// Assigns a handler to the SecurityEvents.Authenticate.Execute event
// This event occurs when users attempt to log in on the website
SecurityEvents.Authenticate.Execute += OnAuthentication;
}
}
}
For more info refer to the documentation.
Related
i'm new with xamarin forms. I'm writing an app and i need to create a function that allow call api continuously to check the change of data, if have any change, i will handle something.
I'm looking for the solution but nothing, please help me :(
Thread is an idea?
Okay so first of all you need to poll the API in order to receive the data that you need to check. To do this you can implement my PollingTimer.cs class:
using System;
using System.Threading;
using Xamarin.Forms;
namespace CryptoTracker.Helpers
{
/// <summary>
/// This timer is used to poll the middleware for new information.
/// </summary>
public class PollingTimer
{
private readonly TimeSpan timespan;
private readonly Action callback;
private CancellationTokenSource cancellation;
/// <summary>
/// Initializes a new instance of the <see cref="T:CryptoTracker.Helpers.PollingTimer"/> class.
/// </summary>
/// <param name="timespan">The amount of time between each call</param>
/// <param name="callback">The callback procedure.</param>
public PollingTimer(TimeSpan timespan, Action callback)
{
this.timespan = timespan;
this.callback = callback;
this.cancellation = new CancellationTokenSource();
}
/// <summary>
/// Starts the timer.
/// </summary>
public void Start()
{
CancellationTokenSource cts = this.cancellation; // safe copy
Device.StartTimer(this.timespan,
() => {
if (cts.IsCancellationRequested) return false;
this.callback.Invoke();
return true; // or true for periodic behavior
});
}
/// <summary>
/// Stops the timer.
/// </summary>
public void Stop()
{
Interlocked.Exchange(ref this.cancellation, new CancellationTokenSource()).Cancel();
}
}
}
Now that you have added a polling timer to your project, you must now go to the content page that you wish to poll from. Here is the pseudo code for what your content page should look like:
namespace YourApp.Views
{
public class MainPage : ContentPage
{
PollingTimer timer;
public MainPage ()
{
//PUT UI CODE HERE
Content = layout;
//Instantiate Polling timer to call handleaction every 5 seconds
timer = new PollingTimer(TimeSpan.FromSeconds(5), HandleAction);
}
/// <summary>
/// When the page enters the users view, this procedure is called.
/// </summary>
protected override void OnAppearing()
{
base.OnAppearing();
//Handle action and start your timer
HandleAction();
timer.Start();
}
/// <summary>
/// When the page disappears from the users view this procedure is called.
/// </summary>
protected override void OnDisappearing()
{
base.OnDisappearing();
//Stop your timer
timer.Stop(); //Stop the timer
}
/// <summary>
/// Callback for the timer.
/// </summary>
void HandleAction()
{
//Make call to your api to get data
//Compare data with data you currently have
// Do whatever you want.
}
I hope this helps you. Let me know if you need any more help :)
You can use Timer Class for you issue.
I am a electronic student, I am developing a GUI with Visual Studio; so I found examples and information in the next page.
http://www.voip-sip-sdk.com/
my principal class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using Ozeki.Media;
using Ozeki.VoIP;
using Ozeki.Common;
namespace Consola2
{
/// <summary>
/// Basic softphone logic.
/// </summary>
/// <remarks>
/// This class is used to introduce how to declare, define and initialize a softphone,
/// how to handle some of it's events, and use some of it's functions.
/// The Program.cs uses this class to create a softphone,
/// uses the functions and events declared here as public.
/// </remarks>
class Softphone
{
ISoftPhone _softphone; // softphone object
IPhoneLine _phoneLine; // phone line object
IPhoneCall _call; // the call object
Microphone _microphone;
Speaker _speaker;
MediaConnector _connector; // connects the devices to each other (eg. microphone, speaker, mediaSender, mediaReceiver)
PhoneCallAudioSender _mediaSender; // after connected with the microphone, this will be attached to the call
PhoneCallAudioReceiver _mediaReceiver; // after connected with the speaker, this will be attached to the call
bool _incomingCall; // indicates wheter we have an incoming call (so, the phone is ringing)
#region Events
/// <summary>
/// Occurs when an incoming call received.
/// </summary>
public event EventHandler IncomingCall;
/// <summary>
/// Occurs when the registration state of the phone line has changed.
/// </summary>
public event EventHandler<RegistrationStateChangedArgs> PhoneLineStateChanged;
/// <summary>
/// Occurs when the state of the call has changed.
/// </summary>
public event EventHandler<CallStateChangedArgs> CallStateChanged;
#endregion
/// <summary>
/// Default constructor, initalizes the softphone with deafult parameters.
/// </summary>
public Softphone()
{
_softphone = SoftPhoneFactory.CreateSoftPhone(5000, 10000);
_microphone = Microphone.GetDefaultDevice();
_speaker = Speaker.GetDefaultDevice();
_connector = new MediaConnector();
_mediaSender = new PhoneCallAudioSender();
_mediaReceiver = new PhoneCallAudioReceiver();
_incomingCall = false;
}
/// <summary>
/// Registers the SIP account to the PBX.
/// Calls cannot be made while the SIP account is not registered.
/// If the SIP account requires no registration, the RegisterPhoneLine() must be called too to register the SIP account to the ISoftPhone.
/// </summary>
public void Register(bool registrationRequired, string displayName, string userName, string authenticationId, string registerPassword, string domainHost, int domainPort)
{
try
{
// We need to handle the event, when we have an incoming call.
_softphone.IncomingCall += softphone_IncomingCall;
// To register to a PBX, we need to create a SIP account
var account = new SIPAccount(registrationRequired, displayName, userName, authenticationId, registerPassword, domainHost, domainPort);
//Console.WriteLine("\nCreating SIP account {0}", account);
// With the SIP account and the NAT configuration, we can create a phoneline.
_phoneLine = _softphone.CreatePhoneLine(account);
//Console.WriteLine("Phoneline created.");
// The phoneline has states, we need to handle the event, when it is being changed.
_phoneLine.RegistrationStateChanged += phoneLine_PhoneLineStateChanged;
// If our phoneline is created, we can register that.
_softphone.RegisterPhoneLine(_phoneLine);
// For further information about the calling of the ConnectMedia(), please check the implementation of this method.
ConnectMedia();
}
catch (Exception ex)
{
Console.WriteLine("Error during SIP registration: " + ex);
}
}
/// <summary>
/// This will be called when the registration state of the phone line has changed.
/// </summary>
private void phoneLine_PhoneLineStateChanged(object sender, RegistrationStateChangedArgs e)
{
DispatchAsync(() =>
{
var handler = PhoneLineStateChanged;
if (handler != null)
handler(this, e);
});
}
/// <summary>
/// Starts the capturing and playing audio/video devices.
/// Other devices can be used (and started), for example: WebCamera or WaveStreamPlayback.
/// </summary>
private void StartDevices()
{
if (_microphone != null)
{
_microphone.Start();
}
if (_speaker != null)
{
_speaker.Start();
}
}
/// <summary>
/// Stops the capturing and playing audio/video devices.
/// Other devices can be stopped, for example: WebCamera.
/// </summary>
private void StopDevices()
{
if (_microphone != null)
{
_microphone.Stop();
}
if (_speaker != null)
{
_speaker.Stop();
}
}
#region Media handling guide
/*
To send our voice through the microphone to the other client's speaker, we need to connect them.
We send our voice through the mediaSender, and we get the other client's voice through the mediaSender to our speaker object.
To disconnect these handlers, we will use the DisconnectMedia() method.
It is possible to use other mediahandlers with the connector, for example we can connect a WaveStreamPlayback or an MP3StreamPlayback object to the MediaSender, so we can play music/voice
during the call. For exmaple: when can create an IVR (Interactive Voice Response), we can create voice recorder etc.
For example:
We can connect an .mp3 file player (which plays an mp3 file into the voice call) by the "connector.Connect(Mp3StreamPlayback, mediaSender); " line.
(We should also create an MP3StreamPlayback object: "MP3StreamPlayback Mp3StreamPlayback; "
and we need to tell to this object the details (what to play into the speaker, etc.))
*/
#endregion
/// <summary>
/// Connects the audio handling devices to each other.
/// The audio data will flow from the source to the destination.
/// </summary>
private void ConnectMedia()
{
if (_microphone != null)
{
_connector.Connect(_microphone, _mediaSender);
}
if (_speaker != null)
{
_connector.Connect(_mediaReceiver, _speaker);
}
}
/// <summary>
/// Disconnects the audio handling devices from each other.
/// </summary>
private void DisconnectMedia()
{
if (_microphone != null)
{
_connector.Disconnect(_microphone, _mediaSender);
}
if (_speaker != null)
{
_connector.Disconnect(_mediaReceiver, _speaker);
}
// You can close all of the connections by using: connector.Dispose();
}
/// <summary>
/// Subscribes to the events of a call to receive notifications such as the state of the call has changed.
/// In this sample subscribes only to the state changed and error occurred events.
/// </summary>
private void WireUpCallEvents()
{
_call.CallStateChanged += (call_CallStateChanged);
}
/// <summary>
/// Unsubscribes from the events of a call.
/// </summary>
private void WireDownCallEvents()
{
_call.CallStateChanged -= (call_CallStateChanged);
}
/// <summary>
/// This will be called when an incoming call received.
/// To receive notifications from the call (eg. ringing), the program need to subscribe to the events of the call.
/// </summary>
private void softphone_IncomingCall(object sender, VoIPEventArgs<IPhoneCall> e)
{
_call = e.Item;
WireUpCallEvents();
_incomingCall = true;
DispatchAsync(() =>
{
var handler = IncomingCall;
if (handler != null)
handler(this, EventArgs.Empty);
});
}
/// <summary>
/// This will be called when the state of the call call has changed.
/// </summary>
/// <remarks>
/// In this sample only three states will be handled: Answered, InCall, Ended
///
/// Answered: when the call has been answered, the audio devices will be started and attached to the call.
/// It is required to comminicate with the other party and hear them.
/// The devices are connected at softphone initialization time,
/// so no need to connect them every time when a call is being answered.
///
/// InCall: when the call is in an active state, the audio deveices will be started.
///
/// Ended: when the call ends, the audio devices will be stopped and detached from the call.
/// </remarks>
private void call_CallStateChanged(object sender, CallStateChangedArgs e)
{
// the call has been answered
if (e.State == CallState.Answered)
{
StartDevices();
_mediaReceiver.AttachToCall(_call);
_mediaSender.AttachToCall(_call);
}
// the call is in active communication state
// IMPORTANT: this state can occur multiple times. for example when answering the call or the call has been taken off hold.
if (e.State == CallState.InCall)
{
StartDevices();
}
// the call has ended
if (e.State.IsCallEnded())
{
if (_call != null)
{
CallFinished();
}
}
DispatchAsync(() =>
{
var handler = CallStateChanged;
if (handler != null)
handler(this, e);
});
}
/// <summary>
/// Starts calling the specified number.
/// In this sample an outgoing call can be made if there is no current call (outgoing or incoming) on the phone line.
/// </summary>
public void StartCall(string numberToDial)
{
if (_call == null)
{
_call = _softphone.CreateCallObject(_phoneLine, numberToDial);
WireUpCallEvents();
// To make a call simply call the Start() method of the call object.
_call.Start();
}
}
/// <summary>
/// Answers the current incoming call.
/// </summary>
public void AcceptCall()
{
// when the value of the incomingCall member is true, there is an incoming call
if (_incomingCall == true)
{
_incomingCall = false;
***_call.Answer();***
}
}
/// <summary>
/// Hangs up the current call.
/// </summary>
public void HangUp()
{
if (_call != null)
{
_call.HangUp();
_call = null;
}
}
/// <summary>
/// If the call ends, we won't need our speaker and microphone anymore to communicate,
/// until we enter into a call again, so we are calling the StopDevices() method.
/// The mediaHandlers are getting detached from the call object
/// (since we are not using our microphone and speaker, we have no media to send).
/// We won't need the call's events anymore, becouse our call is about to be ended,
/// and with setting the call to null, we are ending it.
/// </summary>
public void CallFinished()
{
StopDevices();
_mediaReceiver.Detach();
_mediaSender.Detach();
WireDownCallEvents();
_call = null;
}
/// <summary>
/// This method is used to solve the task blockings.
/// </summary>
private void DispatchAsync(Action action)
{
var task = new WaitCallback(o => action.Invoke());
ThreadPool.QueueUserWorkItem(task);
}
}
}
My GUI code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Threading;
using Ozeki.VoIP;
namespace Consola2
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private static Softphone _mySoftphone; // softphone object
/// <summary>
/// The entry point of the program.
/// - initializes the softphone
/// - shows a greeting message
/// - registers the SIP account
/// </summary>
///
private static void InitSoftphone()
{
_mySoftphone = new Softphone();
_mySoftphone.PhoneLineStateChanged += mySoftphone_PhoneLineStateChanged;
_mySoftphone.CallStateChanged += mySoftphone_CallStateChanged;
_mySoftphone.IncomingCall += mySoftphone_IncomingCall;
}
/// <summary>
/// This will be called when the registration state of the phone line has changed.
/// </summary>
static void mySoftphone_PhoneLineStateChanged(object sender, RegistrationStateChangedArgs e)
{
Console.WriteLine("Phone line state changed: {0}", e.State);
if (e.State == RegState.Error || e.State == RegState.NotRegistered)
{
MessageBox.Show("Datos Invalidos", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
else if (e.State == RegState.RegistrationSucceeded)
{
MessageBox.Show("¡Registro Exitoso!");
//StartToDial();
}
}
/// <summary>
/// This will be called when an incoming call received.
/// In this sample when an incoming call receveived, it will be answered automatically.
/// </summary>
static void mySoftphone_IncomingCall(object sender, EventArgs e)
{
MessageBox.Show("Llamada entrante");
_mySoftphone.AcceptCall();
MessageBox.Show("Llamada aceptada:");
}
/// <summary>
/// This will be called when the state of the call has changed. (eg. ringing, answered, rejected)
/// </summary>
private static void mySoftphone_CallStateChanged(object sender, CallStateChangedArgs e)
{
Console.WriteLine("Call state changed: {0}", e.State);
if (e.State.IsCallEnded())
{
MessageBox.Show("Llamada terminada:");
}
if (e.State == CallState.Error)
{
Console.WriteLine("Call error occured. {0}", e.Reason);
}
}
public MainWindow()
{
InitializeComponent();
InitSoftphone();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
string id = textBox1.Text;
string user = textBox2.Text;
string displayed = textBox3.Text;
string pass = textBox4.Text;
string domain = textBox5.Text;
int port = Convert.ToInt32(textBox6.Text);
bool check = false;
if (checkBox1.IsChecked == true)
{
check = true;
}
_mySoftphone.Register(check, id, user, displayed, pass, domain, port);
}
private void Llamar_Click(object sender, RoutedEventArgs e)
{
string numero = textBox7.Text;
_mySoftphone.StartCall(numero);
}
private void button2_Click(object sender, RoutedEventArgs e)
{
_mySoftphone.AcceptCall();
}
}
}
With that, I can register into a PBX and make calls , the problem is that when you receive calls an error message appears "NullReferenceException was unhandled" In my class principal "AcceptCall()" method in the line "_call,Answer();".
Where is the problem? i'm not sure about de references with the "Ozeki" library.
I appreciate your help, or an example to make and receive calls.
Thanks.
Your call button (Llamar) instantiates _call inside StartCall. However, when AcceptCall is run, _call is still null, and cannot be used.
I am working on an application that uses a Mutex to ensure that it is the only instance of the application running on the system.
When another instance of the application attempts to start, I want a method to run in the original instance.
Can I invoke a specific method in my application from another instance of the application?
I've found some examples using RegisterWindowMessage/PostMessage Win32 APIs by sending the message to HWND_BROADCAST, but I couldn't get them to work, and I've read elsewhere that using HWND_BROADCAST can be dangerous.
Is there a better way to do this that doesn't involve the app needing to be run in privileged mode?
Here's a little helper I wrote.
To use it:
var pipeListener = new NamedPipeListener<String>(); // instantiate an instance
pipeListener.MessageReceived += (sender, e) => MessageBox.Show(e.Message); // when a message is received, show a messagebox with the message
pipeListener.Error += (sender, e) => MessageBox.Show("Error ({0}): {1}", e.ErrorType, e.Exception.Message); // oh noes!
pipeListener.Start(); // when you're ready, start listening
From another process:
NamedPipeListener<String>.SendMessage("Howdy howdy howdy");
Note that it uses the full name of the PipeListener as the default name of the pipe. If you need to get more discrete than that, use the constructor overload that takes a pipe name.
Here's the class:
using System;
using System.IO.Pipes;
using System.Runtime.Serialization.Formatters.Binary;
namespace FunWithNamedPipes
{
/// <summary>Contains event data for <see cref="NamedPipeMessageReceiveHandler{TMessage}" /> events.</summary>
/// <typeparam name="TMessage"></typeparam>
public class NamedPipeListenerMessageReceivedEventArgs<TMessage> : EventArgs
{
/// <summary>Initializes an instance of <see cref="NamedPipeListenerMessageReceivedEventArgs{TMessage}" /> with the specified <paramref name="message" />.</summary>
/// <param name="message">The message passed by the event.</param>
public NamedPipeListenerMessageReceivedEventArgs(TMessage message)
{
this.Message = message;
}
/// <summary>Gets the message passed by the event.</summary>
public TMessage Message { get; private set; }
}
/// <summary>Contains event data for <see cref="NamedPipeListenerErrorEventHandler" /> events.</summary>
public class NamedPipeListenerErrorEventArgs : EventArgs
{
/// <summary>Initializes an instance of <see cref="NamedPipeListenerErrorEventArgs" /> with the specified <paramref name="errorType" /> and <paramref name="exception" />.</summary>
/// <param name="errorType">A <see cref="NamedPipeListenerErrorType" /> describing the part of the listener process where the error was caught.</param>
/// <param name="ex">The <see cref="Exception" /> that was thrown.</param>
public NamedPipeListenerErrorEventArgs(NamedPipeListenerErrorType errorType, Exception ex)
{
this.ErrorType = errorType;
this.Exception = ex;
}
/// <summary>Gets a <see cref="NamedPipeListenerErrorType" /> describing the part of the listener process where the error was caught.</summary>
public NamedPipeListenerErrorType ErrorType { get; private set; }
/// <summary>Gets the <see cref="Exception" /> that was caught.</summary>
public Exception Exception { get; private set; }
}
/// <summary>Represents a method that will handle an event where a message is received via named pipes.</summary>
/// <typeparam name="TMessage">The type of message that will be received.</typeparam>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The event data passed by the event, which includes the message that was received.</param>
public delegate void NamedPipeMessageReceivedHandler<TMessage>(Object sender, NamedPipeListenerMessageReceivedEventArgs<TMessage> e);
/// <summary>Represents a method that will handle an event that is fired when an exception is caught.</summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The event data passed by the event, included the error type and exception that was caught.</param>
public delegate void NamedPipeMessageErrorHandler(Object sender, NamedPipeListenerErrorEventArgs e);
/// <summary>Includes different types of errors that describe where in the listening process an exception was caught.</summary>
public enum NamedPipeListenerErrorType : byte
{
/// <summary>Indicates that an exception was caught while calling <see cref="NamedPipeServerStream.BeginWaitForConnection" />.</summary>
BeginWaitForConnection = 1,
/// <summary>Indicates that an exception was caught while calling <see cref="NamedPipeServerStream.EndWaitForConnection" />.</summary>
EndWaitForConnection = 2,
/// <summary>Indicates that an exception was caught while deserializing a message received from the named pipe.</summary>
DeserializeMessage = 3,
/// <summary>Indicates that an exception was caught while closing or disposing a used named pipe.</summary>
CloseAndDisposePipe = 4,
/// <summary>Indicates that an exception was caught while invoking the <see cref="NamedPipeListener{TMessage}.MessageReceived"/> event.</summary>
NotifyMessageReceived = 5
}
/// <summary>A helper class for sending and receiving messages using named pipes.</summary>
/// <typeparam name="TMessage">The type of message that will be sent or received.</typeparam>
public class NamedPipeListener<TMessage> : IDisposable
{
/// <summary>Occurs when a message is received.</summary>
public event NamedPipeMessageReceivedHandler<TMessage> MessageReceived;
/// <summary>Occurs when an exception is caught.</summary>
public event NamedPipeMessageErrorHandler Error;
static readonly String DEFAULT_PIPENAME = typeof(NamedPipeListener<TMessage>).FullName;
static readonly BinaryFormatter formatter = new BinaryFormatter();
NamedPipeServerStream pipeServer;
/// <summary>Initializes a new instance of <see cref="NamedPipeListener{TMessage}" /> using the specified <paramref name="pipeName" />.</summary>
/// <param name="pipeName">The name of the named pipe that will be used to listen on.</param>
public NamedPipeListener(String pipeName)
{
this.PipeName = pipeName;
}
/// <summary>Initializes a new instance of <see cref="NamedPipeListener{TMessage}" /> using the default pipe name.</summary>
/// <remarks>The default pipe name is the full name of the type of the instance.</remarks>
public NamedPipeListener()
: this(DEFAULT_PIPENAME) { }
/// <summary>The name of the named pipe that will be used to listen on.</summary>
public String PipeName { get; private set; }
/// <summary>Starts listening on the named pipe specified for the instance.</summary>
internal void Start()
{
if (pipeServer == null) pipeServer = new NamedPipeServerStream(DEFAULT_PIPENAME, PipeDirection.In, 1, PipeTransmissionMode.Message, PipeOptions.Asynchronous);
try { pipeServer.BeginWaitForConnection(new AsyncCallback(PipeConnectionCallback), null); }
catch (Exception ex) { this.OnError(NamedPipeListenerErrorType.BeginWaitForConnection, ex); }
}
private void PipeConnectionCallback(IAsyncResult result)
{
try
{
pipeServer.EndWaitForConnection(result);
}
catch (Exception ex)
{
this.OnError(NamedPipeListenerErrorType.EndWaitForConnection, ex);
return;
}
TMessage message;
try
{
message = (TMessage)formatter.Deserialize(pipeServer);
}
catch (Exception ex)
{
this.OnError(NamedPipeListenerErrorType.DeserializeMessage, ex);
return;
}
try
{
this.OnMessageReceived(new NamedPipeListenerMessageReceivedEventArgs<TMessage>(message));
}
catch (Exception ex)
{
this.OnError(NamedPipeListenerErrorType.NotifyMessageReceived, ex);
return;
}
if (this.End())
{
this.Start();
}
}
internal Boolean End()
{
try
{
pipeServer.Close();
pipeServer.Dispose();
pipeServer = null;
return true;
}
catch (Exception ex)
{
this.OnError(NamedPipeListenerErrorType.CloseAndDisposePipe, ex);
return false;
}
}
private void OnMessageReceived(TMessage message)
{
this.OnMessageReceived(new NamedPipeListenerMessageReceivedEventArgs<TMessage>(message));
}
protected virtual void OnMessageReceived(NamedPipeListenerMessageReceivedEventArgs<TMessage> e)
{
if (this.MessageReceived != null)
{
this.MessageReceived(this, e);
}
}
private void OnError(NamedPipeListenerErrorType errorType, Exception ex)
{
this.OnError(new NamedPipeListenerErrorEventArgs(errorType, ex));
}
protected virtual void OnError(NamedPipeListenerErrorEventArgs e)
{
if (this.Error != null)
{
this.Error(this, e);
}
}
void IDisposable.Dispose()
{
if(pipeServer != null)
{
try { pipeServer.Disconnect(); }
catch { }
try { pipeServer.Close(); }
catch { }
try { pipeServer.Dispose(); }
catch { }
}
}
/// <summary>Sends the specified <paramref name="message" /> to the default named pipe for the message.</summary>
/// <param name="message">The message to send.</param>
public static void SendMessage(TMessage message)
{
NamedPipeListener<TMessage>.SendMessage(DEFAULT_PIPENAME, message);
}
/// <summary>Sends the specified <paramref name="message" /> to the specified named pipe.</summary>
/// <param name="pipeName">The name of the named pipe the message will be sent to.</param>
/// <param name="message">The message to send.</param>
public static void SendMessage(String pipeName, TMessage message)
{
using (var pipeClient = new NamedPipeClientStream(".", DEFAULT_PIPENAME, PipeDirection.Out, PipeOptions.None))
{
pipeClient.Connect();
formatter.Serialize(pipeClient, message);
pipeClient.Flush();
pipeClient.WaitForPipeDrain();
pipeClient.Close();
}
}
}
}
I've done research on this before - you can use a memory mapped file, demonstrated in this article http://www.codeproject.com/KB/cs/singleinstanceapplication.aspx, or you can do what I did (the easy way) and take advantage of vb.net features (specifically, one that lets you make single instance apps and calls a method in the currently running instance that passes on command line args [so you could use it to invoke the method in your application]). I know using VB classes in C# sounds a bit poor but it's the most abstract and easy way. Link to the relevant articles - http://www.codeproject.com/KB/cs/CSSIApp.aspx, last part of http://msdn.microsoft.com/en-us/magazine/cc163741.aspx
I just can't make out if the entity context is disposed in the usage flow when used in a using statement in a web application or a console application.
Thanks!
using System;
using System.Web;
namespace Foo.Model
{
public partial class FooEntities : ObjectContext
{
private const string CurrentContextKey = "FooEntities.Current";
[ThreadStatic]
private static FooEntities _currentOnThreadStatic;
private FooEntities _previousContext;
/// <summary>
/// Gets the current <see cref="FooEntities"/> instance, if an instance can be shared in the current context.
/// </summary>
/// <remarks>
/// The current context is stored in the HTTP context, if it is available (otherwise it is stored in a thread-static instance).
/// Multiple contexts can be stacked.
/// </remarks>
public static FooEntities Current
{
get
{
if (HttpContext.Current != null)
{
return HttpContext.Current.Items[CurrentContextKey] as FooEntities;
}
else
{
return _currentOnThreadStatic;
}
}
private set
{
if (HttpContext.Current != null)
{
HttpContext.Current.Items[CurrentContextKey] = value;
}
else
{
_currentOnThreadStatic = value;
}
}
}
/// <summary>
/// Returns a repository instance bound to this object context.
/// </summary>
/// <typeparam name="TRepository">The type of repository to instantiate.</typeparam>
/// <returns>The repository instance.</returns>
public TRepository GetRepository<TRepository>()
where TRepository: BaseRepository
{
return (TRepository) Activator.CreateInstance(typeof(TRepository), this);
}
/// <summary>
/// Ensures that an ambient context is available through <see cref="Current"/>, throwing an exception otherwise.
/// </summary>
/// <exception type="InvalidOperationException)">
/// Thrown if <see cref="Current"/> is null.
/// </exception>
public static void EnsureContext()
{
if (Current == null)
{
throw new InvalidOperationException("An ambient FooEntities context is expected.");
}
}
/// <summary>
/// Releases the context instance.
/// </summary>
/// <param name="disposing"></param>
protected override void Dispose(bool disposing)
{
Current = _previousContext;
base.Dispose(disposing);
}
/// <summary>
/// Is called by all constructors.
/// </summary>
partial void OnContextCreated()
{
_previousContext = Current;
Current = this;
}
}
}
It is an odd design. As #Joel C points out in his comment you should regard the object context as a shortlived object that you create when you need it and release right afterwards.
But I see no reason that this would leak memory. You are only dealing with managed resources and you are using the same key all the time to the HttpContext so you won't create new objects all over.
I have a Windows Form that starts some console application in background(CreateNoWindow = rue,WindowStyle = ProcessWindowStyle.Hidden).
Windows form gives me opportunity to stop the console application at any time. But I'd like to handle somehow the close message inside the console application. I tried to use hooking like:
[DllImport("Kernel32")]
public static extern bool SetConsoleCtrlHandler(HandlerRoutine handler, bool add);
// A delegate type to be used as the handler routine
// for SetConsoleCtrlHandler.
public delegate bool HandlerRoutine(CtrlTypes ctrlType);
// An enumerated type for the control messages
// sent to the handler routine.
public enum CtrlTypes
{
CTRL_C_EVENT = 0,
CTRL_BREAK_EVENT,
CTRL_CLOSE_EVENT,
CTRL_LOGOFF_EVENT = 5,
CTRL_SHUTDOWN_EVENT
}
private static bool ConsoleCtrlCheck(CtrlTypes ctrlType)
{
StaticLogger.Instance.DebugFormat("Main: ConsoleCtrlCheck: Got event {0}.", ctrlType);
if (ctrlType == CtrlTypes.CTRL_CLOSE_EVENT)
{
// Handle close stuff
}
return true;
}
static int Main(string[] args)
{
// Subscribing
HandlerRoutine hr = new HandlerRoutine(ConsoleCtrlCheck);
SetConsoleCtrlHandler(hr, true);
// Doing stuff
}
but I get the message inside ConsoleCtrlCheck only if the console window is created. But if window is hidden - I don't get any message.
In my windows Form to close console application process I use
proc.CloseMainWindow();
to send message to the console window.
P.S. AppDomain.CurrentDomain.ProcessExit += CurrentDomain_ProcessExit; - also does not help
Do you now other way to handle this situation?
Thanks.
This might work. I used it in NUnit testes to clean up environment. Unfortunately it is not garantieed to be called. To make it working you need to create an instance of it and pass callback function that should be called on shutdown.
/// <summary>
/// Detects the moment when environment is about to be shutdown.
/// <remarks>
/// For usage just create single instance of it.
/// Each time when GC calles Finilize a '~ShutdownDetector' will be called.
/// </remarks>
/// </summary>
public sealed class ShutdownDetector
{
/// <summary>
/// Initializes a new instance of the <see cref="T:ShutdownDetector"/> class.
/// </summary>
/// <param name="notifier">The notifier</param>
public ShutdownDetector(Notifier notifier)
{
if (notifier == null) throw new ArgumentNullException("notifier");
_notifier = notifier;
}
/// <summary>
/// Releases unmanaged resources and performs other cleanup operations before the
/// <see cref="T:CQG.PDTools.Common.ShutdownDetector"/> is reclaimed by garbage collection.
/// </summary>
~ShutdownDetector()
{
if (Environment.HasShutdownStarted)
{
onShutdown();
}
else
{
new ShutdownDetector(_notifier);
}
}
/// <summary>
/// Called when component needs to signal about shutdown.
/// </summary>
private void onShutdown()
{
if (_notifier != null)
{
_notifier();
}
}
Notifier _notifier;
public delegate void Notifier();
}