How to run exe as window service using c# [duplicate] - c#

This question already has answers here:
How To: Execute command line in C#, get STD OUT results
(18 answers)
Closed 7 years ago.
I am trying to run an exe file as window service. I have done it before manually by doing like this:
sc create TestService binPath= "C:\MyExePathWhichIsToBeRunAsWindowService"
and it could worked properly, when i see the services i am able to find it, Now have to do the same using c# code.
The code should ask the user for the path of exe file and this file has to be run as window service and also the name which he has to provide to this window service.So these two things user will enter at runtime, which is an easy task for me but once if i got that, then how i will run the command below from c# code ?
sc create TestServiceNameUsrEntered binPath= "path user entered for exe at run time"
Could some one please help me ?
EDIT: Please note that user will always enter serviceApplication exe file Not arbitrary files

You should look into Process.Start. You might want to try something like this:
Process.Start("sc", String.Format("create \"{0}\" binPath=\"{1}\"", serviceName, binPath));

You can take a look at Topshelf.
If you like to do it from scratch yourself, you can take a look into the HostInstaller.cs, where it simply adds the needed registry key:
using (RegistryKey system = Registry.LocalMachine.OpenSubKey("System"))
using (RegistryKey currentControlSet = system.OpenSubKey("CurrentControlSet"))
using (RegistryKey services = currentControlSet.OpenSubKey("Services"))
using (RegistryKey service = services.OpenSubKey(_settings.ServiceName, true))
{
service.SetValue("Description", _settings.Description);
var imagePath = (string)service.GetValue("ImagePath");
_log.DebugFormat("Service path: {0}", imagePath);
imagePath += _arguments;
_log.DebugFormat("Image path: {0}", imagePath);
service.SetValue("ImagePath", imagePath);
}

Related

Connecting to an SQL database over the internet using C#

I'm currently doing an assignment where I want my program to be able to read and update a database. The database itself runs on oracle and was provided by my university (I have my own schema I believe?)
Right now I can connect via SSH using programs such as teraterm or putty, once I log in it takes me to an interactive menu which allows me to select a few various options. One of which is shell. Once I select that I am able to use bash commands to log into the SQL section and use these:
bash$ export ORACLE_HOME=/opt/oracle/product/client/11.2.0
bash$ export TWO_TASK=SSID
bash$ $ORACLE_HOME/bin/sqlplus
to connect to the SQL database. Easy.
However, I want to be able to do that through my program and it is proving difficult for me. I am using SSH.NET and can connect via SSH seemingly well. The problem is I cannot access the SQL section. When I run the commands the first two work correctly I believe, but the last one does not. It seems to not be able to see the anything past $ORACLE_HOME. When I "echo $ORACLE_HOME /*" it even tells me that /bin is a folder:
/bin /boot /dev /etc /export /hey.php /home /lib /lib64 /local /lost+found /media /misc
/mnt /opt /proc /root /sbin /selinux /srv /stage /sys /tmp /usr /var
But instead, when I run the last line of code I get the error message:
Error = "bash: /bin/sqlplus: No such file or directory\n"
I'm not sure whether there is an easier way of accessing the SQL stuff... But I am very close using SSH.NET but I just can't see why I can't open the SQL section like I can in putty or teraterm...
Any help would be greatly appreciated, thank you for your time.
My actual C# code is this:
//Connection information
string user = "SSHusername";
string pass = "password";
string host = "address";
//Set up the SSH connection
using (var client = new SshClient(host, user, pass))
{
//Start the connection
client.Connect();
var output = client.RunCommand("export ORACLE_HOME=/opt/oracle/product/client/11.2.0");
Console.WriteLine(output.Result);
output = client.RunCommand("export TWO_TASK=SSID");
Console.WriteLine(output.Result);
output = client.RunCommand("$ORACLE_HOME/bin/sqlplus");
Console.WriteLine(output.Result);
output = client.RunCommand("username");
Console.WriteLine(output.Result);
output = client.RunCommand("password");
Console.WriteLine(output.Result);
output = client.RunCommand("SELECT * FROM users;");
Console.WriteLine(output.Result);
client.Disconnect();
Console.WriteLine(output.Result);
}
1.I suggest you use native C# package for connect Oracle. You will get wrong format of output.
I see your variable is not work. Because SQLPLUS client should be under
$ORACLE_HOME/bin/sqlplus. But your code show /bin/sqlplus. Means $ORACE_HOME not work.
You can directly change code and run directly sqlplus like /opt/oracle/product/client/11.2.0/bin/sqlplus user/pass#SSID
You can set some script on remote oracle server and get result over that or upload script from C# host to remote each time.
If you're using the SSH.NET library, using a Shell instead of separate Commands should work - something like (untested):
using (var client = new SshClient(host, user, pass)) {
client.Connect();
client.CreateCommand("export ORACLE_HOME=/opt/oracle/product/client/11.2.0").Execute();
client.CreateCommand("export TWO_TASK=SSID").Execute();
client.CreateCommand("$ORACLE_HOME/bin/sqlplus").Execute());
...
client.Disconnect();
}
Original source code found at SSH.NET example

The process cannot access the file 'filename' because it is being used by another process

I am new in C# and I have a problem connecting to a Firebird database. I want my program to access a Firebird Database [FDB format file]. I have problem, see the code below:
File.Copy(pathway, new_pathway, true);
FbConnection addDetailsConnection = new FbConnection("User=sysdba;Password=masterkey;Dialect=3;Database= " + new_pathway +
";DataSource=localhost;" );
string SQLCOMMAND = " SELECT UOM FROM ST_ITEM_UOM WHERE CODE = 'ANT'";
addDetailsConnection.Open();
FbCommand readCommand = new FbCommand(SQLCOMMAND, addDetailsConnection);
FbDataReader myreader = readCommand.ExecuteReader();
while (myreader.Read())
{
MessageBox.Show(myreader[0].ToString());
}
myreader.Close();
readCommand.Dispose();
addDetailsConnection.Close();
addDetailsConnection.Dispose();
This code lets me read my FDB file and extract the data. When the code executes for the first time, there is no error or problem, However when when I execute it again, this error is shown:
The process cannot access the file 'C:\Users\ACC-0001.FDB' because it is being used by another process.
You can use Handle to check which program is locking the file. It might be caused by your code or by another process running on your machine.
The tool identifies the process, for example:
C:>handle.exe c:\test.xlsx
Handle v3.46 Copyright (C) 1997-2011 Mark Russinovich Sysinternals -
www.sysinternals.com
EXCEL.EXE pid: 3596 type: File 414: C:\test.xlsx
As found here.
If the problem lies within your code, make sure you dispose and close all connections, preferably by using them within using sections:
using (FbConnection addDetailsConnection = new FbConnection("..."))
{
// do work
}
More details on using using can be found here.
You might have bumped into this Firebird issue: FB server reports that DB file is used by another application on secondary attachment attempt through a symlink
It only happens on Windows and only when two non-embedded connections use different path names of which one or both have a symlink in their path so they effectively point to the same location.
Both handle.exe and Process Explorer will only show the canonical (final) filename that fbserver.exe actually opens.
The only way to find out is to:
compare connection strings.
verify with handle.exe or Process Explorer that the files are indeed opened by fbserver.exe (and not by your process itself using an embedded connection)

recognize if program was run from Desktop

Is there any way to recognize if the application has been run from a shortcut instead of executable file? I need to make my users to copy exe file to their desktops rather than create shortcuts to it due to personalization issues. Any ideas?
Edit: creating the installer is not an option.
I don't know if this helps, but if you want your exe file to be on the desktop, this could work:
string path = Directory.GetCurrentDirectory();
string desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
if (!path.Equals(desktopPath))
{
Console.WriteLine("file is not at desktop");
}
If you do have an app in the windows shared folder you can configure it to prevent execution of the applications.
Or you can provide user just with link to .bat file instead of .exe and it would do something like this (using robocopy):
robocopy \\remote\server\exe %AppData%\your\folder app.exe /XO
start %AppData%\your\folder\app.exe
And on the C# side you can just check application path and do something like this:
public class Program
{
public int Main()
{
string original_path = System.IO.Path.GetFullPath(#"\\remote\app.exe");
string current_path = System.IO.Path.GetFullPath(
System.Reflection.Assembly.GetExecutingAssembly().Location);
if(original_path == current_path){
System.IO.File.Copy(original_path, #"C:\foo\bar\app.exe", true);
System.Diagnostics.Process.Start(#"C:\foo\bar\app.exe");
return 0;
}
// Run program normally here
}
}

Not able to run batch file from Windows Service Application [duplicate]

This question already has answers here:
Calling a batch file from a windows service
(3 answers)
Closed 9 years ago.
I am having batch file : sample.bat with following code:
#ECHO OFF
SET /a INT1=%1
SET /a INT2=%2
SET /a ANSWER=INT1*INT2
ECHO %ANSWER%
PAUSE
Also created another batch file : cmdSample.bat with following code:
sample 2 4
So if i run cmdSample.bat file, it gives me correct result.
After that i have created 1 windows service application in which i tried to call that batch file and pass the command, as follows:
private void DoWork()
{
try
{
string fname = #"C:\Users\of4\Desktop\sample.bat";
string cmd = "sample 2 4";
RunSampleBatch(fname, cmd);
}
}
private void RunSampleBatch(string fname, string cmd)
{
Process p = new Process();
p.StartInfo.FileName = fname;
p.StartInfo.Arguments = cmd;
p.Start();
}
Can anyone help me, why i am not able to execute batch file through windows service application??
Thanks in advance..
Your parameters are off, you are giving "sample" as your first parameter to the sample.bat.
Your service is probably not running under your user account. Maybe it cannot even access your file.
You need to start your batchfile using cmd.exe. You can find a very good explanation here.
What are you trying to do? Running a batch file from a windows service doesn't make much sense, you won't be able to see the results. Maybe you should try a console application first to debug your problems.
You might also want to post an actual error next time, because all of the above is just guesswork, we need more info than just "doesn't work".

See command line arguments being passed to a program

You may skip this part
I am using a batch file that I have in my thumb drive in order to
mount a true crypt volume. I created that batch file with the help of
this link. on that batch file I have the username and password
that I pass as arguments to trueCrypt.exe in order for it to be
mounted.
Anyways so my question is: will it be possible to see the arguments being passed to a program from a third party process? In other words, will it be possible to see the arguments being passed to this program:
using System;
using System.Reflection;
using System.Diagnostics;
class Program
{
static string password = "";
static void Main(string[] args)
{
if (args.Length > 0)
password = args[0];
// get location where this program resides
var locationOfThisExe = Assembly.GetExecutingAssembly().Location;
Console.Write("Press enter to start a new instance of this program.");
Console.Read();
var randomArgument = new Random().NextDouble().ToString();
Process.Start(locationOfThisExe, randomArgument);
// I am passing a random argument to a new process!
// is it possible to see these arguments from another process?
}
}
Edit
I am creating an edit cause I think I explained my self incorrectly but this edit should be a solution instead of a question
I think this question has not received enough attention. Executing the command showed by https://stackoverflow.com/users/235660/alois-kraus shows:
(I pasted the output on notepad++)
on the image it does not show very clearly but I was able to see the argument being pass to that process. That matters a lot to me because I mount my true crypt volumes with the command:
"C:\Program Files\TrueCrypt\TrueCrypt.exe" /v "a:\volume.tc" /lz /a /p a
that tells to truecrypt that I want to mount the volume located at a:\volume.tc on drive letter z and the password is a
If I execute that command true crypt will mount that volume on drive z:
the problem is that If I then execute the command wmic process note what shoes up:
Note the password is in there!
So in summary it is not safe to pass secure information as an argument. It may be secure if you close the process that received the arguments but I think it is important to be aware of this...
If other users with administrative rights or with the same user account can execute programs you can see all command lines with
wmic process
from all processes with this single command line.

Categories

Resources