Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Salve a tutti!
Una delle più importanti e vistose novità di Vista e Windows 7 è la Session 0 isolation. Questa novità, è una delle più impattanti dal punto di vista della compatibilità delle applicazioni, in quanto una applicazione che gira come servizio o una applicazione eseguita da un servizio, non è più accedibile direttamente e non può comunicare con le altre applicazioni che girano sul Desktop. Lo switch “Allow this service to interact with desktop” non serve più.
Application Compatibility: Session 0 Isolation, http://msdn.microsoft.com/en-us/library/bb756986.aspx, spiega il perchè esattamente.
Se vogliamo quindi creare un evento da un servizio che sia poi accedibile da una sessione utente, dobbiamo crearlo usando il prefisso “Global\” e dobbiamo crearlo con il descrittore della sicurezza impostato, perchè per default solo gli Administrators possono accedere agli oggetti definiti “Global\” e deve essere appunto globale per poter essere “visibile” al di fuori della sessione 0, quella dei servizi.
Questo piccolo esempio mostra come fare a creare un evento globale accedibile a tutti gli utenti da un servizio:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.Security.AccessControl;
using System.ServiceProcess;
using System.Text;
using System.Threading;
using System.Windows.Forms;
namespace EventRightsServiceTest
{
public partial class Service1 : ServiceBase
{
public Service1()
{
Trace.Listeners.Add(new TextWriterTraceListener(string.Format(@"C:\Logs\MyService.log", DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss"))));
Trace.AutoFlush = true;
InitializeComponent();
}
private Thread _worker = null;
protected override void OnStart(string[] args)
{
if (_worker == null)
{
_worker = new Thread(new ThreadStart(ThreadFunction));
_worker.Start();
}
}
protected override void OnStop()
{
if (_worker != null)
{
_worker.Abort();
}
}
private EventWaitHandle _event;
private void ThreadFunction()
{
bool created;
try
{
System.Security.Principal.SecurityIdentifier sid = new System.Security.Principal.SecurityIdentifier(System.Security.Principal.WellKnownSidType.WorldSid, null);
System.Security.Principal.NTAccount acct = sid.Translate(typeof(System.Security.Principal.NTAccount)) as System.Security.Principal.NTAccount;
EventWaitHandleSecurity sec = new EventWaitHandleSecurity();
sec.AddAccessRule(new EventWaitHandleAccessRule(acct, EventWaitHandleRights.FullControl, AccessControlType.Allow));
EventWaitHandle myEvent = new EventWaitHandle(true, EventResetMode.ManualReset, "Global\\SampleEvent", out created, sec);
Trace.WriteLine("EventWaitHandle 'Global\\SampleEvent' new: " + created);
}
catch (Exception ex)
{
Trace.WriteLine(ex.ToString());
}
}
}
}
Per testare se l’evento è visibile, una volta avviato il servizio, potete realizzare una veloce Console application con questo codice:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.AccessControl;
using System.Text;
using System.Threading;
namespace EventRightsTestConsole
{
class Program
{
static void Main(string[] args)
{
try
{
EventWaitHandle handle = EventWaitHandle.OpenExisting("Global\\SampleEvent", EventWaitHandleRights.Synchronize);
Console.WriteLine("Successfully opened");
}
catch (Exception ex)
{
Console.WriteLine("Open failed");
Console.WriteLine(ex.ToString());
Console.ReadLine();
}
}
}
}
Gli eventi sono utili per sincronizzare il funzionamento di applicazioni diverse, quali ad esempio proprio un servizio e una applicazione user mode.
Alla prossima!
Mario Raccagni
Senior Support Engineer
Platform Development Support Team