15

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

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

4

3 回答 3

13

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

以下是MS对此的评价:

对于更复杂的交互,开发人员应该将他们的 UI 代码移动到在用户会话中运行并处理所有 UI 要求的代理中。代理通过 RPC 或命名管道与服务通信。如果用户使用控制面板、Internet Explorer 或类似的 UI 体验启动 UI 交互,则该 UI 体验应启动代理。然后代理处理所有 UI 交互。如果需要 UI 但用户未启动,则服务必须请求代理启动任何所需的 UI,而不是尝试自行启动该 UI。在服务必须启动用户交互并且代理尚未运行的极少数情况下,服务应调用 CreateProcessAsUser API 来启动代理。然后代理可以启动所有 UI 交互。

于 2012-10-12T10:37:31.940 回答
2

这里的问题是windows服务在后台运行,对用户桌面没有影响。

您可以创建一个与此类似的应用程序(没有 windows 窗体):Notify Icon control in .Net 2.0

然后在应用程序中使用类似以下类的东西与 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();
    }
}
于 2012-10-12T10:47:54.007 回答
1

我认为您需要NotifyIcon.ShowBalloonTipMethod 在您的服务中实施。您可能需要阅读内容。

于 2012-10-12T11:33:47.620 回答