I would like to be able to change the title of the Command window at various points throughout my NAnt script.
I have tried to use the task to call 'title myTargetName' but it gives me the following error:
'title' failed to start.
The system cannot find the file specified
Is there a way to do this please? Thanks in advance!
You can set the console title in a custom task. If the task is defined in a script, the build file is self contained.
The console title will revert once nant finishes.
<project default="title">
<target name="title">
<consoletask title='step 1'/>
<sleep minutes="1" />
<consoletask title='step 2'/>
<sleep minutes="1" />
<consoletask title='step 3'/>
<sleep minutes="1" />
</target>
<script language="C#">
<code>
[TaskName("consoletask")]
public class TestTask : Task
{
private string title;
[TaskAttribute("title", Required=true)]
public string Title
{
get { return title; }
set { title = value; }
}
protected override void ExecuteTask() {
System.Console.Title = title;
}
}
</code>
</script>
</project>
If you compile this small program as a console app:
namespace SetTitle
{
internal static class Program
{
private static void Main(string[] args)
{
System.Console.Title = string.Join(" ", args);
}
}
}
Then this would work:
<exec>SetTitle.exe "Step One"</exec>
<!-- Do some stuff -->
<exec>SetTitle.exe "Step Two"</exec>
You could do the same with a custom NAnt task, but the work involved would be more complicated and you'd still have to make your NAnt task assembly discoverable during the script's execution.
Try this:
' In your command prompt
title foobar
' The title now should say 'foobar' without quotes
' Now issue this...
cmd /k fubar
' The title now should say 'fubar' without quotes
So I guess you need to change it to like this:
<exec>cmd /k title one </exec>
Edit: At the end of the script, invoke the exit command to exit the nested levels of the cmd.exe command line processor...Suppose you have three 'exec' for the 'cmd /k', you would need three 'exit' commands in order to get back to the original cmd.exe shell, think of it like popping cmd.exe off the stack for the duration of the nant script...
Edit#2: As per Brett's comment...just a thought - why not do it this way....
<exec>cmd /k title one </exec>
<exec>exit</exec>
Add the 'exit' command immediately after setting the title of the window...?
Hope this helps,
Best regards,
Tom.
You could use a cmd or batch file to run the nant script containing this:
title %1
%NANT_PATH%\nant.exe %1
This should work:
<exec>title Step One</exec>
<!-- Do some stuff -->
<exec>title Step Two</exec>
This uses a regular cmd.exe command.
Related
Goal
I am trying to make my Cocoa Application that has been written in Swift scriptable from Applescript.
What I've Done
I have created a SDEF file, configured my info.plist and created a class which I think is appropriate.
definition.sdef
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dictionary SYSTEM "file://localhost/System/Library/DTDs/sdef.dtd">
<dictionary title="SamX">
<!-- specific suite(s) for the application follow... -->
<suite name="SamX Scripting Suite" code="Samx" description="Suite for communication with the application">
<command name="savedoc" code="corecnte" description="description">
<cocoa class="ProjectName.ScriptingSaveNotification" id="BLah"/>
<parameter name="with dname" code="WTdc" type="text" optional="no" description="description">
<cocoa key="DocumentName"/>
</parameter>
<result type="boolean" description="The result of the invocation. True if it succeeds, False if it does not"/>
</command>
</suite>
</dictionary>
info.plist
ScriptingSaveNotification.swift
import Foundation
import Cocoa
class ScriptingSaveNotification: NSScriptCommand, NSUserNotificationCenterDelegate {
override func performDefaultImplementation() -> AnyObject? {
let parms = self.evaluatedArguments
var name = ""
if let args = parms {
if let DocumentName = args["DocumentName"] as? String {
name = DocumentName
}
}
debugPrint("We were prompted to save");
return "hello world"
}
func userNotificationCenter(center: NSUserNotificationCenter, shouldPresentNotification notification: NSUserNotification) -> Bool {
debugPrint("We were prompted to save");
return true
}
}
Where I Am
I have an application that launches. The application's SDEF file appears to be reflecting in the Applescript Editor. The Applescript editors also returns a dictionary definition. However when I run the command, I always get an output of 5 (int), and none of my debug lines appears to be outputting in Xcode.
It appears to me that maybe I'm referencing my class in the SDEF improperly. But I'm not 100% sure. I've tried renaming it several times. Any help would be greatly appreciated.
Applescript Dictionary
Test Script
tell application "MyApplication"
set testString to "Hello"
set returnValue to savedoc testString
display alert returnValue
end tell
Edit:
The main issue is that you don't actually use the with dname parameter in your script. It should be:
set returnValue to savedoc with dname testString
That said, the info below is still valid for creating a proper sdef and the other suggestions/examples may be helpful.
This is a basic example of passing a string in the evaluatedArguments of the NSScriptCommand and then returning that string as the result of the script command in Swift (you could return a boolean on success/failure of the command or any other type of result; and, actually, in your sdef you say you're going to return a boolean but your command is returning a string (text in sdef definitions)). Creating your sdef can be tricky. Your command's code should start with the suite's code and you can remove the id and optional parameter (if you omit the optional parameter, the default is that the parameter is required). If you do just need a single parameter you could also just use the direct-parameter instead.
You can download a demo project:
ScriptableSwift.zip
Here are the relevant bits (aside from the plist entries that you have correct in your tests).
ScriptableSwift.sdef
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dictionary SYSTEM "file://localhost/System/Library/DTDs/sdef.dtd">
<dictionary title="ScriptableSwift Terminology">
<suite name="ScriptableSwift Scripting Suite" code="SSss" description="Standard suite for application communication.">
<command name="save" code="SSssSave" description="Save something.">
<cocoa class="ScriptableSwift.SaveScriptCommand"/>
<parameter name="in" code="Fpat" type="text" description="The file path in which to save the document.">
<cocoa key="FilePath"/>
</parameter>
<result type="text" description="Echoes back the filepath supplied."/>
</command>
</suite>
</dictionary>
SaveScriptCommand.swift
import Foundation
import Cocoa
class SaveScriptCommand: NSScriptCommand {
override func performDefaultImplementation() -> AnyObject? {
let filePath = self.evaluatedArguments!["FilePath"] as! String
debugPrint("We were prompted to save something at: \(filePath)");
return filePath
}
}
Test AppleScript
tell application "ScriptableSwift" to save in "path/to/file"
Result:
"path/to/file"
I have an install4j project that I'm running from both GUI and command line.
As you might know it is possible to pass installer parameters in varfile.
I would like to know if there is a simple way to give a relative path in the varfile in the form:
my.variable=${installer:installerDir}\a.txt
I can see a workaround where I can ask the user to specify the file name only and I will put the directory path in the code. but I would still like to know if this is possible.
Thanks.
Ika.
You cannot use installer variables in the variable file. That file is read at startup before any other installer variables are defined, so you would not have a chance to set up the "installerDir" variable first.
The only option I see here is to use your own token, say
my.variable=#installerDir#\a.txt
and use a "Run script" action in the "Startup" node to replace that token with a particular directory. Here's some which checks all defined variables:
String installerDir = null;
InstallerContext context = null;
for (Object o : context.getVariableNames()) {
String variableName = (String)o;
Object variableValue = context.getVariable(variableName);
if (variableValue instanceof String) {
String replacedValue = ((String)variableValue).replaceAll("#installerDir#", installerDir);
if (!replacedValue.equals(variableValue)) {
context.setVariable(variableName, replacedValue);
}
}
}
I am wondering how to handle program arguments when you are running Groovy within Eclipse. It isn't as straight forward as it is from the command line and I am having trouble figure it out. Im using Eclipse 3.5. My run configuration has these arguments all on one line:
--classpath "${workspace_loc:/GroovyProject};${workspace_loc:/GroovyProject}"
--main groovy.ui.GroovyMain "C:\Temp\Workspace\GroovyProject\GroovyTest.groovy "
argtest1
argtest2
argtest3
The script I am using to try to make this work looks like this:
// GroovyTest.groovy
class GroovyTest {
static main(args) {
println "hello, world"
for (arg in this.args ) {
println "Argument:" + arg;
}
}
}
The error I get is:
hello, world
Caught: groovy.lang.MissingPropertyException: No such property: args
for class: GroovyTest at GroovyTest.main(GroovyTest.groovy:5)
You have az unnecessary this in the for (arg in this.args) line.
this.args means that you have an instance of the GroovyTest object and you refer to its args field. In this case args is a method parameter so you have to refer to it simply as args.
I have custom NAnt task for test purposes and I would like to cancel NAnt build process if the task is failed.
I have created custom ErrorTask:
[NAnt.Core.Attributes.TaskName("errorTask")]
public class ErrorTask : NAnt.Core.Task
{
public ErrorTask()
{
FailOnError = true;
}
protected override void ExecuteTask()
{
Log(NAnt.Core.Level.Error, "Error!");
}
}
Here is what I have in NAnt build file:
<target name="errorTarget">
<errorTask failonerror="true" />
<errorTask failonerror="true" />
</target>
In the result (build.log) I have:
errorTarget:
[errorTask] Error!
[errorTask] Error!
BUILD SUCCEEDED - 2 non-fatal error(s), 0 warning(s)
Total time: 0 seconds.
So, I can see that second task is also run, but I would like to cancel it, because first call returns "Error!". Could you assist me to fix it?
Also, I assume, that it is not necessary to hardcode FailOnError value, it should be enough to use just failonerror attribute in build script, but it does not work for me in any case.
Thank you.
You need to let an exception bubble out of your ExecuteTask function. After your log statement, add this line:
throw new BuildException("Something terrible has happened!");
I am converting an old cmd command to Powershell, and currently use:
START "My Title" Path/To/ConsoleApp.exe
This works as expected to launch ConsoleApp with My Title as it's window title. This has been replaced with Start-Process which works correctly, but does not provide a mechanism to change the title.
Is there another way to do this without resorting to using the cmd command?
There is a small quirk when changing the text of the process' main window: if you try to change the text straight after you have started the process, it may fail due to one of many possible reasons (e.g. the handle to the control which displays the text does not exist at the time of the function call). So the solution is to use the WaitForInputIdle() method before trying to change the text:
Add-Type -TypeDefinition #"
using System;
using System.Runtime.InteropServices;
public static class Win32Api
{
[DllImport("User32.dll", EntryPoint = "SetWindowText")]
public static extern int SetWindowText(IntPtr hWnd, string text);
}
"#
$process = Start-Process -FilePath "notepad.exe" -PassThru
$process.WaitForInputIdle()
[Win32Api]::SetWindowText($process.MainWindowHandle, "My Custom Text")
Be aware that the application itself can still change the window text after you have made your own change.
I tried this with cmd.exe and it worked well.
Add-Type -Type #"
using System;
using System.Runtime.InteropServices;
namespace WT {
public class Temp {
[DllImport("user32.dll")]
public static extern bool SetWindowText(IntPtr hWnd, string lpString);
}
}
"#
$cmd = Start-Process cmd -PassThru
[wt.temp]::SetWindowText($cmd.MainWindowHandle, 'some text')
If you want to spawn a process with powershell with a custom title try:
$StartInfo = new-object System.Diagnostics.ProcessStartInfo
$StartInfo.FileName = "$pshome\powershell.exe"
$StartInfo.Arguments = "-NoExit -Command `$Host.UI.RawUI.WindowTitle=`'Your Title Here`'"
[System.Diagnostics.Process]::Start($StartInfo)
Note the backtick characters that escape the string for the title, they are vital!
$host.UI.RawUI.WindowTitle = "new title"
As already been said by George, anything/anyone can set it back (like custom prompt functions for example).