Centrum Skryptów - Systemy Operacyjny

Jak losowo przypisać obraz z folderu Moje obrazy jako tapetę (tło pulpitu)?

Udostępnij na: Facebook

Skrypciarze odpowiadają na Wasze pytania

Witamy w rubryce TechNet, w której Skrypciarze z firmy Microsoft odpowiadają na częste pytania dotyczące używania skryptów w administracji systemu. Jeśli macie jakieś pytania z tej dziedziny, zachęcamy do wysłania e-maila na adres: scripter@microsoft.com. Nie możemy zagwarantować odpowiedzi na każde otrzymane pytanie, ale staramy się jak możemy.

Jak losowo przypisać obraz z folderu Moje obrazy jako tapetę (tło pulpitu)?

Cześć, Skrypciarze! W waszej rubryce opisane zostało losowego przypisywanie obrazów jako tapety na komputerze. Chcę zrobić to samo, ale zamiast wybierania zdjęć z określonej listy obrazów, chcę losowo przypisywać obraz znajdujące się w folderze Moje obrazy użytkownika. Jak to zrobić?

-- JJ

Cześć, JJ. Wiecie co, to był dla Skrypciarzy zwariowany miesiąc. Na początku byliśmy całkowicie pochłonięci przygotowaniami do naszego wyjazdu do Barcelony na forum informatyczne TechEd (j.ang.) i bardzo się staraliśmy, żeby dopiąć wszystko na ostatni guzik. (Ponieważ Skrypciarze nie należą do najbystrzejszych pracowników firmy Microsoft, będąc na „wakacjach” w Barcelonie napracowaliśmy się bardziej niż przez normalny tydzień.) Nie było nas 9 dni i wróciliśmy akurat na Święto Dziękczynienia; nasza Redaktorka nie pofatygowała się do pracy nawet na te kilka dni.

Uwaga. Zdziwilibyście się bardzo na wieść o tym ile ludzi mówiło to samo. I macie rację: podczas jej nieobecności wszystko szło zadziwiająco dobrze, nieprawdaż?

Teraz jednakże koniec zabawy (przynajmniej do Świąt Bożego Narodzenia, które zbliżają się wielkimi krokami). Między innymi oznacza to, że czas naprawdę zabrać się do pracy i nadrobić trochę zaległości. Na przykład, nie miałem ostatnio okazji wspomnieć konkursu IT Forum Challenge (j.ang.) który właśnie się rozgrywa w naszym Centrum Skryptów. Jest to nie tylko fajny konkurs, ale także absolutnie ostatnia szansa na wygranie laleczki doktora Scripto; zostało nam ich już raptem kilka.

Uwaga. Naprawdę jest fajnie, jak Redaktorka nie przychodzi do pracy, nieprawdaż? Miejmy więc nadzieję, że zapomni w ogóle zajrzeć do tej rubryki po powrocie. Co Wy na to, żeby dzisiejszy artykuł pozostał naszą słodką tajemnicą?

Jakie to jeszcze zaległości mieliśmy do nadrobienia? No cóż, ktoś bardzo prosił o skrypt losowo pobierający obraz z folderu Moje obrazy i przypisujący go jako tapetę użytkownika. Na szczęście dla mnie, miałem taki właśnie taki skrypt w zanadrzu:

Const MY_PICTURES = &H27&

Const HKEY_CURRENT_USER = &H80000001



Set objDictionary = CreateObject("Scripting.Dictionary")



Set objShell = CreateObject("Shell.Application")

Set objFolder = objShell.Namespace(MY_PICTURES) 

Set objFolderItem = objFolder.Self   

   

strPath = objFolderItem.Path



Set objFSO = CreateObject("Scripting.FileSystemObject")

Set objFolder = objFSO.GetFolder(strPath)

Set colFiles = objFolder.Files



i = 0



For Each objFile in colFiles

    i = i + 1

    objDictionary.Add i, objFile.Path

Next



intHighNumber = objDictionary.Count

intLowNumber = 1



Randomize

intNumber = Int((intHighNumber - intLowNumber + 1) * Rnd + intLowNumber)



strPicture = objDictionary.Item(intNumber)   



strKeyPath = "Control Panel\Desktop"

ValueName = "Wallpaper"



strComputer = "."



Set objReg = GetObject("winmgmts:\\" & strComputer & "\root\default:StdRegProv")



objReg.SetStringValue HKEY_USERS, strKeyPath, ValueName, strPicture

Macie wszystko? Bo teraz przechodzimy do ciekawszej części: zobaczymy, co ten skrypt potrafi zdziałać i jak to zrobi. Jak widzimy, zaczynamy od zdefiniowania dwóch stałych, MY_PICTURES (która informuje skrypt o tym, z którym folderem będziemy pracować) oraz HKEY_CURRENT_USER (która informuje skrypt, z którą gałęzią rejestru będziemy pracować). Po zdefiniowaniu tych dwóch stałych, stosujemy poniższy wiersz kodu w celu utworzenia wystąpienia obiektu Scripting.Dictionary:

Set objDictionary = CreateObject("Scripting.Dictionary")

Dlaczego utworzyliśmy wystąpienie obiektu Dictionary? Dobre pytanie! Szczerze mówiąc wcale nie musieliśmy tego robić; są jeszcze inne sposoby rozwiązania tego problemu. W końcu zdecydowałem jednak, że to najbardziej sensowne wyjście: pobierzemy ścieżki dla wszystkich plików znajdujących się w folderze Moje obrazy i dodamy je do obiektu Dictionary. Następnie wygenerujemy losową liczbę z przedziału od 1 do liczby elementów w Dictionary (czyli liczby plików znajdujących się w folderze); na razie zakładamy, że wygenerowaliśmy losową liczbę 13. Teraz pobierzemy element 13 z obiektu Dictionary. No i jest: losowo wybraliśmy plik z folderu Moje obrazy i mamy ścieżkę pliku do uruchomienia.

Czy to ma jakiś sens? Naprawdę tak myślicie?

No, no! Po czterech latach w końcu powiedziałem coś sensownego. Wygląda na to, że lata praktyki zaczynają dawać jakieś efekty.

Naszym następnym zadaniem jest określenie lokalizacji folderu Moje obrazy użytkownika. Do tego posłuży nam ten oto wiersz kodu:

Set objShell = CreateObject("Shell.Application")

Set objFolder = objShell.Namespace(MY_PICTURES) 

Set objFolderItem = objFolder.Self   

   

strPath = objFolderItem.Path

Przyznaję, wygląda on nieco dziwnie. My tutaj jednakże tylko tworzymy wystąpienie obiektu Shell.Application i stosujemy metodę Namespace w celu połączenia się z folderem Moje obrazy (zauważcie, że przekazujemy tej metodzie stałą MY_PICTURES). Oczywiście, tajemnicze zjawisko połączenia obiektu Shell z folderem za pomocą metody Namespace to tylko połowa sukcesu; aby móc pobierać informacje z tego folderu należy odnieść się do właściwości Self, która przekaż obiekt FolderItem wskazujący na ten folder. (No dobra, to nie ma prawie w ogóle sensu, ale to już nie moja wina, że tak działa obiekt Shell.) Poniższy wiersz kodu przekazuje obiekt FolderItem dla folderu Moje obrazy:

Set objFolderItem = objFolder.Self

Przynajmniej wiersz 4 ma jakiś sens; w tym wierszu pobieramy po prostu wartość właściwości Path folderu i zachowujemy ją w zmiennej o nazwie strPath:

strPath = objFolderItem.Path

Jak tylko będziemy znać ścieżkę do folderu Moje obrazy, możemy pobrać kolekcję wszystkich plików znajdujących się w tym folderze. Do tego służy poniższy fragment kodu:

Set objFSO = CreateObject("Scripting.FileSystemObject")

Set objFolder = objFSO.GetFolder(strPath)

Set colFiles = objFolder.Files

Te wiersze kodu powinny być trochę prostsze. W wierszach 1 i 2 tworzymy wystąpienie obiektu Scripting.FileSystemObject i stosujemy metodę GetFolder w celu połączenia się z folderem Moje obrazy. Skąd będziemy wiedzieć, że łączymy się z folderem Moje obrazy? Ponieważ przekazujemy metodzie getFolder zmienną strPath zawierającą ścieżkę do tego folderu. Następnie stosujemy poniższy wiersz kodu w celu pobrania kolekcji wszystkich plików znajdujących się w tym folderze:

Set colFiles = objFolder.Files

Rzeczywiście, cały ten wiersz jest jakiś nieustawny. Ale za to działa: mamy teraz kolekcję wszystkich plików znajdujących się w folderze Moje obrazy.

Co dokładnie zrobimy teraz z tą kolekcją? No cóż, przypiszemy wartość 0 do zmiennej licznika o nazwie:

i = 0

Potem zastosujemy następujący wiersz kodu w celu uruchomienia pętli, która przejdzie przez kolekcję tych plików:

For Each objFile in colFiles

    i = i + 1

    objDictionary.Add i, objFile.Path

Next

Jak widzimy, wewnątrz tej pętli najpierw zwiększamy wartość zmiennej i o 1. Następnie wywołujemy metodę Add i dodajemy plik do obiektu Dictionary, używając zmienną licznika i jako klucza obiektu Dictionary oraz wartość właściwości Path pliku jako elementu obiektu Dictionary:

objDictionary.Add i, objFile.Path

Uwaga. Klucz obiektu Dictionary? Element obiektu Dictionary? Mówicie, że nie macie nawet pojęcia, co te terminy oznaczają? W takim przypadku wypadałoby zajrzeć do tego artykułu (j.ang.) z serii Sesame Script.

Kiedy skończymy, nasz obiekt Dictionary będzie zawierał informacje podobne do poniższych:

Klucz

Element

1

C:\Documents and Settings\kenmyer\My Documents\My Pictures\Picture1.jpg

2

C:\Documents and Settings\kenmyer\My Documents\My Pictures\Picture2.jpg

3

C:\Documents and Settings\kenmyer\My Documents\My Pictures\Picture3.jpg

Powinniśmy zauważyć, że zakładamy, iż jedynymi plikami znajdującymi się w folderze Moje obrazy są właśnie obrazy. Jeżeli tak nie jest, konieczne jest uwzględnienie kodu, który gwarantuje, że mamy do czynienia z obrazem, zanim zostanie on dodany do obiektu Dictionary. Jak można to zrobić? No cóż, bez zbędnych szczegółów, za pomocą zmodyfikowanej pętli For Each, która wykorzystuje metodę GetExtensionName w celu pobrania rozszerzenia pliku dla każdego pliku, a następnie dodaje ten plik do obiektu Dictionary tylko w przypadku, gdy rozszerzenie pliku to: JPG, BMP lub GIF:

For Each objFile in colFiles

    strExtension = objFSO.GetExtensionName(objFile.Path)

    If strExtension = "jpg" or strExtension = "bmp" or strextension = "gif" Then

        Wscript.Echo strExtension

        i = i + 1

        objDictionary.Add i, objFile.Path

    End If

Next

Teraz trochę zabawy: Na początek stosujemy poniższy wiersz kodu w celu przypisania całkowitej liczby plików w obiekcie Dictionary (właściwość Count) do zmiennej o nazwie intHighNumber:

intHighNumber = objDictionary.Count

Następnie przypisujemy wartość 1 do zmiennej o nazwie intLowNumber; teraz możemy zastosować poniższe dwa wiersze kodu w celu wygenerowania losowej liczby z przedziału od 1 (intLowNumber) do całkowitej liczby plików w obiekcie Dictionary (intHighNumber):

Randomize

intNumber = Int((intHighNumber - intLowNumber + 1) * Rnd + intLowNumber)

Jak widać, losowa liczba, którą wygenerowaliśmy, zostaje zachowana w zmiennej o nazwie intNumber. Ponownie załóżmy, że intNumber to 13. Oznacza to, że chcemy zastosować obraz nr 13 jako tapetę. Jak pobierzemy ścieżkę dla obrazu nr 13? To proste: pobieramy wartość elementu Item dla elementu Dictionary, który posiada klucz równy 13:

strPicture = objDictionary.Item(intNumber)

Wystarczy tylko przekazać obiektowi Dicrtionary odpowiedni klucz (intNumber) a wartość tego określonego elementu (będącego ścieżką pliku) zostanie przypisana do zmiennej o nazwie strPicture.

W tym momencie wykorzystujemy trochę magii WMI (oraz klasy StdRegProv) w celu wpisanie ścieżki nowej tapety do rejestru. Nie będę omawiał dzisiaj tego procesu szczegółowo; więcej informacji znajduje się w naszym archiwalnym artykule na temat losowego przypisywania tapety do komputera.

Musimy mieć jeszcze na uwadze dwie rzeczy. Po pierwsze, ten skrypt może zostać uruchomiony tylko na lokalnym komputerze. Czy można go zmodyfikować tak, żeby działał na komputerze zdalnym? No cóż, prawdopodobnie tak, chociaż wytropienie lokalizacji folderu Moje obrazy może stanowić spore wyzwanie. Tymczasem zakładamy, że działamy tylko na lokalnym komputerze. Nie stanowi to żadnego problemu, ponieważ skrypt jest i tak przeznaczony do wykorzystania jako skrypt wylogowywania.

To z kolei jest ta druga kwestia. Czy można zastosować ten skrypt jako skrypt logowania? Oczywiście, tylko, że w takiej sytuacji nie zauważymy zmiany tapety dopóki użytkownik się nie wyloguje i zaloguje ponownie: zmienia wartości tapety w rejestrze nie powoduje odświeżenia pulpitu i wyświetlenia nowej tapety. Są pewne sztuczki, które niekiedy okazują się w tej kwestii skuteczne, ale nie mogę ich nikomu polecać. Możecie poszukać w Internecie i spróbować sami (ale na własne ryzyko, ostrzegam). Możecie jednak zamiast tego zastosować po prostu skrypt wylogowywania.

Mam nadzieję, że jest to wyczerpująca odpowiedź na Twoje pytanie JJ. Ja tymczasem mam całą masę innych zaległości do nadrobienia, wszystkie są bezwzględnie najważniejsze i nieczepiące zwłoki.

Mam najszczerszy zamiar zając się nimi jak najszybciej. Zaraz po lunchu.

 Do początku strony Do początku strony

Centrum Skryptów - Systemy Operacyjny