Skip to content

Conversation

@NikolaMilosavljevic
Copy link
Member

@NikolaMilosavljevic NikolaMilosavljevic commented Jun 15, 2022

Fixes: #53

Launcher is being extended to share ClickOnce ApplicationDeployment properties with the application being launched (.NET based). Properties are shared via Environment variables.

Variable names closely match old ClickOnce ApplicationDeployment class: https://docs.microsoft.com/en-us/dotnet/api/system.deployment.application.applicationdeployment?view=netframework-4.8

New environment variables use the same name as old ones, with addition of ClickOnce_ prefix:

ClickOnce_IsNetworkDeployed
ClickOnce_ActivationUri
ClickOnce_CurrentVersion
ClickOnce_DataDirectory
ClickOnce_IsFirstRun
ClickOnce_TimeOfLastUpdateCheck
ClickOnce_UpdatedApplicationFullName
ClickOnce_UpdatedVersion
ClickOnce_UpdateLocation

New property is being added, for Launcher version:

ClickOnce_LauncherVersion

.NET application, launched by new Launcher, can use these properties directly, or indirectly.

Direct use would look like the following:

NameValueCollection nameValueTable = new NameValueCollection();
if (Environment.GetEnvironmentVariable("ClickOnce_IsNetworkDeployed")?.ToLower() == "true")
{
    string value = Environment.GetEnvironmentVariable("ClickOnce_ActivationUri");
    Uri activationUri = string.IsNullOrEmpty(value) ? null : new Uri(value);
    if (activationUri != null)
    {
        nameValueTable = HttpUtility.ParseQueryString(activationUri.Query);
        Console.WriteLine("Query string: " + activationUri.Query);
        Console.ReadKey();
    }
}

Indirect usage would require implementation of a new ApplicationDeployment class, at application level, that could abstract reading of environment variables and provide experience that is very similar to old .NET FX class.

A sample implementation of this class is shared as ApplicationDeployment.cs in this PR (under Documentation/dotnet-mage folder).

With addition of this class, sample usage becomes:

NameValueCollection nameValueTable = new NameValueCollection();
if (ApplicationDeployment.IsNetworkDeployed)
{
    ApplicationDeployment ad = ApplicationDeployment.CurrentDeployment;
    if (ad.ActivationUri != null)
    {
        nameValueTable = HttpUtility.ParseQueryString(ad.ActivationUri.Query);
    }
}

This PR also adds a new switch to dotnet-mage, -TrustURLParameters (or (-tu). This allows developer to set the required deployment attribute using dotnet-mage tool. This is an improvement over old Mage tool, which did not support this functionality and required developer to manually modify application manifest to add trustURLParameters attribute, like this: <deployment install="true" trustURLParameters="true">

trustURLParameters need to be set to true in order for application to have access to ActivationUri and the URL parameters.

@nzain
Copy link

nzain commented Jun 15, 2022

Great to see some love for click once... Is there a chance to tackle #113 (click once file associations)? Is it possible to hijack the ClickOnce_ActivationUri to somehow detect file association arguments?

@NikolaMilosavljevic
Copy link
Member Author

Great to see some love for click once... Is there a chance to tackle #113 (click once file associations)? Is it possible to hijack the ClickOnce_ActivationUri to somehow detect file association arguments?

Thanks @nzain - we plan to look at few other issues after this one is merged, one of those is the file-association issue you referred to.

Current change for deployment properties and URL parameters was straightforward, well understood and prioritized.

@NikolaMilosavljevic NikolaMilosavljevic merged commit dfb0a98 into dotnet:main Jun 17, 2022
{
ApplicationDeployment ad = ApplicationDeployment.CurrentDeployment;

Environment.SetEnvironmentVariable("ClickOnce_ActivationUri", ad.ActivationUri?.ToString());

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some of these ToStrings appear unnecessary for string properties.

Environment.SetEnvironmentVariable("ClickOnce_CurrentVersion", ad.CurrentVersion?.ToString());
Environment.SetEnvironmentVariable("ClickOnce_DataDirectory", ad.DataDirectory?.ToString());
Environment.SetEnvironmentVariable("ClickOnce_IsFirstRun", ad.IsFirstRun.ToString());
Environment.SetEnvironmentVariable("ClickOnce_TimeOfLastUpdateCheck", ad.TimeOfLastUpdateCheck.ToString());

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest using the round-trip format (O) rather than the default culture-specific format to preserve timezone and sub-seconds (assuming they are present).

@SilentBlueD666
Copy link

What mage tool version was this released in? Currently we use version 6.0.1.

@SwedishBobby
Copy link

How can I view the dotnet mage version?
And where does it install?

@heku
Copy link

heku commented Nov 11, 2022

I find there is a difference between .NET 4.8 and .NET 6/7. If you have app .setting file in your clickonce app.

  • In .NET 4.8, the file was installed to AppData\Local\Apps\2.0\Data\....\user.config, which is the clickonce DataDirectory
  • In .NET 6/7, the file was installed to AppData\Local\<AppName>\...\user.config, but the ClickOnce_DataDirectory environment variable still gives me the legacy path.

I didn't find any doc explain this difference, not sure if this is a bug or something by design. If it's by design, may I know any benefit of it?

Gunslap added a commit to Gunslap/babysmash that referenced this pull request Feb 14, 2023
Created ApplicationDeployment.cs to reimplement some of the features from System.Deployment.Application that aren't available in .NET 7, as per: dotnet/deployment-tools#208
@mzxqv
Copy link

mzxqv commented Feb 5, 2024

The old .NET Framework ClickOnce solution has a fully covered code example in the link:
https://learn.microsoft.com/en-us/visualstudio/deployment/how-to-check-for-application-updates-programmatically-using-the-clickonce-deployment-api?view=vs-2022&tabs=csharp

Would it be possible to get a equal covered code example in a .NET based solution?
As it is now, I don't understand how to perform eg Update()?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add support for URL parameters

9 participants