I'm using C# and AWS's CLI for S3. I seem to be having the same or a similar issue in two different places. In the first, I'm trying to execute multiple commands with the same process. The first command is to set the environment variables for the access key and secret key for AWS S3. The next two commands are just a simple ls to see what's in the bucket already and a sync to update its contents. If I take the commands to set the environment variables out, it works fine (because I'm already configured on the machine I'm working on), but since I need this to work on other machines, the environment variables need to be set. However, if they are, the following commands do not execute. Here's code for this:
String commands = #"set AWS_ACCESS_KEY_ID=keykeykey set AWS_SECRET_ACCESS_KEY=secretsecretsecret";
commands += #" & aws s3 ls s3://bucket";
commands += #" & aws s3 sync C:\test s3://bucket/kaaaaay";
The issue reappears in a different method. There, I need to get the value from a registry key. I know the command is correct, because it works just fine in a command line window. Here's code for that:
String commands = #"Reg.exe QUERY HKEY_LOCAL_MACHINE\Software\GIJOE\HASAKEY";
Any help would be much appreciated, because I'm stumped.
Related
I'm definitely new to C# but learning it to pickup where another left things at work so be gentle if I ask silly questions (I think this is an easy one). I'm using SSH.NET and the current code isn't wrong but the way the previous guy wrote it can leave open ssh connections on the other side.
Current working code opens the SSH session as normal but uses something like this to run commands on the remote system:
Stream.Writeline("part of the command")
Stream.Readline();
Stream.Writeline("second part of command")
Stream.Readline();
Stream.Writeline("last part of command")
Stream.Readline();
This works and gathers the data exactly as it should but I've seen repeated times where the SSH connection stays open afterwards on the remote system. What I would like to do is send this all within a single command via create.command like:
command1 = client.CreateCommand("full command to run")
result = command1.Execute()
My problem is that the command I'd like to run on the remote system requires returns to run, it's a database command:
mysql -u user <<EOF
select COUNT(*) from table1
go
EOF
What I'd like to do:
command1 = client.CreateCommand("mysql -u user <<EOF\nselect COUNT(*) from table1\ngo\nEOF\n")
How/can one insert returns into the Create.Command? I'm assuming so, see no reason why not but I'm having a hard time finding the correct syntax to send a database command that requires returns after each line like above via the Create.Command. I've tried using \n for newlines but 99% sure I'm using it incorrectly.
And just to be clear I used mysql as the DB example, it's actually a sybase database but uses that syntax to connect.
Why do you need the breaks in the first place? They're just to nicely format the query for humans. MySQL isn't human. It couldn't care less. why not just do it this?
mysql -u user -e 'select count(*) from table1'
you don't need a go command, period.
If you DO want to send multiple commands, then you still don't need any line breaks, just a ;:
mysql -u user -e 'command1; command2; command3; ....'
USE \r\n like in here:
command1 = client.CreateCommand("mysql -u user <<EOF\r\nselect COUNT(*) from table1\r\ngo\r\nEOF\n")
I am using the Microsoft Data-Tier Application framework to create a deployment script based on a DacPackage object. I am attempting to use the Microsoft.SqlServer.Management.Smo.Server class to execute this script...
SqlConnection deployConnection = new SqlConnection(connBuilder.ToString());
deployConnection.Open();
Server server = new Server(new ServerConnection(deployConnection));
server.ConnectionContext.ExecuteNonQuery(deployScript);
However, this errors out with...
Unhandled Exception: Microsoft.SqlServer.Management.Common.ExecutionFailureException:
An exception occurred while executing a Transact-SQL statement or batch. --->
System.Data.SqlClient.SqlException: Incorrect syntax near ':'.
I know that the answer to this problem is that I need to be in SQLCMD mode, but I don't know how to tell my ServerConnection to execute in said mode.
I guess my problem isn't as specific as what I state in the title. What I really need to be able to do is execute the script generated from the DacPackage via the .Net framework. Can anyone help me with this?
SQLCMD mode commands are not T-SQL commands; they only work in SQL Server Management Studio (SSMS) / Visual Studio (VS) and SQLCMD.EXE. SQLCMD-mode is inherently how SQLCMD.EXE works and can be manually enabled in SSMS / VS; it is a part of those applications and not something that can be done via a provider.
Those applications interpret the SQLCMD-mode commands and do not pass them through to SQL Server. SQLCMD-mode commands are parsed/executed first (which is how they are able to affect the SQL that is about to be submitted) and then the final version of the SQL is submitted to SQL Server.
Hence, the deployment SQL scripts generated by SQL Server Data Tools (SSDT) / Visual Studio need to be run via one of these three programs.
Since you have a .dacpac file already, Microsoft provides a few ways to publish those that you should check out:
SqlPackage.exe and MSDeploy.exe. They are both described on the MSDN page for Project-Oriented Database Development using Command-Line Tools.
DacServices.Deploy(). This can be done in C# via the DacServices Class.
You can also create a publish SQL script via DacServices.GenerateDeployScript(), but this won't change the situation as stated above since the publish / deploy SQL script, whether generated from Visual Studio "Publish {project_name}" or GenerateDeployScript(), is the same script. Meaning, it will have the SQLCMD-mode colon-commands such as :setvar and :on error exit as well as the SQLCMD-mode variables, which at the very least will be $(DatabaseName) which is used in the following line:
USE [$(DatabaseName)];
While it is possible to comment out the initial :setvar lines by setting the DacDeployOptions property of CommentOutSetVarDeclarations to true, that will still leave the :on error exit line as well as a line for :setvar __IsSqlCmdEnabled "True" that is used to detect whether or not SQLCMD-mode has been enabled. Just above this particular :setvar line is a comment stating:
/*
Detect SQLCMD mode and disable script execution if SQLCMD mode is not supported.
To re-enable the script after enabling SQLCMD mode, execute the following:
SET NOEXEC OFF;
*/
So they really do intend that this script is only run via SQLCMD, whether through DOS -> SQLCMD.EXE or PowerShell -> Invoke-SqlCMD.
Technically, it is possible to generate a string of the deploy script contents (rather than to a stream) and manipulate that string by a) removing any colon-commands, and b) replacing "$(DatabaseName)" with whatever database you intend on deploying to. However, I have not tried this, I am not recommending this, and I am not sure it would work in all situations of what deployment scripts could be generated by SQL Server Data Tools. But it does seem like an option.
Also, minorly related: you don't need SMO to run SQL Scripts. SMO is means of interacting with SQL Server via objects rather than directly through T-SQL commands.
EDIT:
Links where others have tried this and found it did not work:
http://www.sqlservercentral.com/Forums/Topic1161673-22-1.aspx
https://social.msdn.microsoft.com/Forums/sqlserver/en-US/7d3f64b0-f6ed-44ad-99cc-ce4c8324c09e/running-sqlcmd-commands-using-smodatabaseexecutenonquery?forum=sqlsmoanddmo
Possibilities for getting the generated publish SQL script to work programmaticaly:
C# via Process.Start to call SQLCMD.EXE -i filename.sql: http://msdn.microsoft.com/en-us/library/system.diagnostics.process.start(v=vs.110).aspx
C# via open source library to handle "GO" statements and SQLCMD-mode colon-commands (currently handles SQL files, but can be easily updated to accept a string instead): https://github.com/rusanu/DbUtilSqlCmd
PowerShell via Invoke-SqlCMD: http://www.sqlservercentral.com/Forums/Topic1502697-1351-1.aspx
I currently run MongoDB pointing to the appropriate data directory using the command line below:
mongod --dbpath "somePath/data"
But currently this is a manual step that I run before running a particular suite of tests. Is there a way I can set the path within the code (without calling a script or batch file) using the Mongo C# driver to use a specific data directory?
Update:
To clarify, the reason I'm looking to do this isn't for use in production code, but to isolate test databases for different test suites and to point at a disposable and isolated data directory so that each server instance is clean at the time of running tests and is only populated with the data it requires for the same server settings as production.
You probably won't find any way to do that. The Mongo C# Driver is for programming a MongoClient, not a server. The documentation for C# Driver for MongoDB says - MongoClient class serves as the root object for working with a MongoDB server. When you are programming a client, you automatically would assume that the server is up and running. Whether you do it manually or you write another code for it, that is a different story.
Very rarely would you allow people to connect to a machine and let them start a server AND A CLIENT on it. And why is it rare? You may try to start a server on another machine and screw up with that machine (which may be providing some other completely different service too!). There are some ways (and there are times when it is needed) to start a server remotely, but that is not what you can do using the MongoDB C# Driver.
Now, in order to get your task done, you can try this:
Start one mongod per database on your server, and make each mongod listen to a different port. Then in your code, you can connect your MongoClient to mongod running on the concerned database's port. You can achieve this by using a simple if condition (or a switch case) and checking what database the MongoClient wants to connect to and thus finding the right port value to put in the connection string. Each mongod can serve only one database or more or whatever you want.
So if you are running three mongod's on port1, port2 and port3 and all those three are connected to their respective db paths, the code can be somewhat like this:
var DBNAME = name_of_the_db;
string connectionString;
switch (DBNAME)
{
case name_of_first_DB:
connectionString = "mongodb://[user:pass#]hostname[:port1][/[DBNAME][?options]]";
break;
case name_of_second_DB:
connectionString = "mongodb://[user:pass#]hostname[:port2][/[DBNAME][?options]]";
break;
case name_of_third_DB:
connectionString = "mongodb://[user:pass#]hostname[:port3][/[DBNAME][?options]]";
break;
default:
Console.WriteLine("Invalid DB Name");
}
Answering the updated part of the question:
You can start mongod's on different partitions of the server. Even start the daemons from different drives altogether and make them listen to different ports. Goes without saying that the dbpaths should not be pointing to the same drive for any two databases to at least pretty closely mimic what you wanted.
Just to complete this answer I am adding what #Schaliasos has mentioned in comments.. Consider installing mongo as a window service.
I'm using SharpSSH to connect to an SSH server and I've tried using both SshShell and SshExec.
I need to be able to take a series of commands and send them to the server in order, so SshShell doesn't really do what I need since I would have to wrangle streams the whole time and it seems that it would be a bit of a kludge. So I've tried SshExec but found one problem with it, every time I send a command it seems to be making a new connection and losing the context of the last command. For example if I ran the following commands:
pwd
cd .ssh
pwd
I would expect it to output
/home/adam
/home/adam/.ssh
But, instead it just ouputs "/home/adam" both times, meaning that the directory change was lost in between.
Is there a way I can configure this so that it maintains a constant connection to the SSH server until I tell it to disconnect?
Do this:
exec.RunCommand("pwd; cd Desktop; pwd")
I am not sure how to do advanced commands, but I tried that and it outputs:
/Users/MyUser
/Users/MyUser/Desktop
To cd to a hidden directory (any directory beginning with a dot (.) character), you need to enclose the value in quotes.
According to the documentation:
4) If the first component of the directory operand is dot or dot-dot, proceed to step 6.
6) Set curpath to the string formed by the concatenation of the value of PWD , a slash character, and the operand.
In short, cd '.ssh' should do the trick.
I have a set of commands like:
C:
cd Project
testproj.exe
My system gets these commands one by one from a remote system.
I need to execute each command in cmd.exe on receiving the command from the remote system. How to execute these using .NET?
I also need to return the result of testproj.exe to the remote machine. How to take the result after running command?
Process.Start cmd.exe, and hook StandardIn, StandardOut, and StandardError. Then, when a command comes in, just write it to StandardIn and read StandardOut/Error for the return. The whole thing shouldn't be more than 15 LOC.
That being said, just installing the Telnet Server would probably be easier - as it sounds like that's what you're essentially replicating....
var process = System.Diagnostics.Process.Start( "testproj.exe" );
process.WaitForExit();
var result = process.ExitCode;
This won't really honor things like "C:" or "CD path". Instead you'd want to create a batch file in a temporary folder then call the batch file.
Take a look at System.Diagnostics.Process. You can redirect stdout/stderr somewhere to get the output.
The C: and cd Project operations can be done inside the lanching application using the Directory class using the SetCurrentDirectory method.
Then just use the Process class to launch the testproj.exe executable.
Instead of trying to support all the commands of DOS, just have a small subset implemented which will guarantee nothing can go wrong. Like Don't allow DELETE, RD, FORMAT etc.
So, basically you would only have a subset of DOS commands. Once you have the command set, you can code for those specific commands using a extension mechanisms or as pluggable modules.
This will also helps you safe guard your machine from malicious attacks and worst to happen is there could be data sent out but from machine, the data / system can never be harmed.
UPDATE: The implementaion of specific commands is left to you. You could use .NET API or have System.Diagnostics.Process