Centrum Skryptów - Systemy operacyjne

Jak umożliwić użytkownikom zmianę rozszerzenia pliku przy pomocy polecenia SendTo?

Udostępnij na: Facebook

Skrypciarze odpowiadają na Wasze pytania

Cześć Skrypciarze!

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 umożliwić użytkownikom zmianę rozszerzenia pliku przy pomocy polecenia SendTo?

Cześć Skrypciarze! Pytanie

Cześć, Skrypciarze! Chciałbym umieścić skrypt w folderze SendTo tak, aby użytkownicy byli w stanie bez większych problemów zmienić rozszerzenie pliku (zwykle rozszerzenia plików użytkowników są ukryte, stąd problemy z ich zmianą gdy zachodzi taka potrzeba). Czy jest na to jakiś sposób?

-- JvdB

Cześć Skrypciarze! Pytanie

Cześć, JvdB! Mamy nadzieję, że tegoroczna edycja Zimowej Olimpiady Skrypciarskiej (j.ang.) przypadła Wam do gustu i nie możecie oderwać się od monitorów. Termin ostateczny dla pierwszej i drugiej konkurencji minął wprawdzie 20 lutego, ale dla dziewiątej i dziesiątej przewidziany jest gdzieś w okolicach 3 marca. Macie więc jeszcze sporo czasu, żeby się przyłączyć, szczególnie, że nagrody są naprawdę świetne w tym roku, zresztą sami zobaczcie (j.ang.).

Jak już pisałem, postanowiliśmy uhonorować osoby niemieszkające w pacyficznej strefie czasowej i rozpocząć rozgrywki nie o 8 rano czasu Redmond, ale o północy. O północy więc zamiast spać siedziałem jak … (tu proszę wstawić epitet wedle uznania) i umieszczałem na stronie wszystkie instrukcje, łącznie z tymi w różnych egzotycznych językach (j.ang.).

Ze wszystkich 200 stron dwie sprawiły mi szczególnie wiele problemów, a mianowicie sekcja dla początkujących oraz zaawansowanych, czyli te, które naprawdę były nam bardziej niż niezbędne. Po kilku godzinach syczenia i frustracji spowodowanej niemożliwością umieszczenia tych sekcji na stronie, dopiero koło trzeciej nad ranem udało się wszystko załadować jak należy. Wolę nie wspominać, że budzik nastawiłem na 6:15… Początkujący i zaawansowani, doceńcie moje starania!

Doceńcie je tym bardziej, że za chwilę Waszym oczom ukaże się skrypt, który umożliwi użytkownikom zmianę rozszerzenia pliku, jeżeli przechowamy go w folderze SendTo:

strFilePath = Wscript.Arguments(0)

strFilePath = Replace(strFilePath, "\", "\\")



strNewExtension = InputBox("Please enter the new file extension (without the period):")



strComputer = "."



Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")



Set colFiles = objWMIService.ExecQuery _

    ("Select * from CIM_DataFile where Name = '" & strFilePath & "'")



For Each objFile In colFiles

    strNewName = objFile.Drive & objFile.Path & objFile.FileName & "." & strNewExtension

    errResult = objFile.Rename(strNewName)

Next

Skrypt zaczynamy następującym fragmentem kodu. Pobiera on pierwszy argument wiersza polecenia w momencie uruchamiania skryptu:

strFilePath = Wscript.Arguments(0)

Jeżeli przeciągniecie jakiś plik lub folder na plik .VBS, to całkowita ścieżka zostanie automatycznie dodana jako argument wiersza plecenia dla tego skryptu (pliku .VBS). Tak samo dzieje się w przypadku polecenia SendTo. Jeżeli użyjecie polecenia SendTo w celu wysłania pliku lub folderu do skryptu, to całkowita ścieżka zostanie dodatkowo poszerzona o argument wiersza polecenia. Innymi słowy – kliknijcie prawym klawiszem na plik:\Scripts\Test.txt, a następnie wybierzcie opcję SendTo. Jeżeli „wyślecie” ten plik do skryptu w folderze SendTo, to jaki będzie pierwszy element kolekcji Arguments? Zgadza się - C:\Scripts\Test.txt.

To rozumie się samo przez się. Z drugim wierszem jest jednak trochę więcej zamieszania:

strFilePath = Replace(strFilePath, "\", "\\")

O co chodzi? Chodzi o użycie ścieżki pliku do kwerendy WMI. Ścieżka będzie wyglądać w sposób następujący:

C:\Scripts\Test.txt

Ścieżka zawiera dwa znaki \, mamy więc problem. Znak \ jest znakiem zastrzeżonym w kwerendzie WMI, jeżeli więc skorzystamy z niego, to plik nie zadziała. Poniższy fragment kodu wygląda dość niewinnie, ale wierzcie nam – niewinny nie jest:

Set colFiles = objWMIService.ExecQuery _

    ("Select * from CIM_DataFile where Name = 'C:\Scripts\Test.txt'")

Czy oznacza to, że w kwerendach WMI nie można używać ścieżek? Nic bardziej błędnego, musimy tylko pamiętać, że za każdym razem, gdy korzystamy ze znaku zastrzeżonego w kwerendzie WMI, musimy go jakoś „ominąć”. Dobrym sposobem

na „ominięcie” znaku \ jest zastąpienie go znakiem podwójnym w każdej ścieżce:  

C:\\Scripts\\Test.txt

Tym właśnie zajmuje się drugi wiersz – zamienia wszystkie znaki \ na \\. To da nam ścieżkę, której będzie można używać w kwerendzie WMI. Następnie prosimy użytkownika o wpisanie nowego rozszerzenia pliku (bez kropki) i przechowujemy tę wartość w zmiennej strNewExtension:

strNewExtension = InputBox("Please enter the new file extension (without the period):")

Następnie łączymy się z usługą WMI na komputerze lokalnym i wpisujemy kwerendę:

Set colFiles = objWMIService.ExecQuery _

    ("Select * from CIM_DataFile where Name = '" & strFilePath & "'")

Łączymy się tu bezpośrednio z plikiem, na który kliknął użytkownik. W tym celu wybieramy wszystkie wystąpienia klasy CIM_Datafile których nazwa – Name (ścieżka) jest równa wartości zmiennej strFilePath; czyli zmiennej zawierającej zmodyfikowaną ścieżkę (C:\\Scripts\\Test.txt). Z uwagi na to, że pliki na komputerze nie mogą się dublować, połączy nas to dokładnie z plikiem, na który kliknął użytkownik.

Uwaga: To najlepszy czas na uwagę z serii „ten skrypt działa tylko na komputerze lokalnym.” Rzeczywiście tak jest. Nie wdając się w zbytnie szczegóły, jeżeli klikniecie na ścieżkę UNC, WMI założy, że plik przechowywany jest na komputerze lokalnym. Teoretycznie można byłoby zrobić to samo na komputerze zdalnym, trzeba tylko pamiętać, aby podać skryptowi jego nazwę. Można także zmapować dysk do folderu na komputerze zdalnym. W takim przypadku to także powinno zadziałać, ścieżka będzie bowiem zawierała literę dysku, a nie ścieżkę UNC.

Nawet jeżeli kolekcja składa się tylko z jednego elementu, to nadal pozostaje kolekcją. Oznacza to, że musimy ustawić pętlę For Each, która przejdzie przez wszystkie elementy kolekcji. Pierwszą rzeczą jaką robimy w pętli jest co następuje:

strNewName = objFile.Drive & objFile.Path & objFile.FileName & "." & strNewExtension

Używamy tu wybranych właściwości pliku wyjściowego oraz nowego rozszerzenia pliku (zmieniamy nazwę pliku nadając mu nową ścieżkę). Jak się zapewne domyślacie właściwość Drive zwróci nam nazwę dysku, na którym przechowywany jest nasz plik:

C:

Właściwość Path jest właściwością, która zwraca informację o folderze minus litera dysku i nazwa pliku. W naszym przypadku ścieżka pliku to C:\Scripts\Test.txt; co oznacza, że właściwość Path jest równa \Scripts\. W połączeniu z właściwością Drive da nam to następującą ścieżkę:

C:\Scripts\

Następną właściwością jest FileName, która składa się z nazwy minus rozszerzenie pliku (pamiętamy oczywiście o kropce między nazwą a rozszerzeniem):

C:\Scripts\Test

Teraz już tylko dodajemy kropkę oraz rozszerzenie pliku (zawarte w zmiennej strNewExtension). Załóżmy, że nowym rozszerzeniem będzie log; da nam to następującą ścieżkę:

C:\Scripts\Test.log

Tym razem nie trzeba „omijać” znaków \ w ścieżce. Konieczne jest to jedynie w kwerendach. Teraz trzeba już tylko przywołać metodę Rename i zmienić nazwę pliku:

errResult = objFile.Rename(strNewName)

Tylko tyle. Działa to nawet jeżeli użytkownik ma ukryte rozszerzenia w programie Windows Explorer. Usługa WMI nie musi „widzieć” rozszerzenia, ona je po prostu zna czy tego chcemy czy nie.

Pamiętajmy jednak o dwóch rzeczach: po pierwsze - skrypt musi zostać przechowany w folderze SendTo, w innym wypadku nie będziemy mogli skorzystać z polecenia SendTo; po drugie – działa tylko na plikach. Można oczywiście próbować wysłać folder do skryptu, ale nic się nie zdarzy, gwarantuję. Foldery nie należą przecież do klasy CIM_DataFile tylko Win32_Directory.

Powinno starczyć, JvdB! Nie wiem czy jesteś początkującym czy zaawansowanym skrypciarzem, ale pamiętaj, dzięki moim workom pod oczami możesz już dziś wziąć udział w konkurencjach w obydwu działach. Wybierz sobie tylko język programowania, masz do dyspozycji VBScript, Windows PowerShell oraz Perl. Dla każdego coś miłego.

Do jutra!

 Do początku strony Do początku strony

Centrum Skryptów - Systemy operacyjne