none
How to Read or Write ProductVersion/AssemblyVersion to or from an existing line in a file post build RRS feed

  • Question

  • ****UPDATE*****

    My original question ended up getting answer somewhere else. I then ended up having to use a variant of the answer code to achieve a slightly different task. I have updated the Title accordingly. Be sure to read the whole thread.

    ****Oringinal Post****

    My program auto increments it's productversion/AssemblyVersion on every build (using https://marketplace.visualstudio.com/items?itemName=PrecisionInfinity.AutomaticVersions). It also includes an updater (https://github.com/ravibpatel/AutoUpdater.NET) for the updater to work it requires an XML file on a remote server that includes a line for the current assembly version so it can be checked by the application.

    Here's the xml:

    <?xml version="1.0" encoding="utf-8" ?>
    <item>
    <version>1.0.0.8</version>
    <url>https://codctk.000webhostapp.com/downloads/codctksetup/codctksetup.zip</url>
    <changelog></changelog>
    <mandatory>True</mandatory>
    </item>

    The updater does not support automatic incrementing of this version number in the xml file (no variable option etc) so I'm trying to figure out how I can do it by amending that one line in the xml file after the application has built with the object ProductVersion?

    The application is also built remotely on visualstudio.com so I guess a postbuild element in the msbuild project file would work so I started messing around with the post-build event command line in the project properties and I came up with this:

    <Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets" />
    <ItemGroup>
    <File include="$(ProjectDir)autoupdate.xml" />
    </ItemGroup>
    <FileUpdate File"Regex="(\d+)\.(\d+)\.(\d+)\.(\d+)" ReplacementText="$1.$2.$3.1" />

    But at build time it errors with code 255. I've tried several other variations both more and less complex and I get the same problem.

    I've also tried creating a console application to do it with streamreader/streamwriter so I could call it post build but I can't get the console app to link to the assemblyversion/productversion of the main application.

    I would really appreciate any help you guys can provide.

    Thanks M3PH



    • Edited by M3PH Friday, September 29, 2017 12:23 AM
    Sunday, September 24, 2017 5:47 PM

Answers

  • ok but how would I then write that to the xml file at line 3 after or at compile time?

    You can use LINQ-To-XML for that:

    Option Strict On
    Option Explicit On
    Option Infer Off
    
    Public Class Form1
        Private _desktop As String = _
            Environment.GetFolderPath(Environment.SpecialFolder.Desktop)
    
        Private Sub _
            Form1_Load(sender As System.Object, _
                       e As System.EventArgs) _
                       Handles MyBase.Load
    
            Dim xmlFilePath As String = IO.Path.Combine(_desktop, "Example.xml")
    
            Dim xDoc As XElement = XElement.Load(xmlFilePath)
    
            Dim newVersionText As String = "This Is A Test"
    
            xDoc...<version>.Value = newVersionText
    
            Stop
    
            ' Now hover your mouse over "xDoc" and you'll see
            ' that I've changed the value. You'll now want to
            ' use xDoc.Save(filepath) to update the XML file.
    
        End Sub
    End Class


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    • Marked as answer by M3PH Friday, September 29, 2017 12:19 AM
    Sunday, September 24, 2017 7:45 PM
  • Frank,

    I have just come to the need to use the LINQ -To- XML code you provided above but I need to modify it so it reads the value of the tag <version> into a variable so it can then be used to construct a filename (so does the opposite of what it does now).

    If you go back to what I posted a while ago, don't set it up as an assignment; instead "read" the value:

    What I had:

            Dim xmlFilePath As String = IO.Path.Combine(_desktop, "Example.xml")
    
            Dim xDoc As XElement = XElement.Load(xmlFilePath)
    
            Dim newVersionText As String = "This Is A Test"
    
            xDoc...<version>.Value = newVersionText
    
            Stop

    Instead, set the variable to be something like:

    Dim verString As String = xDoc...<version>.Value

    You might also want to parse that string into an actual instance of the version class:

    https://msdn.microsoft.com/en-us/library/system.version.parse(v=vs.110).aspx


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    • Marked as answer by M3PH Friday, September 29, 2017 12:19 AM
    Thursday, September 28, 2017 10:18 PM
  • Yeah, I just looked at it again and realised what was up. Thanks again

    Once you get going with it, it's not too bad. Dealing with the weird syntax (axis properties) will make you cross your eyes for a while, but once you get it, it'll make sense.

    https://msdn.microsoft.com/en-us/library/bb308960.aspx

    *****

    If you're satisfied with everything then please close this thread by marking one or more posts as the answer.


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    • Marked as answer by M3PH Friday, September 29, 2017 12:19 AM
    Thursday, September 28, 2017 10:26 PM

All replies

  • M3PH,

    I'm not sure what your question is, not totally, but you can get the assembly version of a dotNET assembly using System.Reflection:

    Dim ver As Version = AssemblyName.GetAssemblyName(exePath).Version

    I'm not sure if that answers your question or not though?


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Sunday, September 24, 2017 6:31 PM
  • ok but how would I then write that to the xml file at line 3 after or at compile time?
    Sunday, September 24, 2017 7:38 PM
  • ok but how would I then write that to the xml file at line 3 after or at compile time?

    You can use LINQ-To-XML for that:

    Option Strict On
    Option Explicit On
    Option Infer Off
    
    Public Class Form1
        Private _desktop As String = _
            Environment.GetFolderPath(Environment.SpecialFolder.Desktop)
    
        Private Sub _
            Form1_Load(sender As System.Object, _
                       e As System.EventArgs) _
                       Handles MyBase.Load
    
            Dim xmlFilePath As String = IO.Path.Combine(_desktop, "Example.xml")
    
            Dim xDoc As XElement = XElement.Load(xmlFilePath)
    
            Dim newVersionText As String = "This Is A Test"
    
            xDoc...<version>.Value = newVersionText
    
            Stop
    
            ' Now hover your mouse over "xDoc" and you'll see
            ' that I've changed the value. You'll now want to
            ' use xDoc.Save(filepath) to update the XML file.
    
        End Sub
    End Class


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    • Marked as answer by M3PH Friday, September 29, 2017 12:19 AM
    Sunday, September 24, 2017 7:45 PM
  • Thanks again.

    Am I right in saying that code does what I need but at application start? How would I go about making it so that when I build the program it does the above but as an msbuild instruction thus making it VSTS compatible?

    Sunday, September 24, 2017 8:04 PM
  • Am I right in saying that code does what I need but at application start?

    That's up to you, but you're dealing with files.

    My initial thought is to create a "maintenance" routine as an application where you select the two files then let it update the XML file from there.


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Sunday, September 24, 2017 8:09 PM
  • So I was thinking about this last night and I figured it would be way easier to lift the assemblyversion of the application at compile time (as much as the code provided up is great what i'm trying to do really should be done by the compiler as a compiler task imo) and place it in a text file. So I created a beforebuild event in the .proj file that looks like this (not sure yet if it actually works but it is ballpark):

    <ItemGroup>
         <AssemInfo Include="Assemblyinfo.vb"/>
    </ItemGroup>
    
    <Target Name="ReadLinesFromVersion">
        <ReadLinesFromFile File=@(AssemInfo)
               <Output TaskParameter="Lines" 
                PropertyName="AssemblyVersion" />						 
                <WriteLinesToFile File="Version.txt"
                Lines="using System.Reflection%3B&#xD;&#xA;&#xD;&#xA;
                [("$(AssemInfo)")]" />
                Overwrite="true"
                Encoding="Unicode"/>
          </ReadLinesFromFile>
    </Target>  

    Next we use a batch file that is run post build to copy the line placed in Version.Txt to line 3 character 10 in autoupdate.xml. The problem is that after spending almost 2 hours googling I'm struggling to find code that would do that. I know I need to use findstr but I'm not sure how I would then place the text where I need it. This is what the batch file looks like so far:

    @Echo Off
    findstr /r (0-9)1......* Version.txt > autoupdate.xml

    You wouldn't by chance have any ideas on how to complete that would you?

    Thanks again

    M3PH



    • Edited by M3PH Monday, September 25, 2017 3:55 PM
    Monday, September 25, 2017 3:49 PM
  • You wouldn't by chance have any ideas on how to complete that would you?

    Thanks again

    M3PH


    I'm not really following any of what you're talking about there, but if you're going to put the code inside the application itself, you don't need to go outside of it to look at the file just to bring it back.

    You can get it directly:

     Dim thisV As Version = _
                System.Reflection.Assembly.GetExecutingAssembly().GetName().Version

    In VB (this is part of VB, not part of the framework), you can shorten that quite a lot:

    Dim ver As Version = My.Application.Info.Version


    "A problem well stated is a problem half solved.” - Charles F. Kettering


    Monday, September 25, 2017 3:57 PM
  • What I need is a solution that is not part of the programs core code but is something that is done at build time by the compiler. Once the xml file is updated at build time by the compiler it should then remain static until the next build is run. Having it be part of the core code will be a problem because changing it every time the program runs or as an optional action the program can do will not only completely break another core system of the program (it's self auto update system. Changing the xml this way will cause the updater to think it is always on the latest version thus never running updates), it would cause an exception as the xml is remotely hosted, not on the file system of the local machine and thus not accessible for writes.

    So, what needs to happen is:

    when compiler runs the build it reads the assemblyversion out of assemblyinfo.vb and creates a file called version.txt in the projectdir. This has to be done this way for the reasons given above.

    Next we have a post build task, run either by the compiler or as a step that VSTS can run using it's batch script tool that copies the text from version.txt and inserts it into autoupdate.xml at line 3 char 10 (overwriting the text that is at the position and the following 7 characters). The release phase of the build in VSTS then uploads the compiled, zipped program and the xml file to my web hosting so that older versions of the program, when next run, can read the xml file, know it's OOD and auto update itself by downloading the zip, extracting it and running the contained installer.

    Monday, September 25, 2017 6:08 PM
  • What I need is a solution that is not part of the programs core code but is something that is done at build time by the compiler. Once the xml file is updated at build time by the compiler it should then remain static until the next build is run. Having it be part of the core code will be a problem because changing it every time the program runs or as an optional action the program can do will not only completely break another core system of the program (it's self auto update system. Changing the xml this way will cause the updater to think it is always on the latest version thus never running updates), it would cause an exception as the xml is remotely hosted, not on the file system of the local machine and thus not accessible for writes.

    So, what needs to happen is:

    when compiler runs the build it reads the assemblyversion out of assemblyinfo.vb and creates a file called version.txt in the projectdir. This has to be done this way for the reasons given above.

    Next we have a post build task, run either by the compiler or as a step that VSTS can run using it's batch script tool that copies the text from version.txt and inserts it into autoupdate.xml at line 3 char 10 (overwriting the text that is at the position and the following 7 characters). The release phase of the build in VSTS then uploads the compiled, zipped program and the xml file to my web hosting so that older versions of the program, when next run, can read the xml file, know it's OOD and auto update itself by downloading the zip, extracting it and running the contained installer.


    Sorry that I couldn't help then...

    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Monday, September 25, 2017 6:16 PM
  • No worries. Thanks for trying.
    Monday, September 25, 2017 7:14 PM
  • Hi M3PH,

    I find one article that allows to modify AssemblyVersion attribute specified in AssemblyInfo.cs files, you can take a look.

    https://www.codeproject.com/Articles/31236/How-To-Update-Assembly-Version-Number-Automaticall

    https://stackoverflow.com/questions/14254554/how-to-update-the-value-in-assemblyinfo-cs-dynamically

    Best Regards,

    Cherry


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Wednesday, September 27, 2017 6:04 AM
    Moderator
  • Hi M3PH,

    I find one article that allows to modify AssemblyVersion attribute specified in AssemblyInfo.cs files, you can take a look.

    https://www.codeproject.com/Articles/31236/How-To-Update-Assembly-Version-Number-Automaticall

    https://stackoverflow.com/questions/14254554/how-to-update-the-value-in-assemblyinfo-cs-dynamically

    Best Regards,

    Cherry


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Thanks Cherry,

    Fortunately I got talking to the developer of my update system and he randomly coded something out for me as an additional module to his software. So now anyone that wants to use AutoUpdate.Net can grab the addon module PostBuildXmlCreator from github.

    Frank,

    I have just come to the need to use the LINQ -To- XML code you provided above but I need to modify it so it reads the value of the tag <version> into a variable so it can then be used to construct a filename (so does the opposite of what it does now). I tried using productversion.insert like this:

    Dim PreVerSet As String = ProductVersion.Chars(6)
    Dim PreVerSet2 As Integer = PreVerSet + 1
    Dim PreVerSet3 As String = PreVerSet2
    Dim VerInsert As String = PreVerSet.Insert("4", "2")
    
    Process.Start(My.Application.Info.DirectoryPath + "appsetup_" + VerInsert)
    (Lifting the revision number in productversion into a new variable then incrementing it by 1 and insert it back) The problem with that is keeps giving me a startindex out of range exception and I can't see why. So if you have any ideas on how I would convert that code so it reads the xml that would be great. I have had a look at it already but I'm having trouble understanding the code.


    • Edited by M3PH Thursday, September 28, 2017 10:12 PM
    Thursday, September 28, 2017 10:10 PM
  • Frank,

    I have just come to the need to use the LINQ -To- XML code you provided above but I need to modify it so it reads the value of the tag <version> into a variable so it can then be used to construct a filename (so does the opposite of what it does now).

    If you go back to what I posted a while ago, don't set it up as an assignment; instead "read" the value:

    What I had:

            Dim xmlFilePath As String = IO.Path.Combine(_desktop, "Example.xml")
    
            Dim xDoc As XElement = XElement.Load(xmlFilePath)
    
            Dim newVersionText As String = "This Is A Test"
    
            xDoc...<version>.Value = newVersionText
    
            Stop

    Instead, set the variable to be something like:

    Dim verString As String = xDoc...<version>.Value

    You might also want to parse that string into an actual instance of the version class:

    https://msdn.microsoft.com/en-us/library/system.version.parse(v=vs.110).aspx


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    • Marked as answer by M3PH Friday, September 29, 2017 12:19 AM
    Thursday, September 28, 2017 10:18 PM
  • Yeah, I just looked at it again and realised what was up. Thanks again
    Thursday, September 28, 2017 10:23 PM
  • Yeah, I just looked at it again and realised what was up. Thanks again

    Once you get going with it, it's not too bad. Dealing with the weird syntax (axis properties) will make you cross your eyes for a while, but once you get it, it'll make sense.

    https://msdn.microsoft.com/en-us/library/bb308960.aspx

    *****

    If you're satisfied with everything then please close this thread by marking one or more posts as the answer.


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    • Marked as answer by M3PH Friday, September 29, 2017 12:19 AM
    Thursday, September 28, 2017 10:26 PM