WPF Image laden wenn Programm von ein Dienst gestartet wurde



  • Hallo
    Ich habe ein Problem, wenn ich ein WPF Programm von einen Dienst aus starten lasse in einer Benutzersitzung über CreateProcessAsUser und das gestartete Programm in einen Listview ein binding auf ein Bitmapimage hat, dann wird diese nicht geladen 😞

    Zum testen kann das Programm psexec genutzt werden bsp. psexec -i -s Programmname.exe (https://technet.microsoft.com/de-de/sysinternals/bb897553.aspx)

    ich habe ein Objekt was den wert IMAGE enthält dieses ist mit

    <Image Grid.Column="0" Grid.RowSpan="2" x:Name="icon" Margin="2" Source="{Binding Path=IMAGE}"/>
    

    gebunden

    Ich lasse mir vor den Laden und danach eine Meldung ins Ereignisslog schreiben

    public BitmapImage IMAGE 
            { 
                get 
                {
                    global_program_information.LOG.add_warning("Starte laden: " );
                    BitmapImage ret = new BitmapImage(new Uri("Pfad_zum_HTTP_Bild", UriKind.Absolute));
    
                     global_program_information.LOG.add_warning("geladen!");
                    return ret;
                } 
            }
    

    Die erste Meldung erscheint auch im Erignisslog doch die zweite nicht. Auf den Webserver sehe ich im Log auch kein abruf des Bildes.

    Starte ich das Programm normal als Benutzer funktioniert es ohne Probleme

    edit:
    Ich habe das ganze jetzt noch einmal mit einer Programmresource probiert

    BitmapImage ret = new BitmapImage(new Uri("/meinprogramm;component/Klassen/default.png", UriKind.RelativeOrAbsolute));
    

    das Bild wird angezeigt die aus den Web funktionieren nicht 😞



  • Ich nehme man an, wenn die erste Meldung geloggt wird, und die zweite nicht, dann wird beim "new BitmapImage" eine exception ausgelösct?!?! sieht du zudem irgendelche Binding errors?

    Du kannst in XAML auch bei Image direkt die Iamge Path angeben, brauch also kein Binding... bin mir da aber nich 100 % sicher



  • Hi NullBockException

    nein eine Exception wird nicht ausgelöst 😞

    was mir noch aufgefallen ist das wenn ich die Anwendung über den Dienst starte dann hängt auch der GC dies konnte ich aber lösen -> https://social.msdn.microsoft.com/Forums/vstudio/en-US/835db88e-db51-4f83-bd4f-a10d126effa6/gc-does-not-work-in-console-application-with-stathread-specified?forum=clr

    leider konnte ich das nur auf den Dienst abschnitt anwenden sobald ich versuche etwas mit einer GUI zu starten über

    Thread t = new Thread(delegate() {
                            MainWindow mw = new MainWindow ();
                        mw.Show();
    });
    t.Start();
    

    dann bekomme ich eine System.InvalidOperationException



  • Hmm .. ich kann nur mal vermuten, dass du versuchst ein WPF Window in einem WindowsService Kontext anzuzeigen!?!? Ich bin mir nich sicher ob das geht.. da du hiefür eine WPF Applikation brauchst... 😕

    Aber nur so ne Idee-



  • Er hat doch geschrieben dass das Service sein Programm mittels CreateProcessAsUser startet. Und dass er das WPF Fenster sieht, bloss kein Bild darin.

    @PMGZED
    Bist du ganz ganz sicher dass keine Exception geworfen wird?
    Hast du ne Log-Ausgabe in einem finally versucht?
    Wenn da nämlich keine Exception fliegt, und auch nix geloggt wird, dann müsste das Programm in new BitmapImage hängen. Und dann müsste dein GUI Fensterli hängen. Und davon hast du ja nix geschrieben.
    Also: vermutlich Exception.



  • Das Programm an sich stürzt nicht ab auch im Ereignisslog taucht auch nichts auf
    das Programm funktioniert auch so ohne Probleme eben nur das die Bilder fehlen.

    Leider kenn ich mich mit WPF noch nicht so gut aus kann es sein das es bei WPF ein Thread gibt der sich um das laden der Bilder kümmert der eventuell nicht gestartet wird da das ganze aus den Systemaccount mit einen Benutzertoken heraus gestartet wird

    das Problem scheint an WPF zu liegen ich habe ein neues "Projekt" erstellt und in die Zeile eingefügt

    <Image Grid.Column="0" Grid.RowSpan="2" x:Name="icon" Margin="2" Source="http://www.golem.de/staticrl/images/logo-g.png" HorizontalAlignment="Left"/>
    

    wenn ich das Programm dann mithilfe von psexec /i /s Programmname.exe
    starte tritt der Fehler auf (https://technet.microsoft.com/de-de/sysinternals/bb897553.aspx)
    psexec mit /i /s startet das angegebene Programm als Dienst/Systemaccount auf den Benutzerdesktop starte ich das Programm per Doppelklick funktioniert es 😞

    Mein Programm macht an sich das selbe wie psexec
    Das Programm läuft als Dienst und wenn der Benutzer ein Information angezeigt bekommen soll wird vom Dienst in der Benutzersitzung ein WPF Programm gestartet was die Info ausgibt
    Ich hole mir mit WTSQueryUserToken den Benutzertoken und starte das Programm dann mithilfe von CreateProcessAsUser

    Eine variante womit es funktioniert hat

    byte[] fileBytes = new byte[1];
                    using (WebClient wc = new WebClient())
                    {
                        try
                        {
                            fileBytes = wc.DownloadData(url);
                        }
                        catch { return new BitmapImage(); }
                    }
                    MemoryStream memoryStream = new MemoryStream(fileBytes);
    
                    BitmapImage ret = new BitmapImage();
                    ret.BeginInit();
                    ret.StreamSource = memoryStream;
                    ret.CacheOption = BitmapCacheOption.OnLoad;
                    ret.EndInit();
                    ret.Freeze();
                    return ret;
    

    aber die variante wo ich einfach ein Binding auf die URL des Bildes mache wäre mir lieber 😞



  • Wird dir das Rumraten nicht langsam fad?
    Bitte mach doch einfach in den Property-Getter nen try-catch rein und logge da drinnen auftretende Exceptions.
    Oder debugge es gleich. Ist ja net schwer, einfach ne MessageBox vor dem Start des eigentlichen Programms anzeigen, und während diese angezeigt wird mit dem Debugger draufhängen.
    Dann so einstellen dass er bei jeder geworfenen Exception sofort unterbricht (egal ob sie gefangen wird oder nicht), dann die MessageBox wegklicken und gucken was passiert.

    Ist wirklich nicht so schwer, und wird dir vermutlich viel mehr verraten als irgendwie irgendwas rumzuraten und rumzubasteln.



  • Hi hustbaer, hi NullBockException
    Danke für eure Geduld 🙂

    Ich habe das jetzt mit

    public BitmapImage IMAGE
            {
                get
                {
                    global_program_information.LOG.add_warning("Starte laden: "); 
                    BitmapImage ret = new BitmapImage();
                    try { 
                    ret = new BitmapImage(new Uri("http://www.golem.de/staticrl/images/logo-g.png", UriKind.Absolute));
                    }
                    catch (Exception e)
                    {
                        global_program_information.LOG.add_warning("Fehler: " + e.ToString()); 
                    }
                    finally
                    {
                        global_program_information.LOG.add_warning("Fertig"); 
                    }
    
                    return ret;
                }
            }
    

    und es kommt die exception

    Fehler: System.Runtime.InteropServices.COMException (0x80070078): Diese Funktion wird vom System nicht unterstützt. (Ausnahme von HRESULT: 0x80070078)
       bei System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32 errorCode, IntPtr errorInfo)
       bei System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(Int32 errorCode)
       bei MS.Win32.WinInet.get_InternetCacheFolder()
       bei System.Windows.Media.Imaging.BitmapDownload.BeginDownload(BitmapDecoder decoder, Uri uri, RequestCachePolicy uriCachePolicy, Stream stream)
       bei System.Windows.Media.Imaging.LateBoundBitmapDecoder..ctor(Uri baseUri, Uri uri, Stream stream, BitmapCreateOptions createOptions, BitmapCacheOption cacheOption, RequestCachePolicy requestCachePolicy)
       bei System.Windows.Media.Imaging.BitmapDecoder.CreateFromUriOrStream(Uri baseUri, Uri uri, Stream stream, BitmapCreateOptions createOptions, BitmapCacheOption cacheOption, RequestCachePolicy uriCachePolicy, Boolean insertInDecoderCache)
       bei System.Windows.Media.Imaging.BitmapImage.FinalizeCreation()
       bei System.Windows.Media.Imaging.BitmapImage.EndInit()
       bei System.Windows.Media.Imaging.BitmapImage..ctor(Uri uriSource, RequestCachePolicy uriCachePolicy)
       bei System.Windows.Media.Imaging.BitmapImage..ctor(Uri uriSource)
    


  • Hallo

    laut dem ersten Link im Nachfolgenden Eintrag sollte es helfen, wenn du das Bild auf die Root des Webservers legst:

    https://social.msdn.microsoft.com/Forums/silverlight/en-US/905c8af4-50ae-492d-afe4-527456b408ad/xamlreader-cant-parse-imagebrush

    Mfg Marco



  • Hm.
    Also irgendwas geht beim Starten deines Prozesses gröber daneben. Bist du sicher dass der Prozess unter dem Account des eingeloggten Users läuft? Ich beginne schön langsam zu vermuten dass NullBockException recht hat, und du versuchst das Ding mit dem Service-User laufen zu lassen. Was nicht hinhauen wird. Es geht zwar sehr sehr viel wenn man als SYSTEM/NetworkService/... läuft, aber eben nicht alles.

    Denn...

    Wenn du dir MS.Win32.WinInet.get_InternetCacheFolder mit dem IL Disassembler/Decompiler deiner Wahl anguckst, dann siehst du dass da drinnen bloss eine Funktion aufgerufen wird, und zwar GetUrlCacheConfigInfo .
    Der Fehlercode dieser Funktion wird dann in ein HRESULT eingewickelt, und damit die Exception geworfen.
    Der HRESULT Code ist wie wir sehen können 0x80070078 . Wickeln wir den Win32 Error Code wieder aus, dann bekommen wir 0x78 aka. 120 aka. ERROR_CALL_NOT_IMPLEMENTED .

    Und wenn wir uns die MSDN Seite zu GetUrlCacheConfigInfo angucken...
    https://msdn.microsoft.com/en-us/library/windows/desktop/cc817578(v=vs.85).aspx
    ...dann steht da

    Note WinINet does not support server implementations. In addition, it should not be used from a service. For server implementations or services use Microsoft Windows HTTP Services (WinHTTP).

    Bevor du nen Workaround baust, nur um dann gleich über die nächste Sache zu stolpern die nicht funktioniert weil du nicht mit einem normalen Userkonto läufst, würde ich empfehlen das Starten deines GUI Prozesses umzuschreiben. So dass er mit dem eingeloggten Userkonto läuft.
    Dazu brauchst du vermutlich einen Hilfsprozess, den du per Autostart starten lässt. Zumindest ist (bzw. war) das die übliche Art es zu machen.

    ps

    add_warning("Fehler: " +
    

    😃 🤡 🤡 😃



  • ps2:
    Ich bin allerdings nicht sicher was hier mit "server implementations" gemeint ist. Server Windowse sind sicher nicht gemeint. Aber was dann?



  • Laut Taskmanager stimmt der Benutzer und die SitzungsID
    Aber OK an sich war das ganze Thema ganz intersannt aber ich denke ich werde es dann doch so wie MS den Standardweg vorgibt über den Regestryautostart-Key erledigen.

    Ich danke euch für die gute Unterstützung 🙂



  • Was genau hast Du den vor? Du willst eine UI für deinen Service oder? Wenn Ja:

    Dann bau dir ein WCF Service in deinen Win-Service, und eine UI Host mit der du dich auf den Service verbinden kannst!

    Wenn nein: Vergiss den letzen Absatz;)=


Log in to reply