新たな作業領域「デスクトップ」を別に作る

過去のブログのアーカイブ
この記事は前身のブログのアーカイブを引き継いだものです. 画像が正しく表示できないなど,コンテンツの表示に問題がある恐れがあります.

実はWindowsにはデスクトップが複数あります。普段使っているDefaultのデスクトップのほかにセキュリティデスクトップがあります。
このデスクトップは実は簡単に管理することができるのです。

そもそも新しいデスクトップとは

普段使っているデスクトップはDefaultという名前のデスクトップです。
デスクトップにはアイコンが並び、タスクバーがあり、通知バーがあり…と揃っています。
それに対し、セキュリティデスクトップはCtrl+Alt+Deleteで開く画面。Windowsの中でもスクリーンショットさせないとか、非常に権限が厳しい画面です。
これに加え、新しい作業領域として、新しいデスクトップを作成することができます。
作成したばっかりのデスクトップはこの通り真っ新。(左下のウィンドウは元のデスクトップに戻るためのプログラムです。)
new-desktop1
最初はまっさらですが、もちろんこのデスクトップにプログラムを起動することもできます。
new-desktop2

Win32APIを使う必要あり

デスクトップの操作/そのデスクトップにプログラムを表示するのにはWin32APIが必要です。
C#コードで使うものを一通りおいておきます。

private const short SW_HIDE = 0;
private const short SW_NORMAL = 1;
private const int STARTF_USESTDHANDLES = 0x00000100;
private const int STARTF_USESHOWWINDOW = 0x00000001;
private const int UOI_NAME = 2;
private const int STARTF_USEPOSITION = 0x00000004;
private const int NORMAL_PRIORITY_CLASS = 0x00000020;
private const long DESKTOP_CREATEWINDOW = 0x0002L;
private const long DESKTOP_ENUMERATE = 0x0040L;
private const long DESKTOP_WRITEOBJECTS = 0x0080L;
private const long DESKTOP_SWITCHDESKTOP = 0x0100L;
private const long DESKTOP_CREATEMENU = 0x0004L;
private const long DESKTOP_HOOKCONTROL = 0x0008L;
private const long DESKTOP_READOBJECTS = 0x0001L;
private const long DESKTOP_JOURNALRECORD = 0x0010L;
private const long DESKTOP_JOURNALPLAYBACK = 0x0020L;
private const long AccessRights = DESKTOP_JOURNALRECORD | DESKTOP_JOURNALPLAYBACK | DESKTOP_CREATEWINDOW | DESKTOP_ENUMERATE | DESKTOP_WRITEOBJECTS | DESKTOP_SWITCHDESKTOP | DESKTOP_CREATEMENU | DESKTOP_HOOKCONTROL | DESKTOP_READOBJECTS;
[DllImport("kernel32.dll")]
private static extern int GetThreadId(IntPtr thread);
[DllImport("kernel32.dll")]
private static extern int GetProcessId(IntPtr process);
[DllImport("user32.dll")]
private static extern IntPtr CreateDesktop(string lpszDesktop, IntPtr lpszDevice, IntPtr pDevmode, int dwFlags, long dwDesiredAccess, IntPtr lpsa);
[DllImport("user32.dll")]
private static extern bool CloseDesktop(IntPtr hDesktop);
[DllImport("user32.dll")]
private static extern IntPtr OpenDesktop(string lpszDesktop, int dwFlags, bool fInherit, long dwDesiredAccess);
[DllImport("user32.dll")]
private static extern IntPtr OpenInputDesktop(int dwFlags, bool fInherit, long dwDesiredAccess);
[DllImport("user32.dll")]
private static extern bool SwitchDesktop(IntPtr hDesktop);
[DllImport("user32.dll")]
private static extern bool EnumDesktops(IntPtr hwinsta, EnumDesktopProc lpEnumFunc, IntPtr lParam);
[DllImport("user32.dll")]
private static extern IntPtr GetProcessWindowStation();
[DllImport("user32.dll")]
private static extern bool EnumDesktopWindows(IntPtr hDesktop, EnumDesktopWindowsProc lpfn, IntPtr lParam);
[DllImport("user32.dll")]
private static extern bool SetThreadDesktop(IntPtr hDesktop);
[DllImport("user32.dll")]
private static extern IntPtr GetThreadDesktop(int dwThreadId);
[DllImport("user32.dll")]
private static extern bool GetUserObjectInformation(IntPtr hObj, int nIndex, IntPtr pvInfo, int nLength, ref int lpnLengthNeeded);
[DllImport("user32.dll")]
private static extern int GetWindowText(IntPtr hWnd, IntPtr lpString, int nMaxCount);
private delegate bool EnumDesktopProc(string lpszDesktop, IntPtr lParam);
private delegate bool EnumDesktopWindowsProc(IntPtr desktopHandle, IntPtr lParam);
[StructLayout(LayoutKind.Sequential)]
private struct STARTUPINFO
{
    public int cb;
    public string lpReserved;
    public string lpDesktop;
    public string lpTitle;
    public int dwX;
    public int dwY;
    public int dwXSize;
    public int dwYSize;
    public int dwXCountChars;
    public int dwYCountChars;
    public int dwFillAttribute;
    public int dwFlags;
    public short wShowWindow;
    public short cbReserved2;
    public IntPtr lpReserved2;
    public IntPtr hStdInput;
    public IntPtr hStdOutput;
    public IntPtr hStdError;
}
[StructLayout(LayoutKind.Sequential)]
private struct PROCESS_INFORMATION
{
    public IntPtr hProcess;
    public IntPtr hThread;
    public int dwProcessId;
    public int dwThreadId;
}
[DllImport("kernel32.dll")]
private static extern bool CreateProcess(
    string lpApplicationName,
    string lpCommandLine,
    IntPtr lpProcessAttributes,
    IntPtr lpThreadAttributes,
    bool bInheritHandles,
    int dwCreationFlags,
    IntPtr lpEnvironment,
    string lpCurrentDirectory,
    ref STARTUPINFO lpStartupInfo,
    ref PROCESS_INFORMATION lpProcessInformation
);

結構長ったらしくなってますね。

サンプルプログラム

[追記] この技術を使ったプログラムを公開しました。

即座に画面を隠すことができる「ボスが来た」v1.00公開

2016.10.20