Creating and deleting files on remote machine - c#

I want to create and delete a file on a remote machine of which i have admin username and password.
I am using this code
ConnectionOptions options = new ConnectionOptions();
options.Username = "admin";
options.Password = "12345";
ManagementScope scope = null;
ObjectQuery query = null;
ManagementObjectSearcher searcher = null;
try
{
scope = new ManagementScope(#"\\192.168.3.125\root\CIMV2", options);
scope.Connect();
query = new ObjectQuery(#"SELECT * FROM CIM_Datafile WHERE name = 'c:\\c$\\Testing\\Test.txt'");
searcher = new ManagementObjectSearcher(scope, query); // EDIT forgot to include 'scope' previously
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
return;
}
foreach(ManagementObject mo in searcher.Get())
{
uint returnCode = (uint)mo.InvokeMethod("Delete", null);
if (returnCode == 0)
Console.WriteLine("File was successfully deleted");
else
Console.WriteLine("Deletion failed due to return code " + returnCode);
}
But it is giving me invalid query error and also i want to know how to Create a file on Remote machine.
and i even cant access the path \\192.168.3.125\C$\Testing\Test.txt
My file location is c:\Testing\Test.txt

Firstly can you access the file via the windows explorer from the machine (start -> run -> \192.168.3.125\C$\Testing\Test.txt)
If so what's wrong with
File.Delete(#"\\192.168.3.125\C$\Testing\Test.txt");

In my case, when I was connecting two windows based computers, you could just put:
#"\\PC-NAME\NEXT-FOLDER\NEXT-FOLDER\test.txt"

Related

Windows Management Instrumentation msi install remote machine

I'm trying to install a msi on a remote machine , i changed DCOM Config to get access from my machine when using methode install of win32_product it fails with return output 1601 ( that means that Windows Installer service could not be accessed )
i did some research in the net , and run the service manually using services.msc
and did msiexec / unreg and msiexec /register , still not working
ps: both machines a running on windows 10
here is my code
Ps : i used the same code for win32_Bios to get SerialNumber and it works
try
{
\\machine is the name of the computer
string PackageLocation = #"\\" + machine + msi;
ConnectionOptions connection = new ConnectionOptions();
connection.Username = username;
connection.Password = password;
connection.Impersonation = ImpersonationLevel.Impersonate;
connection.Authentication = AuthenticationLevel.Default;
connection.EnablePrivileges = true;
//define the WMI root name space
ManagementScope scope =
new ManagementScope(#"\\" + machine + #"\root\CIMV2", connection);
//define path for the WMI class
ManagementPath p =
new ManagementPath("Win32_Product");
//define new instance
ManagementClass classInstance = new ManagementClass(scope, p, null);
// Obtain in-parameters for the method
ManagementBaseObject inParams = classInstance.GetMethodParameters("Install");
// Add the input parameters.
inParams["AllUsers"] = true; //to install for all users
inParams["Options"] = ""; //paramters must be in the format “property=setting“
inParams["PackageLocation"] = #"c:\install\installer.msi";
//source file must be on the remote machine
// Execute the method and obtain the return values.
ManagementBaseObject outParams = classInstance.InvokeMethod("Install", inParams, null);
// List outParams
string retVal = outParams["ReturnValue"].ToString();
string msg = null;
switch (retVal)
{
case "0":
msg = "The installation completed successfully.";
break;
case "2":
msg = "The system cannot find the specified file. \n\r\n\r" + msi;
break;
case "3":
msg = "The system cannot find the path specified. \n\r\n\r" + msi;
break;
case "1619":
msg = "This installation package \n\r\n\r " + msi + "\n\r\n\rcould not be opened, please verify that it is accessible.";
break;
case "1620":
msg = "This installation package \n\r\n\r " + msi + "\n\r\n\rcould not be opened, please verify that it is a valid MSI package.";
break;
default:
msg = "Please see... \n\r\n\r http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/error_codes.asp \n\r\n\rError code: " + retVal;
break;
}
// Display outParams
Console.WriteLine(msg, "Installation report");
}
catch (ManagementException me)
{
Console.WriteLine(me.Message + "Management Exception");
}
catch (COMException ioe)
{
Console.WriteLine(ioe.Message, "COM Exception");
}
}

Execute .bat File on a Server in C#

I am attempting to execute a .bat file on a remote machine (a server) that ends a process and kicks the user out of a database system. When executed on the server, the file works correctly and ends the process on the client machine.
However, when executed through C#, the command is entered into the command prompt and cannot execute. Here is the .bat file;
psexec \\lp-100 msg * Hi Dan - your being removed!
pskill \\lp-100 sdcdatabase.vshost.exe
pause
The issue arises when executed in C#, this is the error message:
What this leads me to believe is that actually the .bat file is not being executed on the server (that does have PsTools installed), but instead the contents is being copied over and executed on the client machine instead.
Here is the code I am using to execute the .bat file;
Process proc = null;
try
{
string batDir = string.Format(#"\\hqdb1\sdc_sqldb\pstools\");
proc = new Process();
proc.StartInfo.WorkingDirectory = batDir;
proc.StartInfo.FileName = "removeuser.bat";
proc.StartInfo.CreateNoWindow = false;
proc.Start();
proc.WaitForExit();
MessageBox.Show("Bat file executed !!");
}
catch (Exception ex)
{
Console.WriteLine(ex.StackTrace.ToString());
}
Is this executing the .bat file on the server, kicking the client off, or executing on the client and not finding PsTools?
Years ago I wrote this code, try if it's still working:
ConnectionOptions options = new ConnectionOptions();
options.Password = args[2];
options.Username = args[1];
string machine= args[0];
ManagementScope scope = new ManagementScope();
scope.Options = options;
scope.Path = new ManagementPath(#"\\" + machine + #"\root\cimv2");
scope.Connect();
ObjectQuery query = new ObjectQuery("Select * from Win32_Process Where Name = '" + args[3] + "'");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
ManagementObjectCollection queryCollection = searcher.Get();
foreach (ManagementObject m in queryCollection)
{
object y = m.GetPropertyValue("ProcessID");
int pID = Convert.ToInt32(y);
m.InvokeMethod("Terminate", null);
}

ManagementObjectSearcher Get() method returns no results

I'm trying to terminate a process on a remote machine with WMI / C# on .NET 4.5. In the code below, when the Get method is called on the ManagementObjectSearcher instance nothing is returned, so the line inside the foreach is not reached. The ManagementScope is connected and the query variable contains the name of the process for termination.
Thx for any help.
try
{
ConnectionOptions connOptions = new ConnectionOptions();
connOptions.Impersonation = ImpersonationLevel.Impersonate;
connOptions.EnablePrivileges = true;
ManagementScope manScope = new ManagementScope(String.Format(#"\\{0}\ROOT\CIMV2", NetworkName), connOptions);
manScope.Connect();
var query = new SelectQuery("select * from Win32_process where name = '" + ProcessName + "'");
using (var searcher = new ManagementObjectSearcher(manScope, query))
{
foreach (ManagementObject process in searcher.Get())
{
process.InvokeMethod("Terminate", null);
}
}
}
catch (ManagementException err)
{
//Do something with error message here
}
As outlined in my comment above, for completeness here's the code with my changes that are as follows.
try
{
ConnectionOptions connOptions = new ConnectionOptions();
connOptions.Impersonation = ImpersonationLevel.Impersonate;
connOptions.EnablePrivileges = true;
ManagementScope manScope = new ManagementScope(String.Format(#"\\{0}\ROOT\CIMV2", NetworkName), connOptions);
manScope.Connect();
ProcessName = ProcessName + ".exe";
using (var searcher = new ManagementObjectSearcher(manScope, new SelectQuery("select * from Win32_Process where Name = '" + ProcessName + "'")))
{
foreach (ManagementObject process in searcher.Get())
{
process.InvokeMethod("Terminate", null);
}
}
}
catch (ManagementException err)
{
//Do something with error message here
}
In my case i was unable to receive CPU utilization value remotely using WMI query:
SELECT PercentProcessorTime FROM Win32_PerfFormattedData_PerfOS_Processor WHERE Name='_Total'
I changed project build platform target from Any CPU to x64 to match my system bitness, and problem was solved. Another way is uncheck Prefer 32-bit checkbox when Any CPU is selected.
Use the Count property to check, whether it contains any record. That is, if(searcher.Get().count == 0) returns true, means no record is present.

Remotely Install an Application from a FileShare using WMI

So far my code will start a process (Install an application) with command line arguments on a target computer and wait for the process to finish, IF I copy the install files to that computer.
My goal now is to:
Start a process with command line arguments (Install an application) on the remote computer.
NOT copy the files to the remote computer. The installer files will be located on a network share that both the sender computer and the remote computer have access to.
Wait for the process to finish.
Any help is much appreciated!
private void StartAppAction(string PCName, string Params)
{
//Example of Params \\Server\Folder\Application.EXE /s
ConnectionOptions conn = new ConnectionOptions();
conn.Impersonation = ImpersonationLevel.Impersonate;
conn.Authentication = AuthenticationLevel.Default;
conn.EnablePrivileges = true;
ManagementScope manScope = new ManagementScope(String.Format(#"\\{0}\ROOT\CIMV2", PCName), conn);
try
{
manScope.Connect();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
ObjectGetOptions objOpt = new ObjectGetOptions();
ManagementPath manPath = new ManagementPath("Win32_Process");
ManagementClass manClass = new ManagementClass(manScope, manPath, objOpt);
ManagementBaseObject inParams = manClass.GetMethodParameters("Create");
inParams["CommandLine"] = Params;
ManagementBaseObject outParams = manClass.InvokeMethod("Create", inParams, null);
string query = String.Format("SELECT * FROM __InstanceDeletionEvent WITHIN 3 WHERE TargetInstance ISA 'Win32_Process' AND TargetInstance.ProcessID = '{0}'", outParams["ProcessId"].ToString());
string scope = #"\\" + PCName + #"\root\CIMV2";
EventWatcherOptions evOp = new EventWatcherOptions(null, new TimeSpan(1, 0, 0), 1);
ManagementEventWatcher manWatch = new ManagementEventWatcher(scope, query, evOp);
try
{
ManagementBaseObject watcher = manWatch.WaitForNextEvent();
var ID = ((ManagementBaseObject)watcher["TargetInstance"]);
//Process Ended
}
catch
{
MessageBox.Show("Unable to watch for the remote process to finish");
}
}

Get a list of all UNC shared folders on a local network server

I'm trying to get a list of all shared folders available on a local intranet server.
The System.IO.Directory.GetDirectories() works fine for a path like \\myServer\myShare, however I'm getting an exception for a path like \\myServer:
Unhandled Exception: System.ArgumentException: The UNC path should be of the form \server\share.
Is there a way to get a list all shared folders for a server? Ultimately I'm looking for a method that can handle both scenarios based on a given path - returning a list of all shares for a given server and returning a list of all subdirectories for a given network shared folder.
Here's a technique that uses System.Management (add a reference to this assembly):
using (ManagementClass shares = new ManagementClass(#"\\NameOfTheRemoteComputer\root\cimv2", "Win32_Share", new ObjectGetOptions())) {
foreach (ManagementObject share in shares.GetInstances()) {
Console.WriteLine(share["Name"]);
}
}
Appropriate permissions are required.
I think this is what you are looking for http://www.codeproject.com/KB/IP/networkshares.aspx
private DataTable GetSharedFolderAccessRule()
{
DataTable DT = new DataTable();
try
{
DT.Columns.Add("ShareName");
DT.Columns.Add("Caption");
DT.Columns.Add("Path");
DT.Columns.Add("Domain");
DT.Columns.Add("User");
DT.Columns.Add("AccessMask");
DT.Columns.Add("AceType");
ManagementScope Scope = new ManagementScope(#"\\.\root\cimv2");
Scope.Connect();
ObjectQuery Query = new ObjectQuery("SELECT * FROM Win32_LogicalShareSecuritySetting");
ManagementObjectSearcher Searcher = new ManagementObjectSearcher(Scope, Query);
ManagementObjectCollection QueryCollection = Searcher.Get();
foreach (ManagementObject SharedFolder in QueryCollection)
{
{
String ShareName = (String) SharedFolder["Name"];
String Caption = (String)SharedFolder["Caption"];
String LocalPath = String.Empty;
ManagementObjectSearcher Win32Share = new ManagementObjectSearcher("SELECT Path FROM Win32_share WHERE Name = '" + ShareName + "'");
foreach (ManagementObject ShareData in Win32Share.Get())
{
LocalPath = (String) ShareData["Path"];
}
ManagementBaseObject Method = SharedFolder.InvokeMethod("GetSecurityDescriptor", null, new InvokeMethodOptions());
ManagementBaseObject Descriptor = (ManagementBaseObject)Method["Descriptor"];
ManagementBaseObject[] DACL = (ManagementBaseObject[])Descriptor["DACL"];
foreach (ManagementBaseObject ACE in DACL)
{
ManagementBaseObject Trustee = (ManagementBaseObject)ACE["Trustee"];
// Full Access = 2032127, Modify = 1245631, Read Write = 118009, Read Only = 1179817
DataRow Row = DT.NewRow();
Row["ShareName"] = ShareName;
Row["Caption"] = Caption;
Row["Path"] = LocalPath;
Row["Domain"] = (String) Trustee["Domain"];
Row["User"] = (String) Trustee["Name"];
Row["AccessMask"] = (UInt32) ACE["AccessMask"];
Row["AceType"] = (UInt32) ACE["AceType"];
DT.Rows.Add(Row);
DT.AcceptChanges();
}
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.StackTrace, ex.Message);
}
return DT;
}

Categories