Passing file name with spaces to SPOOL command using SQL Plus gives SP2-0768 Illegral SPOOL command error - c#

My sql file contains
`SPOOL &1;
//sql code to execute
SPOOL OFF;`
The sql file is executed using SQL Plus and SQL Plus is being called from C# code using Process.Start... Code snipped
`var m_StartInfo = new ProcessStartInfo();
m_StartInfo.FileName = "SQLPLUS.EXE";
m_StartInfo.CreateNoWindow = true;
m_StartInfo.UseShellExecute = false;
m_StartInfo.Arguments = String.Format("{0}\"{1}\" \"{2}\"", connectionString, sqlfile, sqlLogFileName);
m_Process = Process.Start(m_StartInfo);
Other code.....`
It works fine and the sqlplus log is created fine at sqlLogFileName location. However if the sqlLogFileName has spaces in between (say like "C:\My Application\log.txt"), then the log file is not created, instead gives the error SP2-0768 Illegal SPOOL command on SQL Plus window
Any suggestion how to resolve this? I am using Oracle 11GR2

You just have to surround your file name with double quotes.
Something like:
spool "Test with spaces.txt"
Or in your case with a parameter:
SPOOL "&1"
I think is best not to use spaces though, as #tvCa explained.
Side Note:
What StarPilot is refering to, I believe, is about the redirect a command output to a file, and that is why it didn't work when you tried to use it.
For example in command prompt you would write:
dir > dir.txt
And that saves the output of dir inside dir.txt.

Oracle software is designed to be used with directories not having whitespaces (which is an accepted standard in Linux/Unix, even though technically you can do otherwise). On Windows, things are different, but the Oracle software has the same idea : it does not like whitespaces. So, the fix is clear : spool to a directory without whitespaces. This is advice, anybody is free to take or not.

Related

'C:Program' not recognized as an internal or external command

Trying to send the code below to the command line, but I get errors. I know there is an issue with backslashes sent to CMD. Any help here on how to send it? Thanks!
string strCmdText="/C C:\\Program Files\\MetaTrader 5\\terminal64.exe /config:C:\\Users\\vguer036\\AppData\\Roaming\\MetaQuotes\\Terminal\\D0E8209F77C8CF37AD8BF550E51FF075\\config\\common.ini";
System.Diagnostics.Process.Start("CMD.exe", strCmdText);
When you use this:
string strCmdText="/C C:\\Program Files\\MetaTrader 5\\terminal64.exe /config:C:\\Users\\vguer036\\AppData\\Roaming\\MetaQuotes\\Terminal\\D0E8209F77C8CF37AD8BF550E51FF075\\config\\common.ini";
System.Diagnostics.Process.Start("CMD.exe", strCmdText);
then you are trying to start the application CMD.exe, which in turn you instruct to execute a particular application. However, because of the spaces, what CMD is trying to execute is the command C:\\Program with parameters Files\\MetaTrader, 5\\terminal64.exe etc. That is where your error message comes from.
One way to solve this is to add extra quotes around the filename (as Dour High Arch commented):
string strCmdText=#"/C ""C:\Program Files\MetaTrader 5\terminal64.exe"" ""/config:C:\Users\vguer036\AppData\Roaming\MetaQuotes\Terminal\D0E8209F77C8CF37AD8BF550E51FF075\config\common.ini""";
Note the doubled quotes, which are required to use a literal quote inside a verbatim string literal (#"...").
But this way you are still executing one application (CMD.exe) to start another (terminal64.exe). Why not start that terminal64 directly?
System.Diagnostics.Process.Start(
#"C:\Program Files\MetaTrader 5\terminal64.exe",
#"/config:C:\Users\vguer036\AppData\Roaming\MetaQuotes\Terminal\D0E8209F77C8CF37AD8BF550E51FF075\config\common.ini");
You should experiment to see whether you need extra quotes around that application name, but I don't think so.

Why input redirection works by default for sudo and not for passwd? (.NET)

Simple F# script:
#!/usr/bin/env fsharpi
open System
open System.Diagnostics
let Exec (command: string, arguments: string, echo: bool) =
let psi = new System.Diagnostics.ProcessStartInfo(command)
psi.Arguments <- arguments
psi.UseShellExecute <- false
if (echo) then
Console.WriteLine("{0} {1}", command, arguments)
let p = System.Diagnostics.Process.Start(psi)
p.WaitForExit()
p.ExitCode
Exec("sudo", "-k ls -lha /root", true)
Exec("passwd", "myusername", true)
(But actually this is a generic ".NET on Linux" question I guess, because you could write the same in C#)
Why the first Exec() call works and the second one doesn't?
The first one calls sudo properly, and sudo asks me for my password (I can even fail to type it, and it asks it to me again, so it's not related to number of carrier returns employed in stdin).
However, the second one only allows me to write one character and suddenly drops out. It seems to not redirect characters to passwd properly, as the latter doesn't let me write the complete password, and fails saying that passwords don't match.
Can someone explain this?
By default, passwd usually doesn't use standard I/O (mostly for security reasons). You can check the man page for your passwd to see if there's an option to enable stdio - e.g. passwd --stdin. If not, you'll need to use a different utility, like chpasswd.
All in all, nothing to do with .NET. You couldn't do the same thing from your shell either :) Passwords aren't for applications or scripts - they're for users.

Reading MySql binlog

I don't agree that this question was answered effectively: decode mysqlbinlog in C#.
I have, what I think is the same question: I want to read the MySql binlogs from within a c# application, but do not know the format of the file. How can I properly parse these files' data?
First, what I learned:
Most of the source code files for MySql are installed along with the assemblies and generally located in [basedir]\include. For example, a typical install would place the files in Program Files\MySql\MySql 5.6\include.
mysqlbin.cc was NOT in that folder. However, I was easily able to get the file by doing a quick Google search. The file can be found here: https://code.google.com/p/mg-common-utils/source/browse/trunk/myreplicator/src/mysqlbinlog.cc?r=4 . It is well documented and easy to read.
Second, my solution:
As akuzminsky pointed out, the format of MySql's binlog is subject to change. However, the format returned from the mysqlbinlog.exe utility is consistent. This application is typically included in a MySql install and should be located in [basedir]\bin. I now run this application from within a c# Console Application and parse the results. I used the following steps to accomplish this:
Enabled binlogging on the MySql server from within the options file. In MySql Workbench, check 'log-bin' under the logging tab. Or, type 'log-bin=' in the settings file (often located in [basedir]. Might be called 'my.ini' or 'my.cnf' or something else. Generally, with .cnf or .ini extension). A filename is not required. When one is not specified, MySql will automatically create filenames for the logs. However, review MySql documentation on possible issues with this.
From within my client application, I query the server to get the path of each binary log (there could be many). To do this:
query show global variables like 'datadir' //returns the data directory.
query show binary logs //returns the filename of each binary log, along with its file size (helpful for reading).
Parsing these together gets the path for each binary log.
Since mysqlbinlog.exe is located in [basedir]\bin, I query the server to get the path of the base directory:
query show global variables like 'basedir'
Then, I parse the result with '\bin\mysqlbinlog.exe'
I use the Process class to create a new process, execute each binary log using mysqlbinlog.exe, and read each files results into a string variable:
private static string GetLogTexts(Liststring> logfilenames)
{
List<string> _logtexts = new List<string>();
string _basedir = GetBaseDir();
foreach(string logfilename in logfilenames)
{
Process proc = new Process();
proc.StartInfo.FileName = _basedir + "\\bin\\mysqlbinlog";
proc.StartInfo.Arguments = string.Format("\"{0}\"", logfile);
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.RedirectStandardInput = proc.StartInfo.RedirectStandardOutput = true;
proc.Start();
_logtexts.Add(proc.StandardOutput.ReadToEnd());
}
return _logtexts;
}
private static string GetBaseDir()
{
string path = "";
using (MySqlConnection conn = new MySqlConnection(RemoteServerConnectionString))
{
conn.Open();
using (MySqlCommand cmd1 = new MySqlCommand("show global variables like 'basedir'", conn))
{
using (MySqlDataReader reader = cmd1.ExecuteReader())
{
while (reader.Read())
{
path = reader.GetString(1);
}
}
}
}
return path;
}
Finally, I parse the results using my own logic (specific for what I am looking for). The results are very easy to read: mysqlbinlog uses regular line breaks and statements are terminated by a delimiter, which is defined prior to the statement (as usual, there can be multiple delimiters).
I hope this helps someone!

CMD command with space in path

I am having an issue with the spaces in my command. I am trying to run the cmd prompt and execute a program that takes command line arguments. I need the cmd window to remain open after the process is finished executing.
I managed to get it working in another section of code, but this time i am almost sure it has to do with the spaces in the path of the argument. If i use a path with no spaces, it works fine. I tried to escape the quotes, but either i am doing it incorrectly, or escaping the quotes do not work.
Basically, I need to make the line below work with spaces and keep the cmd window open after the execution...
Dim ps As Process = System.Diagnostics.Process.Start("cmd /k", "C:\common\tools\tap.exe -f flash C:\Users\test project\Desktop\image.signed")
I'm know the space between "test" and "project" is the issue, but i haven't been able to get around it.
Thanks in advance for your help.
Wrap the path in double-quotes, like this:
"C:\common\tools\tap.exe -f flash ""C:\Users\test project\Desktop\image.signed"""
Giving you:
Dim ps As Process = System.Diagnostics.Process.Start ("cmd /k", "C:\common\tools\tap.exe -f flash ""C:\Users\test project\Desktop\image.signed""")

SQL Server perform backup with C#

I've investigated the possibilities of creating database backups through SMO with C#.
The task is quite easy and code straightforward. I've got only one question: how can I check if the backup was really created?
SqlBackup.SqlBackup method returns no parameters and I don't even know if it throws any exceptions. (the only thing that I know is that it is blocking, because there's also SqlBackupAsync method)
I would appreciate any help.
you can and its very possible to do what you asked for,
but doing the backup it self using SMO its not very hard, but the hard part is managing the backup and the restore.
it would be hard to put all the code here, but its wont fit. so I will try my best to put the lines you need.
SqlBackup.SqlBackup doesn't return any value, its a void function.
but it takes one parameter which is "Server", try out the following code:
Server srvSql;
//Connect to Server using your authentication method and load the databases in srvSql
// THEN
Backup bkpDatabase = new Backup();
bkpDatabase.Action = BackupActionType.Database;
bkpDatabase.Incremental = true; // will take an incemental backup
bkpDatabase.Incremental = false; // will take a Full backup
bkpDatabase.Database = "your DB name";
BackupDeviceItem bDevice = new BackupDeviceItem("Backup.bak", DeviceType.File);
bkpDatabase.Devices.Add(bDevice );
bkpDatabase.PercentCompleteNotification = 1;// this for progress
bkpDatabase.SqlBackup(srvSql);
bkpDatabase.Devices.Clear();
I've investigated the problem using Reflector.NET (I suppose this is legal since RedGate is Ms Gold Certified Partner and Reflector.NET opens .NET libraries out of the box). As I found out the method throws two types of exceptions:
FailedOperationException - in most cases, other exceptions are "translated" (I suppose translating means creating new FailedOperationException and setting InnerException to what was actually thrown)
UnsupportedVersionException - in one case when log truncation is set to TruncateOnly and server major version is more or equal to 10 (which is sql server 2008?)
This solves my problem partially, because I'm not 100% sure that if something goes wrong those exceptions will actually be thrown.

Categories