WMI and Rebooting

G

Guest

I am trying to use WMI to reboot my system. I have admin privileges. I've
tried two different solutions but both fail for separate reasons.

private void button1_Click(object sender, System.EventArgs e)
{
ManagementBaseObject outParams = null;
ManagementClass os = new ManagementClass("Win32_OperatingSystem");

os.Scope.Options.EnablePrivileges = true; // enables required security
privilege.
os.Get();
ManagementBaseObject inParams = os.GetMethodParameters("Win32Shutdown");
inParams["Flags"] = "2"; // System forced reboot
inParams["Reserved"] = "0";
foreach (ManagementObject mo in os.GetInstances())
outParams = mo.InvokeMethod("Win32Shutdown", inParams, null);
}

This method gives me a run-time errors with System.Management telling me
"Privilege not held."

This next attempt, called from the click method, fails with a run-time error
saying "Invalid Method Parameter(s)".

ManagementClass os = new ManagementClass("Win32_OperatingSystem");
os.Scope.Options.EnablePrivileges = true; // enables required security
privilege.
os.Get();
ManagementBaseObject inParams = os.GetMethodParameters("Reboot");
ManagementBaseObject outParams = os.InvokeMethod("Reboot", inParams, null);

What am I doing wrong? I have .NET 1.1 on my system.
 
W

Willy Denoyette [MVP]

Steve Teeples said:
I am trying to use WMI to reboot my system. I have admin privileges. I've
tried two different solutions but both fail for separate reasons.

private void button1_Click(object sender, System.EventArgs e)
{
ManagementBaseObject outParams = null;
ManagementClass os = new ManagementClass("Win32_OperatingSystem");

os.Scope.Options.EnablePrivileges = true; // enables required security
privilege.
os.Get();
ManagementBaseObject inParams = os.GetMethodParameters("Win32Shutdown");
inParams["Flags"] = "2"; // System forced reboot
inParams["Reserved"] = "0";
foreach (ManagementObject mo in os.GetInstances())
outParams = mo.InvokeMethod("Win32Shutdown", inParams, null);
}

This method gives me a run-time errors with System.Management telling me
"Privilege not held."

This next attempt, called from the click method, fails with a run-time
error
saying "Invalid Method Parameter(s)".

ManagementClass os = new ManagementClass("Win32_OperatingSystem");
os.Scope.Options.EnablePrivileges = true; // enables required security
privilege.
os.Get();
ManagementBaseObject inParams = os.GetMethodParameters("Reboot");
ManagementBaseObject outParams = os.InvokeMethod("Reboot", inParams,
null);

What am I doing wrong? I have .NET 1.1 on my system.

This is confirmed to be a known problem with v1.1 SP1 (and v1.0 SP3), check
[1] for a reply from MSFT on microsoft.public.dotnet.framework. for the same
issue.

Subject: PrivilegeNotHeld, .Net 1.1 sp1 bug, hotfix
Date: April 24, 2005

Willy.
 
G

Guest

Willy,

Is there any type of work-around? I am writing test code and would like to
call WMI methods as part of my test functionality.
--
Steve


Willy Denoyette said:
Steve Teeples said:
I am trying to use WMI to reboot my system. I have admin privileges. I've
tried two different solutions but both fail for separate reasons.

private void button1_Click(object sender, System.EventArgs e)
{
ManagementBaseObject outParams = null;
ManagementClass os = new ManagementClass("Win32_OperatingSystem");

os.Scope.Options.EnablePrivileges = true; // enables required security
privilege.
os.Get();
ManagementBaseObject inParams = os.GetMethodParameters("Win32Shutdown");
inParams["Flags"] = "2"; // System forced reboot
inParams["Reserved"] = "0";
foreach (ManagementObject mo in os.GetInstances())
outParams = mo.InvokeMethod("Win32Shutdown", inParams, null);
}

This method gives me a run-time errors with System.Management telling me
"Privilege not held."

This next attempt, called from the click method, fails with a run-time
error
saying "Invalid Method Parameter(s)".

ManagementClass os = new ManagementClass("Win32_OperatingSystem");
os.Scope.Options.EnablePrivileges = true; // enables required security
privilege.
os.Get();
ManagementBaseObject inParams = os.GetMethodParameters("Reboot");
ManagementBaseObject outParams = os.InvokeMethod("Reboot", inParams,
null);

What am I doing wrong? I have .NET 1.1 on my system.

This is confirmed to be a known problem with v1.1 SP1 (and v1.0 SP3), check
[1] for a reply from MSFT on microsoft.public.dotnet.framework. for the same
issue.

Subject: PrivilegeNotHeld, .Net 1.1 sp1 bug, hotfix
Date: April 24, 2005

Willy.
 
G

Guest

CSharper,

Thanks for the lead. Given the issue with 1.1 and WMI I implemented your
suggested. It does work wonderfully. However, unfortunately, this only
addresses the issue of powering the system. I still need to be able to
implement calls to WMI methods generically for my test tools to function as
expected. Any suggestions?
--
Steve


CSharper said:
I'd suggest going with Mentalis.org's solution. I've used it in a production
environment, and it works like a charm.
You can find it here:

http://www.mentalis.org/soft/class.qpx?id=7

Hope this helps,

Dan Cox

Steve Teeples said:
I am trying to use WMI to reboot my system. I have admin privileges. I've
tried two different solutions but both fail for separate reasons.

private void button1_Click(object sender, System.EventArgs e)
{
ManagementBaseObject outParams = null;
ManagementClass os = new ManagementClass("Win32_OperatingSystem");

os.Scope.Options.EnablePrivileges = true; // enables required security
privilege.
os.Get();
ManagementBaseObject inParams = os.GetMethodParameters("Win32Shutdown");
inParams["Flags"] = "2"; // System forced reboot
inParams["Reserved"] = "0";
foreach (ManagementObject mo in os.GetInstances())
outParams = mo.InvokeMethod("Win32Shutdown", inParams, null);
}

This method gives me a run-time errors with System.Management telling me
"Privilege not held."

This next attempt, called from the click method, fails with a run-time
error
saying "Invalid Method Parameter(s)".

ManagementClass os = new ManagementClass("Win32_OperatingSystem");
os.Scope.Options.EnablePrivileges = true; // enables required security
privilege.
os.Get();
ManagementBaseObject inParams = os.GetMethodParameters("Reboot");
ManagementBaseObject outParams = os.InvokeMethod("Reboot", inParams,
null);

What am I doing wrong? I have .NET 1.1 on my system.
 
G

Guest

Willy, I read the article you pointed me to. It seems that the hotfix is
language specific. Is that true? If so, I deal with over 26 languages and
would need a hot fix for each. Any suggestions of how I should proceed?
--
Steve


Willy Denoyette said:
Steve Teeples said:
I am trying to use WMI to reboot my system. I have admin privileges. I've
tried two different solutions but both fail for separate reasons.

private void button1_Click(object sender, System.EventArgs e)
{
ManagementBaseObject outParams = null;
ManagementClass os = new ManagementClass("Win32_OperatingSystem");

os.Scope.Options.EnablePrivileges = true; // enables required security
privilege.
os.Get();
ManagementBaseObject inParams = os.GetMethodParameters("Win32Shutdown");
inParams["Flags"] = "2"; // System forced reboot
inParams["Reserved"] = "0";
foreach (ManagementObject mo in os.GetInstances())
outParams = mo.InvokeMethod("Win32Shutdown", inParams, null);
}

This method gives me a run-time errors with System.Management telling me
"Privilege not held."

This next attempt, called from the click method, fails with a run-time
error
saying "Invalid Method Parameter(s)".

ManagementClass os = new ManagementClass("Win32_OperatingSystem");
os.Scope.Options.EnablePrivileges = true; // enables required security
privilege.
os.Get();
ManagementBaseObject inParams = os.GetMethodParameters("Reboot");
ManagementBaseObject outParams = os.InvokeMethod("Reboot", inParams,
null);

What am I doing wrong? I have .NET 1.1 on my system.

This is confirmed to be a known problem with v1.1 SP1 (and v1.0 SP3), check
[1] for a reply from MSFT on microsoft.public.dotnet.framework. for the same
issue.

Subject: PrivilegeNotHeld, .Net 1.1 sp1 bug, hotfix
Date: April 24, 2005

Willy.
 
W

Willy Denoyette [MVP]

Steve Teeples said:
Willy, I read the article you pointed me to. It seems that the hotfix is
language specific. Is that true? If so, I deal with over 26 languages
and
would need a hot fix for each. Any suggestions of how I should proceed?
--
Steve


"Willy Denoyette [MVP]" wrote:

The article is suggest that hotfixes can be language specific, that is why
MSFT doesn't make hotfixes publicly available, but in this particular case
there isn't a language issue.

However, if you don't like to contact PSS, here are some work-around:

1. Enable the privilege required yourself in code using PInvoke. Following
class should give you a head start....

public sealed class TokenAdjuster
{
// PInvoke stuff required to set/enable security privileges
[DllImport("advapi32", SetLastError=true),
SuppressUnmanagedCodeSecurityAttribute]
static extern int OpenProcessToken(
System.IntPtr ProcessHandle, // handle to process
int DesiredAccess, // desired access to process
ref IntPtr TokenHandle // handle to open access token
);

[DllImport("kernel32", SetLastError=true),
SuppressUnmanagedCodeSecurityAttribute]
static extern bool CloseHandle(IntPtr handle);

[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
static extern int AdjustTokenPrivileges(
IntPtr TokenHandle,
int DisableAllPrivileges,
IntPtr NewState,
int BufferLength,
IntPtr PreviousState,
ref int ReturnLength);

[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
static extern bool LookupPrivilegeValue(
string lpSystemName,
string lpName,
ref LUID lpLuid);

[StructLayout(LayoutKind.Sequential)]
internal struct LUID {
internal int LowPart;
internal int HighPart;
}

[StructLayout(LayoutKind.Sequential)]
struct LUID_AND_ATTRIBUTES {
LUID Luid;
int Attributes;
}

[StructLayout(LayoutKind.Sequential)]
struct _PRIVILEGE_SET {
int PrivilegeCount;
int Control;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=1)] // ANYSIZE_ARRAY = 1
LUID_AND_ATTRIBUTES [] Privileges;
}

[StructLayout(LayoutKind.Sequential)]
internal struct TOKEN_PRIVILEGES
{
internal int PrivilegeCount;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=3)]
internal int[] Privileges;
}
const int SE_PRIVILEGE_ENABLED = 0x00000002;
const int TOKEN_ADJUST_PRIVILEGES = 0X00000020;
const int TOKEN_QUERY = 0X00000008;
const int TOKEN_ALL_ACCESS = 0X001f01ff;
const int PROCESS_QUERY_INFORMATION = 0X00000400;

public static bool EnablePrivilege (string lpszPrivilege, bool
bEnablePrivilege )
{
bool retval = false;
int ltkpOld = 0;
IntPtr hToken = IntPtr.Zero;
TOKEN_PRIVILEGES tkp = new TOKEN_PRIVILEGES();
tkp.Privileges = new int[3];
TOKEN_PRIVILEGES tkpOld = new TOKEN_PRIVILEGES();
tkpOld.Privileges = new int[3];
LUID tLUID = new LUID();
tkp.PrivilegeCount = 1;
if (bEnablePrivilege)
tkp.Privileges[2] = SE_PRIVILEGE_ENABLED;
else
tkp.Privileges[2] = 0;
if(LookupPrivilegeValue(null , lpszPrivilege , ref tLUID))
{
Process proc = Process.GetCurrentProcess();
if(proc.Handle != IntPtr.Zero) {
if (OpenProcessToken(proc.Handle, TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,
ref hToken) != 0) {
tkp.PrivilegeCount = 1;
tkp.Privileges[2] = SE_PRIVILEGE_ENABLED;
tkp.Privileges[1] = tLUID.HighPart;
tkp.Privileges[0] = tLUID.LowPart;
const int bufLength = 256;
IntPtr tu = Marshal.AllocHGlobal( bufLength );
Marshal.StructureToPtr(tkp, tu, true);
if(AdjustTokenPrivileges(hToken, 0, tu, bufLength, IntPtr.Zero, ref
ltkpOld) != 0)
{
// successful AdjustTokenPrivileges doesn't mean privilege could be
changed
if (Marshal.GetLastWin32Error() == 0)
{
retval = true; // Token changed
}
}
TOKEN_PRIVILEGES tokp = (TOKEN_PRIVILEGES) Marshal.PtrToStructure(tu,
typeof(TOKEN_PRIVILEGES) );
Marshal.FreeHGlobal( tu );
}
}
}
if (hToken != IntPtr.Zero)
{
CloseHandle(hToken);
}
return retval;
}

Usage:

ManagementObject mo = new ManagementObject(path);
// Enable shutdown privilege
if(!TokenAdjuster.EnablePrivilege("SeShutdownPrivilege", true))
// Could not enable privilege
..
else
// Go on and invoke your method.


2. take Wminet_utils.dll from a pre SP1 framework.

Willy.
 
G

Guest

Option 2 definately looks the simplest! Thanks. Do you know an approximate
timeframe when .NET Frameworks 2.0 is to be released?
--
Steve


Willy Denoyette said:
Steve Teeples said:
Willy, I read the article you pointed me to. It seems that the hotfix is
language specific. Is that true? If so, I deal with over 26 languages
and
would need a hot fix for each. Any suggestions of how I should proceed?
--
Steve


"Willy Denoyette [MVP]" wrote:

The article is suggest that hotfixes can be language specific, that is why
MSFT doesn't make hotfixes publicly available, but in this particular case
there isn't a language issue.

However, if you don't like to contact PSS, here are some work-around:

1. Enable the privilege required yourself in code using PInvoke. Following
class should give you a head start....

public sealed class TokenAdjuster
{
// PInvoke stuff required to set/enable security privileges
[DllImport("advapi32", SetLastError=true),
SuppressUnmanagedCodeSecurityAttribute]
static extern int OpenProcessToken(
System.IntPtr ProcessHandle, // handle to process
int DesiredAccess, // desired access to process
ref IntPtr TokenHandle // handle to open access token
);

[DllImport("kernel32", SetLastError=true),
SuppressUnmanagedCodeSecurityAttribute]
static extern bool CloseHandle(IntPtr handle);

[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
static extern int AdjustTokenPrivileges(
IntPtr TokenHandle,
int DisableAllPrivileges,
IntPtr NewState,
int BufferLength,
IntPtr PreviousState,
ref int ReturnLength);

[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
static extern bool LookupPrivilegeValue(
string lpSystemName,
string lpName,
ref LUID lpLuid);

[StructLayout(LayoutKind.Sequential)]
internal struct LUID {
internal int LowPart;
internal int HighPart;
}

[StructLayout(LayoutKind.Sequential)]
struct LUID_AND_ATTRIBUTES {
LUID Luid;
int Attributes;
}

[StructLayout(LayoutKind.Sequential)]
struct _PRIVILEGE_SET {
int PrivilegeCount;
int Control;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=1)] // ANYSIZE_ARRAY = 1
LUID_AND_ATTRIBUTES [] Privileges;
}

[StructLayout(LayoutKind.Sequential)]
internal struct TOKEN_PRIVILEGES
{
internal int PrivilegeCount;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=3)]
internal int[] Privileges;
}
const int SE_PRIVILEGE_ENABLED = 0x00000002;
const int TOKEN_ADJUST_PRIVILEGES = 0X00000020;
const int TOKEN_QUERY = 0X00000008;
const int TOKEN_ALL_ACCESS = 0X001f01ff;
const int PROCESS_QUERY_INFORMATION = 0X00000400;

public static bool EnablePrivilege (string lpszPrivilege, bool
bEnablePrivilege )
{
bool retval = false;
int ltkpOld = 0;
IntPtr hToken = IntPtr.Zero;
TOKEN_PRIVILEGES tkp = new TOKEN_PRIVILEGES();
tkp.Privileges = new int[3];
TOKEN_PRIVILEGES tkpOld = new TOKEN_PRIVILEGES();
tkpOld.Privileges = new int[3];
LUID tLUID = new LUID();
tkp.PrivilegeCount = 1;
if (bEnablePrivilege)
tkp.Privileges[2] = SE_PRIVILEGE_ENABLED;
else
tkp.Privileges[2] = 0;
if(LookupPrivilegeValue(null , lpszPrivilege , ref tLUID))
{
Process proc = Process.GetCurrentProcess();
if(proc.Handle != IntPtr.Zero) {
if (OpenProcessToken(proc.Handle, TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,
ref hToken) != 0) {
tkp.PrivilegeCount = 1;
tkp.Privileges[2] = SE_PRIVILEGE_ENABLED;
tkp.Privileges[1] = tLUID.HighPart;
tkp.Privileges[0] = tLUID.LowPart;
const int bufLength = 256;
IntPtr tu = Marshal.AllocHGlobal( bufLength );
Marshal.StructureToPtr(tkp, tu, true);
if(AdjustTokenPrivileges(hToken, 0, tu, bufLength, IntPtr.Zero, ref
ltkpOld) != 0)
{
// successful AdjustTokenPrivileges doesn't mean privilege could be
changed
if (Marshal.GetLastWin32Error() == 0)
{
retval = true; // Token changed
}
}
TOKEN_PRIVILEGES tokp = (TOKEN_PRIVILEGES) Marshal.PtrToStructure(tu,
typeof(TOKEN_PRIVILEGES) );
Marshal.FreeHGlobal( tu );
}
}
}
if (hToken != IntPtr.Zero)
{
CloseHandle(hToken);
}
return retval;
}

Usage:

ManagementObject mo = new ManagementObject(path);
// Enable shutdown privilege
if(!TokenAdjuster.EnablePrivilege("SeShutdownPrivilege", true))
// Could not enable privilege
..
else
// Go on and invoke your method.


2. take Wminet_utils.dll from a pre SP1 framework.

Willy.
 
W

Willy Denoyette [MVP]

Steve Teeples said:
Option 2 definately looks the simplest! Thanks. Do you know an
approximate
timeframe when .NET Frameworks 2.0 is to be released?

Not really, my best guess is a RC by mid September (PDC 2005) and RTM a few
months later.

Willy.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top