Using API to shutdown a PC

  • Thread starter Thread starter Peter Duniho
  • Start date Start date
P

Peter Duniho

greatbarrier86 said:
Sorry. i am somewhat of a noob...how do i figure that out?

Well, one way would be to set a breakpoint on the line of code inside
the method, then run your program and click the button.

If it's hooked up correctly, you'll hit the breakpoint.

IMHO, almost every line of code you write, you should step through it in
the debugger at least once. But especially if the code doesn't seem to
be working, the very first step would be to use the debugger to see if
it's being executed at all, and if it is, whether the code is doing what
you think (including returning the value you think it should).

Only once you have confirmed all of that should you worry about what
else might be wrong.

If you don't hit the breakpoint, then one way to ensure that it's hooked
up correctly would be to, in the VS designer, go to your form with the
button, select the button, then click on the lightning-bolt icon in the
properties window to display the events. Find the Click event and see
if that method is listed as the assigned handler.

If it's not, you should be able to click on the arrow in the field, find
the method you wrote, and select it as the handler.

Pete
 
I've already got the code written but for some reason, when i click the
button, nothing occurs. Here is the code.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

[DllImport("advapi32.dll",EntryPoint="InitiateSystemShutdown")]
public static extern bool InitiateSystemShutdownA(string
lpMachineName, string lpMessage, int dwTimeout, int bForceAppsClosed, int
bRebootAfterShutdown);

private void button1_Click(object sender, System.EventArgs e)
{
InitiateSystemShutdownA(null,null, 30, 1, 1);
}

It compiles fine, but when i click button1, nothing happens. Any ideas?
 
Hello greatbarrier86,

Is your Button1 linked to OnClick event handler?

---
WBR,
Michael Nemtsev [.NET/C# MVP] :: blog: http://spaces.live.com/laflour

"The greatest danger for most of us is not that our aim is too high and we
miss it, but that it is too low and we reach it" (c) Michelangelo


g> I've already got the code written but for some reason, when i click
g> the button, nothing occurs. Here is the code.
g>
g> using System;
g> using System.Collections.Generic;
g> using System.ComponentModel;
g> using System.Data;
g> using System.Drawing;
g> using System.Text;
g> using System.Windows.Forms;
g> using System.Runtime.InteropServices;
g> [DllImport("advapi32.dll",EntryPoint="InitiateSystemShutdown")]
g> public static extern bool InitiateSystemShutdownA(string
g> lpMachineName, string lpMessage, int dwTimeout, int bForceAppsClosed,
g> int
g> bRebootAfterShutdown);
g>
g> private void button1_Click(object sender, System.EventArgs e)
g> {
g> InitiateSystemShutdownA(null,null, 30, 1, 1);
g> }
g> It compiles fine, but when i click button1, nothing happens. Any
g> ideas?
g>
 
greatbarrier86 said:
I've already got the code written but for some reason, when i click the
button, nothing occurs. Here is the code.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

[DllImport("advapi32.dll",EntryPoint="InitiateSystemShutdown")]
public static extern bool InitiateSystemShutdownA(string
lpMachineName, string lpMessage, int dwTimeout, int bForceAppsClosed, int
bRebootAfterShutdown);

private void button1_Click(object sender, System.EventArgs e)
{
InitiateSystemShutdownA(null,null, 30, 1, 1);
}

It compiles fine, but when i click button1, nothing happens. Any ideas?



How do you know the call succeeded when you don't check the return value of
the API call?

Willy.
 
Heh...like i said, i'm a noob :)

How do i check the return value?



Willy Denoyette said:
greatbarrier86 said:
I've already got the code written but for some reason, when i click the
button, nothing occurs. Here is the code.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

[DllImport("advapi32.dll",EntryPoint="InitiateSystemShutdown")]
public static extern bool InitiateSystemShutdownA(string
lpMachineName, string lpMessage, int dwTimeout, int bForceAppsClosed, int
bRebootAfterShutdown);

private void button1_Click(object sender, System.EventArgs e)
{
InitiateSystemShutdownA(null,null, 30, 1, 1);
}

It compiles fine, but when i click button1, nothing happens. Any ideas?



How do you know the call succeeded when you don't check the return value of
the API call?

Willy.
 
1) Change the DllImport declaration such that it returns an int value like:
public static extern int InitiateSystemShutdownA(string....

assign the return value to a variable like this:
int ret = InitiateSystemShutdownA(null,null, 30, 1, 1);

2) Make sure the GetLastError returns something meaningful, by setting the
SetLastError to true.
[DllImport("advapi32.dll",EntryPoint="InitiateSystemShutdown",SetLastError=true)]

3) Check what "InitiateSystemShutdown" can possibly return (in MSDN) and
take appropriate actions when the return is an error value.

if(ret == 0)
{
// Failed, most (but not all) Win32 API's return 0 on failure
// Call Marshall.GetLastWin32Error to get the Win32 error code
}
else
// success.

Note that your code will most probably return error code 5, which means
"Access Denied". The reason for this is that you need to enable the
SE_SHUTDOWN_NAME privileges. This again has to be done using native API
calls as this is not covered by the Framework classes.

That said, calling into Win32 through PInvoke is not something you should
start without reading the API description in the docs.

Willy.




greatbarrier86 said:
Heh...like i said, i'm a noob :)

How do i check the return value?



Willy Denoyette said:
message
I've already got the code written but for some reason, when i click the
button, nothing occurs. Here is the code.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

[DllImport("advapi32.dll",EntryPoint="InitiateSystemShutdown")]
public static extern bool InitiateSystemShutdownA(string
lpMachineName, string lpMessage, int dwTimeout, int bForceAppsClosed,
int
bRebootAfterShutdown);

private void button1_Click(object sender, System.EventArgs e)
{
InitiateSystemShutdownA(null,null, 30, 1, 1);
}

It compiles fine, but when i click button1, nothing happens. Any ideas?



How do you know the call succeeded when you don't check the return value
of
the API call?

Willy.
 
Willy,

Thank you for all your help. It turned out that it failed. Can you explain
to me a little more about the SE_SHUTDOWN_NAME privilege? Or at least how to
give that thread that privilege?

Willy Denoyette said:
1) Change the DllImport declaration such that it returns an int value like:
public static extern int InitiateSystemShutdownA(string....

assign the return value to a variable like this:
int ret = InitiateSystemShutdownA(null,null, 30, 1, 1);

2) Make sure the GetLastError returns something meaningful, by setting the
SetLastError to true.
[DllImport("advapi32.dll",EntryPoint="InitiateSystemShutdown",SetLastError=true)]

3) Check what "InitiateSystemShutdown" can possibly return (in MSDN) and
take appropriate actions when the return is an error value.

if(ret == 0)
{
// Failed, most (but not all) Win32 API's return 0 on failure
// Call Marshall.GetLastWin32Error to get the Win32 error code
}
else
// success.

Note that your code will most probably return error code 5, which means
"Access Denied". The reason for this is that you need to enable the
SE_SHUTDOWN_NAME privileges. This again has to be done using native API
calls as this is not covered by the Framework classes.

That said, calling into Win32 through PInvoke is not something you should
start without reading the API description in the docs.

Willy.




greatbarrier86 said:
Heh...like i said, i'm a noob :)

How do i check the return value?



Willy Denoyette said:
message
I've already got the code written but for some reason, when i click the
button, nothing occurs. Here is the code.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

[DllImport("advapi32.dll",EntryPoint="InitiateSystemShutdown")]
public static extern bool InitiateSystemShutdownA(string
lpMachineName, string lpMessage, int dwTimeout, int bForceAppsClosed,
int
bRebootAfterShutdown);

private void button1_Click(object sender, System.EventArgs e)
{
InitiateSystemShutdownA(null,null, 30, 1, 1);
}

It compiles fine, but when i click button1, nothing happens. Any ideas?



How do you know the call succeeded when you don't check the return value
of
the API call?

Willy.
 
Willy, I used the GetLastWin32Error and it returned "The Parameter is
Incorrect." I'm a little confused.

Willy Denoyette said:
1) Change the DllImport declaration such that it returns an int value like:
public static extern int InitiateSystemShutdownA(string....

assign the return value to a variable like this:
int ret = InitiateSystemShutdownA(null,null, 30, 1, 1);

2) Make sure the GetLastError returns something meaningful, by setting the
SetLastError to true.
[DllImport("advapi32.dll",EntryPoint="InitiateSystemShutdown",SetLastError=true)]

3) Check what "InitiateSystemShutdown" can possibly return (in MSDN) and
take appropriate actions when the return is an error value.

if(ret == 0)
{
// Failed, most (but not all) Win32 API's return 0 on failure
// Call Marshall.GetLastWin32Error to get the Win32 error code
}
else
// success.

Note that your code will most probably return error code 5, which means
"Access Denied". The reason for this is that you need to enable the
SE_SHUTDOWN_NAME privileges. This again has to be done using native API
calls as this is not covered by the Framework classes.

That said, calling into Win32 through PInvoke is not something you should
start without reading the API description in the docs.

Willy.




greatbarrier86 said:
Heh...like i said, i'm a noob :)

How do i check the return value?



Willy Denoyette said:
message
I've already got the code written but for some reason, when i click the
button, nothing occurs. Here is the code.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

[DllImport("advapi32.dll",EntryPoint="InitiateSystemShutdown")]
public static extern bool InitiateSystemShutdownA(string
lpMachineName, string lpMessage, int dwTimeout, int bForceAppsClosed,
int
bRebootAfterShutdown);

private void button1_Click(object sender, System.EventArgs e)
{
InitiateSystemShutdownA(null,null, 30, 1, 1);
}

It compiles fine, but when i click button1, nothing happens. Any ideas?



How do you know the call succeeded when you don't check the return value
of
the API call?

Willy.
 
Should work, anyway herewith a complete sample illustrating how to enable
privileges and shutdown a system. Hope you take some time to understand the
details.

using System;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Security;
namespace Willys
{
sealed class Win32TokenPrivileges
{
internal const uint SE_PRIVILEGE_DISABLED = 0x00000000;
internal const uint SE_PRIVILEGE_ENABLED = 0x00000002;

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

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

[StructLayout(LayoutKind.Sequential)]
internal struct TOKEN_PRIVILEGE {
internal uint PrivilegeCount;
internal LUID_AND_ATTRIBUTES Privilege;
}

[DllImport("advapi32", CharSet = CharSet.Unicode, SetLastError = true),
SuppressUnmanagedCodeSecurity]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool LookupPrivilegeValue(string lpSystemName,
string lpName, [In, Out] ref LUID Luid);

[DllImport("advapi32", CharSet = CharSet.Unicode, SetLastError = true),
SuppressUnmanagedCodeSecurity]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool AdjustTokenPrivileges(IntPtr tokenHndl,
bool diasableAll, [In] ref TOKEN_PRIVILEGE newTokenState, int length,
ref TOKEN_PRIVILEGE prevTokenState, ref uint retLength);

[DllImport("advapi32.dll",EntryPoint="InitiateSystemShutdown", CharSet =
CharSet.Unicode, SetLastError = true), SuppressUnmanagedCodeSecurity]
[return: MarshalAs(UnmanagedType.Bool)] // Explicit marshaling
directive required here! (BOOL in Windows is a DWORD, bool in C# is a byte
value)
internal static extern bool InitiateSystemShutdown(string lpMachineName,
string lpMessage,
int dwTimeout,
[MarshalAs(UnmanagedType.Bool)] bool bForceAppsClosed,
[MarshalAs(UnmanagedType.Bool)] bool bRebootAfterShutdown);
}

sealed class Program
{
static void Main()
{
IntPtr tokenHandle = WindowsIdentity.GetCurrent().Token; // consider
using a safehandle here

Win32TokenPrivileges.LUID luid = new Win32TokenPrivileges.LUID();
bool ret = Win32TokenPrivileges.LookupPrivilegeValue ("",
"SeShutdownPrivilege", ref luid);
if(ret == true)
{
Win32TokenPrivileges.TOKEN_PRIVILEGE tokenPriv = new
Win32TokenPrivileges.TOKEN_PRIVILEGE();
Win32TokenPrivileges.TOKEN_PRIVILEGE prevToken = new
Win32TokenPrivileges.TOKEN_PRIVILEGE();
tokenPriv.PrivilegeCount = 1;
tokenPriv.Privilege.Luid = luid;
tokenPriv.Privilege.Attributes =
Win32TokenPrivileges.SE_PRIVILEGE_ENABLED;
uint retlen = 0;
ret = Win32TokenPrivileges.AdjustTokenPrivileges (tokenHandle, false,
ref tokenPriv, Marshal.SizeOf(tokenPriv), ref prevToken, ref retlen);
if(ret == false)
{
Console.WriteLine("AdjustTokenPrivileges error {0}",
Marshal.GetLastWin32Error());
Environment.Exit(1);
}

ret = Win32TokenPrivileges.InitiateSystemShutdown("", "System shutdown
requested .... ", 30, true, true);
if(ret == false)
{
Console.WriteLine("InitiateSystemShutdown error {0}",
Marshal.GetLastWin32Error());
Environment.Exit(1);
}
}
}
}
}


Willy.



greatbarrier86 said:
Willy, I used the GetLastWin32Error and it returned "The Parameter is
Incorrect." I'm a little confused.

Willy Denoyette said:
1) Change the DllImport declaration such that it returns an int value
like:
public static extern int InitiateSystemShutdownA(string....

assign the return value to a variable like this:
int ret = InitiateSystemShutdownA(null,null, 30, 1, 1);

2) Make sure the GetLastError returns something meaningful, by setting
the
SetLastError to true.
[DllImport("advapi32.dll",EntryPoint="InitiateSystemShutdown",SetLastError=true)]

3) Check what "InitiateSystemShutdown" can possibly return (in MSDN) and
take appropriate actions when the return is an error value.

if(ret == 0)
{
// Failed, most (but not all) Win32 API's return 0 on failure
// Call Marshall.GetLastWin32Error to get the Win32 error code
}
else
// success.

Note that your code will most probably return error code 5, which means
"Access Denied". The reason for this is that you need to enable the
SE_SHUTDOWN_NAME privileges. This again has to be done using native API
calls as this is not covered by the Framework classes.

That said, calling into Win32 through PInvoke is not something you should
start without reading the API description in the docs.

Willy.




message
Heh...like i said, i'm a noob :)

How do i check the return value?



:

message
I've already got the code written but for some reason, when i click
the
button, nothing occurs. Here is the code.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

[DllImport("advapi32.dll",EntryPoint="InitiateSystemShutdown")]
public static extern bool InitiateSystemShutdownA(string
lpMachineName, string lpMessage, int dwTimeout, int
bForceAppsClosed,
int
bRebootAfterShutdown);

private void button1_Click(object sender, System.EventArgs e)
{
InitiateSystemShutdownA(null,null, 30, 1, 1);
}

It compiles fine, but when i click button1, nothing happens. Any
ideas?



How do you know the call succeeded when you don't check the return
value
of
the API call?

Willy.
 
I appreciate it. I will indeed take time to understand this. What is this
called? i know that InitiateSystemShutdown is a Framework API but what is
this considered? I'd like to do some background reading on it so i dont have
trouble every time. I really appreciate your effort Willy. Much appreciated.

Willy Denoyette said:
Should work, anyway herewith a complete sample illustrating how to enable
privileges and shutdown a system. Hope you take some time to understand the
details.

using System;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Security;
namespace Willys
{
sealed class Win32TokenPrivileges
{
internal const uint SE_PRIVILEGE_DISABLED = 0x00000000;
internal const uint SE_PRIVILEGE_ENABLED = 0x00000002;

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

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

[StructLayout(LayoutKind.Sequential)]
internal struct TOKEN_PRIVILEGE {
internal uint PrivilegeCount;
internal LUID_AND_ATTRIBUTES Privilege;
}

[DllImport("advapi32", CharSet = CharSet.Unicode, SetLastError = true),
SuppressUnmanagedCodeSecurity]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool LookupPrivilegeValue(string lpSystemName,
string lpName, [In, Out] ref LUID Luid);

[DllImport("advapi32", CharSet = CharSet.Unicode, SetLastError = true),
SuppressUnmanagedCodeSecurity]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool AdjustTokenPrivileges(IntPtr tokenHndl,
bool diasableAll, [In] ref TOKEN_PRIVILEGE newTokenState, int length,
ref TOKEN_PRIVILEGE prevTokenState, ref uint retLength);

[DllImport("advapi32.dll",EntryPoint="InitiateSystemShutdown", CharSet =
CharSet.Unicode, SetLastError = true), SuppressUnmanagedCodeSecurity]
[return: MarshalAs(UnmanagedType.Bool)] // Explicit marshaling
directive required here! (BOOL in Windows is a DWORD, bool in C# is a byte
value)
internal static extern bool InitiateSystemShutdown(string lpMachineName,
string lpMessage,
int dwTimeout,
[MarshalAs(UnmanagedType.Bool)] bool bForceAppsClosed,
[MarshalAs(UnmanagedType.Bool)] bool bRebootAfterShutdown);
}

sealed class Program
{
static void Main()
{
IntPtr tokenHandle = WindowsIdentity.GetCurrent().Token; // consider
using a safehandle here

Win32TokenPrivileges.LUID luid = new Win32TokenPrivileges.LUID();
bool ret = Win32TokenPrivileges.LookupPrivilegeValue ("",
"SeShutdownPrivilege", ref luid);
if(ret == true)
{
Win32TokenPrivileges.TOKEN_PRIVILEGE tokenPriv = new
Win32TokenPrivileges.TOKEN_PRIVILEGE();
Win32TokenPrivileges.TOKEN_PRIVILEGE prevToken = new
Win32TokenPrivileges.TOKEN_PRIVILEGE();
tokenPriv.PrivilegeCount = 1;
tokenPriv.Privilege.Luid = luid;
tokenPriv.Privilege.Attributes =
Win32TokenPrivileges.SE_PRIVILEGE_ENABLED;
uint retlen = 0;
ret = Win32TokenPrivileges.AdjustTokenPrivileges (tokenHandle, false,
ref tokenPriv, Marshal.SizeOf(tokenPriv), ref prevToken, ref retlen);
if(ret == false)
{
Console.WriteLine("AdjustTokenPrivileges error {0}",
Marshal.GetLastWin32Error());
Environment.Exit(1);
}

ret = Win32TokenPrivileges.InitiateSystemShutdown("", "System shutdown
requested .... ", 30, true, true);
if(ret == false)
{
Console.WriteLine("InitiateSystemShutdown error {0}",
Marshal.GetLastWin32Error());
Environment.Exit(1);
}
}
}
}
}


Willy.



greatbarrier86 said:
Willy, I used the GetLastWin32Error and it returned "The Parameter is
Incorrect." I'm a little confused.

Willy Denoyette said:
1) Change the DllImport declaration such that it returns an int value
like:
public static extern int InitiateSystemShutdownA(string....

assign the return value to a variable like this:
int ret = InitiateSystemShutdownA(null,null, 30, 1, 1);

2) Make sure the GetLastError returns something meaningful, by setting
the
SetLastError to true.
[DllImport("advapi32.dll",EntryPoint="InitiateSystemShutdown",SetLastError=true)]

3) Check what "InitiateSystemShutdown" can possibly return (in MSDN) and
take appropriate actions when the return is an error value.

if(ret == 0)
{
// Failed, most (but not all) Win32 API's return 0 on failure
// Call Marshall.GetLastWin32Error to get the Win32 error code
}
else
// success.

Note that your code will most probably return error code 5, which means
"Access Denied". The reason for this is that you need to enable the
SE_SHUTDOWN_NAME privileges. This again has to be done using native API
calls as this is not covered by the Framework classes.

That said, calling into Win32 through PInvoke is not something you should
start without reading the API description in the docs.

Willy.




message
Heh...like i said, i'm a noob :)

How do i check the return value?



:

message
I've already got the code written but for some reason, when i click
the
button, nothing occurs. Here is the code.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

[DllImport("advapi32.dll",EntryPoint="InitiateSystemShutdown")]
public static extern bool InitiateSystemShutdownA(string
lpMachineName, string lpMessage, int dwTimeout, int
bForceAppsClosed,
int
bRebootAfterShutdown);

private void button1_Click(object sender, System.EventArgs e)
{
InitiateSystemShutdownA(null,null, 30, 1, 1);
}

It compiles fine, but when i click button1, nothing happens. Any
ideas?



How do you know the call succeeded when you don't check the return
value
of
the API call?

Willy.
 
Ooo..that's nice...thanks!!

Andrew P. said:
I haven't read the whole list of messages so I'm not sure if anyone
suggested that you use the System.Management assembly. Just yesterday I
wrote the code for this:
http://www.geekpedia.com/code36_Shut-down-system-using-Csharp.html

The reason your original code doesn't work is that it doesn't get the
required privileges. My code does that.

Let me know if you have questions.

Andrew

greatbarrier86 said:
I've already got the code written but for some reason, when i click the
button, nothing occurs. Here is the code.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

[DllImport("advapi32.dll",EntryPoint="InitiateSystemShutdown")]
public static extern bool InitiateSystemShutdownA(string
lpMachineName, string lpMessage, int dwTimeout, int bForceAppsClosed, int
bRebootAfterShutdown);

private void button1_Click(object sender, System.EventArgs e)
{
InitiateSystemShutdownA(null,null, 30, 1, 1);
}

It compiles fine, but when i click button1, nothing happens. Any ideas?
 
Andrew,
Sure this is a better way to shutdown or restart, the reason I didn't
mention System.Management is because it is not exactly what the
"InitiateSystemShutdown" is doing.
InitiateSystemShutdown allows:
1) the caller to abort the shutdown request (it's asynchronous),
2) the user to close the running applications and save the applications
state,
3) to specify a time-out before the actual shutdown takes places and,
4) specify a message to the user.

Note that WMI on Vista has the Win32_OperatingSystem Win32ShutdownTracker
method that has nearly the same functionality plus more.

Willy.



Andrew P. said:
I haven't read the whole list of messages so I'm not sure if anyone
suggested that you use the System.Management assembly. Just yesterday I
wrote the code for this:
http://www.geekpedia.com/code36_Shut-down-system-using-Csharp.html

The reason your original code doesn't work is that it doesn't get the
required privileges. My code does that.

Let me know if you have questions.

Andrew

greatbarrier86 said:
I've already got the code written but for some reason, when i click the
button, nothing occurs. Here is the code.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

[DllImport("advapi32.dll",EntryPoint="InitiateSystemShutdown")]
public static extern bool InitiateSystemShutdownA(string
lpMachineName, string lpMessage, int dwTimeout, int bForceAppsClosed, int
bRebootAfterShutdown);

private void button1_Click(object sender, System.EventArgs e)
{
InitiateSystemShutdownA(null,null, 30, 1, 1);
}

It compiles fine, but when i click button1, nothing happens. Any ideas?
 
"InitiateSystemShutdown" is not a Framework API, it's an exported Windows
DLL API , that is why you need to call it through PInvoke.
More detailed info can be found in MSDN
http://msdn2.microsoft.com/en-us/library/aa376873.aspx .
The same goes for PInvoke,
http://msdn2.microsoft.com/en-us/library/26thfadc(vs.71).aspx
However, I would suggest you (a newbie) to stay away from this a focus on
the Framework and the Language first.

Willy.


greatbarrier86 said:
I appreciate it. I will indeed take time to understand this. What is this
called? i know that InitiateSystemShutdown is a Framework API but what is
this considered? I'd like to do some background reading on it so i dont
have
trouble every time. I really appreciate your effort Willy. Much
appreciated.

Willy Denoyette said:
Should work, anyway herewith a complete sample illustrating how to enable
privileges and shutdown a system. Hope you take some time to understand
the
details.

using System;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Security;
namespace Willys
{
sealed class Win32TokenPrivileges
{
internal const uint SE_PRIVILEGE_DISABLED = 0x00000000;
internal const uint SE_PRIVILEGE_ENABLED = 0x00000002;

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

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

[StructLayout(LayoutKind.Sequential)]
internal struct TOKEN_PRIVILEGE {
internal uint PrivilegeCount;
internal LUID_AND_ATTRIBUTES Privilege;
}

[DllImport("advapi32", CharSet = CharSet.Unicode, SetLastError = true),
SuppressUnmanagedCodeSecurity]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool LookupPrivilegeValue(string lpSystemName,
string lpName, [In, Out] ref LUID Luid);

[DllImport("advapi32", CharSet = CharSet.Unicode, SetLastError = true),
SuppressUnmanagedCodeSecurity]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool AdjustTokenPrivileges(IntPtr tokenHndl,
bool diasableAll, [In] ref TOKEN_PRIVILEGE newTokenState, int length,
ref TOKEN_PRIVILEGE prevTokenState, ref uint retLength);

[DllImport("advapi32.dll",EntryPoint="InitiateSystemShutdown", CharSet
=
CharSet.Unicode, SetLastError = true), SuppressUnmanagedCodeSecurity]
[return: MarshalAs(UnmanagedType.Bool)] // Explicit marshaling
directive required here! (BOOL in Windows is a DWORD, bool in C# is a
byte
value)
internal static extern bool InitiateSystemShutdown(string
lpMachineName,
string lpMessage,
int dwTimeout,
[MarshalAs(UnmanagedType.Bool)] bool bForceAppsClosed,
[MarshalAs(UnmanagedType.Bool)] bool bRebootAfterShutdown);
}

sealed class Program
{
static void Main()
{
IntPtr tokenHandle = WindowsIdentity.GetCurrent().Token; // consider
using a safehandle here

Win32TokenPrivileges.LUID luid = new Win32TokenPrivileges.LUID();
bool ret = Win32TokenPrivileges.LookupPrivilegeValue ("",
"SeShutdownPrivilege", ref luid);
if(ret == true)
{
Win32TokenPrivileges.TOKEN_PRIVILEGE tokenPriv = new
Win32TokenPrivileges.TOKEN_PRIVILEGE();
Win32TokenPrivileges.TOKEN_PRIVILEGE prevToken = new
Win32TokenPrivileges.TOKEN_PRIVILEGE();
tokenPriv.PrivilegeCount = 1;
tokenPriv.Privilege.Luid = luid;
tokenPriv.Privilege.Attributes =
Win32TokenPrivileges.SE_PRIVILEGE_ENABLED;
uint retlen = 0;
ret = Win32TokenPrivileges.AdjustTokenPrivileges (tokenHandle, false,
ref tokenPriv, Marshal.SizeOf(tokenPriv), ref prevToken, ref retlen);
if(ret == false)
{
Console.WriteLine("AdjustTokenPrivileges error {0}",
Marshal.GetLastWin32Error());
Environment.Exit(1);
}

ret = Win32TokenPrivileges.InitiateSystemShutdown("", "System
shutdown
requested .... ", 30, true, true);
if(ret == false)
{
Console.WriteLine("InitiateSystemShutdown error {0}",
Marshal.GetLastWin32Error());
Environment.Exit(1);
}
}
}
}
}


Willy.



message
Willy, I used the GetLastWin32Error and it returned "The Parameter is
Incorrect." I'm a little confused.

:

1) Change the DllImport declaration such that it returns an int value
like:
public static extern int InitiateSystemShutdownA(string....

assign the return value to a variable like this:
int ret = InitiateSystemShutdownA(null,null, 30, 1, 1);

2) Make sure the GetLastError returns something meaningful, by setting
the
SetLastError to true.
[DllImport("advapi32.dll",EntryPoint="InitiateSystemShutdown",SetLastError=true)]

3) Check what "InitiateSystemShutdown" can possibly return (in MSDN)
and
take appropriate actions when the return is an error value.

if(ret == 0)
{
// Failed, most (but not all) Win32 API's return 0 on failure
// Call Marshall.GetLastWin32Error to get the Win32 error code
}
else
// success.

Note that your code will most probably return error code 5, which
means
"Access Denied". The reason for this is that you need to enable the
SE_SHUTDOWN_NAME privileges. This again has to be done using native
API
calls as this is not covered by the Framework classes.

That said, calling into Win32 through PInvoke is not something you
should
start without reading the API description in the docs.

Willy.




message
Heh...like i said, i'm a noob :)

How do i check the return value?



:

in
message
I've already got the code written but for some reason, when i
click
the
button, nothing occurs. Here is the code.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

[DllImport("advapi32.dll",EntryPoint="InitiateSystemShutdown")]
public static extern bool InitiateSystemShutdownA(string
lpMachineName, string lpMessage, int dwTimeout, int
bForceAppsClosed,
int
bRebootAfterShutdown);

private void button1_Click(object sender, System.EventArgs
e)
{
InitiateSystemShutdownA(null,null, 30, 1, 1);
}

It compiles fine, but when i click button1, nothing happens. Any
ideas?



How do you know the call succeeded when you don't check the return
value
of
the API call?

Willy.
 
Back
Top