Finalmente encontré this C++ code en CodeProject, que funciona bien cuando se inicia como Usuario del sistema. Por lo tanto, convertí el código en un dll y llamé a la función desde mi código.
Este es el código C++ (se puede utilizar la función ErrorExit ejemplo que utiliza GetLastError
de MSDN en caso de un problema ocurrió):
#include "windows.h"
#include <strsafe.h>
__declspec(dllexport) BOOL SimulateAltControlDel()
{
HDESK hdeskCurrent;
HDESK hdesk;
HWINSTA hwinstaCurrent;
HWINSTA hwinsta;
//
// Save the current Window station
//
hwinstaCurrent = GetProcessWindowStation();
if (hwinstaCurrent == NULL)
return FALSE;
//
// Save the current desktop
//
hdeskCurrent = GetThreadDesktop(GetCurrentThreadId());
if (hdeskCurrent == NULL)
return FALSE;
//
// Obtain a handle to WinSta0 - service must be running
// in the LocalSystem account
//
hwinsta = OpenWindowStation("winsta0", FALSE,
WINSTA_ACCESSCLIPBOARD |
WINSTA_ACCESSGLOBALATOMS |
WINSTA_CREATEDESKTOP |
WINSTA_ENUMDESKTOPS |
WINSTA_ENUMERATE |
WINSTA_EXITWINDOWS |
WINSTA_READATTRIBUTES |
WINSTA_READSCREEN |
WINSTA_WRITEATTRIBUTES);
if (hwinsta == NULL)
return FALSE;
//
// Set the windowstation to be winsta0
//
if (!SetProcessWindowStation(hwinsta))
return FALSE;
//
// Get the default desktop on winsta0
//
hdesk = OpenDesktop("Winlogon", 0, FALSE,
DESKTOP_CREATEMENU |
DESKTOP_CREATEWINDOW |
DESKTOP_ENUMERATE |
DESKTOP_HOOKCONTROL |
DESKTOP_JOURNALPLAYBACK |
DESKTOP_JOURNALRECORD |
DESKTOP_READOBJECTS |
DESKTOP_SWITCHDESKTOP |
DESKTOP_WRITEOBJECTS);
if (hdesk == NULL)
return FALSE;
//
// Set the desktop to be "default"
//
if (!SetThreadDesktop(hdesk))
return FALSE;
PostMessage(HWND_BROADCAST,WM_HOTKEY,0,MAKELPARAM(MOD_ALT|MOD_CONTROL,VK_DELETE));
//
// Reset the Window station and desktop
//
if (!SetProcessWindowStation(hwinstaCurrent))
return FALSE;
if (!SetThreadDesktop(hdeskCurrent))
return FALSE;
//
// Close the windowstation and desktop handles
//
if (!CloseWindowStation(hwinsta))
return FALSE;
if (!CloseDesktop(hdesk))
return FALSE;
return TRUE;
}
También es necesario agregar un archivo .def al proyecto para exportar la función correcta (el proyecto se denomina AltCtrlDelCpp) y decirle al enlazador que el archivo de definición del módulo es este archivo
;altctrldel.def
LIBRARY AltCtrlDelCpp
;CODE PRELOAD MOVEABLE DISCARDABLE
;DATA PRELOAD MOVEABLE
EXPORTS
SimulateAltControlDel
a continuación, en la solución de .NET, se agrega el DLL al proyecto, lo configura de modo que siempre se copia en el directorio de salida, y sólo tiene que utilizar DllImport importar la función:
C# Código
[DllImport(@"AltCtrlDelCpp.dll")]
static extern bool SimulateAltControlDel();
Código VB.NET
<DllImport("AltCtrlDelCpp.dll")> _
Private Function SimulateAltControlDel() As Boolean
En VB.NET, también necesita agregar el atributo al Sub principal:
<MTAThread()> _
Sub Main()
Luego solo tiene que llamar a la función SimulateAltControlDel
y listo. Tenga en cuenta que tuve este trabajo solo para las aplicaciones de consola , no funcionó en las aplicaciones de winform.
@mdmullinax: Técnicamente, no. Él pregunta cómo simular las llaves, no las atrapa. – mellamokb
my bad, comment removed – MikeM
¿Desea simular realmente las claves, o simplemente desea llamar al diálogo de seguridad estándar? Si esto último, puede invocar [el método 'WindowsSecurity'] (http://msdn.microsoft.com/en-us/library/windows/desktop/bb774126%28v=vs.85%29.aspx) en el objeto de envío de shell. –