Witam,
Walczę z MetroUI. Ponieważ, jak wielu, nie mogę się przyzwyczaić do nowego sposobu wyłączania Windows 8, postanowiłem napisać sobie program dla Metro, który po włączeniu będzie miał trzy przyciski: "Wyłącz", "Restartuj", "Uśpij". W życiu nie podejrzewałem, że będzie to takie trudne...
Z powodu wszelakich ograniczeń jakie M$ zastosował do metro (paranoja...) stwierdziłem, że aby tego dokonać najłatwiej będzie zrobić nową zwykłą C#-ową DLL, która będzie wywoływać ExitWindowsEx i wywołać ją z aplikacji Metro.
Dowiedziawszy się, że nie może to być po prostu dołączona nowa referencja, a musi być to DLL załączony do projektu, z właściwością Build Action: Content i potem jakoś magicznie wywołany, po kolejnym namyśle stwierdziłem, że najłatwiej będzie zastosować reflection (wtedy jeszcze nie wiedziałem, że zaszły tam takie zmiany...).
Do sedna - spłodziłem genialną DLL:
public static class Library
{
[DllImport("User32.dll")]
public static extern int ExitWindowsEx(int uFlags, int dwReason);
[DllImport("Kernel32.dll")]
public static extern int GetLastError();
public static string MsgBox()
{
return "Dupa";
}
public static int TurnOff()
{
return ExitWindowsEx(2, 0);
}
public static int Error()
{
return GetLastError();
}
}
Jej wywołanie w Metro wygląda następująco:
AssemblyName name = new AssemblyName("TurnOffLibrary");
Assembly ass = Assembly.Load(name);
TypeInfo ti = ass.DefinedTypes.ElementAt(0);
MethodInfo msgbox = ti.GetDeclaredMethod("MsgBox");
object dupa = msgbox.Invoke(ti, null);
if (dupa is string)
{
pageTitle.Text = (dupa as string);
}
MethodInfo turnoff = ti.GetDeclaredMethod("TurnOff");
int return1 = (int)turnoff.Invoke(ti, null);
MethodInfo error = ti.GetDeclaredMethod("Error");
int return2 = (int)error.Invoke(ti, null);
I teraz:
return1 posiada wartość 0 (słownie: zero)
return2 posiada wartość 5 (słownie: pięć) - Access Denied
pageTitle otrzymuje napis "Dupa" bez problemu, więc DLL się wykonuje, ale nie ma żadnej reakcji na ExitWindowsEx. Mogę ją wywoływać z różnymi parametrami i nic się nie stanie.
Przed napisaniem tej library próbowałem bezpośredniego Invoka w MetroApp bez używania zew. DLL, ale efekt był ten sam. Po prostu to wygląda tak jak by M$ się zawziął i wyciął wszelkie sposoby na wyłączenie Windows z menu start... pfuuuu z MetroUI.
Czy da się to zrobić jakoś inaczej?