首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >OpenWindowStation错误183 / error _EXISTS_EXISTS/

OpenWindowStation错误183 / error _EXISTS_EXISTS/
EN

Stack Overflow用户
提问于 2016-07-11 15:18:46
回答 1查看 1.1K关注 0票数 0

我正在编写一个具有远程管理功能的程序,但我仍然遇到了一些问题。主要问题是,每次调用“OpenWindowStation”都会导致'error 183‘和一个空指针。

此代码作为LocalSystem帐户上的服务运行。我也试图允许桌面交互,但所有这些都是徒劳的。

我在这里回顾了几个类似的问题,但他们的决定都没有帮助我。

代码语言:javascript
复制
    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: OpenWindowStation。信息: Running2 12.07.2016 10:29:47.3646\sasserv_FUNC: SetProcessWindowStation。信息:运行12.07.2016 10:29:47.3646\sasserv\FUNC: SetProcessWindowStation。信息:错误:18312.07.2016 10:29:47.3746\sasserv\FUNC: OpenDesktop。信息:运行12.07.2016 10:29:47.3746\sasserv\FUNC: OpenDesktop。信息:错误:18312.07.2016 10:29:47.4025\sasserv\FUNC: SetThreadDesktop。信息:错误:18312.07.2016 10:29:47.4065\sasserv\FUNC: PostMessage。信息:跑步..。2016年7月12日10时29分:47.4065分: PostMessage。信息:错误:87

EN

回答 1

Stack Overflow用户

发布于 2016-07-11 18:06:42

您需要将DLL导入标记为SetLastError=true,然后直接使用Marshal.GetLastWin32Error()而不是GetLastError()。从文件中:

GetLastError GetLastWin32Error公开了Kernel32.DLL中的Win32 GetLastError函数,之所以存在,是因为不安全地直接调用来获取信息。如果要访问此错误代码,则必须调用GetLastWin32Error,而不是为GetLastError编写自己的平台调用定义并调用它。公共语言运行库可以对覆盖操作系统维护的GetLastError的API进行内部调用。 只有将System.Runtime.InteropServices.DllImportAttribute应用于方法签名并将SetLastError字段设置为true时,才能使用此方法获取错误代码。根据所使用的源语言,此过程不同:默认情况下,C#和C++为false,但Visual中的声明语句为true。

例如:

代码语言:javascript
复制
namespace sasserv
{
    public class sasserv : ServiceBase
    {
        [DllImport("User32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
        static extern IntPtr OpenWindowStation( string name, bool fInherit, uint needAccess );

        [DllImport("User32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
        static extern IntPtr CloseWindowStation( IntPtr hWinSta );

        [DllImport("User32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
        static extern IntPtr OpenDesktop( string name, Int32 flags, bool fInherit, long param );

        [DllImport("User32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
        static extern IntPtr CloseDesktop( IntPtr hDesktop );

        [DllImport("User32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
        static extern bool PostMessage( IntPtr hWnd, UInt32 msg, UInt32 wParam, IntPtr lParam );

        [DllImport("User32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
        static extern bool SetThreadDesktop( IntPtr hDesktop );

        [DllImport("User32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
        static extern bool SetProcessWindowStation( IntPtr hWinSta );

        public const string MyServiceName = "sasserv";

        public sasserv()
        {
            InitializeComponent();
        }

        private void InitializeComponent()
        {
            this.ServiceName = MyServiceName;
        }

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        protected override void Dispose(bool disposing)
        {
            // TODO: Add cleanup code here (if required)
            base.Dispose(disposing);
        }

        /// <summary>
        /// Start this service.
        /// </summary>
        protected override void OnStart(string[] args)
        {
            RunWinlogon();
        }

        /// <summary>
        /// Stop this service.
        /// </summary>
        protected override void OnStop()
        {
            // TODO: Add tear-down code here (if required) to stop your service.
        }


        protected void OutputLastError(string funcName) {
            int err = Marshal.GetLastWin32Error();
            Out(funcName, "ERR:"+err);
        }

        private void RunWinlogon()
        {
            int err = 9999;
            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", "Running1");
            var hWinSta = OpenWindowStation( "WinSta0", false,  MAXIMUM_ALLOWED );
            if ( hWinSta == IntPtr.Zero ) {
                OutputLastError("OpenWindowStation");
                return;
            }

            Out("SetProcessWindowStation", "Running");
            if ( !SetProcessWindowStation( hWinSta ) ) {
                OutputLastError("SetProcessWindowStation");
                CloseWindowStation( hWinSta );          
                return;
            }

            Out("OpenDesktop", "Running");
            var hDesk = OpenDesktop( "Winlogon", 0, false, MAXIMUM_ALLOWED);

            if ( hDesk == IntPtr.Zero ) {
                OutputLastError("OpenDesktop");
                CloseWindowStation( hWinSta );          
                return;
            }

            if ( !SetThreadDesktop(hDesk) ) {
                OutputLastError("SetThreadDesktop");
                CloseDesktop( hDesk );
                CloseWindowStation( hWinSta );          
                return;
            }

            Out("PostMessage", "Running...");
            if ( !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 );
        }
    }
}

也就是说,发出Ctrl序列的另一种方法是使用SendSAS()函数,而不是广播WLX_WM_SAS窗口消息。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38310564

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档