Can't create log file from hook program call - c#

My hook post-commit template calls my postcommitlog.exe to create a MyFile_LOG.txt and write to it the 3 arguments. The repository and the transaction is passed from the postcommit template.
The problem is that, after committing a file in TurtoiseSVN, there is no log created. It looks like either I do not have the permission to create a file on the repository or there is an error in my code.
My code works locally, when I Debug it and pass random arguments to it, a log file is created on my local machine. But its not working on the SVN hook.
THE TEMPLATE
\\myserver\e$\Repositories\CONRAD\hooks\postcommitlog.exe %1 %2
MY PROGRAM
using System;
using System.IO;
namespace postcommitlog
{
internal class Program
{
private static void Main(string[] args)
{
string repositories = args[0];
string transaction = args[1];
const string LOG_PATH = #"\\myserver\e$\Repositories\CONRAD\hooks\MyFile_LOG.txt";
FileInfo fileInfo = new FileInfo(LOG_PATH);
File.AppendAllText(LOG_PATH, "Repositories " + args[0]
+ "\t Transaction " + args[1] + "\t Date " + DateTime.Now.ToString("MMM ddd d HH:mm yyyy") + Environment.NewLine);
}
}
}

The mistake was that I was supposed to create a BAT file from the template, not use the template. The template does nothing, it is what it is : a template. The BAT file is run by SVN then runs the script.
More info here:
http://svnbook.red-bean.com/en/1.5/svn.reposadmin.create.html#svn.reposadmin.create.hooks

Related

Can I produce a simple flat text file using System.IO.Log?

I am currently using the Microsoft.Practices.EnterpriseLibrary.Logging but I can't find a way to control where the file is written to except through pre-runtime configuration.
I am looking at System.IO.Log, but it only seems to create a binary file that cannot be viewed by a simple text editor.
Is there a way to produce a flat text file with System.IO.Log?
or
Is there a way to control the location of the log file at runtime using Microsoft.Practices.EnterpriseLibrary.Logging
I do not know if this helps but here goes.
public class Logger
{
public void WriteToLog(string messageText)
{
// echo message to console
Console.WriteLine(messageText);
string strLogFile = "C:\\Users\\gandalf\\Documents\\Visual Studio 2000\\Projects\\fasterTest_Log.txt";
string strLogText = messageText;
// Create a writer and open the file:
StreamWriter log;
if (!File.Exists(strLogFile))
{
log = new StreamWriter(strLogFile);
}
else
{
log = File.AppendText(strLogFile);
}
// Write to the file:
log.WriteLine(DateTime.Now + " : " + strLogText);
// Close the stream:
log.Close();
}
}

How to append build version to end of the output exe file name in console appilication with using post build event?

I have a simple console application and it has auto increment build version. When I build project, I’d like to append build version to end of the output exe file name with using post-build event. There is no macro for build version.
You will need a small utility to rename the target:
using System;
using System.Diagnostics;
using System.IO;
namespace RenameWithVersion
{
public class Program
{
public static void Main(String[] args)
{
if (args.Length != 1)
throw new Exception("There should only be one command line parameter - the file to be renamed.");
var oldFilename = Path.GetFullPath(args[0]);
if (!File.Exists(oldFilename))
throw new Exception($"File '{oldFilename}' does not exist.");
var oldFilenameWithoutExt = Path.ChangeExtension(oldFilename, null);
var fileVersion = FileVersionInfo.GetVersionInfo(oldFilename).FileVersion;
var ext = Path.GetExtension(oldFilename);
var newFilename = $"{oldFilenameWithoutExt}{fileVersion}{ext}";
File.Delete(newFilename);
File.Move(oldFilename, newFilename);
}
}
}
Compile it and put the executable somewhere on your path.
In the post-build event, call the utility like this:
RenameWithVersion "$(TargetPath)"
(Remember to put $(TargetPath) in double quotes in case the path contains spaces.)

Changing the base path of an assembly from the bin directory to a different directory

I have a Test.cs file in C:\ This test file reads from an input file and writes the same to an output file.
Test.cs
public class Test
{
public static int Main(string[] args)
{
var reader = new StreamReader("in.txt");
string input = reader.ReadLine();
var writer = new StreamWriter("out.txt");
writer.WriteLine(input);
return 0;
}
}
Here it should be noted that the code only uses the filename and not the full file path, which means the file is expected to be in the directory where the program is running. And I have created the in.txt in C:\
Now, there is a c# code called Runner.cs in a solution in C:\Project\Runner.cs, that dynamically compiles the Test.cs code and runs it using reflection. Now, when the Test.cs runs, it expects the in.txt file to be in C:\Project\bin\Debug\in.txt , but it is actually present in C:\in.txt
So, my question is, is there a way to make the code to get the file from C:\in.txt and not from the bin directory without changing the path of the file in the Test.cs code file.
Edit: It is my bad that I forgot to mention why I am in need of this requirement.
The Test.cs file comes from over the wire. And I felt it will not be a good choice to edit this file and set the file path accordingly. I want to compile it and run it as it is.
I hope I am clear. If not, please feel free to ask for more information.
If it is as simple as you show in your code switching the CurrentDirectory works for this example:
var mainMembers = new CSharpCodeProvider()
.CreateCompiler()
.CompileAssemblyFromSource(
new CompilerParameters { GenerateInMemory = true }
, #"
using System;
using System.IO;
public class M {
public static int Main() {
Console.WriteLine(""CurDir = ""+ Environment.CurrentDirectory);
var reader = new StreamReader(""in.txt"");
string input = reader.ReadLine();
var writer = new StreamWriter(""out.txt"");
writer.WriteLine(input);
return 0;
}
}")
.CompiledAssembly
.GetType("M")
.GetMember("Main");
// inspect
Environment.CurrentDirectory.Dump("current");
// keep
var oldcd = Environment.CurrentDirectory;
// switch
Environment.CurrentDirectory = "c:\\temp";
// invoke external code
((MethodInfo) mainMembers[0]).Invoke(null,null);
// restore
Environment.CurrentDirectory = oldcd;
In a multi threaded scenario this becomes unreliable.

Wrapper for a Command Line Tool in C#

Using MSDN I got the class to write a wrapper for my command line tool.
I now am facing a problem, if I execute the exe through the command line with arguments, it works perfect without any errors.
But when I try to pass the arguments from the Wrapper it crashes the program.
Wanted to know if I am passing the arguments properly and if I am wrong, could somebody point out please.
This is the LaunchEXE class from MSDN
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.IO;
namespace SPDB
{
/// <summary>
/// Class to run any external command line tool with arguments
/// </summary>
public class LaunchEXE
{
internal static string Run(string exeName, string argsLine, int timeoutSeconds)
{
StreamReader outputStream = StreamReader.Null;
string output = "";
bool success = false;
try
{
Process newProcess = new Process();
newProcess.StartInfo.FileName = exeName;
newProcess.StartInfo.Arguments = argsLine;
newProcess.StartInfo.UseShellExecute = false;
newProcess.StartInfo.CreateNoWindow = true; //The command line is supressed to keep the process in the background
newProcess.StartInfo.RedirectStandardOutput = true;
newProcess.Start();
if (0 == timeoutSeconds)
{
outputStream = newProcess.StandardOutput;
output = outputStream.ReadToEnd();
newProcess.WaitForExit();
}
else
{
success = newProcess.WaitForExit(timeoutSeconds * 1000);
if (success)
{
outputStream = newProcess.StandardOutput;
output = outputStream.ReadToEnd();
}
else
{
output = "Timed out at " + timeoutSeconds + " seconds waiting for " + exeName + " to exit.";
}
}
}
catch (Exception e)
{
throw (new Exception("An error occurred running " + exeName + ".", e));
}
finally
{
outputStream.Close();
}
return "\t" + output;
}
}
}
This is the way I am passing arguments from my main program (Form1.cs)
private void button1_Click(object sender, EventArgs e)
{
string output;
output = LaunchEXE.Run(#"C:\Program Files (x86)\MyFolder\MyConsole.exe", "/BACKUP C:\\MyBackupProfile.txt", 100);
System.Windows.Forms.MessageBox.Show(output);
}
The command line tool accepts the following command and works perfectly:
C:\Program Files (x86)\MyFolder>MyConsole.exe /BACKUP C:\MyBackupProfile.txt
I have two options for you -
1) Please try running your Visual Studio on "administrator mode".
or 2) Try to implement this instead. https://github.com/commandlineparser/commandline.
"The Command Line Parser Library offers to CLR applications a clean and concise API for manipulating command line arguments and related tasks. It allows you to display an help screen with an high degree of customization and a simple way to report syntax errors to the user. Everything that is boring and repetitive to be programmed stands up on library shoulders, letting you concentrate yourself on core logic. This library provides hassle free command line parsing with a constantly updated API since 2005."
Worked great for me.
I have a feeling it doesn't like the spaces in your path. See this post: C# How to use Directory White Spaces into process.arguements?

Can I add date/time to outputted filename in C# file.writeallbytes

I am writing an errorlog to to file in the same directory the script exists. Id like to potentially create a new folder as it writes as well as add date/time to the filenames so they 2nd doesnt save over the first.
Here is what I have so far:
File.WriteAllBytes("ErrorLog.txt")
Thanks!
You can create a valid Windows file name with DateTime in it like this:
string filename = "ErrorLogFolder" + DateTime.Now.ToString("dd-MM-yyyy_hh-mm-ss") + ".txt";
Take a look at this sample code for naming a file
using System;
using System.IO;
class Program
{
static void Main()
{
//
// Write file containing the date with BIN extension
//
string n = string.Format("text-{0:yyyy-MM-dd_hh-mm-ss-tt}.bin",
DateTime.Now);
File.WriteAllText(n, "aaa");
}
}

Categories