Как я могу создать оконную станцию ​​и рабочий стол Windows с помощью C # - PullRequest
2 голосов
/ 28 августа 2009

Я хотел бы создать новую оконную станцию ​​и рабочий стол Windows и присоединить к ней свой процесс. как я могу это сделать

мне нужно знать

  1. Создание оконной станции и присоединение моего рабочего стола

  2. Эффективное создание и переключение между рабочим столом

  3. как мне прикрепить процесс к рабочему столу winlogon (если это возможно)

  4. Уничтожить созданный рабочий стол и вернуться на рабочий стол Windows

Ответы [ 2 ]

3 голосов
/ 24 марта 2010

В сеансе есть только одна интерактивная оконная станция, но вы можете иметь несколько сеансов.

http://blogs.technet.com/markrussinovich/archive/2010/02/24/3315174.aspx

Я не знаю API для непосредственного создания сеанса входа в систему, но если вы используете версию Windows Server, вы можете использовать удаленный рабочий стол для создания локального сеанса, автоматически запустить там свою программу, а затем снова выйти из системы после ее завершения (программа, запущенная в сеансе удаленного рабочего стола, может выйти из системы после завершения).

Приведенный ниже код будет использовать элемент управления ActiveX MSTSC для программного создания сеанса RDP. Вам нужно будет вручную создать заглушки ActiveX и добавить их в свой проект.

  1. В командной строке Visual Studio введите следующее:

    aximp.exe %windir%\system32\mstscax.dll
  2. Скопируйте созданные файлы (MSTSCLib.dll и AxMSTSCLib.dll) в каталог проекта.

  3. Добавьте оба файла к ссылкам проекта.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using AxMSTSCLib;
using MSTSCLib;
using System.Runtime.InteropServices;</p>

<p>namespace AutoLogin
{
    public partial class Form1 : Form
    {
        private AxMSTSCLib.AxMsRdpClient5 rdpClient;
        public Form1()
        {
            InitializeComponent();
            rdpClient = new AxMSTSCLib.AxMsRdpClient5();
            ((ISupportInitialize)rdpClient).BeginInit();
            rdpClient.Enabled = true;
            rdpClient.Location = new System.Drawing.Point(0, 0);
            rdpClient.Name = "MsRdpClient";
            rdpClient.Size = ClientSize;
            rdpClient.TabIndex = 1;
            rdpClient.Anchor = (AnchorStyles)
                (AnchorStyles.Top | AnchorStyles.Bottom |
                 AnchorStyles.Left | AnchorStyles.Right);
            Controls.Add(rdpClient);
            ((ISupportInitialize)rdpClient).EndInit();
        }</p>

<code>    void axRemoteDesktop_OnDisconnected
        (object sender, IMsTscAxEvents_OnDisconnectedEvent e)
    {
        Application.Idle += ExitTimerEvent;
    }

    public void ExitTimerEvent(object source, EventArgs e)
    {
        Application.Idle -= ExitTimerEvent;
        // Attempt to close down the session we just connected to (there
        // appears to be no way to get the session id, so we just close all
        // disconnected sessions.
        if (rdpClient.Connected == 1) {
            rdpClient.Disconnect();
        }
        LogoffDisconnectedSessions();
        Close();
    }

    private Timer logoffTimer;
    private void Form1_Load(object sender, EventArgs e)
    {
        // Close down any existing disconnected sessions, the number of
        // available sessions is limited.
        LogoffDisconnectedSessions();

        String username = "username";
        String password = "password";
        rdpClient.Server = "localhost";
        rdpClient.UserName = username;
        rdpClient.AdvancedSettings2.ClearTextPassword = password;
        rdpClient.Domain = "";
        rdpClient.FullScreen = false;
        rdpClient.AdvancedSettings2.RedirectDrives = false;
        rdpClient.AdvancedSettings2.RedirectPrinters = false;
        rdpClient.AdvancedSettings2.RedirectPorts = false;
        rdpClient.AdvancedSettings2.RedirectSmartCards = false;
        rdpClient.AdvancedSettings6.RedirectClipboard = false;
        rdpClient.AdvancedSettings6.MinutesToIdleTimeout = 1;

        rdpClient.OnDisconnected += new 
            AxMSTSCLib.IMsTscAxEvents_OnDisconnectedEventHandler
                (axRemoteDesktop_OnDisconnected);

        rdpClient.Connect();

        logoffTimer = new Timer();
        logoffTimer.Tick += new EventHandler(LogoutTimerEvent);
        logoffTimer.Interval = 150000;
        logoffTimer.Start();
    }

    private void Form1_Close(object sender, FormClosedEventArgs e)
    {
        Application.Idle -= ExitTimerEvent;
        if (rdpClient.Connected == 1) {
            rdpClient.Disconnect();
        }
    }

    public void LogoutTimerEvent(object source, EventArgs e)
    {
        logoffTimer.Stop();
        rdpClient.Disconnect();
    }

    enum WTS_CONNECTSTATE_CLASS
    {
        WTSActive,
        WTSConnected,
        WTSConnectQuery,
        WTSShadow,
        WTSDisconnected,
        WTSIdle,
        WTSListen,
        WTSReset,
        WTSDown,
        WTSInit
    };

    [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
    struct WTS_SESSION_INFO
    {
        public int SessionId;
        public string pWinStationName;
        public WTS_CONNECTSTATE_CLASS State;
    }

    [DllImport("wtsapi32.dll")]
    private static extern bool WTSLogoffSession(IntPtr hServer, int SessionId, bool bWait);
    private static IntPtr WTS_CURRENT_SERVER_HANDLE = IntPtr.Zero;

    [DllImport("wtsapi32.dll", CharSet = CharSet.Auto)]
    private static extern bool WTSEnumerateSessions(
            IntPtr hServer,
            [MarshalAs(UnmanagedType.U4)]
            int Reserved,
            [MarshalAs(UnmanagedType.U4)]
            int Version,
            ref IntPtr ppSessionInfo,
            [MarshalAs(UnmanagedType.U4)]
            ref int pCount);

    [DllImport("wtsapi32.dll")]
    private static extern void WTSFreeMemory(IntPtr pMemory);

    private void LogoffDisconnectedSessions()
    {
        IntPtr buffer = IntPtr.Zero;
        int count = 0;
        if (WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1,
                                 ref buffer, ref count)) {
            WTS_SESSION_INFO sessionInfo = new WTS_SESSION_INFO();

            for (int index = 0; index < count; index++) {
                sessionInfo = (WTS_SESSION_INFO)Marshal.PtrToStructure(
                   new IntPtr(buffer.ToInt32() +
                              (Marshal.SizeOf(sessionInfo) * index)),
                   typeof(WTS_SESSION_INFO));

                WTS_CONNECTSTATE_CLASS state = sessionInfo.State;
                if (state == WTS_CONNECTSTATE_CLASS.WTSDisconnected)
                {
                    WTSLogoffSession(WTS_CURRENT_SERVER_HANDLE,
                                     sessionInfo.SessionId, true);
                }
            }
        }
        WTSFreeMemory(buffer);
    }
}
</code>

}

0 голосов
/ 28 августа 2009

Хотя Windows поддерживает несколько «оконных станций», документация гласит:

Интерактивная оконная станция , Winsta0, является единственной оконной станцией, которая может отображать пользовательский интерфейс или принимать пользовательский ввод. Он назначается сеансу входа в систему интерактивного пользователя и содержит клавиатуру, мышь и устройство отображения. Все остальные оконные станции не являются интерактивными, что означает, что они не могут отображать пользовательский интерфейс или принимать пользовательский ввод.

Это означает, что возможность переключения между оконными станциями так, как вы предлагаете, невозможна.

...