【发布时间】:2016-07-11 15:18:46
【问题描述】:
我正在编写一个具有远程管理功能的程序,但遇到了一些问题。主要问题是,每次调用“OpenWindowStation”都会导致“错误 183”和空指针。
此代码在 LocalSystem 帐户上作为服务运行。我也尝试过允许桌面交互,但所有这些都是徒劳的。
我在这里查看了几个类似的问题,但他们的任何决定都没有帮助我。
namespace sasserv
{
public class sasserv : ServiceBase
{
[DllImport("User32.dll", CharSet=CharSet.Auto, SetLastError=true)]
static extern IntPtr OpenWindowStation( string name, bool fInherit, uint needAccess );
[DllImport("User32.dll", CharSet=CharSet.Auto, SetLastError=true)]
static extern IntPtr CloseWindowStation( IntPtr hWinSta );
[DllImport("User32.dll", CharSet=CharSet.Auto, SetLastError=true)]
static extern IntPtr OpenDesktop( string name, Int32 flags, bool fInherit, long param );
[DllImport("User32.dll", CharSet=CharSet.Auto, SetLastError=true)]
static extern IntPtr CloseDesktop( IntPtr hDesktop );
[DllImport("User32.dll", CharSet=CharSet.Auto, SetLastError=true)]
static extern bool PostMessage( IntPtr hWnd, UInt32 msg, UInt32 wParam, IntPtr lParam );
[DllImport("User32.dll", CharSet=CharSet.Auto, SetLastError=true)]
static extern bool SetThreadDesktop( IntPtr hDesktop );
[DllImport("User32.dll", CharSet=CharSet.Auto, SetLastError=true)]
static extern bool SetProcessWindowStation( IntPtr hWinSta );
public const string MyServiceName = "sasserv";
public sasserv()
{
InitializeComponent();
}
private void InitializeComponent()
{
this.ServiceName = MyServiceName;
}
/// <summary>
/// Start this service.
/// </summary>
protected override void OnStart(string[] args)
{
RunWinlogon();
}
/// <summary>
/// Stop this service.
/// </summary>
protected override void OnStop()
{
}
protected void OutputLastError(string funcName) {
int err = Marshal.GetLastWin32Error();
if ( err > 0 )
Out(funcName, "ERR:"+err);
}
private void RunWinlogon()
{
int WINSTA_ALL_ACCESS = 0x37F;
long DESKTOP_CREATEMENU = 0x0004L;
long DESKTOP_CREATEWINDOW = 0x0002L;
long DESKTOP_ENUMERATE = 0x0040L;
long DESKTOP_HOOKCONTROL = 0x0008L;
long DESKTOP_JOURNALPLAYBACK = 0x0020L;
long DESKTOP_JOURNALRECORD = 0x0010L;
long DESKTOP_READOBJECTS = 0x0001L;
long DESKTOP_SWITCHDESKTOP = 0x0100L;
long DESKTOP_WRITEOBJECTS = 0x0080L;
int HWND_BROADCAST = 0xffff;
uint WM_HOTKEY = 0x0312;
short MOD_ALT = 0x0001;
short MOD_CONTROL = 0x0002;
short VK_DELETE = 0x2E;
uint MAXIMUM_ALLOWED = 0x2000000;
uint WLX_WM_SAS = 0x0659;
uint WLX_SAS_TYPE_CTRL_ALT_DEL = 0x0001;
uint GENERIC_READ = 0x80000000;
uint GENERIC_WRITE = 0x40000000;
uint GENERIC_EXECUTE = 0x20000000;
uint GENERIC_ALL = 0x10000000;
uint GENERIC_RIGHTS_CHK = 0xF0000000;
Out("OpenWindowStation", "Running2");
var hWinSta = OpenWindowStation( "WinSta0", false, MAXIMUM_ALLOWED );
if ( hWinSta == IntPtr.Zero ) {
Out("OpenWindowStation", "hWinSta=ZERO");
return;
}
OutputLastError("OpenWindowStation");
Out("SetProcessWindowStation", "Running");
if ( !SetProcessWindowStation( hWinSta ) ) {
Out("SetProcessWindowStation", "FALSE");
return;
}
OutputLastError("SetProcessWindowStation");
Out("OpenDesktop", "Running");
var hDesk = OpenDesktop( "Winlogon", 0, false, MAXIMUM_ALLOWED);
OutputLastError("OpenDesktop");
if ( hDesk == IntPtr.Zero ) {
Out("OpenDesktop", "HDESK=ZERO");
return;
}
if ( !SetThreadDesktop(hDesk) ) {
Out("SetThreadDesktop", "FALSE");
return;
}
OutputLastError("SetThreadDesktop");
Out("PostMessage", "Running...");
var postSucc = PostMessage( new IntPtr(HWND_BROADCAST),
WLX_WM_SAS,
WLX_SAS_TYPE_CTRL_ALT_DEL,
IntPtr.Zero);
OutputLastError("PostMessage");
CloseDesktop( hDesk );
CloseWindowStation( hWinSta );
}
static IntPtr MakeLongPtr( short wLow, short wHigh ) {
return new IntPtr( (UInt32)(wLow | ( (UInt32)wHigh << 16 )));
}
static void Out( string func, string info ) {
NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
logger.Info( "FUNC: "+func+" . INFO: "+info );
}
}
}
这是执行日志:
这是执行日志: 12.07.2016 10:29:47.3526|sasserv|FUNC: 打开窗口站。信息:正在运行2 12.07.2016 10:29:47.3646|sasserv|FUNC: SetProcessWindowStation 。信息:正在运行 12.07.2016 10:29:47.3646|sasserv|FUNC: SetProcessWindowStation 。信息:错误:183 12.07.2016 10:29:47.3746|sasserv|FUNC: OpenDesktop 。信息:正在运行 12.07.2016 10:29:47.3746|sasserv|FUNC: OpenDesktop 。信息:错误:183 12.07.2016 10:29:47.4025|sasserv|FUNC: SetThreadDesktop 。信息:错误:183 12.07.2016 10:29:47.4065|sasserv|FUNC: PostMessage 。信息:正在运行... 12.07.2016 10:29:47.4065|sasserv|FUNC: PostMessage 。信息:错误:87
【问题讨论】:
-
您的错误报告已损坏。您不能以这种方式调用
GetLastError,因为 .net 运行时调用 Win32 API 函数。在DllImport属性中使用SetLastError = true,然后调用Marshal.GetLastWin32Error()。 -
谢谢,大卫!我提供了您的更正,但主要问题仍然存在!
-
所以,这个问题还没有决定。因此,我决定使用 ExitWindowsEx 函数(临时)来更改用户(通过注销)。
-
当然,这也是一个很奇怪的决定,但对于第一个版本来说已经足够了。