I'm deploying now a WPF c# project and want to put the clickonce version (rather than the assembly or product version) on the screen title.
I used to do it in Win form application in the following way. But it seems that it is not the way in WPF applications. I searched on Google but didn't find anything. Please help.
if (System.Deployment.Application.ApplicationDeployment.IsNetworkDeployed)
{
ApplicationDeployment ad = ApplicationDeployment.CurrentDeployment;
lblVer.Text = "V" + ad.CurrentVersion.ToString();
}
else
lblVer.Text = "V" + Application.ProductVersion.ToString();
Try this:
public static Version GetPublishedVersion()
{
XmlDocument xmlDoc = new XmlDocument();
Assembly asmCurrent = System.Reflection.Assembly.GetExecutingAssembly();
string executePath = new Uri(asmCurrent.GetName().CodeBase).LocalPath;
xmlDoc.Load(executePath + ".manifest");
string retval = string.Empty;
if (xmlDoc.HasChildNodes)
{
retval = xmlDoc.ChildNodes[1].ChildNodes[0].Attributes.GetNamedItem("version").Value.ToString();
}
return new Version(retval);
}
What error do you get? There's no difference in the ClickOnce API's between Windows Forms and WPF. It is not dependent upon any UI framework.
Did you remember to add a reference to System.Deployment.dll?
using System;
using System.Deployment.Application;
namespace Utils
{
public class ClickOnce
{
public static Version GetPublishedVersion()
{
return ApplicationDeployment.IsNetworkDeployed
? ApplicationDeployment.CurrentDeployment.CurrentVersion
: System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
}
}
}
If you get an error about System.Deployment.Application, then Solution > Project > References > Add Reference > Assemblies > Framework > System.Deployment.
Do not parse the assembly XML for this information; you're relying on undocumented behaviour which simply happens to work 'for now'.
OK,
I found the problem.
I had to add reference to System.Deployment
That is why I couldn't use it. This dll is for winforms also.
This solution is similar to #Engin, but uses XPath.
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load("...");
XmlNamespaceManager ns = new XmlNamespaceManager(xmlDoc.NameTable);
ns.AddNamespace("asmv1", "urn:schemas-microsoft-com:asm.v1");
string xPath = "/asmv1:assembly/asmv1:assemblyIdentity/#version";
XmlNode node = xmlDoc.SelectSingleNode(xPath, ns);
string version = node.Value;
Related
I have some code which must be able to generated a console application at runtime (Codegeneration with System.CodeDom). I did this already a lot, but in NET 6 now I am struggling with that and the new API. In the code below I try to compile simply from a string. See below the static class with method Start() which then should generates the application.
The compilations seems fine, no errors at the end. But when starting the generated AppCodegenerated.exe, it shows some reference exception with System.Runtime.
Please help, any Idea? Already researched a lot but could not find any useful solution..
//-
I used the Visual Studio 2022 / NET 6 and theses Nuget's:
using Basic.Reference.Assemblies;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Text;
using System.Text;
namespace CompilerSimplified
{
public static class Compiler
{
public static bool Start()
{
string FileName = "AppCodegenerated";
string ExePath = AppDomain.CurrentDomain.BaseDirectory + #"\" + FileName + ".exe";
string code = #"using System; Console.WriteLine(""Hello.""); Console.ReadLine(); ";
// ------- References -------------
// .net platform references
List<MetadataReference> References = new List<MetadataReference>();
foreach (var item in ReferenceAssemblies.Net60) // ReferenceAssemblies from Nuget: Basic.Reference.Assemblies;
References.Add(item);
// or tried this: loop manually through system platform
//string[] fileEntries = Directory.GetFiles(#"C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.0\ref\net6.0\", "*.dll");
//foreach (string fileName in fileEntries)
// references.Add(MetadataReference.CreateFromFile(fileName));MetadataReference.CreateFromFile(fileName));
// ------- References END -------------
// delete existing file
if (File.Exists(ExePath))
File.Delete(ExePath);
// compiler options
CSharpCompilationOptions DefaultCompilationOptions =
new CSharpCompilationOptions(outputKind: OutputKind.ConsoleApplication, platform: Platform.AnyCpu)
.WithOverflowChecks(true).WithOptimizationLevel(OptimizationLevel.Release);
// encode soucre code
string sourceCode = SourceText.From(code, Encoding.UTF8).ToString();
// CSharp options
var parsedSyntaxTree = Parse(sourceCode, "", CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp10));
// compilation
var compilation = CSharpCompilation.Create(FileName, new SyntaxTree[] { parsedSyntaxTree }, references: References, DefaultCompilationOptions);
var result = compilation.Emit(ExePath);
// return
if (result.Success)
return true;
else
return false;
}
private static SyntaxTree Parse(string text, string filename = "", CSharpParseOptions options = null)
{
var stringText = SourceText.From(text, Encoding.UTF8);
return SyntaxFactory.ParseSyntaxTree(stringText, options, filename);
}
}
}
Above code runs fine without error and exports the AppCodegenerated.exe into the project /bin folder.
Execution of this generated AppCodegenerated.exe shows following on the output console:
Unhandled exception: System.IO.FileNotFoundException:
The file or assembly "System.Runtime, Version = 6.0.0.0, Culture = neutral,
PublicKeyToken = b03f5f7f11d50a3a" or a dependency on it was not found.
The system can not find the stated file.
It is not possible to codegenerate directly a console application like the initial approach above. One possible solution is to generate first a dll (what I mentioned above in the example code is working fine), and from there include that .dll into a .exe, from where the functionality can run.
I am trying to use XmlDocument class **
and **XmlDocument .Load(..) function
on the Portable Project of XAMARIN.Forms Portable solution with visual studio community.
The compiler says that "The type or namespace name 'XmlDocument' could not be found (are you missing a using directive or an assembly reference?"
If i go in References it don't allow me to add the System.XML namespace (there is no) and if i browse file and go to system.xml.dll it says me that the file could not be added because this component is already automatically referenced by build system.
what i can to do to use the class??
NOTE:
in .Droid and .IOS project there is a referenc to System.xml and in those projects I can use XmlDocument class.
PCL doesn't support XmlDocument. You can use System.Xml.Linq.XDocument instead.
The XmlDocument class is not available for use in a PCL library, as you can see on its documentation page under Version Information. (Compare to the Version Information section of the XmlDictionary class - notice how this class has Portable Class Library available while XmlDocument does not.)
If you want to use an XmlDocument, you'll have to create a dependency service and implement it separately under both Android and iOS versions.
I had no trouble adding XML to my project:
using System.Xml;
using System.Xml.Serialization;
public string ToXML(Object oObject)
{
XmlDocument xmlDoc = new XmlDocument();
XmlSerializer xmlSerializer = new XmlSerializer(oObject.GetType());
using (MemoryStream xmlStream = new MemoryStream())
{
xmlSerializer.Serialize(xmlStream, oObject);
xmlStream.Position = 0;
xmlDoc.Load(xmlStream);
return xmlDoc.InnerXml;
}
}
After that the XML string can be shared:
public MvxCommand ShareWaypoints => new MvxCommand(ShareWaypointsAsync);
public async void ShareWaypointsAsync()
{
try
{
string strXML = "";
foreach (var wp in waypoints)
{
strXML += ToXML(wp);
}
if (strXML != "")
await Share.RequestAsync(new ShareTextRequest
{
Text = strXML,
Title = "Share Text"
});
}
catch (Exception ex)
{
await _userDialogs.AlertAsync(ex.Message);
}
}
I am creating code generation tool (auto code generation based on table structure) as a Windows forms application in Visual Studio 2012 using .NET Framework 4.0. It's generating the portable object, controller, WCF services and business logic code files.
All code files bundle in the appropriate project and all project bundle in one solution. The solution and projects need to create dynamically through program.
I have tried to create the solution and project using Visual Studio Add-in project. It is working fine in Add-In project (separate solution). The OnConnection method call automatically in Add-in project. Now I want to implements this in my code generation tool. While debugging in Add-In project the application variable shown like COM object.
I am tried to pass the value for OnConnection method from code generation tool, it throws an error (I passed this object for application variable). I really don't know how to call this method from my code generation tool. Anyone help this?
Code
private DTE2 _applicationObject;
private AddIn _addInInstance;
public void OnConnection(object application, ext_ConnectMode connectMode, object addInInst, ref Array custom)
{
_applicationObject = (DTE2)application;
_addInInstance = (AddIn)addInInst;
createProjectsFromTemplates(_applicationObject);
}
public void createProjectsFromTemplates(DTE2 dte)
{
try
{
Solution2 soln = (Solution2)dte.Solution;
string csTemplatePath;
string csPrjPath = "SamplePath\\TestCreateProject";
csTemplatePath = soln.GetProjectTemplate("WpfApplication.zip", "CSharp");
System.Windows.Forms.MessageBox.Show("C# template path: " + csTemplatePath);
soln.AddFromTemplate(csTemplatePath, csPrjPath, "NewWCFCSharpAutoGeneratorProject", false);
Project prj;
ProjectItem prjItem;
String itemPath;
// Point to the first project (the Visual Basic project).
prj = soln.Projects.Item(1);
prjItem = prj.ProjectItems.AddFromFileCopy("SampelCSharp.cs");
}
catch (System.Exception ex)
{
System.Windows.Forms.MessageBox.Show("ERROR: " + ex.Message);
}
}
You can instantiate a VS from the host application and generate the files. Hope that will work. The below code works well for me.
Use the following namespaces to get work the below given code.
Namespaces:
using System;
using Extensibility;
using EnvDTE;
using EnvDTE80;
using Microsoft.VisualStudio.CommandBars;
using System.Resources;
using System.Reflection;
Code:
EnvDTE80.DTE2 dte2;
dte2 = (EnvDTE80.DTE2)System.Runtime.InteropServices.Marshal.GetActiveObject("VisualStudio.DTE.11.0");
Connect objConnect = new Connect();
Array objArray = null;
objConnect.OnConnection(dte2, ext_ConnectMode.ext_cm_UISetup, null, ref objArray);
I got this reference it is really useful.
http://rcos.rpi.edu/projects/unmake/commit/programmatically-launch-devenv-generate-a-solution-and-save-it/
You can use this. This is for .cs project files and framewwork above .NET 2.0 versions. VB project sources are not compatible.
protected void Build(string project)
{
Engine engine = new Engine();
BuildPropertyGroup properties = new BuildPropertyGroup();
properties.SetProperty(#"Configuration", #"Debug");
// Point to the path that contains the .NET Framework 2.0 CLR and tools
engine.BinPath = #"c:\windows\microsoft.net\framework\v3.5";
// Instantiate a new FileLogger to generate build log
FileLogger logger = new FileLogger();
// Set the logfile parameter to indicate the log destination
string str = #"logfile=D:\temp";
str += project.Substring(project.LastIndexOf("\\"), project.LastIndexOf(".") - project.LastIndexOf("\\")) + ".log";
logger.Parameters = str;
// Register the logger with the engine
engine.RegisterLogger(logger);
// Build a project file
bool success = engine.BuildProjectFile(project, new string[] { "build" }, properties);
//Unregister all loggers to close the log file
engine.UnregisterAllLoggers();
using (BinaryWriter writer = new BinaryWriter(File.Open(#"D:\temp\Prj.log", FileMode.Append)))
{
if (success)
{
writer.Write("\nBuild Success :" + project.Substring(project.LastIndexOf("\\")));
}
else
{
writer.Write("\nBuild Fail :" + project.Substring(project.LastIndexOf("\\")));
}
}
}
How can I programmatically get the current product version in C#?
My code:
VersionNumber = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();
I am getting VersionNumber=1.0.0.0, but the current version is 1.0.0.12.
There are three versions: assembly, file, and product. To get the product version:
using System.Reflection;
using System.Diagnostics;
Assembly assembly = Assembly.GetExecutingAssembly();
FileVersionInfo fileVersionInfo = FileVersionInfo.GetVersionInfo(assembly.Location);
string version = fileVersionInfo.ProductVersion;
I got the answer to my question its Just give the reference to System.Deployment.Application and though it wont work in developement of the visual studio but it will work once the application is deployed.
//using System.Deployment.Application;
//using System.Reflection;
public string CurrentVersion
{
get
{
return ApplicationDeployment.IsNetworkDeployed
? ApplicationDeployment.CurrentDeployment.CurrentVersion.ToString()
: Assembly.GetExecutingAssembly().GetName().Version.ToString();
}
}
System.Reflection.Assembly.GetEntryAssembly().GetName().Version
Another approach to getting the product version (which is specified using the AssemblyInformationalVersionAttribute) is
private static string AssemblyProductVersion
{
get
{
object[] attributes = Assembly.GetExecutingAssembly()
.GetCustomAttributes(typeof(AssemblyInformationalVersionAttribute), false);
return attributes.Length == 0 ?
"" :
((AssemblyInformationalVersionAttribute)attributes[0]).InformationalVersion;
}
}
Try this:
var thisApp = Assembly.GetExecutingAssembly();
AssemblyName name = new AssemblyName(thisApp.FullName);
VersionNumber = "v. " + name.Version;
Also, see this Microsoft Doc on the AssemblyName.Version property.
In C# you need to use reflection and diagnostics
Assembly assembly = Assembly.GetExecutingAssembly();
FileVersionInfo fileVersionInfo = FileVersionInfo.GetVersionInfo(assembly.Location);
string version = fileVersionInfo.ProductVersion;
All these answers ask for the assembly with .GetExecutingAssembly().
If you have this code in a dll, it will return the dll version number.
Swap that call for GetCallingAssembly() to get the place in your code that wanted to know.
/// <summary>
/// Returns version like 2.1.15
/// </summary>
public static String ProductVersion
{
get
{
return new Version(FileVersionInfo.GetVersionInfo(Assembly.GetCallingAssembly().Location).ProductVersion).ToString();
}
}
var productVersion = FileVersionInfo.GetVersionInfo(typeof(SomeClassFromDesiredAssembly).Assembly.Location).ProductVersion;
I had the same issue as most of you. It would always show 1.0.0.0 unless you manually went in and updated assemblyInfo.cs to the version you wanted to display. I think we wanted to display the publish version-revision number under the project properties but that doesn't seem to be an option (from what I've read).
I'm not sure if back when these comments were made this existed, but now in the assemblyinfo.cs there is a way to do this automatically. I too was not content with having to manually update these with every publish.
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.*")]
That * auto-increments with each publish. It won't be the same as the publish number you see under the project properties, but it definitely increments and is definitely better than doing it by hand.
You then have a couple options to display it as mentioned above. I personally used this which I found on another site
Version version = Assembly.GetExecutingAssembly().GetName().Version;
lblRevision.Text = String.Format("{0}.{1}.{2}.{3}", version.Major, version.Minor, version.Build, version.Revision);
Traditionally I use the regular asp.net website (created using the File > New Website). Recently, I opted to work off of a full fledged project (created using File > New Project > ASP.net Web Application).
I've been using the same custom controls for years without incident. I simply create the new website, place my CustomControls.cs file in the App_Code directory, add one line to the web.config file and I can use all of my custom server controls.
When I try that with my web project I get the following error
Error 225 The
type or namespace name 'DTF' could not
be found in the global namespace (are
you missing an assembly
reference?) D:[Project Location On
Drive]\AgIn02.aspx.designer.cs
My custom control file looks like this
using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using AjaxControlToolkit;
using System.Text;
using System.IO;
using System.Text.RegularExpressions;
namespace DTF.Web.UI
{
public class IntOnlyBox : TextBox
{
private RequiredFieldValidator rfv;
private ValidatorCalloutExtender vce;
private AjaxControlToolkit.FilteredTextBoxExtender ftb;
private string strInvalidMessage = "";
private string strValidationGroup = "";
public string ValidationGroup
{
get
{
return strValidationGroup;
}
set
{
strValidationGroup = value;
}
}
public string InvalidMessage
{
get
{
return strInvalidMessage;
}
set
{
strInvalidMessage = value;
}
}
protected override void OnInit(EventArgs e)
{
rfv = new RequiredFieldValidator();
rfv.ControlToValidate = this.ID;
rfv.ErrorMessage = "<span style=\"color:black\"><b>Required Field Missing</b><br />" + this.InvalidMessage + "</span>";
//rfv.ErrorMessage = this.InvalidMessage;
rfv.ID = "rfv" + this.ID;
rfv.Display = ValidatorDisplay.None;
rfv.SetFocusOnError = true;
rfv.EnableClientScript = true;
rfv.ValidationGroup = this.ValidationGroup;
vce = new AjaxControlToolkit.ValidatorCalloutExtender();
vce.ID = "vce" + this.ID;
vce.TargetControlID = "rfv" + this.ID;
vce.Width = 300;
ftb = new FilteredTextBoxExtender();
ftb.ID = "ftb" + this.ID;
ftb.TargetControlID = this.ID;
ftb.FilterType = FilterTypes.Numbers;
Controls.Add(rfv);
Controls.Add(vce);
Controls.Add(ftb);
}
protected override void Render(HtmlTextWriter w)
{
//w.Write(this.InvalidMessage);
base.Render(w);
rfv.RenderControl(w);
vce.RenderControl(w);
ftb.RenderControl(w);
}
}
}
my web.config entry looks like this (in the pages/controls area)
<add tagPrefix="DTF" namespace="DTF.Web.UI" />
I've tried everything I can think of to get this to work and compile. The intellisense for the custom server controls works fine, it simply won't compile.
I also get the error "The base class
includes the field 'blanro', but its
type (DTF.DateBoxFull) is not
compatible with the type of control
(DTF.DateBoxFull)."
Any idea how to fix this, and why it would work in the regular asp.net website but not in a web project?
Thanks Everyone.
Compile your custom classes to a .dll and add a reference to your project.
Well, to answer it simply WAP and Web Site have a different way of compiling the applications and hence you may be seeing this behavior.
When using a WAP, it's best not to put your custom control in App_Code. Instead, simply put that code somewhere else in your project, and you should be able to use the control from your pages without problems.
The App_Code directory in a WebApplication project has no effect. All code files, regardless of the directory in which it resides, are compiled into a single assembly, and that assembly is placed in the bin directory.
Just move all your files out of App_Code and then delete App_Code.