I am passing a set of parameters from main setup through the command line which also includes file paths and reading the values in Subsetup. The command line parameters output looks like below
/dir="D:\XXX.Web" /dbname="XXX" /dbinstancename="XXX" /dbsapwd="123!"#$%" /dataFileDirectory="D:\MSSQL10_50.XXX\MSSQL\DATA" /logFileDirectory="D:\MSSQL10_50.XXX\MSSQL\Log" /backupDirectory="E:\MSSQL10_50.XXX\MSSQL\Backup" /sqlCmdLocation="C:\Program Files\Microsoft SQL Server\100\Tools\Binn\SQLCMD.EXE" /webappname="yyyy" /Nameservice="VVVV" /UserUsername="user"
I am getting the parameter values in the Subsetup using a custom GetParameter function and storing in the String like mentioned below...
// This is how I get the values and store in String
DBName := GetParameter('/dbname=', DBName);
DataFileDirectory := GetParameter('/dataFileDirectory=', DataFileDirectory);
// function to get the parameters from the commandline parameters
function GetParameter(ParamName, Default: String): String;
var
P, I: Integer;
begin
Result := Default;
if Length(ParamName) < 1 then Exit;
ParamName := Lowercase(ParamName);
for I := 2 to ParamCount() do begin
P := pos(ParamName, Lowercase(ParamStr(I)));
if P > 0 then begin
P := P + Length(ParamName);
Result := Copy(ParamStr(I), P, Length(ParamStr(I))+1-P);
Result := Trim(RemoveQuotes(Trim(Result)));
Exit;
end;
end;
end;
When I print all the values in the log file, I am getting the output like mentioned below.
DBName = XXX
DBSaPwd = ********
DBInstanceName = XXX
DataFileDirectory = D:\MSSQL10_50.XXX\MSSQL\DATA /logFileDirectory=D:\MSSQL10_50.XXX\MSSQL\Log /backupDirectory=E:\MSSQL10_50.XXX\MSSQL\Backup /sqlCmdLocation=C:\Program
LogFileDirectory = D:\MSSQL10_50.XXX\MSSQL\Log /backupDirectory=E:\MSSQL10_50.XXX\MSSQL\Backup /sqlCmdLocation=C:\Program
BackupDirectory = E:\MSSQL10_50.XXX\MSSQL\Backup /sqlCmdLocation=C:\Program
SqlCmdLocation = C:\Program
WebAppName = yyyy /Nameservice=VVVV /UserUsername=user /UserPassword=user /MSSQLServerSelection= /silent /restart=false
The file path value of DataFileDirectory for example is taking the next parameter values and so on for the subsequent values which is throwing "File name, directory name or volume label syntax is incorrect" error at the end of the setup execution.
I believe an escape sequence must be used to solve this problem. Please provide your suggestions to solve this error and to implement it correctly.
Thanks in advance
DeeJay
Related
input comes from an JSON request which looks like
{
"inputString" : "\"C:\\Program Files (x86)\\7-Zip\\7z.exe\" x c:\\temp\\test.zip -oc:\\temp\\test"
}
package main
import (
"fmt"
"os/exec"
)
func main() {
//Input received will be of this format
var inputstring string = "\"C:\Program Files (x86)\7-Zip\7z.exe\" x c:\temp\firmware8.zip -oc:\temp\fw"
cmd := exec.Command("cmd", "/c", inputstring)
out, err := cmd.Output()
fmt.Println("doneee", string(out), "err", err)
}
Output : "'\"C:\Program Files (x86)\7-Zip\7z.exe\
"' is not recognized as an internal or external command,\r\noperable program or batch file.\r\n"
"C:\Program Files (x86)\7-Zip\7z.exe" x c:\temp\test.zip -oc:\temp\test - I have to run this command on command prompt but it is just executing the part which is highlighted
As the input string is not static (it comes from a JSON),So we cannot split them into arguments
You can use raw string. look this tutorial.
var inputstring string = `"C:\Program Files (x86)\7-Zip\7z.exe" x c:\temp\test.zip -oc:\temp\test`
var inputstring string = "\"C:\\Program Files (x86)\\7-Zip\\7z.exe\" x c:\\temp\\firmware8.zip -oc:\\temp\\fw"
var buf, stderr bytes.Buffer
*proc := exec.Command("cmd")
proc.SysProcAttr = &syscall.SysProcAttr{CmdLine: fmt.Sprintf(`/c "%s"`, inputstring)}* //Adding this line helped to add the cmd as single line
proc.Stderr = &stderr
proc.Stdout = &buf
proc.Start()
time.Sleep(5 * time.Second)
fmt.Println("doneee", buf.String(), "error is ", stderr.String())
I saw this question here: How to get an output of an Exec'ed program in Inno Setup?
But I can't get it to work myself, the commented out code are my attempts to make this work, but I resorted to a bat file because I couldn't make my redirection work. CacheInstanceName and CacheInstanceDir are global variable defined elsewhere:
function CheckCacheExists(): Integer;
var
args: String;
buffer: String;
ResultCode: Integer;
begin
// args := 'qlist ' + CacheInstanceName + ExpandConstant(' nodisplay > {tmp}\appcheck.txt');
// MsgBox(args, mbInformation, MB_OK);
// Exec(CacheInstanceDir + '\bin\ccontrol.exe', 'qlist ' + CacheInstanceName + ExpandConstant(' nodisplay > "{tmp}\appcheck.txt"'), '', SW_SHOW,
ExtractTemporaryFile('checkup.BAT');
Exec(ExpandConstant('{tmp}\checkup.BAT'), CacheInstanceDir + ' ' +
CacheInstanceName + ' ' + ExpandConstant('{tmp}'), '', SW_SHOW,
ewWaitUntilTerminated, ResultCode);
LoadStringFromFile(ExpandConstant('{tmp}\appcheck.txt'),buffer);
if Pos('^', buffer) = 0 then
begin
Result := 0
end
else
begin
Result := 1
end
end;
What am I doing wrong?
The output redirection syntax is a feature of the command prompt, not the core Windows APIs. Therefore if you want to redirect output then you need to invoke the command via {cmd} /c actual-command-line > output-file. Don't forget to include quotes where appropriate, as {tmp} (and other constants) may contain spaces.
However, you should strongly consider rewriting whatever is in that batch file into actual code. Anything you can do in a batch file you can do either directly in the Inno script or in a DLL that you call from the script. And this permits you greater control over error checking and the format of whatever data you want to retrieve.
Try running the command directly on your command line with the arguments in your args string to see what the result is which may give an indication of the problem.
Also, check that the file you are trying to redirect your output to is not in use by another process. I have found that when this occurs the actual command may execute successfully with the Exec command returning True but the ResultCode indicates an error and no output is written to the file used in the redirect. In this particular instance of the file being used by another instance the SysErrorMessage(ResultCode) command returns simply Incorrect function. However, testing directly on the command line as I mentioned first returns that the file is in use by another process.
if I am in directory A and running the GO code, and I need to copy a file from directory B to directory C , how to do it? I tried adding cmd.Dir = "B" but it can copy the files in "B" directory, but when I try full path for directory "C" it throws error "exit status 1"
basic code sample
Currently in directory A with location "/var/A"
cmd := exec.Command("cp","/var/C/c.txt","/var/B/")
err := cmd.Run()
"os/exec" is the Go package used to run external programs, which would include Linux utilities.
// The command name is the first arg, subsequent args are the
// command arguments.
cmd := exec.Command("tr", "a-z", "A-Z")
// Provide an io.Reader to use as standard input (optional)
cmd.Stdin = strings.NewReader("some input")
// And a writer for standard output (also optional)
var out bytes.Buffer
cmd.Stdout = &out
// Run the command and wait for it to finish (the are other
// methods that allow you to launch without waiting.
err := cmd.Run()
if err != nil {
log.Fatal(err)
}
fmt.Printf("in all caps: %q\n", out.String())
I am trying to use zexmlss http://neborak.org/zexmlss/index.php?lang=en for export to Excel of ODS. I have compiled the library and I have included Synapse generator in the library. Now I am trying to use it from the code:
procedure Test;
var tz: TZEXMLSS;
begin
tz := TZEXMLSS.Create(nil);
tz.Sheets.Count:=2;
tz.Sheets[0].Title:='Test';
with tz.Sheets[0] do begin
RowCount:=20;
ColCount:=20;
Cell[0, 0].Data := 'zexmlss';
end;
TZXMLSSave.From(tz).Save('C:\A_EXCEL\test.xlsx');
end
And I receive the error message 'No zip generators registered, folder output disabled'. Save to xml completes succesfully. How and where to register zip generators?
Do you copy files from \delphizip\synzip\ to src folder (zipusesyn.pas, xlsxzipfunc.inc, xlsxzipfuncimpl.inc, xlsxzipuses.inc etc)? If files present in scr folder use function SaveXmlssToXLSX() like:
//uses zexlsx;
procedure Test;
var tz: TZEXMLSS;
begin
tz := TZEXMLSS.Create(nil);
tz.Sheets.Count:=2;
tz.Sheets[0].Title:='Test';
with tz.Sheets[0] do begin
RowCount:=20;
ColCount:=20;
Cell[0, 0].Data := 'zexmlss';
end;
SaveXmlssToXLSX(tz, 'C:\A_EXCEL\test.xlsx');
end
I tested code posted here:
Why ini file is not being saved?
After call "SaveSettings" procedure settings.ini is saved in UTF-8 format, all is OK. After second call (settings.ini already exists), ini file is updated but UTF8 encoded characters are lost, ??????????? is displayed instead. File encoding is lost ini contain plain TEXT.
Uses IniFiles;
const
SZ_APP_NAME;
Procedure TForm1.SaveSettings;
var
_MemIniU: TMemIniFile;
SettingsPath: string;
begin
SettingsPath := GetHomePath + PathDelim + SZ_APP_NAME + PathDelim;
_MemIniU := TMemIniFile.Create(ChangeFileExt(SettingsPath, 'Settings.ini'),
TEncoding.UTF8);
try
if Form1.WindowState <> TWindowState.wsMaximized then
begin
_MemIniU.WriteInteger(SZ_APP_NAME, 'WindowLeft', Form1.Left);
_MemIniU.WriteInteger(SZ_APP_NAME, 'WindowTop', Form1.Top);
_MemIniU.WriteInteger(SZ_APP_NAME, 'WindowWidth', Form1.Width);
_MemIniU.WriteInteger(SZ_APP_NAME, 'WindowHeight', Form1.Height);
_MemIniU.WriteString(SZ_APP_NAME, 'UnicodeText', Edit1.Text);
_MemIniU.UpdateFile;
end;
finally
_MemIniU.Free;
end;
end;