c# - 跨同一台计算机上的用户会话的 WCF 命名管道。可能的?
问题描述
要求
我正在尝试创建一个“单实例”winforms 应用程序,如果调用第二个实例,则传递参数。我希望Mutex
不会像这样工作。我已经在 winform 应用程序上创建了一个 WCF 管道,这样如果另一个实例来了,它将通知主实例并带有所需的参数,我将根据需要处理主实例上的参数,并在通知后关闭第二个实例。
问题: 上面的代码似乎工作正常,当涉及多个用户会话时出现问题,当我以“用户 A”身份登录机器并打开我的应用程序时,它打开了应用程序(主实例)。同时,如果另一个用户登录说“用户 B”并尝试打开应用程序,它很高兴打开 :(
代码:
这是我的 WCF 单实例代码。
public static class SingleInstanceManager
{
/// <summary>
/// Raised when another instance attempts to start up.
/// </summary>
public static event StartupEventHandler OtherInstanceStarted;
/// <summary>
/// Checks to see if this instance is the first instance running on this machine. If it is not, this method will
/// send the main instance this instance's startup information.
/// </summary>
/// <param name="guid">The application's unique identifier.</param>
/// <returns>True if this instance is the main instance.</returns>
public static bool VerifySingleInstance(Guid guid)
{
if (!AttemptPublishService(guid))
{
NotifyMainInstance(guid);
return false;
}
return true;
}
/// <summary>
/// Attempts to publish the service.
/// </summary>
/// <param name="guid">The application's unique identifier.</param>
/// <returns>True if the service was published successfully.</returns>
private static bool AttemptPublishService(Guid guid)
{
try
{
ServiceHost serviceHost = new ServiceHost(typeof(SingleInstance));
NetNamedPipeBinding binding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None);
serviceHost.AddServiceEndpoint(typeof(ISingleInstance), binding, CreateAddress(guid));
serviceHost.Open();
return true;
}
catch
{
return false;
}
}
/// <summary>
/// Notifies the main instance that this instance is attempting to start up.
/// </summary>
/// <param name="guid">The application's unique identifier.</param>
private static void NotifyMainInstance(Guid guid)
{
NetNamedPipeBinding binding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None);
EndpointAddress remoteAddress = new EndpointAddress(CreateAddress(guid));
using (ChannelFactory<ISingleInstance> factory = new ChannelFactory<ISingleInstance>(binding, remoteAddress))
{
ISingleInstance singleInstance = factory.CreateChannel();
singleInstance.NotifyMainInstance(Environment.GetCommandLineArgs());
}
}
/// <summary>
/// Creates an address to publish/contact the service at based on a globally unique identifier.
/// </summary>
/// <param name="guid">The identifier for the application.</param>
/// <returns>The address to publish/contact the service.</returns>
private static string CreateAddress(Guid guid)
{
return string.Format(CultureInfo.CurrentCulture, "net.pipe://localhost/{0}", guid);
}
/// <summary>
/// The interface that describes the single instance service.
/// </summary>
[ServiceContract]
private interface ISingleInstance
{
/// <summary>
/// Notifies the main instance that another instance of the application attempted to start.
/// </summary>
/// <param name="args">The other instance's command-line arguments.</param>
[OperationContract]
void NotifyMainInstance(string[] args);
}
/// <summary>
/// The implementation of the single instance service interface.
/// </summary>
private class SingleInstance : ISingleInstance
{
/// <summary>
/// Notifies the main instance that another instance of the application attempted to start.
/// </summary>
/// <param name="args">The other instance's command-line arguments.</param>
public void NotifyMainInstance(string[] args)
{
if (OtherInstanceStarted != null)
{
Type type = typeof(StartupEventArgs);
ConstructorInfo constructor = type.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
StartupEventArgs e = (StartupEventArgs)constructor.Invoke(null);
FieldInfo argsField = type.GetField("_args", BindingFlags.Instance | BindingFlags.NonPublic);
Debug.Assert(argsField != null);
argsField.SetValue(e, args);
OtherInstanceStarted(null, e);
}
}
}
}
在 Winforms Main 上:
static void Main()
{
//bool isSingle;
//var mut = new Mutex(true, "MarketFeeder", out isSingle);
var applicationId = new Guid("08f21b4e-86d7-4ddf-abcb-9a72cd2bbd4f");
if (SingleInstanceManager.VerifySingleInstance(applicationId))
{
SingleInstanceManager.OtherInstanceStarted += OnOtherInstanceStarted;
// Start the application
System.Windows.Forms.Application.EnableVisualStyles();
System.Windows.Forms.Application.SetCompatibleTextRenderingDefault(false);
main = new MainForm();
System.Windows.Forms.Application.Run(main);
}
}
需要帮助
有没有办法通过 Namedpipe 在同一台机器上的用户之间进行通信?,我不想为我的要求去寻求“Windows 服务”,我觉得我的要求太过分了。
已经通过以下链接但没有运气。他们也太老了,我觉得我们最近有更好的解决方案。我希望有一些像我一样的开发人员仍在开发 Windows 应用程序:P
解决方案
推荐阅读
- python - 如何在绘制 roc 曲线时根据特定的 fpr 计算特定的 tpr(y 轴)?
- javascript - 工具提示不适用于初始绘图,但在绘图更改后开始工作
- php - php __destruct 为什么通过 file_get_contents 得到不同的结果
- java - Java Swing 中的自定义 UI
- java - Err apk 应用程序正在关闭
- pip - 为什么 pip3 -V 和 sudo pip3 -V 显示不同的版本
- c - 显示 ASCII 而不是字符的 C 代码
- kubernetes - 如果没有额外的就绪门,我们是否可以假设“ContainersReady”为真时“Ready”必须为真?
- powerbi - PowerBI 中具有多个条件的平均值
- javascript - YouTube 聊天直播嵌入不再起作用