I have been following this post for developing a client for query notification. http://www.youdidwhatwithtsql.com/started-query-notifications-sql-server-2008-r2/1676/ I have tried this code on both visual studio and mono on my PC and these seem to fire the onDependencyChange event fine. However when I move it over to the raspberry pi with mono-complete installed it does not seem to fire. I cannot debug as the pi is in another location and I am using SSH to remote into it.
static void Main(string[] args)
{
Console.WriteLine ("-----------------APPLICATION STARTED------------------");
var connection = new SqlConnection(connectionString);
SqlDependency.Start(connectionString);
RefreshDataWithSqlDependency();
Console.WriteLine ("Why is it here?");
//blocks thread so you can read message
Console.ReadLine();
SqlDependency.Stop(connectionString);
}
static void RefreshDataWithSqlDependency()
{
//remove existing dependency if necessary
if (dependency != null)
{
dependency.OnChange -= onDependencyChange;
dependency = null;
}
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
SqlCommand command = new SqlCommand("SELECT ipAddress FROM dbo.dbDevices", connection);
//Create a dependency and associate it with command
dependency = new SqlDependency(command, null, 1);
//Subscribe to the SqlDependency event.
dependency.OnChange += new OnChangeEventHandler(onDependencyChange);
//Start dependency listener
SqlDependency.Start(connectionString);
//execute command and refresh data
RefreshData(command);
}
}
private static void onDependencyChange(Object o, SqlNotificationEventArgs args)
{
Console.WriteLine("ondep gets hit");
if ((args.Source.ToString() == "Data") || (args.Source.ToString() == "Timeout"))
{
Console.WriteLine("Refreshing data due to {0}", args.Source);
RefreshDataWithSqlDependency();
}
else
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("Data not refreshed due to unexpected SqlNotificationEventArgs: Source={0}, Info={1}, Type={2}", args.Source, args.Info, args.Type.ToString());
Console.ForegroundColor = ConsoleColor.Gray;
}
}
private static void RefreshData(SqlCommand command)
{
using (var reader = command.ExecuteReader())
{
Console.Clear();
while (reader.Read())
{
Console.WriteLine("ip = {0}", reader[0]);
}
}
}
I have now put an extra Console.WriteLine just under RefreshDataWithSqlDependency method and when I use Run > Run With > Microsoft .NET or Mono 4.0.2 it seems to jump straight out of RefreshDataWithSqlDependency, however when I run with debugger it acts as it should. It will fire the event.
Remote debugging would be the way to go with SSH tunneling.
On the Ras-pi side, start your app:
mono \
--debug \
--debugger-agent=transport=dt_socket,address=0.0.0.0:10000,suspend=y,server=y,keepalive=250 \
foodata.exe
(Yes, the address of 0.0.0.0 is correct)
On the PC side, set an environment variable to enable a hidden debug feature of Xamarian Studio / MonoDevelop and start the IDE from that cmd line.
On Linux:
export MONODEVELOP_SDB_TEST=1
monodevelop
On OS-X (with Xam Studio, alter the cmd to use MonoDevelop if that is what you have:
export MONODEVELOP_SDB_TEST=1
/Applications/Xamarin\ Studio.app/Contents/MacOS/XamarinStudio
On Windows (update the path to match your install location):
set MONODEVELOP_SDB_TEST=1
<path>\XamarinStudio.exe
Once the IDE starts, load your solution/project that you are debugging, set your breakpoints and then select the following menu items:
Run / Run With / Custom Command Soft Mono Debugger
Note: That option will NOT be there if you you did not set the env var and run it from the cmd line.
In the Launch Soft Debugger Window that appeared:
Command : ssh YourRaspiLogin#RasPiPassword -L 10000:127.0.0.1:10000
Arguments : <leave empty>
IP : YourRasPiHostNameOrIPAddress
Port: : 10000
Click "Connect".
A ssh window will open, just leave it open (minimize it..), that is your reverse tunnel. If you are using some other ssh client; putty, etc.. change the 'ssh' in the command field to match your setup.
You should be debugging now and assuming you set a break point the IDE should be stopped on that line waiting for you ;-)
Related
I'm using SSH.NET in order to get some informations of an external tape drive. Connecting and executing some basic commands works perfectly fine for me:
ConnectionInfo connNfo = new ConnectionInfo("10.12.2.97", 22, "loginuser",
new AuthenticationMethod[]
{
// Password based Authentication
new PasswordAuthenticationMethod("loginuser","password")
}
);
using (var client = new SshClient(connNfo))
{
client.Connect();
//This command works fine
using (var cmd = client.CreateCommand("ls"))
{
string result = cmd.Execute();
}
}
But now i have to switch to root user in order to execute extended commands i need. Initially logging in with root user is not possible because of security restrictions. Referring to this post How to run commands by sudo and enter password by ssh .net c# i tried this code block:
using (var cmd = ssh.RunCommand("echo 'rootpassword' | sudo -u root -S fsstate"))
{
if (cmd.ExitStatus == 0)
Console.WriteLine(cmd.Result);
else
Console.WriteLine(cmd.Error);
}
But then i always receive this error message:
sudo: unknown user: root
sudo: unable to initialize policy plugin
Update 1:
Working PuTTY commands
What i'm doing wrong here?
I have a batch script that launches the mariadb in console mode, so it looks likes this:
run-mariadb.bat
#echo off
cd /D mariadb-10.1.14-win32\bin && mysqld.exe --console
#pause
Using a C# WinForm app, I'd like to launch this batch script and get all output onto a RichTextBox.
This is the code I have so far:
// Configure db server process
Process dbServer = new Process();
dbServer.StartInfo.FileName = "cmd";
dbServer.StartInfo.Arguments = "/c start /wait run-mariadb.bat";
dbServer.StartInfo.CreateNoWindow = true;
dbServer.StartInfo.UseShellExecute = false;
dbServer.StartInfo.RedirectStandardOutput = true;
dbServer.StartInfo.RedirectStandardError = true;
dbServer.OutputDataReceived += new DataReceivedEventHandler(HandleDBServerOutput);
dbServer.ErrorDataReceived += new DataReceivedEventHandler(HandleDBServerOutput);
These are my helper methods:
string FormatOutput(string message)
{
return string.Format("[ {0} ] : {1}",
DateTime.Now.ToShortTimeString(),
message);
}
void HandleDBServerOutput(object sender, DataReceivedEventArgs e)
{
this.BeginInvoke(new MethodInvoker(() =>
{
if (!string.IsNullOrEmpty(e.Data))
dbLogsRTB.AppendText(FormatOutput(e.Data));
}));
}
I start the process like this:
// Start database server
dbServer.Start();
dbServer.BeginOutputReadLine();
dbServer.WaitForExit();
When the above executes, a new command prompt window is created and the mariadb is running in there. Any ideas why dbServer.StartInfo.CreateNoWindow = true; is being ignored?
The help for start starts off with:
Starts a separate window to run a specified program or command.
In other words, by running start as part of your command, you'll launch a new window. You can verify this by running start /wait run-mariadb.bat from a command prompt. It launches a new window to run the command.
Consider changing your command to be simply:
dbServer.StartInfo.Arguments = "/c run-mariadb.bat";
To just run the command without starting a new console process.
I am trying to create a SSH client using C#. I am using the Tamir.SharpSsh library. I am having issues sending the command and getting an appropriate response from the server.
The way I have been testing it is by sending over the ls command, followed by cd.. command, followed by ls command again -- to see whether or not the cd.. command is being executed properly. However, there is no difference between the first ls command and the second ls command. I am not entirely sure what I am doing wrong. Perhaps I am using the wrong Ssh type. I have provided the code and the output I am getting. I have also added the output that I expect.
using Tamir.SharpSsh;
namespace SSHNetExample
{
class Program
{
static void Main(string[] args)
{
SshExec ssh = null;
try
{
Console.Write("-Connecting...");
ssh = new SshExec(host, username, password);
ssh.Connect();
Console.WriteLine("OK ({0}/{1})", ssh.Cipher, ssh.Mac);
Console.WriteLine("Server version={0}, Client version={1}", ssh.ServerVersion, ssh.ClientVersion);
Console.WriteLine("-Use the 'exit' command to disconnect.");
Console.WriteLine();
while(true)
{
string command = Console.ReadLine();
if(command == "exit")
break;
string data = ssh.RunCommand(command);
Console.WriteLine(data);
}
}
catch(Exception e)
{
Console.WriteLine(e.Message);
}
if(ssh != null)
{
Console.WriteLine("Disconnecting...");
ssh.Close();
Console.WriteLine("OK");
}
}
}
}
Output:
Expected Output:
The SshExec class is for executing a single command. It logs into the server for each command, and executes the command you asked it to. It's similar (but not the same) as you logging in, typing cd .., logging out again, logging in again and typing ls - when you logged in the second time you were redirected to the home directory.
If you want to continue to use the SshExec, you should combine your commands so you can just execute a single command. In this instance, for example, you would execute ls ...
If you want to be able to issue multiple commands like an interactive session, look at the SshShell class instead of SshExec.
I'm automating an upgrade of SQL Server 2005 Express to SQL Server 2008R2 Express via a WinForms app that is used to upgrade our application. The application is deployed at some 800+ locations, so we don't want any manual steps.
I've got the following code mostly written to perform the upgrade. I need to know, what's best practice for determining if the SQL Server installer completed successfully? Should I just look for an exit code of 0 for the process? Is that good enough; i.e. could it still exit with code of 0 if the upgrade had a problem and was rolled back (I'd test this, but don't know the best way to simulate a failure)?
Is there any other way to determine if the upgrade was successful in my C# app, so I can handle it properly if there was any error encountered by the SQL Server Installer?
try
{
//First, find the version of the currently installed SQL Server Instance
string sqlString = "SELECT SUBSTRING(CONVERT(VARCHAR, SERVERPROPERTY('productversion')), 0, 5)";
string sqlInstanceVersion = string.Empty;
using (DbCommand cmd = _database.GetSqlStringCommand(sqlString))
{
sqlInstanceVersion = cmd.ExecuteScalar().ToString();
}
if (sqlInstanceVersion.Equals(String.Empty))
{
//TODO throw an exception or do something else
}
//11.00 = SQL2012, 10.50 = SQL2008R2, 10.00 = SQL2008, 9.00 = SQL2005, 8.00 = SQL2000
switch (sqlInstanceVersion)
{
case "11.00":
case "10.50":
case "10.00":
//Log that the version is already up to date and return
return;
case "9.00":
case "8.00":
//We are on SQL 2000 or 2005, so continue with upgrade to 2008R2
break;
default:
//TODO throw an exception for unsupported SQL Server version
break;
}
string upgradeArgumentString = "/Q /ACTION=upgrade /INSTANCENAME={0} /ENU /IACCEPTSQLSERVERLICENSETERMS";
string instanceName = "YourInstanceNameHere";
string installerFilePath = AppDomain.CurrentDomain.BaseDirectory + "\\SQLEXPR_x86_ENU.exe";
if (!File.Exists(installerFilePath))
{
throw new FileNotFoundException(string.Format("Unable to find installer file: {0}", installerFilePath));
}
Process process = new Process
{
StartInfo = { FileName = installerFilePath, Arguments = String.Format(upgradeArgumentString, instanceName), UseShellExecute = false }
};
process.Start();
if (process.WaitForExit(SQLSERVER_UPGRADE_TIMEOUT))
{
//Do something here when the process completes within timeout.
//What should I do here to determine if the SQL Server Installer completed successfully? Look at just the exit code?
}
else
{
//The process exceeded timeout. Do something about it; like throw exception, or whatever
}
}
catch(Exception ex)
{
//Handle your exceptions here
}
Look at the full version string, nut just the first 5 chars of it. A successful upgrade will change the version string.
I am currently developing a twitter streaming web app as part of a College proj. I have written code that uses curl to stream from twitter and writes the data to a sql server 2008 express database.
ProcessStartInfo curl = new ProcessStartInfo();
Process process = new Process();
protected void Page_Load(object sender, EventArgs e)
{
curl.FileName = #"c:\program files\Curl\curl.exe";
curl.Arguments = "http://stream.twitter.com/1/statuses/sample.json -u username:password";
curl.UseShellExecute = false;
curl.RedirectStandardOutput = true;
process = Process.Start(curl);
Twitter_Stream(sender, e);
}
protected void Twitter_Stream(object sender, EventArgs e)
{
SqlConnection conn = new SqlConnection();
// Start curl process
using (process)
{
using (StreamReader reader = process.StandardOutput)
{
try
{
// create connection and open connection
conn = new SqlConnection(ConfigurationManager.AppSettings["strConnectionString"].ToString());
conn.Open();
// Post the output from curl to the queue.
// One line = one tweet in json format.
while (!reader.EndOfStream)
{
// create a SqlCommand object for this connection
SqlCommand command = conn.CreateCommand();
command.CommandText = "save_stream";
string result = reader.ReadLine();
Message message = new Message(result);
JObject obj = JObject.Parse(message.Body.ToString());
/* I parse the obj here and exec query to save data
command.CommandType = CommandType.StoredProcedure;
command.ExecuteNonQuery();
}
}
catch (Exception ex)
{ /*DO some error logging here.*/}
finally
{
// close the connection
conn.Close();
Thread.Sleep(1000);
Twitter_Stream(sender, e);
}
}
}
}`
My question is, As i have put a while loop that will or should never end in my code, will this cause an issue on the server load. Will a continuous loop crash the server? Also what should I use instead?
Any help at all would be much appreciated.
No, this will not crash the server because IIS is already watching for this case. If a page's execution time is greater than the currrent threshold, IIS will kill the thread.
Instead of making this a webpage, you should make this a console application. You can use infinite loops as much as you want in those.