ClickOnce 没有传递第二个 Uri
ClickOnce not passing second Uri
我们有一个 WPF 应用程序,它使用 WindowsFormsApplicationBase
class 使其成为 singleton
;并使用 ClickOne
进行部署。每当我们想要执行这个 exe 时,我们都会通过 Uri(服务器中带有查询字符串的部署目录)调用它。仅适用于此应用程序的第一个实例,一切正常。
问题:无论传递什么Uri,每次启动单实例应用程序时,ClickOnce总是传递第一个Uri。此外,StartupNextInstanceEventArgs
不会为同一应用程序的任何后续实例化填充。
有人遇到过这个问题吗?
提前致谢。
到目前为止,我的问题还没有得到任何具体的答案。因此,我决定实施一个不同的解决方案 here。不幸的是,原始问题在这两种方法中都适用。所以我决定在第二种方法之上做一个变通方法(参见 url)来解决这个问题,直到我有一个干净的解决方案。
解决方法
修改入口点(主要)以包含一项功能,该功能将传入的激活 uri 保存到应用程序配置文件。您必须保留保存该值的位置,因为它往往会在某处用旧的激活 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;
}
帮助 get/set 配置值。
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;
}
}
}
有点迟到的答案,但我在研究将应用程序强制到单个实例时偶然发现了这个问题。
如果我明白你想做什么,你想要一个接受命令行参数的单实例应用程序。第二次尝试应用程序 运行,您只想保留第一个实例,但将第二组命令行参数传递给它。
在这种情况下,为什么不使用适当的方法在您的 WPF 应用程序中托管 WCF 服务,而是将这些参数传递给该方法。使用 ClickOnce 的网页随后只需使用它传递的参数调用此服务方法。
我们有一个 WPF 应用程序,它使用 WindowsFormsApplicationBase
class 使其成为 singleton
;并使用 ClickOne
进行部署。每当我们想要执行这个 exe 时,我们都会通过 Uri(服务器中带有查询字符串的部署目录)调用它。仅适用于此应用程序的第一个实例,一切正常。
问题:无论传递什么Uri,每次启动单实例应用程序时,ClickOnce总是传递第一个Uri。此外,StartupNextInstanceEventArgs
不会为同一应用程序的任何后续实例化填充。
有人遇到过这个问题吗?
提前致谢。
到目前为止,我的问题还没有得到任何具体的答案。因此,我决定实施一个不同的解决方案 here。不幸的是,原始问题在这两种方法中都适用。所以我决定在第二种方法之上做一个变通方法(参见 url)来解决这个问题,直到我有一个干净的解决方案。
解决方法
修改入口点(主要)以包含一项功能,该功能将传入的激活 uri 保存到应用程序配置文件。您必须保留保存该值的位置,因为它往往会在某处用旧的激活 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; }
帮助 get/set 配置值。
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; } } }
有点迟到的答案,但我在研究将应用程序强制到单个实例时偶然发现了这个问题。
如果我明白你想做什么,你想要一个接受命令行参数的单实例应用程序。第二次尝试应用程序 运行,您只想保留第一个实例,但将第二组命令行参数传递给它。
在这种情况下,为什么不使用适当的方法在您的 WPF 应用程序中托管 WCF 服务,而是将这些参数传递给该方法。使用 ClickOnce 的网页随后只需使用它传递的参数调用此服务方法。