Getting publishing information for a ClickOnce deployment
This tip describes a way to get publishing information for a ClickOnce deployed application
Introduction
Sometimes it's good to know basic information concerning a ClickOnce deployment such as publish version, where the application was installed from, name of the manifest and so on.
This tip helps to resolve this information. It's usable only for applications that have ApplicationIdentity
set (such as ClickOnce deployed applications).
The code
First, the full code:
/// <summary>
/// Helper class to extract identity information based on domain identity
/// </summary>
public static class PublishInfo {
/// <summary>
/// Types of identities
/// </summary>
public enum IdentityType {
/// <summary>
/// Deployment identity
/// </summary>
Deployment = 1,
/// <summary>
/// Application identity
/// </summary>
Application = 2
}
// Regular expressions
private static System.Text.RegularExpressions.Regex _versionRegex =
new System.Text.RegularExpressions.Regex(@"Version=(?<Major>\d*)." +
@"(?<Minor>\d*).(?<Build>\d*).(?<Revision>\d*)",
System.Text.RegularExpressions.RegexOptions.Compiled);
private static System.Text.RegularExpressions.Regex _cultureRegex =
new System.Text.RegularExpressions.Regex(@", Culture=(?<Culture>[^,]*),",
System.Text.RegularExpressions.RegexOptions.Compiled);
private static System.Text.RegularExpressions.Regex _publicKeyTokenRegex =
new System.Text.RegularExpressions.Regex(@", PublicKeyToken=(?<PublicKeyToken>[^,]*),",
System.Text.RegularExpressions.RegexOptions.Compiled);
private static System.Text.RegularExpressions.Regex _processorArchitectureRegex =
new System.Text.RegularExpressions.Regex(@", processorArchitecture=(?<ProcessorArchitecture>[^,]*)",
System.Text.RegularExpressions.RegexOptions.Compiled);
/// <summary>
/// Main uri
/// </summary>
public static System.Uri Uri { get; private set; }
/// <summary>
/// Deployment identity
/// </summary>
public static Identity DeploymentIdentity { get; private set; }
/// <summary>
/// Application identity
/// </summary>
public static Identity ApplicationIdentity { get; private set; }
/// <summary>
/// Class that holds the identity information
/// </summary>
public class Identity {
/// <summary>
/// Type of the identity
/// </summary>
public PublishInfo.IdentityType IdentityType { get; private set; }
/// <summary>
/// Version information
/// </summary>
public System.Version Version { get; private set; }
/// <summary>
/// Name of the application
/// </summary>
public string ApplicationName { get; private set; }
/// <summary>
/// Public key token
/// </summary>
public string PublicKeyToken { get; private set; }
/// <summary>
/// Processor architecture
/// </summary>
public System.Reflection.ProcessorArchitecture ProcessorArchitecture { get; private set; }
/// <summary>
/// Default constructor
/// </summary>
private Identity() { }
/// <summary>
/// Constructor
/// </summary>
/// <param name="identity">Identity string to parse</param>
/// <param name="identityType">Type of the identity</param>
internal Identity(string identity, PublishInfo.IdentityType identityType) {
System.Text.RegularExpressions.Match regexMatch;
System.Reflection.ProcessorArchitecture architecture;
this.IdentityType = identityType;
try {
// Parse application name
this.ApplicationName = identity.Substring(0, identity.IndexOf(','));
// Parse version
regexMatch = _versionRegex.Match(identity);
this.Version = new System.Version(int.Parse(regexMatch.Groups["Major"].ToString()),
int.Parse(regexMatch.Groups["Minor"].ToString()),
int.Parse(regexMatch.Groups["Build"].ToString()),
int.Parse(regexMatch.Groups["Revision"].ToString()));
// Parse public key token
regexMatch = _publicKeyTokenRegex.Match(identity);
this.PublicKeyToken = regexMatch.Groups["PublicKeyToken"].ToString();
// Parse processor architecture
regexMatch = _processorArchitectureRegex.Match(identity);
if (!System.Enum.TryParse<System.Reflection.ProcessorArchitecture>(
regexMatch.Groups["ProcessorArchitecture"].ToString(), true, out architecture)) {
architecture = System.Reflection.ProcessorArchitecture.None;
}
this.ProcessorArchitecture = architecture;
} catch { }
}
}
/// <summary>
/// Constructor for the PublishInfo class
/// </summary>
static PublishInfo() {
string identities;
string[] identity;
try {
// Get the full name of the identity
identities = System.AppDomain.CurrentDomain.ApplicationIdentity.FullName;
// Parse uri
PublishInfo.Uri = new System.Uri(identities.Substring(0, identities.IndexOf('#')));
identities = identities.Substring(identities.IndexOf('#') + 1);
//Split the separate identities
if (identities.IndexOf("\\") > -1) {
identity = identities.Split('\\');
} else {
identity = identities.Split('/');
}
//Create the identity information
PublishInfo.DeploymentIdentity = new Identity(identity[0], IdentityType.Deployment);
PublishInfo.ApplicationIdentity = new Identity(identity[1], IdentityType.Application);
} catch { }
}
}
Main parts explained
The ApplicationIdentity
of CurrentDomain
returns a string representation for the application. This string contains three informative parts:
- Application URL
#
as a separator- Deployment identity
- \ as a separator (1)
- Application identity
The PublishInfo
constructor first separates the application URL and stores it statically in this class. After this the remainder of the string is splitted using the separator.
1 Even though the MSDN documentation states that \
is used as a separator, when I tested this /
was the actual separator used. For this reason both variations are implemented in the code.
The Identity
class holds the information for individual identity, application or deployment. In the constructor of this class the key information is parsed from the identity string and placed on proper properties such as Version
.
The properties of the Identity class are:
IdentityType
: Which type of identity is this: Application or DeploymentApplicationName
: either the application name or the deployment manifest name depending on the identity typeVersion
: Version for the identity described using System.Version classPublicKeyToken
: Public key token of the identityProcessorArchitecture
: Processor architecture of the identity, described using System.Reflection.ProcessorArchitecture enumeration
Using the class
As an example of the usage of the class I wrote the property values of both identities to output window of Visual Studio using Debug class:
System.Diagnostics.Debug.WriteLine("Uri: " + PublishInfo.Uri.ToString());
System.Diagnostics.Debug.WriteLine("");
System.Diagnostics.Debug.WriteLine("DeploymentIdentity");
System.Diagnostics.Debug.WriteLine("------------------");
System.Diagnostics.Debug.WriteLine("ApplicationName: " + PublishInfo.DeploymentIdentity.ApplicationName);
System.Diagnostics.Debug.WriteLine("Version: " + PublishInfo.DeploymentIdentity.Version.ToString());
System.Diagnostics.Debug.WriteLine("PublicKeyToken: " + PublishInfo.DeploymentIdentity.PublicKeyToken);
System.Diagnostics.Debug.WriteLine("ProcessorArchitecture: " +
PublishInfo.DeploymentIdentity.ProcessorArchitecture.ToString());
System.Diagnostics.Debug.WriteLine("");
System.Diagnostics.Debug.WriteLine("ApplicationIdentity");
System.Diagnostics.Debug.WriteLine("-------------------");
System.Diagnostics.Debug.WriteLine("ApplicationName: " + PublishInfo.ApplicationIdentity.ApplicationName);
System.Diagnostics.Debug.WriteLine("Version: " + PublishInfo.ApplicationIdentity.Version.ToString());
System.Diagnostics.Debug.WriteLine("PublicKeyToken: " + PublishInfo.ApplicationIdentity.PublicKeyToken);
System.Diagnostics.Debug.WriteLine("ProcessorArchitecture: " +
PublishInfo.ApplicationIdentity.ProcessorArchitecture.ToString());
The results were like
Uri: file:///C:/Temp/publish/Tester.application
DeploymentIdentity
------------------
ApplicationName: Tester.application
Version: 1.0.0.9
PublicKeyToken: 79481f74d589e5cd
ProcessorArchitecture: X86
ApplicationIdentity
-------------------
ApplicationName: Tester.exe
Version: 1.0.0.9
PublicKeyToken: 79481f74d589e5cd
ProcessorArchitecture: X86
Note that if you're running the program from Visual Studio, you'll get different results, such as
Uri: http://tempuri.org/Tester.application
DeploymentIdentity
------------------
ApplicationName: Tester.application
Version: 1.0.0.9
PublicKeyToken: 0000000000000000
ProcessorArchitecture: X86
ApplicationIdentity
-------------------
ApplicationName: DomainIdentity.exe
Version: 1.0.0.9
PublicKeyToken: 0000000000000000
ProcessorArchitecture: X86
Also note that if the application hasn't been deployed yet, ApplicationIdentity
is null so both identities in the static helper class are null.
History
- March 27, 2012: Tip created.