I have this code to check if a service is active, but I would like to know if there is any way for an EditText to show the status of the service, without making this query per second, or in a separate thread, or linking it in some way? that it is possible to detect if the service stopped
private bool MiServicioEstaCorriendo(Class #class, Context contexto)
{
ActivityManager manager = (ActivityManager)contexto.GetSystemService(Context.ActivityService);
foreach (ActivityManager.RunningServiceInfo service in manager.GetRunningServices(Integer.MaxValue))
{
if (#class.Name.Equals(service.Service.ClassName))
{
Log.Info(typeof(BroadcastGps).Name, "MiServcicioEstaCorriendo: true");
return true;
}
}
Log.Info(typeof(BroadcastGps).Name, "MiServcicioEstaCorriendo: false");
return false;
}
You are basically in need of a way to pass events/messages among classes within your application. So this question probably goes down to Android & C# implementation of such a pattern. Xamarin.Forms has a MessagingCenter class, but since you are using Xamarin.Native, you would have to create something yourself
There's nothing actually already baked in to Android or C#, but so you can implement one of the most common ways to let a class spread an event/message using the "Listener" (term used in Android) or "Delegate" (term used in C#) technique.
There are frameworks too like PubNub that you can use as Nuget packages that simplify everything for you.
Some more resources to understand the concept: Wikipedia, IBM.
And Some Android resources: Handlers, AsyncTasks, Parcelables.
Don't forget that your event to update your EditText may not be fired on the Main UIThread so you won't be able to see the changes unless you force that update line to be Run on UI Thread.
I tried to make File open picker asynchronous using TaskComplectionSource however sometimes I get my application closed with -1 return value, sometimes I get exception like:
[System.Runtime.InteropServices.COMException] = {System.Runtime.InteropServices.COMException (0x80004005): Unspecified error
Unspecified error
at Windows.Storage.Pickers.FileOpenPicker.PickSingleFileAndContinue()
at PhotosGraphos.Mobile.Common.StorageFileExtensions.<PickSingleFileAsyncMobile..
Code:
public static class StorageFileExtensions
{
private static TaskCompletionSource<StorageFile> PickFileTaskCompletionSource;
private static bool isPickingFileInProgress;
public static async Task<StorageFile> PickSingleFileAsyncMobile(this FileOpenPicker openPicker)
{
if (isPickingFileInProgress)
return null;
isPickingFileInProgress = true;
PickFileTaskCompletionSource = new TaskCompletionSource<StorageFile>();
var currentView = CoreApplication.GetCurrentView();
currentView.Activated += OnActivated;
openPicker.PickSingleFileAndContinue();
StorageFile pickedFile;
try
{
pickedFile = await PickFileTaskCompletionSource.Task;
}
catch (TaskCanceledException)
{
pickedFile = null;
}
finally
{
PickFileTaskCompletionSource = null;
isPickingFileInProgress = false;
}
return pickedFile;
}
private static void OnActivated(CoreApplicationView sender, IActivatedEventArgs args)
{
var continuationArgs = args as FileOpenPickerContinuationEventArgs;
sender.Activated -= OnActivated;
if (continuationArgs != null && continuationArgs.Files.Any())
{
StorageFile pickedFile = continuationArgs.Files.First();
PickFileTaskCompletionSource.SetResult(pickedFile);
}
else
{
PickFileTaskCompletionSource.SetCanceled();
}
}
}
What's weird - this bug is hardly reproduced while debugging. Does anyone have any idea what could be reason of that?
Don't do that (don't try to turn Continuation behaviour into async). Why?
Normally when your app is put into the background (for example when you call file picker), it's being suspended, and here is one small pitfall - when you have a debugger attached, your app will work without being suspended. Surely that can cause some troubles.
Note also that when you normally run your app and you fire a picker, then in some cases your app can be terminated (low resources, user closes it ...). So you need here two things which are added by VS as a template: ContinuationManager and SuspensionManager. More you will find at MSDN. At the same link you will find a good procedure to debug your app:
Follow these steps to test the case in which your app is terminated after calling the AndContinue method. These steps ensure that the debugger reattaches to your app after completing the operation and continuing.
In Visual Studio, right-click on your project and select Properties.
In Project Designer, on the Debug tab under Start action, enable Do not launch, but debug my code when it starts.
Run your app with debugging. This deploys the app, but does not run it.
Start your app manually. The debugger attaches to the app. If you have breakpoints in your code, the debugger stops at the breakpoints. When your app calls the AndContinue method, the debugger continues to run.
If your app calls a file picker, wait until you have opened the file provider (for example, Phone, Photos, or OneDrive). If your app calls an online identity provider, wait until the authentication page opens.
On the Debug Location toolbar, in the Process dropdown list, select the process for your app. In the Lifecycle Events dropdown list, select Suspend and Shutdown to terminate your app but leave the emulator running.
After the AndContinue operation completes, the debugger reattaches to your app automatically when the app continues.
I've changed file picker to standard way provided by #Romasz - it still was crashing. I've been debugging it for hours and I get same COMException but sometimes with information provided:
"GetNavigationState doesn't support serialization of a parameter type which was passed to Frame.Navigate"
It seems that code with TaskCompletionSource works and there is nothing wrong with that. I found out in msdn documentation for Frame
Note: The serialization format used by these methods is for internal use only. Your app should not form any dependencies on it. Additionally, this format supports serialization only for basic types like string, char, numeric and GUID types.
And I was passing my model-class object in navigation parameter - so it was kept in navigation stack therefore it couldn't be serialized. The lesson is: do not use non-primitive types for navigation parameter - Frame.Navigate should disallow such navigation and throw exception - but it doesn't..
EDIT:
Another bug - if you bind tapped (let say button tapped) or event like that to command which launch FileOpenPicker you need to check if picker.PickFile.. was called before - otherwise when you tap fast on that button you'll get few calls to picker.PickFile.. and UnauthorizedAccessException will be thrown.
I currently have a single application that needs to be started from a windows service that i am coding in .net 3.5. This application is currently running as the user who ran the service, in my case the SYSTEM user. If running as the SYSTEM user it does not show the application to the users desktop. Thoughts? advice?
//constructor
private Process ETCHNotify = new Process();
//StartService()
ETCHNotify.StartInfo.FileName = baseDir + "\\EtchNotify.exe";
ETCHNotify.StartInfo.UseShellExecute = false;
//BackgroundWorkerThread_DoWork()
if (!systemData.GetUserName().Equals(""))
{
// start ETCHNotify
try {
ETCHNotify.Start();
}
catch (Exception ex)
{
systemData.Run("ERR: Notify can't start: " + ex.Message);
}
}
I only execute the try/catch if the function i have written GetUserName() (which determines the username of the user running explorer.exe) is not null
again to reiterate: desired functionality is that this starts ETCHNotify in a state that allows it to interact with the currently logged in user as determined by GetUserName()
Collage of some post found around (this and this)
Note that as of Windows Vista, services are strictly forbidden from interacting directly with a user:
Important: Services cannot directly interact with a user as of Windows
Vista. Therefore, the techniques mentioned in the section titled Using
an Interactive Service should not be used in new code.
This "feature" is broken, and conventional wisdom dictates that you shouldn't have been relying on it anyway. Services are not meant to provide a UI or allow any type of direct user interaction. Microsoft has been cautioning that this feature be avoided since the early days of Windows NT because of the possible security risks.
There are some possible workarounds, however, if you absolutely must have this functionality. But I strongly urge you to consider its necessity carefully and explore alternative designs for your service.
Use WTSEnumerateSessions to find the right desktop, then CreateProcessAsUser to start the application on that desktop (you pass it the handle of the desktop as part of the STARTUPINFO structure) is correct.
However, I would strongly recommend against doing this. In some environments, such as Terminal Server hosts with many active users, determining which desktop is the 'active' one isn't easy, and may not even be possible.
A more conventional approach would be to put a shortcut to a small client app for your service in the global startup group. This app will then launch along with every user session, and can be used start other apps (if so desired) without any juggling of user credentials, sessions and/or desktops.
Ultimately in order to solve this i took the advice of #marco and the posts he mentioned. I have created the service to be entirely independent of the tray application that interacts with the user. I did however install the Tray application via registry 'start up' methods with the service. The Service installer will now install the application which interacts with the user as well... This was the safest and most complete method.
thanks for your help everyone.
I wasn't going to answer this since you already answered it, (and it's oh, what? going on 2.5 years OLD now!?) But there are ALWAYS those people who are searching for this same topic, and reading the answers...
In order to get my service to Interact with the Desktop, no matter WHAT desktop, nor, how MANY desktops, nor if the service was even running on the SAME COMPUTER as the desktop app!! None of that matters with what I got here... I won't bore you with the details, I'll just give you the meat and potatoes, and you and let me know if you want to see more...
Ok. First thing I did was create an Advertisement Service. This is a thread that the service runs, opens up a UDP socket to listen for broadcasts on the network. Then, using the same piece of code, I shared it with the client app, but it calls up Advertise.CLIENT, rather than Advertise.SERVER... The CLIENT opens the port I expect the service to be on, and broadcasts a message, "Hello... Is there anybody out there??", asking if they're there ANY servers listening, and if so, reply back to THIS IP address with your computer name, IP Address and port # where I can find the .NET remoting Services..." Then it waits a small amount of time-out time, gathers up the responses it gets, and if it's more than one, it presents the user with a dialog box and a list of services that responded... The Client then selects one, or, if only ONE responded, it will call Connect((TServerResponse) res); on that, to get connected up. At this point, the server is using Remoting Services with the WellKnownClientType, and WellKnownServerType to put itself out there...
I don't think you are too interested in my "Auto-Service locater", because a lot of people frown on UDP, even more so when your app start broadcasting on large networks. So, I'm assuming you'd be more interested in my RemotingHelper, that gets the client connected up to the server. It looks like this:
public static Object GetObject(Type type)
{
try {
if(_wellKnownTypes == null) {
InitTypeCache();
}
WellKnownClientTypeEntry entr = (WellKnownClientTypeEntry)_wellKnownTypes[type];
if(entr == null) {
throw new RemotingException("Type not found!");
}
return System.Activator.GetObject(entr.ObjectType, entr.ObjectUrl);
} catch(System.Net.Sockets.SocketException sex) {
DebugHelper.Debug.OutputDebugString("SocketException occured in RemotingHelper::GetObject(). Error: {0}.", sex.Message);
Disconnect();
if(Connect()) {
return GetObject(type);
}
}
return null;
}
private static void InitTypeCache()
{
if(m_AdvertiseServer == null) {
throw new RemotingException("AdvertisementServer cannot be null when connecting to a server.");
}
_wellKnownTypes = new Dictionary<Type, WellKnownClientTypeEntry>();
Dictionary<string, object> channelProperties = new Dictionary<string, object>();
channelProperties["port"] = 0;
channelProperties["name"] = m_AdvertiseServer.ChannelName;
Dictionary<string, object> binFormatterProperties = new Dictionary<string, object>();
binFormatterProperties["typeFilterLevel"] = "Full";
if(Environment.UserInteractive) {
BinaryServerFormatterSinkProvider binFormatterProvider = new BinaryServerFormatterSinkProvider(binFormatterProperties, null);
_serverChannel = new TcpServerChannel(channelProperties, binFormatterProvider);
// LEF: Only if we are coming form OUTSIDE the SERVICE do we want to register the channel, since the SERVICE already has this
// channel registered in this AppDomain.
ChannelServices.RegisterChannel(_serverChannel, false);
}
System.Diagnostics.Debug.Write(string.Format("Registering: {0}...\n", typeof(IPawnStatServiceStatus)));
RegisterType(typeof(IPawnStatServiceStatus),m_AdvertiseServer.RunningStatusURL.ToString());
System.Diagnostics.Debug.Write(string.Format("Registering: {0}...\n", typeof(IPawnStatService)));
RegisterType(typeof(IPawnStatService), m_AdvertiseServer.RunningServerURL.ToString());
System.Diagnostics.Debug.Write(string.Format("Registering: {0}...\n", typeof(IServiceConfiguration)));
RegisterType(typeof(IServiceConfiguration), m_AdvertiseServer.RunningConfigURL.ToString());
}
[SecurityPermission(SecurityAction.Demand, Flags=SecurityPermissionFlag.RemotingConfiguration, RemotingConfiguration=true)]
public static void RegisterType(Type type, string serviceUrl)
{
WellKnownClientTypeEntry clientType = new WellKnownClientTypeEntry(type, serviceUrl);
if(clientType != RemotingConfiguration.IsWellKnownClientType(type)) {
RemotingConfiguration.RegisterWellKnownClientType(clientType);
}
_wellKnownTypes[type] = clientType;
}
public static bool Connect()
{
// Init the Advertisement Service, and Locate any listening services out there...
m_AdvertiseServer.InitClient();
if(m_AdvertiseServer.LocateServices(iTimeout)) {
if(!Connected) {
bConnected = true;
}
} else {
bConnected = false;
}
return Connected;
}
public static void Disconnect()
{
if(_wellKnownTypes != null) {
_wellKnownTypes.Clear();
}
_wellKnownTypes = null;
if(_serverChannel != null) {
if(Environment.UserInteractive) {
// LEF: Don't unregister the channel, because we are running from the service, and we don't want to unregister the channel...
ChannelServices.UnregisterChannel(_serverChannel);
// LEF: If we are coming from the SERVICE, we do *NOT* want to unregister the channel, since it is already registered!
_serverChannel = null;
}
}
bConnected = false;
}
}
So, THAT is meat of my remoting code, and allowed me to write a client that didn't have to be aware of where the services was installed, or how many services were running on the network. This allowed me to communicate with it over the network, or on the local machine. And it wasn't a problem to have two or more people running the app, however, yours might. Now, I have some complicated callback code in mine, where I register events to go across the remoting channel, so I have to have code that checks to see if the client is even still connected before I send the notification to the client that something happened. Plus, if you are running for more than one user, you might not want to use Singleton objects. It was fine for me, because the server OWNS the objects, and they are whatever the server SAYS they are. So, my STATS object, for example, is a Singleton. No reason to create an instance of it for EVERY connection, when everyone is going to see the same data, right?
I can provide more chunks of code if necessary. This is, of course, one TINY bit of the overall picture of what makes this work... Not to mention the subscription providers, and all that.
For the sake of completeness, I'm including the code chunk to keep your service connected for the life of the process.
public override object InitializeLifetimeService()
{
ILease lease = (ILease)base.InitializeLifetimeService();
if(lease.CurrentState == LeaseState.Initial) {
lease.InitialLeaseTime = TimeSpan.FromHours(24);
lease.SponsorshipTimeout = TimeSpan.FromSeconds(30);
lease.RenewOnCallTime = TimeSpan.FromHours(1);
}
return lease;
}
#region ISponsor Members
[SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure)]
public TimeSpan Renewal(ILease lease)
{
return TimeSpan.FromHours(12);
}
#endregion
If you include the ISponsor interface as part of your server object, you can implement the above code.
Hope SOME of this is useful.
When you register your service, you can tell it to allow interactions with the desktop. You can read this oldie link http://www.codeproject.com/KB/install/cswindowsservicedesktop.aspx
Also, don't forget that you can have multiple users logged in at the same time.
Apparently on Windows Vista and newer interacting with the desktop has been made more difficult. Read this for a potential solution: http://www.codeproject.com/KB/cs/ServiceDesktopInteraction.aspx
I am currently constructing a C#.NET wrapper for the Asterisk Interface Manager.
I can do simple things like transfers and hangups. I am now in the process of building conference calling. I can set up an n-user conference, but I have to do so in terms of "Action: redirect" on existing active channels.
What I'd like to do is route as now non-existent calls (i.e. there is no channel in "core show channels") to my context/extension that puts people in conference rooms.
But I cannot get "Action: originate" to work for anything. What does originate take a channel as an argument when there is not channel yet? What is it that you pass to the channel header? SIP/ does not work for me.
Thanks in advance.
What exactly are you trying to do? You can't use a non-existent channel to bridge into a conference room. If you're looking to create a conference, then have people called on their extensions (or on any number, really) and placed into the conference room, that's simple.
I assume you're using Asterisk.NET. The originate command expects a number to dial (this is the channel), a context, and an extension to connect the call to within the dialplan (this can be hard-coded or can presumably be created through the AMI).
Say you set up a conference room on extension 300. Your originate command would look something like this:
OriginateAction oc = new OriginateAction();
oc.Context = "YourDialPlanContext";
oc.Priority = 1;
// Channel is however you're dialing (extensions, SIP, DAHDI, etc.)
oc.Channel = "SIP/12125551212#Your-Sip-Prover-Peer-Name";
// or in the alternative
// oc.Channel = "ZAP/ZapChannelName/12125551212";
oc.CallerId = "9998887777";
// This is the extension you want dialed once the call is connected
// 300 in our example
oc.Exten = "300";
oc.Timeout = 60000; // Our timeout in ms
oc.Variable = "VAR1=ABC|VAR2=25"; // If you need to pass variables to the dialplan
// Async should be set to true, unless you want your code to wait until the call
// is complete
oc.Async = true;
// Go ahead and place the call
ManagerResponse originateResponse = AsteriskManager.SendAction(oc, oc.Timeout);
Voila! You have now originated a call to your intended conference participant, and upon answering they will be directed into your conference room.
Is it possible to get shutdown reason in Windows Server 2008 immediately after user choose the reason in dialog window? For the shutdown event I'm using SystemEvents.SessionEnding.
I want to write windows service, which will send e-mail about this event.
Or is there any other way in windows server to send e-mails about shutdown/restart event with getting the reason entered by user? Also, I want to notify about power source change (electic line/battery), but this I have already solved by Kernel32.dll > GetSystemPowerStatus.
You can get the shutdown reason inspecting the EventLog.
I assembled a quick demo on Windows Forms that you can adapt to your Windows service.
I've added a EventLog component to the Form and configured it properly. The snippet below shows the code generated in InitializeComponent() for the settings I've maid through the designer.
this.eventLog1.EnableRaisingEvents = true;
this.eventLog1.Log = "System";
this.eventLog1.Source = "USER32";
this.eventLog1.SynchronizingObject = this;
this.eventLog1.EntryWritten += new System.Diagnostics.EntryWrittenEventHandler(this.eventLog1_EntryWritten);
On the event handler, you'll have something along the following lines:
private void eventLog1_EntryWritten(object sender, System.Diagnostics.EntryWrittenEventArgs e)
{
EventLogEntry entry = e.Entry;
if (e.Entry.EventID == 1074)
{
File.AppendAllText(#"c:\message.txt", entry.Message);
}
}
Take a look at your event log to see the appropriate EventIds to filter out.
The compiler will warn you about EventID being deprecated and telling you that you should use InstanceId, but in the quick tests I've done here, it didn't write to my log file and I think we already have enough information to put you on track.
sure it's possible.
in case you want to get that comboBox value in real-time, you will need to run a Thread monitor on that process to raise an event when that value change.