我们有一个WPF应用程序,它使用WindowsFormsApplicationBase
类来使它成为singleton
;并使用ClickOne
部署。每当我们想要执行这个exe时,我们通过Uri调用它(在服务器中使用查询字符串部署目录)。所有工作仅适用于此应用程序的第一个实例。
问题:每次激活单实例应用程序时,ClickOnce始终会传递第一个Uri,而不管Uri传递的是什么。此外,不会为同一应用程序的任何后续实例化填充StartupNextInstanceEventArgs
。
有人有这个问题吗?
提前致谢。
答案 0 :(得分:1)
到目前为止,我还没有得到任何具体的答案。因此,我决定实施一个不同的解决方案,提到here。不幸的是,原始问题在两种方法中都适用。所以我决定在第二种方法(参见网址)之上做一个解决方法来解决这个问题,直到我有一个干净的解决方案。
解决方法强>
修改后的入口点(Main)包含一项功能,可将传入的激活uri保存到app配置文件中。您必须保留此值保存的位置,因为它倾向于使用旧的激活uri覆盖某个位置。记住这是我的问题。
public static void Main()
{
string uri;
StartupHelpers.SetConfigurationValue("ActivationUri", (StartupHelpers.HasTriggeredFromUrl(out uri)) ? uri : string.Empty);
if (SingleInstance<App>.InitializeAsFirstInstance(Unique))
{
var application = new App();
application.Run();
SingleInstance<App>.Cleanup();
}
}
现在实现接口(ISingletonInstanceApp),如下所示。
public bool SignalExternalCommandLineArgs(IList<string> args)
{
var uri = new Uri(StartupHelpers.GetConfigurationValue("ActivationUri"));
int queryString = 0;
if (StartupHelpers.IsTriggeredFromWLink(uri, out queryString))
{
//in my case I have a function LoadPage which take
//some parameter to populate UI. Your case might be
//totally different. However, the idea is on how we
//could grab running instance and pass value into
// it to do something different.
((YourMainWindow) (Current.MainWindow)).LoadPage(queryString.ToString());
}
// Bring window to foreground
if (this.MainWindow.WindowState == WindowState.Minimized)
{
this.MainWindow.WindowState = WindowState.Normal;
}
this.MainWindow.Activate();
return true;
}
帮助获取/设置配置值。
public static class StartupHelpers
{
public static bool HasTriggeredFromUrl(out string uri)
{
try
{
uri = string.Empty;
var activeUri = ApplicationDeployment.CurrentDeployment.ActivationUri;
uri = activeUri != null ? activeUri.ToString() : string.Empty;
return true;
}
catch (InvalidDeploymentException inv)
{
uri = string.Empty;
return false;
}
}
public static bool IsTriggeredFromLink(Uri activationUri, out int queryStringValue)
{
queryStringValue = 0;
var hasTriggeredFromLink = true;
if (string.IsNullOrWhiteSpace(activationUri.Query) ||
HttpUtility.ParseQueryString(activationUri.Query).Count <= 0)
hasTriggeredFromLink = false;
else
{
if (!int.TryParse(HttpUtility.ParseQueryString(activationUri.Query)[0], out queryStringValue))
throw new Exception("Invalid startup argument found from web site.");
}
return hasTriggeredFromLink;
}
public static bool SetConfigurationValue(string key, string value)
{
try
{
Configuration appConfig = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
appConfig.AppSettings.Settings[key].Value = value;
appConfig.Save(ConfigurationSaveMode.Full);
ConfigurationManager.RefreshSection("appSettings");
}
catch (Exception ex)
{
throw ex;
}
return true;
}
public static string GetConfigurationValue(string key)
{
try
{
Configuration appConfig = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
ConfigurationManager.RefreshSection("appSettings");
return appConfig.AppSettings.Settings[key].Value;
}
catch (Exception ex)
{
throw ex;
}
}
}
答案 1 :(得分:0)
有点迟到的答案,但我偶然发现了这个问题,同时考虑强制将应用程序强加给单个实例。
如果我了解您要执行的操作,则需要一个采用命令行参数的实例应用程序。第二次尝试运行应用程序时,您只想保留第一个实例,但将第二组命令行参数传递给它。
在这种情况下,为什么不使用适当的方法在WPF应用程序中托管WCF服务,而是将这些参数传递给它。使用ClickOnce的网页然后只使用它将传递的参数调用此服务方法。