none
Taskleistenproblem RRS feed

  • Frage

  • Hallo,

    ich habe mehrere PCs die ohne Benutzer laufen müssen und diese starten einen verzögerten Dienst, nach einer zusätzlichen Updateprüfung startet der Dienst einige Programme. Diese Programme habe ich nun mit verschiedenen Lösungen versucht maximiert laufen zu lassen, damit die Leiste nicht mehr zu sehen ist (ein Besucher unserer Filialen soll ja nur mein Programm haben und nicht ins Betriebssystem kommen).

    Wir benutzen für diese Systeme Windows 10 Pro in 64 Bit.

    Ich habe versucht die Leiste im Desktopmodus auszublenden.

    Ich habe das Programm nach dem Laden und positionieren (im Falle von unseren Videowalls haben wir ja mehrere Fenster) des Fensters zu maximieren.

    Ich habe versucht die Leiste beim Laden des Programmes komplett abzuschalten. Dies führt aber zu vielen Folgefehlern, wie z.B. dass man gar nicht mehr an die Leiste kommt wenn man sich dann mal aufschaltet und das Programm abgestürzt ist, etc.)

    Der Fehler ist, dass die Leiste in ca. 70% aller Fälle erst dann ausgeblendet wird wenn man als Benutzer einmal irgendwo auf dem Bildschirm hinklickt. In 30% der Fälle verschwindet die Leiste wie gewünscht. Dies ist immer nur nach einem Start des Systems passiert. Da der Dienst schon verzögert startet kann es ja nicht daran liegen, dass irgendwas noch nicht geladen ist. Die Systeme sind auch alle mit dem gleichen Image und der gleichen Hardware ausgestattet, so dass das auch nicht daran liegen kann. Dennoch habe ich keine Idee wie ich mein Programm nun von Anfang an über die Taskleiste bekomme.

    Hat jemand von euch eine Idee? Der Focus müsste beim Programmstart ja eh schon auf dem aufgerufenen Fenster liegen, oder?


    Freitag, 10. November 2017 10:12

Antworten

  • Kann es sein das du den Kiosk-Modus suchst?

    Leider hab ich zwar auch keine Erfahrung damit, aber soweit ich weiß ist der Modus genau für solche Anforderungen gedacht, wie du es beschreibst.

    Samstag, 11. November 2017 07:56
  • Oha, das sieht komplex aus... ich lese mir das durch sobald ich die Zeit dafür habe und melde mich wieder. Erst einmal danke schön. Vielleicht hilft das wirklich.

    ----

    Update: Ok, ich habe es mir angeschaut und muss sagen dass es NICHT das ist was ich suchte, weil ich einen Dienst starten muss der Programme updatet und danach verschiedene Programme startet und das funktioniert im Kioskmodus alles nicht.

    Ich habe aber eine programmatische Lösung gefunden, falls es jemanden interessiert. Ich simuliere einfach einen Mausklick auf mein Programm und schiebe dann den Cursor einfach zur Seite:

    Nach dem window.Show();

    await Task.Run(() => _mouse.Move(ConfigItems.XStart + ConfigItems.XOffset + 1, ConfigItems.YStart + ConfigItems.YOffset + 1))
    await Task.Run(() => _mouse.Click())
    await Task.Run(() => _mouse.Move(ConfigItems.XEnd + ConfigItems.XOffset, ConfigItems.YStart + ConfigItems.YOffset))

    Und die Methoden sehen so aus (sind aber nur geklaut, vielen Dank an den Entwickler):

        public class MouseControl
        {
            [DllImport("user32.dll", EntryPoint = "SendInput", SetLastError = true)]
            private static extern uint SendInput(uint nInputs, Input[] pInputs, int cbSize);
    
            [DllImport("user32.dll", EntryPoint = "GetMessageExtraInfo", SetLastError = true)]
            private static extern IntPtr GetMessageExtraInfo();
    
            private enum InputType
            {
                InputMouse = 0
            }
    
            [Flags]
            private enum Mouseeventf
            {
                Move = 0x0001,  // mouse move 
                Leftdown = 0x0002,  // left button down
                Leftup = 0x0004,  // left button up
                Rightdown = 0x0008,  // right button down
                Rightup = 0x0010,  // right button up
                Middledown = 0x0020,  // middle button down
                Middleup = 0x0040,  // middle button up
                Xdown = 0x0080,  // x button down 
                Xup = 0x0100,  // x button down
                Wheel = 0x0800,  // wheel button rolled
                Virtualdesk = 0x4000,  // map to entire virtual desktop
                Absolute = 0x8000,  // absolute move
            }
    
            [StructLayout(LayoutKind.Sequential)]
            private struct Mouseinput
            {
                public int dx;
                public int dy;
                public int mouseData;
                public Mouseeventf dwFlags;
                public int time;
                public IntPtr dwExtraInfo;
            }
    
            [StructLayout(LayoutKind.Sequential)]
            private struct Input
            {
                public InputType type;
                public Mouseinput mi;
            }
    
            /// <summary>
            /// Diese Funktion bewegt den Mauscursor an einen bestimmten Punkt.
            /// </summary>
            /// <param name="x">X Koordinate der Position als absoluter Pixelwert</param>
            /// <param name="y">Y Koordinate der Position als absoluter Pixelwert</param>
            /// <returns>Liefert 1 bei Erfolg und 0, wenn der Eingabestream schon blockiert war zurück.</returns>
            public uint Move(int x, int y)
            {
                // Bildschirm Auflösung
                float screenWidth = Screen.PrimaryScreen.Bounds.Width;
                float screenHeight = Screen.PrimaryScreen.Bounds.Height;
                Input inputMove = new Input
                {
                    type = InputType.InputMouse,
                    mi =
                    {
                        dx = (int) Math.Round(x * (65535 / screenWidth), 0),
                        dy = (int) Math.Round(y * (65535 / screenHeight), 0),
                        mouseData = 0,
                        dwFlags = (Mouseeventf.Move | Mouseeventf.Absolute),
                        time = 0,
                        dwExtraInfo = GetMessageExtraInfo()
                    }
                };
                Input[] input = { inputMove };
                return SendInput(1, input, Marshal.SizeOf(inputMove));
            }
    
            /// <summary>
            /// Diese Funktion simuliert einen einfach Mausklick mit der linken Maustaste an der aktuellen Cursurposition.
            /// </summary>
            /// <returns>Liefert 2 zurück, wenn beide Aktionen (Maus down und Maus up) erfolgreich waren. Andernfalls 1 oder 0.</returns>
            public uint Click()
            {
                Input inputDown = new Input
                {
                    type = InputType.InputMouse,
                    mi =
                    {
                        dx = 0,
                        dy = 0,
                        mouseData = 0,
                        dwFlags = Mouseeventf.Leftdown,
                        time = 0,
                        dwExtraInfo = GetMessageExtraInfo()
                    }
                };
                Input inputUp = inputDown;
                inputUp.mi.dwFlags = Mouseeventf.Leftup;
                Input[] input = { inputDown, inputUp };
                return SendInput(2, input, Marshal.SizeOf(inputDown));
            }
        }

    Montag, 13. November 2017 10:54

Alle Antworten

  • Hallo Marcel,

    ein Dienst soll überhaupt nicht mit dem Desktop interagieren. In der Regel kann er das auch gar nicht, da er gar keinen (sichtbaren) Desktop hat.

    Daher stellt sich die Frage, auf welchem Desktop stellst Du die Sachen überhaupt dar?

    In deinem Fall wäre es wohl sinnvoller, ein Autologin durchzuführen, so dass ein Benutzer angemeldet wird und deine Anwendung über Autostart zu laden, so dass diese dann auch den aktuellen Desktop beeinflussen kann.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community

    Freitag, 10. November 2017 10:32
    Moderator
  • Ach das funktioniert ja alles schon. Der Dienst nimmt sich die ID des eingeloggten Users welcher per netplwiz eingeloggt wird und startet unter dieser ID die App. Aber ich habe es auch schon per Autostart versucht und da tritt das gleiche Verhalten der Taskbar auf wie per Dienststart. Ich wollte damit nur verdeutlichen dass alle wichtigen Dienste zu dem Zeitpunkt schon geladen wurden.

    p.s: Wenn jemand wissen möchte wie ein Dienst auf die UI zugreifen kann, einfach eine Frage stellen, ich gebe dann den Code raus. Ist recht komplex, aber funktioniert.

    Freitag, 10. November 2017 11:02
  • Kann es sein das du den Kiosk-Modus suchst?

    Leider hab ich zwar auch keine Erfahrung damit, aber soweit ich weiß ist der Modus genau für solche Anforderungen gedacht, wie du es beschreibst.

    Samstag, 11. November 2017 07:56
  • Oha, das sieht komplex aus... ich lese mir das durch sobald ich die Zeit dafür habe und melde mich wieder. Erst einmal danke schön. Vielleicht hilft das wirklich.

    ----

    Update: Ok, ich habe es mir angeschaut und muss sagen dass es NICHT das ist was ich suchte, weil ich einen Dienst starten muss der Programme updatet und danach verschiedene Programme startet und das funktioniert im Kioskmodus alles nicht.

    Ich habe aber eine programmatische Lösung gefunden, falls es jemanden interessiert. Ich simuliere einfach einen Mausklick auf mein Programm und schiebe dann den Cursor einfach zur Seite:

    Nach dem window.Show();

    await Task.Run(() => _mouse.Move(ConfigItems.XStart + ConfigItems.XOffset + 1, ConfigItems.YStart + ConfigItems.YOffset + 1))
    await Task.Run(() => _mouse.Click())
    await Task.Run(() => _mouse.Move(ConfigItems.XEnd + ConfigItems.XOffset, ConfigItems.YStart + ConfigItems.YOffset))

    Und die Methoden sehen so aus (sind aber nur geklaut, vielen Dank an den Entwickler):

        public class MouseControl
        {
            [DllImport("user32.dll", EntryPoint = "SendInput", SetLastError = true)]
            private static extern uint SendInput(uint nInputs, Input[] pInputs, int cbSize);
    
            [DllImport("user32.dll", EntryPoint = "GetMessageExtraInfo", SetLastError = true)]
            private static extern IntPtr GetMessageExtraInfo();
    
            private enum InputType
            {
                InputMouse = 0
            }
    
            [Flags]
            private enum Mouseeventf
            {
                Move = 0x0001,  // mouse move 
                Leftdown = 0x0002,  // left button down
                Leftup = 0x0004,  // left button up
                Rightdown = 0x0008,  // right button down
                Rightup = 0x0010,  // right button up
                Middledown = 0x0020,  // middle button down
                Middleup = 0x0040,  // middle button up
                Xdown = 0x0080,  // x button down 
                Xup = 0x0100,  // x button down
                Wheel = 0x0800,  // wheel button rolled
                Virtualdesk = 0x4000,  // map to entire virtual desktop
                Absolute = 0x8000,  // absolute move
            }
    
            [StructLayout(LayoutKind.Sequential)]
            private struct Mouseinput
            {
                public int dx;
                public int dy;
                public int mouseData;
                public Mouseeventf dwFlags;
                public int time;
                public IntPtr dwExtraInfo;
            }
    
            [StructLayout(LayoutKind.Sequential)]
            private struct Input
            {
                public InputType type;
                public Mouseinput mi;
            }
    
            /// <summary>
            /// Diese Funktion bewegt den Mauscursor an einen bestimmten Punkt.
            /// </summary>
            /// <param name="x">X Koordinate der Position als absoluter Pixelwert</param>
            /// <param name="y">Y Koordinate der Position als absoluter Pixelwert</param>
            /// <returns>Liefert 1 bei Erfolg und 0, wenn der Eingabestream schon blockiert war zurück.</returns>
            public uint Move(int x, int y)
            {
                // Bildschirm Auflösung
                float screenWidth = Screen.PrimaryScreen.Bounds.Width;
                float screenHeight = Screen.PrimaryScreen.Bounds.Height;
                Input inputMove = new Input
                {
                    type = InputType.InputMouse,
                    mi =
                    {
                        dx = (int) Math.Round(x * (65535 / screenWidth), 0),
                        dy = (int) Math.Round(y * (65535 / screenHeight), 0),
                        mouseData = 0,
                        dwFlags = (Mouseeventf.Move | Mouseeventf.Absolute),
                        time = 0,
                        dwExtraInfo = GetMessageExtraInfo()
                    }
                };
                Input[] input = { inputMove };
                return SendInput(1, input, Marshal.SizeOf(inputMove));
            }
    
            /// <summary>
            /// Diese Funktion simuliert einen einfach Mausklick mit der linken Maustaste an der aktuellen Cursurposition.
            /// </summary>
            /// <returns>Liefert 2 zurück, wenn beide Aktionen (Maus down und Maus up) erfolgreich waren. Andernfalls 1 oder 0.</returns>
            public uint Click()
            {
                Input inputDown = new Input
                {
                    type = InputType.InputMouse,
                    mi =
                    {
                        dx = 0,
                        dy = 0,
                        mouseData = 0,
                        dwFlags = Mouseeventf.Leftdown,
                        time = 0,
                        dwExtraInfo = GetMessageExtraInfo()
                    }
                };
                Input inputUp = inputDown;
                inputUp.mi.dwFlags = Mouseeventf.Leftup;
                Input[] input = { inputDown, inputUp };
                return SendInput(2, input, Marshal.SizeOf(inputDown));
            }
        }

    Montag, 13. November 2017 10:54