C# 窗口服务的通知图标

C# 窗口服务的通知图标,c#,visual-studio-2010,windows-services,C#,Visual Studio 2010,Windows Services,我已经开发了win服务程序,该程序从本地驱动器读取excel文件,然后将该文件的值保存到数据库,现在我想开发一个通知图标,在我的服务启动后显示一条消息(“excel文件保存在数据库中”),并将excel文件保存到数据库中 请给我一些提示来解决这个问题。从Vista开始,您的服务将不允许与桌面交互,因此不能直接从服务中运行UI。您需要构建一个代理应用程序,该应用程序在用户登录时启动,可以与您的服务聊天(可能使用WCF) 下面是这样做的原因: 对于更复杂的交互,开发人员应该将其UI代码移动到在用户会

我已经开发了win服务程序,该程序从本地驱动器读取excel文件,然后将该文件的值保存到数据库,现在我想开发一个通知图标,在我的服务启动后显示一条消息(“excel文件保存在数据库中”),并将excel文件保存到数据库中


请给我一些提示来解决这个问题。

从Vista开始,您的服务将不允许与桌面交互,因此不能直接从服务中运行UI。您需要构建一个代理应用程序,该应用程序在用户登录时启动,可以与您的服务聊天(可能使用WCF)

下面是这样做的原因:

对于更复杂的交互,开发人员应该将其UI代码移动到在用户会话中运行并处理所有UI需求的代理中。代理通过RPC或命名管道与服务通信。如果用户使用控制面板、Internet Explorer或类似的UI体验启动UI交互,则该UI体验应启动代理。然后代理处理所有UI交互。如果UI是必需的,但不是由用户启动的,则服务必须请求代理启动任何必需的UI,而不是试图自行启动该UI。在服务必须启动用户交互且代理尚未运行的罕见情况下,服务应调用CreateProcessAsUser API来启动代理。然后,代理可以启动所有UI交互。对于开发人员来说,仔细审查所有可能的使用场景,并考虑将所有UI代码移动到在用户会话中运行的代理中是非常重要的。p>
这里的问题是windows服务在后台运行,对用户的桌面没有影响

您可以创建类似的应用程序(不使用windows窗体):

然后在应用程序中使用类似以下类的内容与windows服务通信:

public class Program
{
    public int Setting { get; set; }
}

[ServiceContract]
public interface ISettingService
{
    [OperationContract]
    void SetSetting(int setting);
}

public class SettingService : ISettingService
{
    private readonly Program program;

    public SettingService(Program program)
    {
        this.program = program;
    }

    public void SetSetting(int setting)
    {
        program.Setting = setting;
    }
}

internal class CustomInstanceProvider : IInstanceProvider
{
    private readonly Program program;

    public CustomInstanceProvider(Program program)
    {
        this.program = program;
    }

    public object GetInstance(InstanceContext instanceContext, Message message)
    {
        return GetInstance(instanceContext);
    }

    public object GetInstance(InstanceContext instanceContext)
    {
        return new SettingService(program);
    }

    public void ReleaseInstance(InstanceContext instanceContext, object instance)
    {
        IDisposable disposable = instance as IDisposable;
        if (disposable != null)
        {
            disposable.Dispose();
        }
    }
}

internal class CustomInstanceProviderBehaviorAttribute : Attribute, IServiceBehavior
{
    private readonly IInstanceProvider instanceProvider;

    public CustomInstanceProviderBehaviorAttribute(IInstanceProvider instanceProvider)
    {
        this.instanceProvider = instanceProvider;
    }

    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
        foreach (ChannelDispatcher cd in serviceHostBase.ChannelDispatchers)
        {
            foreach (EndpointDispatcher ed in cd.Endpoints)
            {
                if (!ed.IsSystemEndpoint)
                {
                    ed.DispatchRuntime.InstanceProvider = instanceProvider;
                }
            }
        }
    }

    public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters) { }
    public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { }
}

public class CustomServiceHost : ServiceHost
{
    private readonly Program p;

    public CustomServiceHost(Program program, params Uri[] baseAddresses)
    : base(typeof(SettingService), baseAddresses)
    {
        this.p = program;
    }

    protected override void OnOpening()
    {
        Description.Behaviors.Add(new CustomInstanceProviderBehaviorAttribute(new CustomInstanceProvider(p)));
        base.OnOpening();
    }
}
公共类程序
{
公共int设置{get;set;}
}
[服务合同]
公共接口ISettingService
{
[经营合同]
无效设置(int设置);
}
公共类设置服务:ISettingService
{
专用只读程序;
公共设置服务(程序)
{
这个程序=程序;
}
公共void设置(int设置)
{
程序设置=设置;
}
}
内部类CustomInstanceProvider:IInstanceProvider
{
专用只读程序;
公共CustomInstanceProvider(程序)
{
这个程序=程序;
}
公共对象GetInstance(InstanceContext InstanceContext,消息)
{
返回GetInstance(instanceContext);
}
公共对象GetInstance(InstanceContext InstanceContext)
{
返回新的设置服务(程序);
}
public void ReleaseInstance(InstanceContext InstanceContext,对象实例)
{
IDisposable disposable=实例为IDisposable;
if(一次性!=null)
{
一次性的,一次性的;
}
}
}
内部类CustomInstanceProviderBehaviorAttribute:属性,IServiceBehavior
{
专用只读IInstanceProvider instanceProvider;
公共CustomInstanceProviderBehaviorAttribute(IInstanceProvider instanceProvider)
{
this.instanceProvider=instanceProvider;
}
公共无效ApplyDispatchBehavior(ServiceDescription ServiceDescription,ServiceHostBase ServiceHostBase)
{
foreach(serviceHostBase.ChannelDispatchers中的ChannelDispatcher cd)
{
foreach(在cd.Endpoints中终结)
{
如果(!ed.IsSystemEndpoint)
{
ed.DispatchRuntime.InstanceProvider=InstanceProvider;
}
}
}
}
public void AddBindingParameters(ServiceDescription ServiceDescription,ServiceHostBase ServiceHostBase,集合终结点,BindingParameterCollection bindingParameters){}
公共无效验证(ServiceDescription ServiceDescription,ServiceHostBase ServiceHostBase){}
}
公共类CustomServiceHost:ServiceHost
{
专用只读程序p;
公共CustomServiceHost(程序,参数Uri[]基地址)
:base(类型(设置服务),baseAddresses)
{
p=程序;
}
受保护的覆盖无效打开()
{
Description.Behaviors.Add(新CustomInstanceProviderBehaviorAttribute(新CustomInstanceProvider(p));
base.OnOpening();
}
}

我认为您需要
NotifyIcon.showBallootTip
方法在您的服务中实现。
您可能需要阅读。

我找到了另一个有趣的链接。请看一看,你是对的,我确实想这样做,但我认为窗口服务不能与桌面交互,因为安全问题。这是参考资料。然后你不应该选择NotifyIcon或者创建两个项目。一个windows应用程序和你的实际服务。窗口应用程序将与服务进行有限的交互,主要是显示Notify图标。