I have a WCF Service which is running on IIS. ApplicationPool uses the LocalSystem Identity.
The WCF Service has an method for rebooting the system with WMI using the following code:
ManagementBaseObject mboShutdown = null;
ManagementClass mcWin32 = null;
try
{
mcWin32 = new ManagementClass("Win32_OperatingSystem");
mcWin32.Get();
// You can't shutdown without security privileges
mcWin32.Scope.Options.EnablePrivileges = true;
ManagementBaseObject mboShutdownParams = mcWin32.GetMethodParameters("Win32Shutdown");
// Flag 6 means we want to trigger a force reboot
mboShutdownParams["Flags"] = "6";
mboShutdownParams["Reserved"] = "0";
foreach (ManagementObject manObj in mcWin32.GetInstances())
{
mboShutdown = manObj.InvokeMethod("Win32Shutdown", mboShutdownParams, null);
var result = Convert.ToInt32(mboShutdown["returnValue"]);
if (result != 0) throw new Win32Exception(result, "Could not restart local machine!");
}
}
catch (Exception ex)
{
SkippyLogger.WriteError(ex, "Error in IISAdminService.Restart");
throw ex;
}
finally
{
if (mcWin32 != null)
mcWin32.Dispose();
}
The method throw an exception with "Privilege not held".
Few things to try...
this
Can you run the same method, as LocalSystem outside of IIS - i.e host it as a windows service installed of IIS?
We have a similar system (hosted as a windows service) and it performs the actual reboot using this class.
Related
I have a code that tries to access the services of another computer.
try
{
var serviceName = "MyService";
var ip = "10.10.11.16";
var username = "SomeUser";
var password = "APassword";
var connectoptions = new ConnectionOptions();
connectoptions.Impersonation = ImpersonationLevel.Impersonate;
connectoptions.Authentication = AuthenticationLevel.Packet;
connectoptions.EnablePrivileges = true;
connectoptions.Username = username;
connectoptions.Password = password;
var scope = new ManagementScope("\\\\10.10.11.16\\root\\cimv2");
scope.Options = connectoptions;
var query = new SelectQuery("select * from Win32_Service where name = '" + serviceName + "'");
using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query))
{
var collection = searcher.Get();
foreach (ManagementObject service in collection.OfType<ManagementObject>())
{
if (service["started"].Equals(true))
{
service.InvokeMethod("StopService", null);
BtnStartStop.Content = "Stop";
LblService.Content = serviceName;
LblServiceStatus.Content = "Stopped";
}
else
{
service.InvokeMethod("StartService", null);
BtnStartStop.Content = "Stop";
LblService.Content = serviceName;
LblServiceStatus.Content = "Running";
}
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
Will this work on Server and client only? Won't this work on regular pc to another regular pc? Each time I run this when I get to the part of:
var collection = searcher.Get();
I get an error of
Access is denied. (Exception from HRESULT: 0x80070005
(E_ACCESSDENIED))
Do you have an idea on to make this work? Thank you.
STEPS DONE SO FAR
Followed the instruction on
https://learn.microsoft.com/en-us/windows/win32/wmisdk/connecting-to-wmi-remotely-starting-with-vista
typed in the cmd with admin privilege
netsh advfirewall firewall set rule group="windows management instrumentation (wmi)" new enable=yes
I even turned off the firewall just to be sure.
edited the registry of the pc I am connecting to this:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WBEM\CIMOM\AllowAnonymousCallback
Data type
REG\_DWORD
As for the antivirus, the pc I am connecting to does not have any anti virus.
I still get the same error.
As #colosso pointed out, you are receiving that error message because you do not have permission on the remote host to connect to the WMI service.
You should follow the instructions here to ensure the remote host is configured to allow your connection.
I am trying to authenticate my SharePoint service t retrieve SPList Items :
private Cookie AuthenticateFBASite(string AuthenticationSiteURL, string UserName, string Password, NetworkCredential nc2)
{
Cookie CurrentSiteCookie = null;
using (Authentication.Authentication authSvc = new Authentication.Authentication())
{
authSvc.Url = AuthenticationSiteURL + "/_vti_bin/authentication.asmx";
authSvc.CookieContainer = new System.Net.CookieContainer(); //create a new cookie container
//set the FBA login information
authSvc.AllowAutoRedirect = true;
authSvc.PreAuthenticate = true;
authSvc.Credentials = nc2;
Authentication.LoginResult result = authSvc.Login(UserName, Password);
if (result.ErrorCode == Authentication.LoginErrorCode.NoError)
{
try
{
CookieCollection cookies = authSvc.CookieContainer.GetCookies(new Uri(AuthenticationSiteURL));
CurrentSiteCookie = cookies[result.CookieName];
return CurrentSiteCookie;
}
catch (System.Exception ex)
{
//Console.WriteLine("Exception occured while calling lists.asmx" + ex.Message);
return CurrentSiteCookie;
}
}
else if (result.ErrorCode == Authentication.LoginErrorCode.PasswordNotMatch)
{
return CurrentSiteCookie;
}
else
return CurrentSiteCookie;
}
}
and it was working fine till today i try to use it again but it return me an eror cookies[result.CookieName] is null , and this only happens on my machine not other machine .
#Eslan May i knw fom where your are calling this code ? from webpart or app or console application ? I suspect its authentication mode issue.
I have a problem with set Ipv6 in windows.
The below code can set a IPv4 address but I can't try to set IPv6.
Please help me.
ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
try
{
ManagementObjectCollection moc = mc.GetInstances();
foreach (ManagementObject mo in moc)
{
// Make sure this is a IP enabled device. Not something like memory card or VM Ware
if ((bool)mo["IPEnabled"])
{
if (mo["Caption"].Equals(nicName))
{
ManagementBaseObject newIP = mo.GetMethodParameters("EnableStatic");
ManagementBaseObject newGate = mo.GetMethodParameters("SetGateways");
ManagementBaseObject newDNS = mo.GetMethodParameters("SetDNSServerSearchOrder");
newGate["DefaultIPGateway"] = new string[] { Gateway };
newGate["GatewayCostMetric"] = new int[] { 1 };
newIP["IPAddress"] = IpAddresses.Split(',');
newIP["SubnetMask"] = new string[] { SubnetMask };
newDNS["DNSServerSearchOrder"] = DnsSearchOrder.Split(',');
ManagementBaseObject setIP = mo.InvokeMethod("EnableStatic", newIP, null);
ManagementBaseObject setGateways = mo.InvokeMethod("SetGateways", newGate, null);
ManagementBaseObject setDNS = mo.InvokeMethod("SetDNSServerSearchOrder", newDNS, null);
break;
}
}
}
}
catch (Exception ex)
{
string str = ex.Message;
}
I also tried to set a fixed IPv6 address via WMI, but it does not appear to work (the IPv4 address does work).
The only way I found to do this is by starting netsh from within the code, and using it to set the fixed (static) IPv6 address. If anyone has a more elegant solution, I will happily use it. Meanwhile:
Use the .NET System.Diagnostics.Process class to start a netsh process.
The netsh command reference, which tells you the parameters that you need, is here.
I found that I needed to start a new netsh process for each command that I sent.
For each netsh process, I created a handler for the process's OutputDataReceived event, that logged the netsh feedback.
I'm trying to create a virtual directory on a remote server using DirectoryServices by cloning the settings of another virtual directory, but I get a COMException: Unknown name. (Exception from HRESULT: 0x80020006 (DISP_E_UNKNOWNNAME)) when invoking AppCreate.
This is the code I've written (simplified with most of tests removed):
public bool CreateVirtualDirectory(string serverName, string primaryVirtualDirectoryName, string virtualDirectoryName, MyUser user)
{
try
{
DirectoryEntry directoryEntry = null;
if (user != null)
directoryEntry = new DirectoryEntry("IIS://" + serverName + "/W3SVC/1/Root", user.UserName, user.Password, AuthenticationTypes.Secure | AuthenticationTypes.Sealing);
else
directoryEntry = new DirectoryEntry("IIS://" + serverName + "/W3SVC/1/Root");
DirectoryEntry primaryVirtualDirectory = directoryEntry.Children.Find(primaryVirtualDirectoryName, directoryEntry.SchemaClassName);
DirectoryEntry virtualDirectory = directoryEntry.Children.Add(virtualDirectoryName, directoryEntry.SchemaClassName);
virtualDirectory.CommitChanges();
virtualDirectory.Properties["Path"].Value = primaryVirtualDirectory.Properties["Path"].Value;
virtualDirectory.Properties["AppFriendlyName"][0] = virtualDirectoryName;
if (primaryVirtualDirectory.Properties["UNCUserName"] != null && primaryVirtualDirectory.Properties["UNCUserName"].Value != null && primaryVirtualDirectory.Properties["UNCUserName"].Value.ToString().Length > 0)
{
// IIS6 of IIS7
virtualDirectory.Properties["AuthNTLM"][0] = true;
virtualDirectory.Properties["UNCUserName"].Value = primaryVirtualDirectory.Properties["UNCUserName"].Value;
virtualDirectory.Properties["UNCPassword"].Value = primaryVirtualDirectory.Properties["UNCPassword"].Value;
}
else
{
// Older versions
virtualDirectory.Properties["AuthFlags"][0] = 5; // MD_AUTH_ANONYMOUS | MD_AUTH_NT
virtualDirectory.Properties["AnonymousUserName"].Value = primaryVirtualDirectory.Properties["AnonymousUserName"].Value;
virtualDirectory.Properties["AnonymousUserPass"].Value = primaryVirtualDirectory.Properties["AnonymousUserPass"].Value;
}
virtualDirectory.Properties["AccessRead"][0] = true;
virtualDirectory.Properties["AccessExecute"][0] = true;
virtualDirectory.Properties["AccessWrite"][0] = false;
virtualDirectory.Properties["AccessScript"][0] = true;
virtualDirectory.Properties["EnableDefaultDoc"][0] = true;
virtualDirectory.Properties["EnableDirBrowsing"][0] = false;
if (primaryVirtualDirectory.Properties["AppPoolId"] != null && primaryVirtualDirectory.Properties["AppPoolId"].Value != null && primaryVirtualDirectory.Properties["AppPoolId"].Value.ToString().Length > 0)
virtualDirectory.Properties["AppPoolId"].Value = primaryVirtualDirectory.Properties["AppPoolId"].Value;
virtualDirectory.Properties["ScriptMaps"].Value = primaryVirtualDirectory.Properties["ScriptMaps"].Value;
// I Tried adding these 3 lines but I keeo getting the same exception
// virtualDirectory.CommitChanges();
// virtualDirectory.Invoke("SetInfo");
// virtualDirectory.CommitChanges();
virtualDirectory.Invoke("AppCreate", true);
// I tried this instead but I still get the same exception
// virtualDirectory.Invoke("AppCreate2", 0);
virtualDirectory.CommitChanges();
return true;
}
catch (Exception exception)
{
return false;
}
}
I tried some variations (see comments in the code) using AppCreate2 instead of AppCreate or calling a CommitChanges and/or invoking SetInfo before the AppCreate, but all lead to the same exception.
The user credentials I'm using has adminstrator rights on the remote server. In fact if I copy the program to the remote server and run it there with the same credentials (I logged in with the same user on the remote server), using 'localhost' as servername and the user variable = null, it works without throwing the exception, so it must have something to do with the remote execution.
The remote server is a Windows Server 2003 R2 SP2 (32bit), the machine running this program is a Windows 7 Professional (64 bit).
Does anyone have any ideas ?
I wrote the following code to change the user account and password associated with a Windows Service. How can I modify this code to be able to perform the same operation on a remote system?
static void Main(string[] args)
{
string serviceName = "DummyService";
string username = ".\\Service_Test2";
string password = "Password1";
ServiceController sc = new ServiceController(serviceName);
Console.WriteLine(sc.Status.ToString());
if (sc.Status == ServiceControllerStatus.Running)
{
sc.Stop();
}
Thread.Sleep(2000);
sc.Refresh();
Console.WriteLine(sc.Status.ToString());
string objPath = string.Format("Win32_Service.Name='{0}'", serviceName);
using (ManagementObject service = new ManagementObject(new ManagementPath(objPath)))
{
object[] wmiParams = new object[11];
wmiParams[6] = username;
wmiParams[7] = password;
service.InvokeMethod("Change", wmiParams);
}
Thread.Sleep(2000);
Console.WriteLine(sc.Status.ToString());
if (sc.Status == ServiceControllerStatus.Stopped)
{
sc.Start();
}
Thread.Sleep(2000);
sc.Refresh();
Console.WriteLine(sc.Status.ToString());
}
Use ServiceController constructor overload that allows target machine-name to be specified
Modify WMI object path to include the target server.
new ManagementPath(
"\\\\ComputerName\\root" +
"\\cimv2:Win32_Service.Name='{0}'");
Make sure your user/password have sufficient rights on target machine, change those if not.