ClickOnce没有通过第二个Uri

时间:2015-05-26 16:08:19

标签: c# wpf singleton clickonce

我们有一个WPF应用程序,它使用WindowsFormsApplicationBase类来使它成为singleton;并使用ClickOne部署。每当我们想要执行这个exe时,我们通过Uri调用它(在服务器中使用查询字符串部署目录)。所有工作仅适用于此应用程序的第一个实例。

问题:每次激活单实例应用程序时,ClickOnce始终会传递第一个Uri,而不管Uri传递的是什么。此外,不会为同一应用程序的任何后续实例化填充StartupNextInstanceEventArgs

有人有这个问题吗?

提前致谢。

2 个答案:

答案 0 :(得分:1)

到目前为止,我还没有得到任何具体的答案。因此,我决定实施一个不同的解决方案,提到here。不幸的是,原始问题在两种方法中都适用。所以我决定在第二种方法(参见网址)之上做一个解决方法来解决这个问题,直到我有一个干净的解决方案。

解决方法

  1. 修改后的入口点(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();
            }
     }
    
  2. 现在实现接口(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;
            }
    
  3. 帮助获取/设置配置值。

        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的网页然后只使用它将传递的参数调用此服务方法。