c# - C# windows 服务安装后不返回剪贴板数据
问题描述
我有一个 Windows 服务程序的代码,它应该不时清除剪贴板。在控制台应用程序中对其进行测试证明它是一个工作代码(然后通过 Topshelf nuget 包将控制台应用程序变为服务)。但是将它作为服务运行它只是无法完成这项工作。经过一些基本的日志记录后,我发现 Clipboard.Hastext() (以及所有其他)在安装服务(直接从调试文件夹安装)后返回 false。我错过了什么或者应该考虑的调试和部署模式之间的区别是什么?
public class Service
{
readonly Timer timer;
object clipboardData;
public Service()
{
timer = new Timer(TimeSpan.FromMinutes(1).TotalMilliseconds)
{
AutoReset = true
};
timer.Elapsed += Timer_Elapsed;
}
/// <summary>
/// Checks every minute if there is any data on the clipboard.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Timer_Elapsed(object sender, ElapsedEventArgs e)
{
CurrentThreadParse(DoWork);
}
public void Start()
{
timer.Start();
}
public void Stop()
{
timer.Stop();
}
private void ChangeClipboardData()
{
if (Clipboard.ContainsText())
{
clipboardData = Clipboard.GetText();
WriteChanged();
}
else if (Clipboard.ContainsImage())
{
clipboardData = Clipboard.GetImage();
WriteChanged();
}
else if (Clipboard.ContainsAudio())
{
clipboardData = Clipboard.GetAudioStream();
WriteChanged();
}
else if (Clipboard.ContainsFileDropList())
{
clipboardData = Clipboard.GetFileDropList();
WriteChanged();
}
#if DEBUG
else
Console.WriteLine("No change!");
#endif
}
private void WriteChanged()
{
#if DEBUG
Console.WriteLine("Clipboard data has changed!");
#endif
}
private object GetClipboardObject()
{
if (Clipboard.ContainsText())
return Clipboard.GetText();
else if (Clipboard.ContainsImage())
return Clipboard.GetImage();
else if (Clipboard.ContainsAudio())
return Clipboard.GetAudioStream();
else if (Clipboard.ContainsFileDropList())
return Clipboard.GetFileDropList();
return null;
}
private void ClearClipboard()
{
Clipboard.Clear();
clipboardData = null;
#if DEBUG
Console.WriteLine("Clipboard data removed!");
#endif
}
/// <summary>
/// Sets the current thread as STA.
/// </summary>
/// <param name="threadStart">The code to run.</param>
private void CurrentThreadParse(ThreadStart threadStart)
{
Thread thread = new Thread(threadStart);
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
thread.Join();
}
private void DoWork()
{
object clipboardObject = GetClipboardObject();
if (clipboardData == null)
{
ChangeClipboardData();
}
else if (clipboardData.Equals(clipboardObject))
{
ClearClipboard();
}
else
{
//The last check returned data from the clipboard, but was changed,
//so the clipboard should not be cleared.
ChangeClipboardData();
}
}
}
完整的项目可以在这里找到:https ://github.com/profgyuri/ClipboardService
解决方案
服务是不可能的。
服务在 Windows 上的单独会话中运行(会话 0)。用户始终处于不同的会话中(会话 1、2 等)。其他会话中的服务无法访问用户的剪贴板。
相反,您可以创建要在用户会话中执行的 Windows 计划任务,即Run only when user is logged on
任务(链接)。时间表可以有任何重复间隔。