[C#] SystemParametersInfo geeft error

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Hans1990
  • Registratie: Maart 2004
  • Niet online
In deze post heb ik een wallpaper shuffler app gepost. Nu was er vraag naar om het te delen, dus wou ik dat even netjes doen door een echte Windows Service op te zetten. Vooreen draaide er een Console Application die ik liet verbergen d.m.v. ShowWindow in user32.dll. Beetje vieze methode, dus vandaar deze omslag.

Om de wallpaper te verwisselen gebruik ik de functie SystemParametersInfo:

C#:
1
2
3
4
5
6
7
8
9
10
11
12
        [DllImport( "user32.dll", CharSet = CharSet.Auto )]
        private static extern Int32 SystemParametersInfo( UInt32 uiAction, UInt32 uiParam, String pvParam, UInt32 fWinIni );
        private static UInt32 SPI_SETDESKWALLPAPER = 20;
        private static UInt32 SPIF_UPDATEINIFILE = 0x1;
        private static UInt32 SPIF_SENDWININICHANGE = 0x2;

        public void SetImage( string filename )
        {
            int result = SystemParametersInfo( SPI_SETDESKWALLPAPER, 0, filename, SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE);
            if (result == 0) throw new System.ComponentModel.Win32Exception (Marshal.GetLastWin32Error( ));
            
        }


Dit werkte in de Console Application prima. Ik heb nu de applicatie omgezet naar een Windows Service. Echter krijg ik als result 0 mee, met de volgende fout (de Win32Exception):
-----------------------------------------------------
Sunday, February 21, 2010 7:32:14 PM
-----------------------------------------------------
Cannot create a file when that file already exists
WallpaperService
at WallpaperService.Service.SetImage(String filename)
at WallpaperService.Service.TheThread()
System.Collections.ListDictionaryInternal
Dit is ook wel bekend als Windows foutcode 182. Er staat dat 'het' een bestand kan aanmaken als ik de wallpaper verander. Dan vraag ik mij af, welk bestand? Ik kan daar op geen enkele wijze achter komen. Het maakt overigens ook niet uit of ik deze Windows Service laat inloggen op mijn account (logisch, want de wallpaper is User Account gebonden), of als Local Service laat draaien. Heeft iemand hier een idee van waarom deze foutmelding wordt gegeven of hoe ik het verder kan debuggen? Google levert weinig info over deze functie op, omdat maar weinig mensen deze functie in een Windows Service zetten.

Als zijlijntje om toch m'n resultaat aan de gang proberen te krijgen heb ik gekeken naar een IActiveDesktop implementatie. Helaas gaf dat geen feedback, namelijk dat er geen wallpaper wordt veranderd.

Acties:
  • 0 Henk 'm!

  • Snake
  • Registratie: Juli 2005
  • Laatst online: 07-03-2024

Snake

Los Angeles, CA, USA

Mag een service uberhaupt jouw wallpaper wijzigen?

Ik denk eerlijk gezegd niet, een service draait faceless. Ook de instellingen voor stretched ed. worden in het register ingesteld voor de current (!) user. Dus dat kan je al niet direct wijzigen als service.

[ Voor 67% gewijzigd door Snake op 22-02-2010 11:19 ]

Going for adventure, lots of sun and a convertible! | GMT-8


Acties:
  • 0 Henk 'm!

  • Reptile209
  • Registratie: Juni 2001
  • Laatst online: 23:07

Reptile209

- gers -

Check je code eens tegen deze op Codeproject. Misschien valt daar meteen een verschil te vinden.
Nog even for the record: voor welke Windows-versies programmeer je dit? Ik kan me voorstellen dat Vista en W7 nog iets harder tegenstribbelen tegen dit soort programma's dan dat XP en eerder dat doen.

Zo scherp als een voetbal!


Acties:
  • 0 Henk 'm!

  • Snake
  • Registratie: Juli 2005
  • Laatst online: 07-03-2024

Snake

Los Angeles, CA, USA

Reptile209 schreef op maandag 22 februari 2010 @ 11:24:
Check je code eens tegen deze op Codeproject. Misschien valt daar meteen een verschil te vinden.
Nog even for the record: voor welke Windows-versies programmeer je dit? Ik kan me voorstellen dat Vista en W7 nog iets harder tegenstribbelen tegen dit soort programma's dan dat XP en eerder dat doen.
En als je gaat kijken bij de comments zegt iemand: dat werkt als winform app, maar niet als service. Bummer dus :)

Ik heb net evengeprobeerd in HKCU\Control Panel\Desktop de DWORD wallpaper te wijzigen in iets anders maar dan krijg ik een zwarte achtergrond. Ik vergeet waarschijnlijk nog iets.

Maar als ik bij mijn thema's ga kijken dan previewt hij deze wel goed!

@TS probeer eerst eens de wallpaper op te halen met SPI_GETDESKWALLPAPER.

[ Voor 4% gewijzigd door Snake op 22-02-2010 11:30 ]

Going for adventure, lots of sun and a convertible! | GMT-8


Acties:
  • 0 Henk 'm!

  • Hans1990
  • Registratie: Maart 2004
  • Niet online
In het register wijzigen werkt niet, er moet een call in het systeem worden gegeven dat alles netjes wordt bijgewerkt. INI's vernieuwd en dat soort dingen. ;)

Sorry vergeten te vermelden, ik gebruik inderdaad Windows Vista. De functie SetImage wordt uitgeroepen vanuit een Thread die uit een Access database een wallpaper selecteert en de filepath ophaalt. Stelt vrij weinig voor, het verschil zit hem in het verschil tussen Console Application en als Windows Service. Ik vermoed nu steeds meer dat ze dit gewoon hebben dichtgetimmerd..

Zou ik zelf wel vreemd vinden, want het kan irritant zijn dat een wallpaper door kwaadaardige code wordt veranderd (die als Windows Service geinstalleerd staat), maar dat lijkt me nou niet erg schadelijk. Malware is erger.

Acties:
  • 0 Henk 'm!

  • Snake
  • Registratie: Juli 2005
  • Laatst online: 07-03-2024

Snake

Los Angeles, CA, USA

Hans1990 schreef op maandag 22 februari 2010 @ 11:31:
In het register wijzigen werkt niet, er moet een call in het systeem worden gegeven dat alles netjes wordt bijgewerkt. INI's vernieuwd en dat soort dingen. ;)

Sorry vergeten te vermelden, ik gebruik inderdaad Windows Vista. De functie SetImage wordt uitgeroepen vanuit een Thread die uit een Access database een wallpaper selecteert en de filepath ophaalt. Stelt vrij weinig voor, het verschil zit hem in het verschil tussen Console Application en als Windows Service. Ik vermoed nu steeds meer dat ze dit gewoon hebben dichtgetimmerd..

Zou ik zelf wel vreemd vinden, want het kan irritant zijn dat een wallpaper door kwaadaardige code wordt veranderd (die als Windows Service geinstalleerd staat), maar dat lijkt me nou niet erg schadelijk. Malware is erger.
Neem even een XP vm erbij? Of stuur mij de installer + wat uitleg hoe ik het kan installeren in XP, wil gerust even voor je testen.

Going for adventure, lots of sun and a convertible! | GMT-8


Acties:
  • 0 Henk 'm!

  • Hans1990
  • Registratie: Maart 2004
  • Niet online
Even snel een code bij elkaar geraapt:
C#:
1
2
3
4
5
6
7
8
        public string GetImage( )
        {
            String wallpaper = new String( '\0', 260 );
            SystemParametersInfo( SPI_GETDESKWALLPAPER, (UInt32) wallpaper.Length, wallpaper, 0 );
            wallpaper = wallpaper.Substring( 0, wallpaper.IndexOf( '\0' ) );
            return wallpaper;

        }


Werkt weer prima in Console Application, niet in Windows Service.

Als ik het register uitlees, werkt alles prima. Als ik het register schrijf, veranderd de desktop niet mee (krijgt geen tikje om achtergrond te veranderen). Misschien dat k even naar een functie moet zoeken die de Desktop ververst of zo, dan werkt het in principe ook.

Ik ben nog ver weg om alles in een installer te zetten, of het even over te zetten. Ik heb hier zelf wel virtualbox, met XP, dus ik zal even kijken of het daar wel kan werken.

[ Voor 6% gewijzigd door Hans1990 op 22-02-2010 11:56 ]


Acties:
  • 0 Henk 'm!

  • Crazy D
  • Registratie: Augustus 2000
  • Laatst online: 12:27

Crazy D

I think we should take a look.

Hans1990 schreef op maandag 22 februari 2010 @ 11:31:
Zou ik zelf wel vreemd vinden, want het kan irritant zijn dat een wallpaper door kwaadaardige code wordt veranderd (die als Windows Service geinstalleerd staat), maar dat lijkt me nou niet erg schadelijk. Malware is erger.
Een service is bedoelt als applicatie die zonder GUI op de achtergrond draait, en opstart, ook als je niet inlogt. Oftewel typisch iets wat je niets als wallpaper-changer wil hebben. Maar goed, als je zo graag wilt, misschien helpt het om bij de service-instellingen op het tabje Logon een vinkje te zetten bij 'Allow service to interact with the desktop' .

En anders een mooie Windows app van maken die zich keurig nestelt in de system tray, waarvandaan je ook meteen instellingen kunt aanpassen :)

Exact expert nodig?


Acties:
  • 0 Henk 'm!

  • Hans1990
  • Registratie: Maart 2004
  • Niet online
Dat vinkje aanzetten heeft als effect dat de functie nu geen foutmelding meer geeft, maar nu schrijft die informatie naar de user account van zijn eigen service. Als ik de service op mijn user account laat inloggen, kan die de wallpaper niet verversen. En helaas staat dat interact with the desktop vinkje niet bij user account. Lijkt met niet verstandig om zover met het register te klooien om dat het op mijn user account inlogt.

Ik denk dat ik het opgeef, en het gewoon laat bij hoe het was.

[ Voor 11% gewijzigd door Hans1990 op 22-02-2010 12:28 ]


Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Waarom zo moeilijk?
Maak een windows applicatie. Die zet standaard in program.cs een "Application.Run(new Form1());" Mikker de form uit je applicatie, mikker die regel (en die twee erboven) uit de applicatie en leef je uit. Voila een form-less windows applicatie waar niets met ranzige methodes gehide hoeft te worden etc.

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • Alex)
  • Registratie: Juni 2003
  • Laatst online: 21-08 11:20
Wat RobIII zegt. Een service is bedoeld om onafhankelijk te draaien van de ingelogde user, en draait onder een eigen account. Services draaien ook onder een andere session, daardoor kun je nooit bij je actieve sessie komen.

Je kunt dit zien door in task manager te kijken naar de Session ID van de processen (zie je geen Session ID? View -> Select columns). Je zult zien dat de meeste processen (zoals je webbrowser) onder Session ID 1 draaien, terwijl de rest onder 0 draait. Dit verschil is erg belangrijk, en meteen de reden waarom het als service niet lukt: je zit niet in dezelfde sessie. Ook "Interact with the desktop" gaat hierbij niet helpen.

Je zult van het service-idee moeten afstappen, en ofwel je huidige (verborgen) console-app moeten blijven gebruiken, of overschakelen naar een formless WinForms-applicatie.

We are shaping the future

Pagina: 1