I am using the code below to start a process on a remote machine. It does start the process, but it is running under the Admin user instead of the current user that is logged in. I need the current user to be able to interact with the program. If I use their credential in my code instead of admin then I will get an access denied. How do I specify to run under user "JohnDoe" ? I know PSSuite is an option, but I would rather use the ManagementScope class if possible.
class Program
{
static void Main(string[] args)
{
try
{
object[] theProcessToRun = { "notepad.exe" };
ConnectionOptions theConnection = new ConnectionOptions();
theConnection.Username = #"MyDomain\Admin";
theConnection.Password = "mypassword";
ManagementScope theScope = new ManagementScope("\\\\" + "BMBM14" + "\\root\\cimv2", theConnection);
ManagementClass theClass = new ManagementClass(theScope, new ManagementPath("Win32_Process"), new ObjectGetOptions());
theClass.InvokeMethod("Create", theProcessToRun);
Console.WriteLine("Success");
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
Console.ReadLine();
}
Console.ReadLine();
}
}
Related
I'm working on remote computer control by WMI using C#. I can connect after I have made the necessary settings on the remote computer. There is no problem so far. But when I shut down a remote computer with the Win32ShutDown command, after reboot the remote computer I received the following error:
System.Runtime.InteropServices.COMException (0x80070522): A required privilege is not held by the client. (Exception from HRESULT: 0x80070522).
How can I solve this?
My connection function:
public static ManagementScope Connect(string ip, string userName = "", string password = "")
{
ManagementScope scope = null;
try
{
ConnectionOptions opts;
scope = new ManagementScope(string.Format("\\\\{0}\\root\\cimv2", ip.Trim()));
if (!string.IsNullOrEmpty(userName))
{
opts = new ConnectionOptions
{
Username = userName,
Password = password,
EnablePrivileges = true,
Impersonation = ImpersonationLevel.Impersonate
};
scope.Options = opts;
}
scope.Connect(); //Error is thrown here
return scope;
}
catch (Exception ex)
{
scope = null;
throw ex;
}
}
My shutdown function:
static void ShutDown()
{
try
{
ConnectionOptions options = new ConnectionOptions
{
Username = "Administrator",
Password = "123",
EnablePrivileges = true,
Impersonation = ImpersonationLevel.Impersonate
};
ManagementScope scope = new ManagementScope(string.Format("\\\\{0}\\root\\cimv2", "192.168.1.50", options));
scope.Connect(); //Error is thrown here
ManagementClass mcWin32 = new ManagementClass("Win32_OperatingSystem") { Scope = scope };
mcWin32.Get();
ManagementBaseObject mboShutdownParams = mcWin32.GetMethodParameters("Win32Shutdown");
mboShutdownParams["Flags"] = 5;
ManagementBaseObject mboShutdown = null;
foreach (ManagementObject manObj in mcWin32.GetInstances())
{
mboShutdown = manObj.InvokeMethod("Win32Shutdown", mboShutdownParams, null);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
finally
{
Console.ReadLine();
}
}
I'm using the following code to kill a remote desktop session and the application running in it. It works fine, the only problem is that it kills the specified application for all users.
How do I keep this to just the local machine running a session?
We have multiple users logging in and running this application from a server on their local machines. Most are running using work resources, but some use remote desktop.
No matter how they are logged in when I run my code all users loose their sessions.
private void btnCloseSession_Click(object sender, EventArgs e)
{
if (!runningExclusiveProcess)
{
runningExclusiveProcess = true;
btnCloseSession.Enabled = false;
//check and close Labware if running
if (chkCloseLabware.Checked == true)
{
if (chkExit.Checked == true)
{
KillLabWare();
Close();
}
else
{
KillLabWare();
}
}
Process[] my = Process.GetProcessesByName("mstsc");
//loop thru list to get selected item(s)
ListBox.SelectedObjectCollection selectedItems = new ListBox.SelectedObjectCollection(lstOpenSessions);
selectedItems = lstOpenSessions.SelectedItems;
try
{
//remove credentials
string szTestx = "/delete:GOJO.NET/" + cboServer.Text;
ProcessStartInfo infox = new ProcessStartInfo("cmdkey.exe", szTestx);
Process procx = new Process();
procx.StartInfo = infox;
procx.Start();
if (lstOpenSessions.SelectedIndex != -1)
{
for (int i = selectedItems.Count - 1; i >= 0; i--)
{
//loop thru process to match process vs. list selection(s)
foreach (Process remote in my)
{
if (remote.MainWindowTitle == selectedItems[i].ToString())
{
KillRS(remote.MainWindowTitle);
lstOpenSessions.Items.Remove(selectedItems[i]);
}
}
if (lstOpenSessions.Items.Contains(selectedItems[i].ToString()))
{
lstOpenSessions.Items.Remove(selectedItems[i]);
}
}
}
}
catch (Exception ex)
{
Console.WriteLine("{0} Exception caught.", ex);
}
// If your task is synchronous, then undo your flag here:
runningExclusiveProcess = false;
btnCloseSession.Enabled = true;
}
}
public void KillLabWare()
{
ConnectionOptions con = new ConnectionOptions();
con.Username = cboUserName.Text;
con.Password = txtPassWord.Text;
string strIPAddress = cboServer.Text;
ManagementScope scope = new
ManagementScope(#"\\" + strIPAddress + #"\root\cimv2", con);
scope.Connect();
ObjectQuery query = new ObjectQuery("SELECT * FROM Win32_Process WHERE Name='Labware.exe'");
ManagementObjectSearcher searcher = new
ManagementObjectSearcher(scope, query);
ManagementObjectCollection objectCollection = searcher.Get();
foreach (ManagementObject managementObject in objectCollection)
{
managementObject.InvokeMethod("Terminate", null);
}
}
private void KillRS(string rwt)
{
foreach (Process p in Process.GetProcesses())
{
if (p.MainWindowTitle == rwt)
{
p.Kill();
}
}
}
public static void KillRemoteProcess(Process p, string user, string password)
{
new Process
{
StartInfo = new ProcessStartInfo
{
FileName = "TaskKill.exe",
Arguments = string.Format("/pid {0} /s {1} /u {2} /p {3}", p.Id, p.MachineName, user, password),
WindowStyle = ProcessWindowStyle.Hidden,
CreateNoWindow = true
}
}.Start();
}
It sounds like you are trying to force a specific user to log out? Is this because you find that users are forgetting to log out and constantly consuming licenses?
LabWare Application allows for a time out interval (in minutes) to be set on each user where after the interval has passed, the user will be logged out (licence no longer consumed).
For more information see page 204 of the LabWare 7 Technical Manual.
Alternativley if this is for a scheduler (service or cluster instance) session, this can also be controlled by the application. You can either manually change the shutdown and keep alive flags on the instance record on the Services table (if using Service Manager) or you can write a LIMS Basic event trigger/automation script or scheduled subroutine (or have this as a button on a Visual workflow) to do this for you.
HTH.
If you wanna kill remote desktop session or disconnect current RDP session, please read this article:
WTSDisconnectSession function
but if you logout current user, it also disconnect RDP session, here is the code:
using System;
using System.Runtime.InteropServices;
using System.ComponentModel;
class Program
{
[DllImport("wtsapi32.dll", SetLastError = true)]
static extern bool WTSDisconnectSession(IntPtr hServer, int sessionId, bool bWait);
const int WTS_CURRENT_SESSION = -1;
static readonly IntPtr WTS_CURRENT_SERVER_HANDLE = IntPtr.Zero;
static void Main(string[] args)
{
if (!WTSDisconnectSession(WTS_CURRENT_SERVER_HANDLE,
WTS_CURRENT_SESSION, false))
throw new Win32Exception();
}
}
I hope it works, fill free for further info, comment plz
Happy Coding 😎
I am fairly new with C# and I am trying to write an SSH console application using the SSH.NET framework. So far I was able to connect to my server successfully, but now I am trying to run commands and have it display the result. Yet, my console comes out blank when I run my application. My end goal was to execute a set of commands and see the results at the end of it.
Program.cs
using Renci.SshNet;
class Program
{
//Login Parameter
const String Hostname = "somePort";
const int PortNumber = 22;
const String Username = "username";
const String Password = "root";
static void Main(string[] args)
{
//Bypass Keyboard authentication
KeyboardInteractiveAuthenticationMethod kauth = new KeyboardInteractiveAuthenticationMethod(Username);
PasswordAuthenticationMethod pauth = new PasswordAuthenticationMethod(Username, Password);
kauth.AuthenticationPrompt += new EventHandler<Renci.SshNet.Common.AuthenticationPromptEventArgs>(HandleKeyEvent);
//Grab info for connections
ConnectionInfo connectionInfo = new ConnectionInfo(Hostname, PortNumber, Username, pauth, kauth);
//Connect
using (SshClient client = new SshClient(connectionInfo))
{
try
{
//Connect to server
client.Connect();
Console.WriteLine("Connection successful");
var command = client.CreateCommand("ls");
var result = command.Execute();
command.Execute();
Console.WriteLine(result);
//Disconnect from server
client.Disconnect();
}
//Show exp message
catch (Exception exp)
{
throw exp;
}
}
}
//Handle two step auth
static void HandleKeyEvent(Object sender, Renci.SshNet.Common.AuthenticationPromptEventArgs e)
{
foreach (Renci.SshNet.Common.AuthenticationPrompt prompt in e.Prompts)
{
if (prompt.Request.IndexOf("Password:", StringComparison.InvariantCultureIgnoreCase) != -1)
{
prompt.Response = Password;
}
}
}
}
I don't know if you have resolved this issue yet, but the solution is simple in this case.
The function:
command.Execute()
doesn't return your result.
You have to execute like you did, but then grab the result via
command.Result
It would look something like this:
var command = client.CreateCommand("ls");
command.Execute();
var result = command.Result;
Hope i could help you.
I have implemented code to uninstall a msi. The problem is, when I try to uninstall it remotely using WMI it doesnt get happen and even don't throw any exception. I tried on local and found that when I run command "MsiExec.exe /x {Product Code} /qn"; in cmd as administrator the service gets uninstall & even when I try to debug code in Visual Studio (as administrator) the code works too.
But unfortunately this has to get unistall at remote machine. Is there a way where I can run this code or command as administrator remotely?. I googled and found many answers but nothing worked. Any other approach?
private void UnInstall(string ipAddress, long discoveredMachineId)
{
ipAddress = ipAddress.Trim();
ConnectionOptions connection = new ConnectionOptions();
connection.Username = this.userName;
connection.Password = this.password;
ManagementScope scope = new ManagementScope(#"\\" + ipAddress + "\\root\\CIMV2");
try
{
scope.Connect();
if (scope.IsConnected == true)
{
//Start Uninstalling
try
{
var checkKey = Registry.LocalMachine.OpenSubKey(#"Software\Microsoft\Windows\CurrentVersion\Uninstall\{Product Code}");
if (checkKey == null)
{
// Key does not exist
Console.WriteLine("Not Installed");
}
else
{
// Key exist
var wmiProcess = new ManagementClass(scope, new ManagementPath("Win32_Process"), new ObjectGetOptions());
ManagementBaseObject inParams = wmiProcess.GetMethodParameters("Create");
inParams["CommandLine"] = "MsiExec.exe /x {Product Code} /qn";
ManagementBaseObject outParams = wmiProcess.InvokeMethod("Create", inParams, null);
Console.WriteLine("Creation of the process returned: " + outParams["returnValue"]);
Console.WriteLine("Process ID: " + outParams["processId"]);
Console.WriteLine("UnInstalled Successfully...");
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
I create a Windows Service project in VS2010 that contains multiple services. I tried to cull together a way to install it without a complex installer. But, it seems to rollback and not work.
Here's Program.cs:
static class Program
{
static void Main(string[] args)
{
bool install = false, uninstall = false, console = false;
WindowsServiceInstaller inst = new WindowsServiceInstaller();
if (args.Length > 0)
{
foreach (string arg in args)
{
switch (arg)
{
case "-i":
case "-install":
install = true;
break;
case "-u":
case "-uninstall":
uninstall = true;
break;
case "-c":
case "-console":
console = true;
break;
default:
Console.Error.WriteLine("Argument not expected: " + arg);
break;
}
}
}
if (uninstall)
{
inst.InstallServices(false, args);
}
if (install)
{
inst.InstallServices(true, args);
}
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
// scans Email table for outbound email jobs; uses multiple threads to lock and work on data in Email table
new EmailLogScanner()
// generates email digest of document status on secheduled basis; single thread
, new EmailStatusDigester()
// keeps Fax table and third-party fax service accounts synchronized; uses a fixed nb of threads, one thread syncs one account at a time
, new FaxSynchronizer()
};
if (console)
{
foreach (IDebuggableService srv in ServicesToRun)
{
string[] strs = new string[] { String.Empty };
srv.DebugStart(strs);
}
Console.WriteLine("Press any key to terminate...");
Console.ReadKey();
foreach (IDebuggableService srv in ServicesToRun)
{
srv.DebugStop();
}
Console.WriteLine("Service has exited.");
}
else
{
ServiceBase.Run(ServicesToRun);
}
}
}
Here's WindowsServiceInstaller.cs:
[RunInstaller(true)]
public class WindowsServiceInstaller : Installer
{
public WindowsServiceInstaller()
{
ServiceProcessInstaller serviceProcessInstaller = new ServiceProcessInstaller();
serviceProcessInstaller.Account = ServiceAccount.NetworkService;
serviceProcessInstaller.Username = null;
serviceProcessInstaller.Password = null;
Installers.Add(serviceProcessInstaller);
ServiceInstaller emailLogScannerInstaller = new ServiceInstaller();
emailLogScannerInstaller.DisplayName = "Email Scanner";
emailLogScannerInstaller.StartType = ServiceStartMode.Automatic;
emailLogScannerInstaller.ServiceName = "EmailLogScanner"; // must match the ServiceBase ServiceName property
emailLogScannerInstaller.Description = "Scan for and sends out pending emails in stack.";
Installers.Add(emailLogScannerInstaller);
ServiceInstaller emailStatusDigesterInstaller = new ServiceInstaller();
emailStatusDigesterInstaller.DisplayName = "Status Digester";
emailStatusDigesterInstaller.StartType = ServiceStartMode.Automatic;
emailStatusDigesterInstaller.ServiceName = "EmailDigester";
emailStatusDigesterInstaller.Description = "Prepares document status email digests.";
Installers.Add(emailStatusDigesterInstaller);
ServiceInstaller faxSynchronizerInstaller = new ServiceInstaller();
faxSynchronizerInstaller.DisplayName = "Fax Synchronizer";
faxSynchronizerInstaller.StartType = ServiceStartMode.Automatic;
faxSynchronizerInstaller.ServiceName = "FaxSynchronizer";
faxSynchronizerInstaller.Description = "Synchronizes database with external fax service(s).";
Installers.Add(faxSynchronizerInstaller);
}
public void InstallServices(bool doInstall, string[] args)
{
try
{
using (AssemblyInstaller aInstaller = new AssemblyInstaller(typeof(Program).Assembly, args))
{
IDictionary state = new Hashtable();
aInstaller.UseNewContext = true;
try
{
if (doInstall)
{
aInstaller.Install(state);
aInstaller.Commit(state);
}
else
{
aInstaller.Uninstall(state);
}
}
catch
{
try
{
aInstaller.Rollback(state);
}
catch { }
throw;
}
}
}
catch (Exception ex)
{
Console.Error.WriteLine(ex.Message);
}
}
}
The logged output (when I run daemon.exe -i in a command window, as admin) shows the text below. Also, I get the "cannot start service from the command line" dialog:
Installing assembly 'C:\Users\xxx\Documents\~Business\Projects\Daemon\bin\Release\Daemon.exe'.
Affected parameters are:
i =
assemblypath = C:\Users\xxx\Documents\~Business\Projects\Daemon\bin\Release\Daemon.exe
logfile = C:\Users\xxx\Documents\~Business\Projects\Daemon\bin\Release\Daemon.InstallLog
Installing service EmailLogScanner...
Service EmailLogScanner has been successfully installed.
Creating EventLog source EmailLogScanner in log Application...
See the contents of the log file for the C:\Users\xxx\Documents\~Business\Projects\Daemon\bin\Release\Daemon.exe assembly's progress.
The file is located at C:\Users\xxx\Documents\~Business\Projects\Daemon\bin\Release\Daemon.InstallLog.
Rolling back assembly 'C:\Users\xxx\Documents\~Business\Projects\Daemon\bin\Release\Daemon.exe'.
Affected parameters are:
logtoconsole =
i =
assemblypath = C:\Users\xxx\Documents\~Business\Projects\Daemon\bin\Release\Daemon.exe
logfile = C:\Users\xxx\Documents\~Business\Projects\Daemon\bin\Release\Daemon.InstallLog
Restoring event log to previous state for source EmailLogScanner.
Service EmailLogScanner is being removed from the system...
Service EmailLogScanner was successfully removed from the system.
UPDATE: When I comment out the try...catch block around the 'aInstaller.Install(state)' line, I get a slightly different output:
Installing assembly 'C:\Users\xxx\Documents\~Business\Projects\Daemon\bin\Release\Daemon.exe'.
Affected parameters are:
i =
assemblypath = C:\Users\xxx\Documents\~Business\Projects\Da
emon\bin\Release\Daemon.exe
logfile = C:\Users\xxx\Documents\~Business\Projects\Daemon\
bin\Release\Daemon.InstallLog
Installing service EmailLogScanner...
Creating EventLog source EmailLogScanner in log Application...
Source EmailLogScanner already exists on the local computer.
Is it because I already have Event Log sources setup? If so, how do I skip that step in the AssemblyInstaller? If not, wha? :)
You should put this
if (EventLog.SourceExists("YourEventSourceName"))
EventLog.DeleteEventSource("YourEventSourceName");
when service installation begins.