Question

This may seem a bit crazy, but if you can tell me a better way please do. I need a webservice that will display the mercurial revision number for the current version.

I have a very simple batch file that writes this number to a text file

cd C:\inetpub\wwwroot\MyWebsite
hg identify --num > services\version.txt 

and a method that should call the batch file then read the contents of the file and, for now, write to screen (I'm doing it in a web page, but will migrate to a simple service later)

Private Sub GetVersionNumber()
    Dim versionFile = Server.MapPath("~/services/version.txt")
    Dim batchFile = Server.MapPath("~/services/version.bat")
    Process.Start(batchFile)

    Dim revision As String = String.Empty
    Using reader As New StreamReader(versionFile)
        Do While reader.Peek() <> -1
            revision = reader.ReadLine()
        Loop
    End Using
    Response.Write(revision)
End Sub

I have granted Everyone write access to the services directory and explicitly on version.txt, but when I hit the page the version.txt file is always empty. If I have the file open in notepad++ when I do then I get a message saying the file has been modified by another program, do I want to reload it. When I do it's empty. If I set some text in the file and save it then visit the web page again the contents of my text file are wiped out.

I had this in a try/catch block but no exception was thrown, so I've removed it (for clarity).

Ultimately all I need is to get the results of
hg identify --num
to display as a string on the web page/service which will be called by a separate SharePoint site

Was it helpful?

Solution

Instead of manually invoking the batch file from your web server every time the page is requested, you can configure a Mercurial update hook to invoke your identify command automatically every time the working copy updates.

For example, add this to the repository’s .hg\hgrc file:

[hooks]
update.writeversion = hg identify --num > services\version.txt

Some links with additional info on hooks:

OTHER TIPS

The reason the batch file is empty is that a process kicked off and run in this manner can only be alive as long as the parent thread is alive. Also, using Process.Start does not wait for that process to finish. As specified in the documentation, the return of this method is a boolean indicating that the process did or didn't start. Since you're treating it as a void, as soon as the process starts your program keeps right on running and finishes (since it's a web service).

Once your web service exits the sub, the thread is terminated and all children processes are terminated along with it. Specifically, the cmd.exe which is currently running your batch file is terminated before it can ever really get going since your streamreader is reading an empty file.

If you can guarantee that your batch file will process fairly quickly you might try to get away with using Thread.Sleep to cause the web service call to pause long enough for that batch file to finish processing, but this is always going to be a race condition.

I would call Mercurial directly and read from its standard output stream:

var hg = new ProcessStartInfo("C:\Program Files\Mercurial\hg.exe", "identify --num -R c:\inetpub\webroot");
hg.RedirectStandardOutput = True;
hg.RedirectStandardInput = True;
hg.UseShellExecute = False;
hg.CreateNoWindow = True;

var hgProc = New Process()
hgProc.StartInfo = hg
hgProc.Start()

var repoID = hgProc.StandardOutput.ReadToEnd()
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top