środa, 3 lutego, 2010 - 14:09

modyfikacja grup mailowych via powershell

q pamięci, odnośnie poprzedniego wpisu:


$searcher=[ADSISearcher]LDAP://DC=domain,DC=name
$searcher.Filter=(&(ObjectClass=group)(name=STR*)) //wszyskie grupy zaczynajace sie na dany ciąg
$searcher.SearchRoot=OU=mail groups,OU=my ou,DC=domain,DC=name
$res=$searcher.FindAll()
foreach ($r in $res) {
    $grp=[ADSI]$r.path;
    $grp.mail=$($grp.mailnickname)@domain.name;
    $grp.putex(2,proxyAddresses,@(SMTP:$($grp.mailnickname)@domain.name));
    $grp.setinfo()
}



POWERSHELL RLZ! q:

*UPDATE

zostałem poproszony o małe wyjaśnienia niniejszym jakie ciekawostki można wyłapać dla początqjących. samych poleceń ADSI nie będę wyjaśniał, sqpię się na składni PS.

jednym z podstawowych problemów na początq sprawiają najprostsze rzeczy – np. wypisywanie na ekran. z punktu widzenia składni najciekawsze polecenie to “$grp.putex(2,"proxyAddresses",@("SMTP:$($grp.mailnickname)@domain.name"));”. postaram się wyjaśnić co tu się dzieje.

wypisanie zmiennej na ekran jest proste:

echo $zm

ale przy dwóch już robi się dziwnie, ponieważ:

echo $zm1 $zm2

wypisze obie.. ale w oddzielnych liniach. znakiem konkatenacji jest niby ‘+’ ale dodanie

echo $zm1 + $zm2

spowoduje wypisanie 3ech linii – gdzie ‘+’ jest normalnym znakiem. odpowiedz jest dość prosta: wystarczy zamknąć zmienne w cudzysłowach:

echo “$zm1 $zm2”

można też zastosować zapis znany z c++:

echo (“{0} {1}” –f $zm1,$zm2)

ciekawie się robi, kiedy wartość ma być  lub wartością atrybutu obiektu. PS po ‘$’ automatycznie kończy wyliczanie po pierwszym znaq specjalnym – np. kropka. w przedstawionym skrypcie wypisać należy wartość atrybutu ‘mailnickname’. wypisanie go w ten sposób:

echo “$grp.mailnickname”

wypisze $grp a na koniec doda ciąg “.mailnickname”. w związq z tym trzeba zadeklarować zmienną tymczasową, przyjmującą wartość wyliczaną:

echo “$($grp.mailnickname)”

trochę o ADSI musi być – ‘putex’ służy do ustawiania atrybutów wielowartościowych i przyjmuje 3 parametry. ten trzeci z nich to ostateczna wartość – zasady są dokładnie takie same jak przy wypisywaniu na ekran – przedstawione powyżej. dodatkowo, ponieważ atrybut jest wielowartościowy, musi to być tablica. stąd cała postać zmiennej przekazywanej do “putex” musi wyglądać tak:

@("SMTP:$($grp.mailnickname)@domain.name")

gdzie ‘@’ oznacza deklarację tablicy, potem jest ciąg, który zawiera jedną wartość wyliczaną: $($grp.mailnickname) . przykładowy output: [jednoelementowa tablica] “SMTP:nexor@domain.name”

eN.

środa, 16 grudnia, 2009 - 14:12

wypisywanie wartości pliku - powershell

Autor: nExoR | Kategorie: script/developer

muszę to sobie zapisać, bo to prościutkie zadanie po raz eNty zabiera mi czas.. [”myśl inaczej, myśl inaczej…”]

zadanie proste: odczytać wartości z pliq textowego i coś z nimi zrobić - w najłatwiejszej postaci wypisać na ekran, czyli musi to być string. najlogiczniejszą strukturą jaka mi przychodzi zawsze do głowy jest:

Get-Content .\text.file | echo $_

co przysparza mi masę problemów ponieważ dla każdej odczytanej wartości dostaję piękny komunikat błędu. następnym krokiem była próba skonwertowania otrzymanej wartości na String.. no i to jest właśnie złe myślenie - ponieważ to, co jest przepipowane [LOL może przepajpowane? (; ] to obiekt listy - a nie kolejne wartości. w związq z tym zamiast robić operacje na otrzymanej zmiennej ($_) trzeba zrobić dla niej enumerację:

Get-Content .\text.file | %{echo $_}

no… teraz w końcu zapamiętam q:

ps. pełne zadanie: plik z nazwiskiem i imieniem. otrzymać listę emaili:


PS P:\> Get-Content .\USERS.txt | %{dsquery user "OU=AA,OU=BBB,DC=DOMAIN,DC=local" -scope subtree -name "$_"} | %{ $info=dsget user "$_" -email; echo $info[1].trim()}

eN.

poniedziałek, 7 grudnia, 2009 - 9:54

Ku pamięci – usuwanie Forefront Client Security

Taki mały startup script do usuwania FCS-a ze stacji:

if not exist C:\UninstallFCS md C:\UninstallFCS 

rem uninstall Microsoft Forefront Client Security Antimalware Service
MsiExec.exe /X {D3E31640-DC20-4722-A1CF-604FF6C540B0} /norestart /qn /l*v C:\UninstallFCS\UninstallFCSAM.LOG 

rem uninstall Microsoft Forefront Client Security State Assessment Service
MsiExec.exe /X {E8B56B38-A826-11DB-8C83-0011430C73A4} /norestart /qn /l*v C:\UninstallFCS\UninstallFCSSSA.LOG 

rem uninstall Microsoft Operations Manager 2005 Agent
MsiExec.exe /X {F692770D-0E27-4D3F-8386-F04C6F434040} /norestart /qn /l*v C:\UninstallFCS\UninstallMOM.LOG

Przy czym trzeba pamiętać, żeby odfiltrować/odpiąć polisę, która go wcześniej zainstalowała.

środa, 16 września, 2009 - 19:00

AD Powershell na WS2003/2008 – teraz to już możliwe :)

Autor: domel | Kategorie: news, script/developer, server

Jakiś czas temu pisałem o Active Directory Management Gateway Service. Teraz już jest :)

Link do pobrania: http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=008940c6-0296-4597-be3e-1d24c1cf0dda

poniedziałek, 14 września, 2009 - 12:02

Usuwanie nie skasowanych profili

Idea profili mandatoryjnych jest piękna. Niestety czasami skubańce nie chcą się kasować :/ Takimi cudeńkami obdarzamy studentów, żeby jak im się coś popsuje wystarczył restart i mają świeży profil. Aby sam mechanizm wspomóc wrzuciłem do GPO taki prościutki skrypcik:

on error resume next
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFolder = objFSO.GetFolder("C:\Documents and Settings\")
Set colFOlders = objFolder.SubFolders
Dim re 
set re = New RegExp
re.Pattern = "(^s[0-9][0-9][0-9][0-9]?[0-9])|(^pd[0-9][0-9][0-9])"
For Each subFolder In colFOlders
 
if re.Test(subFolder.Name) then 
   
subFolder.delete(true)    
 
end if
Next
wtorek, 25 sierpnia, 2009 - 19:05

FTM nie usuwa kolejki

Autor: nExoR | Kategorie: script/developer

ten stary wpis to jeden z najczęściej przeze mnie wyszukiwanych na w-files. a więc zamieszam nieco uaktualnioną wersję dla powershell’a:

remove-item "$env:USERPROFILE\appdata\roaming\microsoft\File Transfer Manager\ftmTransferList*.*"

remove-item "$env:USERPROFILE\appdata\roaming\microsoft\File Transfer Manager\RequestQueue" –Force -Confirm

n.

poniedziałek, 10 sierpnia, 2009 - 16:08

SCCM Console Extensions – WOL nie działa na WS2008

Ostatnio mocno zainteresowałem się rozszerzeniami konsoli SCCMa. Ogólnie polegają one na fajnym wykorzystaniu przestrzeni nazw WMI, którą daje ConfigMgr. Ale żeby nie malować trawy na zielono najpierw zainstalowałem 2 pakiety wtyczek – SCCM Right Click Tools oraz SCCM Console Extensions. Po ich przetestowaniu muszę powiedzieć, że można robić niezłe cuda w MMC przy użyciu hta i vbs ;)

Tyle, że jedna funkcjonalność mi nie działała – Wake On Lan. Wiem, że komputery mają uruchomiony remote wake up i są podłączone do sieci (1 warstwa) mam możliwość directed broadcast (2. warstwa), więc problem musi być z działaniem samej wtyczki. Po kliknięciu tutaj:

image

Mamy śliczny komunikat, że wszystko się udało.

image

grzebiąc w kodzie znajdujemy coś takiego:

errReturn = WshShell.Run(chr(34) & strCurrentPath & "WOL.exe" & chr(34) & " " & strWOLAddress,0)
If errReturn <> 0 Then
   
LogArea.Value = LogArea.Value & "ERROR!" & vbCrLf
   
LogArea.Value = LogArea.Value & " " & Err.Description & vbCrLf
   
LogFile.WriteLine(Date & " " & Time & vbTab & "Send Wakeup: ERROR!" & vbTab & Err.Description)
   
LogArea.scrollTop = LogArea.scrollHeight
Else
   
WolSuccess = 1
   
LogArea.Value = LogArea.Value & "Wakeup sent to " & strMACAddress & vbCrLf
   
LogArea.scrollTop = LogArea.scrollHeight
   
LogFile.WriteLine(Date & " " & Time & vbTab & arrComputers(iList) & ": Wakeup sent to " & strMACAddress)
End If

Widać, że to nic innego niż wywołanie wol.exe z katalogu z rozszerzeniami. Sprawdzamy co się dzieje z tym programikiem. Po wpisaniu w CMD – "c:\Program Files\SCCMConsoleExtensions\WOL.exe" 00219B7B80CD też działa… ale ale – brakuje adresu IP i maski do kierunkowego bradcastu. Patrzymy wol.exe /? można podać tylko IP :/ niedobrze. sieci z nie klasowymi maskami odpadają. po chwili szperania w bingu znalazłem narzędzie wolcmd.exe. Usage: wolcmd [mac address] [ipaddress] [subnet mask] [port number]. No i pięknie teraz tylko wrzucić je do odpowiedniego katalogu i podmienić kawałęk skryptu na coś takiego:

strNetmask = inputbox("Provide netmask")
For Each instance in colMACAddress
   
strMACAddress = instance.MACAddress
   
strWOLAddress = (Replace(instance.MACAddress,":",""))
   
strIPAddress = instance.IPAddress
   
LogArea.Value = LogArea.Value & arrComputers(iList) & ": "
   
LogArea.scrollTop = LogArea.scrollHeight
   
errReturn = WshShell.Run(chr(34) & strCurrentPath & "wolcmd.exe" & chr(34) & " " & strWOLAddress & " " & strIPAddress & " " & strNetmask & " 7",0)
    
   
If errReturn <> 0 Then
       
LogArea.Value = LogArea.Value & "ERROR!" & vbCrLf
       
LogArea.Value = LogArea.Value & " " & Err.Description & vbCrLf
       
LogFile.WriteLine(Date & " " & Time & vbTab & "Send Wakeup: ERROR!" & vbTab & Err.Description)
       
LogArea.scrollTop = LogArea.scrollHeight
   
Else
       
WolSuccess = 1
       
LogArea.Value = LogArea.Value & "Wakeup sent to " & strMACAddress & "\" & strIPAddress & vbCrLf
       
LogArea.scrollTop = LogArea.scrollHeight
       
LogFile.WriteLine(Date & " " & Time & vbTab & arrComputers(iList) & ": Wakeup sent to " & strMACAddress)
   
End If
Next

No i wtedy działa :) Jeszcze jedna uwaga – w czasie szukania pól do skryptów niezastąpione jest narzędzie WMI CIM Studio. tylko należy pamiętać, żeby wybrać do przeglądania namespace \\Srv1\root\SMS\site_LAB gdzie Srv1 to nazwa serwera SCCM, a LAB to trzyliterowy kod site’u. Najciekawsze klasy są w gałęzi – SMS_Group\SMS_G_System_Current\*

wtorek, 4 sierpnia, 2009 - 14:15

Powershell portable

Autor: domel | Kategorie: ideas, script/developer, server, tools

Powstaje przenośna wersja PS :D na razie w fazie closed beta. nie ukrywam, że fajnie by było mieć możliwość korzystania z PowłokiMocy w śrowisku WinPE lub BartPE :) Więcej szczegółów tutaj: http://karlprosser.com/coder/2009/07/21/shelltools-portable-powershell-description-survey-and-private-beta/

czwartek, 9 lipca, 2009 - 9:22

Visual Studio Unattended

Przyszły wakacje, a więc czas odświeżania oprogramowania w salach laboratoryjnych w PJWSTK. Oczywiście wszystko powinno być nienadzorowane itd. Przez lata instalacje WinXP leżące na RIS było modyfikowane wielokrotnie – Peki, który jest autorem systemu teraz by go już nie poznał ;)

Dobra – zadnie polega na nienadzorowanej instalacji MSSQL2008 (tylko narzędzia klienckie) i Visual Studio 2008. Pierwszą rzeczą jest ustalenie kolejności instalacji. Gdyby zaczynać on VS, to trzeba by zrobić tak:

  • .NET 3.5 + Windows Installer 4.5 (wymaganie SQL2008)
  • restart
  • VS2008
  • restart
  • SP1 do VS2008
  • restart
  • SQL2008
  • restart

No i jakoś dużo tych restartów :/ gdyby zrobić odwrotnie? Zazwyczaj staram się instalować oprogramowanie według kolejności w jakiej wychodzi na świat, ale tutaj zrobię na odwrót :)

  • .NET 3.5 + Windows Installer 4.5
  • restart
  • SQL2008
  • restart
  • VS2008
  • teoretycznie restart, ale już nie wymagany :)

Jest krócej i to sporo :) Dzielimy to na 3 skrypty vbs. stage1.vbs, stage2.vbs i stage3.vbs 
Pierwszy wygląda tak:

Dim WshShell   
Set WshShell = WScript.CreateObject("WScript.Shell")   
WshShell.run "C:\scripts\frmwrk\dotnetfx35.exe /qb /norestart",1,true ‘.NET 3.5   
Wait "msiexec.exe","Administrator"   
Wait "setup.exe","Administrator"   
WshShell.run "C:\scripts\frmwrk\dotnetfx35SP1.exe /qb /norestart",1,true ‘.NET 3.5 SP1   
Wait "msiexec.exe","Administrator"   
Wait "setup.exe","Administrator"   
‘Windows Installer 4.5   
WshShell.run "C:\scripts\WindowsInstaller\WindowsXP-KB942288-v3-x86.exe /passive /norestart /overwriteoem /nobackup",1,true   
Wait "msiexec.exe","Administrator"   
Wait "setup.exe","Administrator"   
‘autologin do stage 2   
WshShell.run "c:\Windows\regedit.exe /s c:\scripts\stage2.reg",1,true   
WshShell.run "c:\scripts\shutdown.exe -r -t 30 -f",1,false   

Sub Wait (processName, userName)    
 
On Error Resume Next    
 
Dim objProcess   
 
Dim wmi   
 
Dim isRunning   
 
Dim strUser   
 
Dim return   
 
isRunning = True   
 
set wmi=GetObject("winmgmts:")   
     
 
Do While isRunning   
   
isRunning = False   
   
for Each objProcess in wmi.ExecQuery("select * from Win32_Process")   
       
strUser = ""   
       
return = objProcess.GetOwner(strUser)   
       
If return = 0 Then   
           
if UCase(objProcess.name) = UCase(processName) And UCase(strUser) = UCase(userName) then   
               
isRunning = True   
           
End if           
       
End If   
   
Next   
   
wscript.sleep 1000   
 
Loop   
wscript.sleep 10000   
     
End Sub  

Dla Ciekawskich: Plik stage2.reg wygląda tak:

Windows Registry Editor Version 5.00 

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon]  
"DefaultDomainName"
="PJWSTK"  
"DefaultUserName"
="Administrator"  
"DefaultPassword"
="StandardoweHasloAdmina"  
"AutoAdminLogon"
="3"  
"ForceAutoLogon"
="1"  

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run]  
"afterreboot"
="c:\\scripts\\stage2.vbs"

Jedziemy dalej. Żeby zrobić nienadzorowaną instalację SQL 2008 trzeba przygotować response file. Jako, że informatycy są z natury ludźmi leniwymi pozwoliłem, żeby setup MSSQL zrobił go za mnie :) Po wyklikaniu jakie składniki chcemy mieć na komputerze (w procesie zwykłej instalacji – więcej szczegółów tutaj). Jak już mamy plik odpowiedzi, to jedziemy.

stage2.vbs:

Dim WshShell  
Set WshShell = WScript.CreateObject("WScript.Shell")  
‘naprawiamy MSDTC - czasami przez zepsuty log instalacja potrafi sie wywalać. polega to na zatrzymaniu usługi MSDTC, wywołaniu msdtc -resetlog i ponownym uruchomieniu MSDTC  
WshShell.run "c:\scripts\fixmsdtc.cmd",0,true  
‘zatrzymanie usługi Automatic Updates - nie chcemy, żeby jakiś inny setup chodził w tle i nam coś popsuł :)  
WshShell.run "c:\scripts\updatesstop.cmd",1,true  
WshShell.run "P:\Db\Microsoft\MsSQL2008dev\setup.exe /q /CONFIGURATIONFILE=P:\Db\Microsoft\MsSQL2008dev\ConfigurationFile.ini",0,true  
Wait "setup.exe","Administrator"  
‘znów MSDTC - same kłopoty z tą usługą :/  
WshShell.run "c:\scripts\fixmsdtc.cmd",0,true  
‘autologin do stage 3  
WshShell.run "c:\Windows\regedit.exe /s c:\scripts\stage3.reg",1,true  
WshShell.run "c:\scripts\shutdown.exe -r -t 30 -f",1,false  

Sub Wait (processName, userName)   
 
On Error Resume Next   
 
Dim objProcess  
 
Dim wmi  
 
Dim isRunning  
 
Dim strUser  
 
Dim return  
 
isRunning = True  
 
set wmi=GetObject("winmgmts:")  
    
 
Do While isRunning  
   
isRunning = False  
   
for Each objProcess in wmi.ExecQuery("select * from Win32_Process")  
       
strUser = ""  
       
return = objProcess.GetOwner(strUser)  
       
If return = 0 Then  
           
if UCase(objProcess.name) = UCase(processName) And UCase(strUser) = UCase(userName) then  
               
isRunning = True  
           
End if          
       
End If  
   
Next  
   
wscript.sleep 1000  
 
Loop  
 
wscript.sleep 10000    
End Sub 

No już prawie koniec – jeszcze tylko Visual Studio. I tu zaczynają się schody. Teoretycznie robię to według tej instrukcji http://www.msfn.org/board/index.php?showtopic=117875, ale coś się nie udawało. Troszkę poczytać i wiem, że mój system to WinXP SP3. Ta aktualizacja zawiera już w sobie Windows Installera 3.5, więc trzeba odpowiednie wpisy usunąć z pliczku ini (więcej informacji tutaj). Ale to niestety jeszcze nie wszystko. Próba ciche instalacji się kończy po paru minutach. Wystarczy spojrzeć do Event Viewer-a, żeby zobaczyć, że Windows Installer próbuje zainstalować .NET 3.5. Jako, że już mamy nowszą wersję, to  setup zwraca błąd i sie kończy. Więc znów trzeba grzebać się w pliczku. Usuwamy wpisy dotyczące net framework z [PreInstallOrder], [InstallOrder] i [PostInstallOrder] oraz zmieniamy InstallActionInteger komponentu na 1. Teraz bangladesz :) dzięki temu mamy taki pliczek stage3.vbs:

Dim WshShell  
Set WshShell = WScript.CreateObject("WScript.Shell")  
WshShell.run "P:\Instalki\MICROSOFT\Developer\visual_studio_2008\Setup\setup.exe /UnattendFile P:\Instalki\MICROSOFT\Developer\visual_studio_2008\2008v3.ini",0,true  
Wait "setup.exe","Administrator"  
WshShell.run "cmd /c""echo y|gpupdate /force """,1,true  
WshShell.run "c:\winnt\shutdown.exe -r -t 30",1,false  

Sub Wait (processName, userName)   
 
On Error Resume Next   
 
Dim objProcess  
 
Dim wmi  
 
Dim isRunning  
 
Dim strUser  
 
Dim return  
 
isRunning = True  
 
set wmi=GetObject("winmgmts:")  
    
 
Do While isRunning  
   
isRunning = False  
   
for Each objProcess in wmi.ExecQuery("select * from Win32_Process")  
       
strUser = ""  
       
return = objProcess.GetOwner(strUser)  
       
If return = 0 Then  
           
if UCase(objProcess.name) = UCase(processName) And UCase(strUser) = UCase(userName) then  
               
isRunning = True  
           
End if          
       
End If  
   
Next  
   
wscript.sleep 1000  
 
Loop  
 
wscript.sleep 10000    
End Sub

To by było na tyle :) Działa aż miło :D

niedziela, 28 czerwca, 2009 - 14:10

skrypt mapujący dyski sieciowe

Autor: nExoR | Kategorie: script/developer

prosty problem: należy spisać co userzy mają podmapowane oraz jakie mają drukarki sieciowe.
sposób 1: podchodzi i spisywać [BUEEEE!]
sposób 2: napisać skrypt. nie jest to trudne i szybko można znaleźć gotowca w netcie ale jeden drobny problem – zarówno ‘net use’ jak obiekt ‘wscript.network’ nie wyświetlają dysqw, do których nie podano haseł. tymczasem na liście w exploratorze normalnie je widać. po kliknięciu na dysk pojawia się prośba o hasło i dopiero user może skorzystać z dysq. aby wylistować takie jeszcze-niezmapowane dyski wystarczy odczytać je z klucza HKCU\Network:


const HKCU=&H80000001
Set WshNetwork = WScript.CreateObject(”WScript.Network”)
computername=WshNetwork.ComputerName
set fso=createObject(”Scripting.FileSystemObject”)
set f=fso.CreateTextFile(computername&”.log”)
f.writeline wshnetwork.username
f.writeLine “DYSKI SIECIOWE:”
‘enum by network
‘ Set AllDrives = WshNetwork.EnumNetworkDrives()
‘ If AllDrives.Count = 0 Then f.writeLine “No Network Disk Mapped “
‘ For i = 0 To AllDrives.Count - 1 Step 2
‘ f.writeLine AllDrives.item(i)&” “&AllDrives.item(i+1)
‘ Next
‘enum by registry
set oReg=getObject(”winmgmts:!\\.\root\Default:StdRegProv”)
oReg.enumKey HKCU,”Network”,subKeys
for each skey in subKeys
oReg.getStringValue HKCU,”Network\”&skey,”RemotePath”,val
f.writeLine skey&”: “&val
next
f.writeLine vbcrlf&”DRUKARKI SIECIOWE:”
Set objPrinter = wshNetwork.EnumPrinterConnections()
‘ Extra section to troubleshoot
If objPrinter.Count = 0 Then f.writeline “No Printers Mapped “
‘ Here is the where the script reads the array
For intDrive = 0 To (objPrinter.Count -1) Step 2
intNetLetter = IntNetLetter +1
f.writeLine objPrinter.Item(intDrive) & ” = ” & objPrinter.Item(intDrive +1) & ” Printer : ” & intDrive
Next
f.writeLine “done.”

n.

sobota, 13 czerwca, 2009 - 11:32

AD Powershell na WS2003/2008 (bez R2)

Autor: domel | Kategorie: news, script/developer, server

Tomek Onyszko wygrzebał nowe KB opisujące instalację The Active Directory Management Gateway Service – czyli po ludzku  Active Directory Web Services z R2 :) teraz będzie wreszcie można korzystać z kapitalnego PS dla AD bez potrzeby upgrade kontrolera :D W poniedziałek wrzucam na środowisko testowe ;)

Link do KB: http://support.microsoft.com/?scid=969041

wtorek, 19 maja, 2009 - 23:50

regexp – wyrażenia regularne na prostym przykładzie

Autor: nExoR | Kategorie: article, script/developer

odkąd poświęciłem kilka godzin na przegryzienie się przez regexpy zakochałem się w tym wynalzq. możliwość matematycznej reprezentacji zapisu słownego – taki revers języków formalnych – to potężna rzecz.

teraz też się przydało. zadanko: jak z sieczki generowanej przez net view wyciągnąć dyski i literki tak, żeby łatwo było potem je obrabiać?

set re = new RegExp
re.pattern="^([a-zA-Z]:) (\\\\(?:[a-zA-Z0-9.]+\\?)+)"
re.ignoreCase=true

to najważniejsza część całego rozwiązania – regexp definiujący zapis typu “X: \\server\jakas\sciezka a potem cokolwiek”. to “cokolwiek” to dopisywaliśmy jako komentarz do pliq, bo nie przywidywaliśmy, że będzie potrzeba późniejszej modyfikacji/sczytywania. geniusz regexpa polega m.in. na tym, że kiedy coś znajdzie, łatwo to wyciągnąć. wyjaśnienie:

^([a-zA-Z]:)[spacja](\\\\(?:[a-zA-Z0-9.]+\\?)+) – każdy znak ma znaczenie:

  • ^ [dash] – oznacza początek linii. jeśli komentarze dawalibyśmy również na początq – wystarczy usunąć
  • () [nawiasy okrągłe]- oznaczają, że to co będzie pasowało do wyrażenia, zostanie zwrócone jako zmienna, z którą można coś później zrobić. w tym przykładzie będzie to literka dysku z dwukropkiem, która będzie przechowywana – dzięki temu mogę to potem wypisać ją lub przerobić jak chcę [np. zamienić na inną]
  • [] [nawiasy kwadratowe] – oznaczają że chodzi o znak z określonego zakresu. tutaj zakresem jest…
  • a-zA-Z – czyli dowolna litera mała lub duża z zakresu a-z
  • : [dwukropek]– po prostu znak. w sumie całe wyrażenie oznacza dowolny ciąg typu “a:”, “M:” itepe
  • [spacja] – podobnie jak w przypadq dwukropka – wszystko co nie jest poprzedzone znakiem specjalnym jest po prostu tym, czym jest – znakiem. a więc spacja to spacja – ta “[spacja]” z przykaładu
  • () – znów nawias, który oznacza, że będzie zwrócona kolejna zmienna [aka $2] – jak się z nich korzysta będzie później
  • \\\\ [4 backslashe] – backslash to znak specjalny, który eliminuje specjalność znaków specjalnych (; jeśli np. “+” jest znakiem specjalnym ale chodzi nam o znak a nie o jego funkcję, to trzeba poprzedzić go backslashem “\+” – i nie będzie interpretowany. znakiem specjalnym jest również backslash, a więc 4 bcks oznacza ciąg “\\”
  • (?:) [pytajnik i dwukropek w nawiasach okrągłych] – potem są znów nawiasy, ale tym razem od razu po nawiasie jest pytajnik i dwukropek. zmiennych zwracanych z regexpa może być 9. przy skomplikowanych dopasowaniach może się okazać, że po prostu chcemy coś zgrupować [np,. po to, żeby powiedzieć, że dany ciąg ma wystąpić X razy] ale nie interesuje nas wynik -  nie będzie przydatny do późniejszej obróbki [ma wyłącznie charakter dopasowania]. wtedy dodaje się “?:” oznaczające “nie zapamiętuj tego dopasowania”
  • [a-zA-Z0-9.]+ – część w nawiasie oznacza dowolny znak z zakresu a-z lub A-Z lub 0-9 lub kropkę. plusik na końcu oznacza od 1 do więcej powtórzeń a więc przykładami dopasowania byłyby “aaa”, “10.20.30”, “asd.kjs.d00.00”
  • \\? [2backslashe pytajnik] – jak widać z wcześniejszego przykładu, tak i tutaj znak sterujący jest na końcu – tak to jakoś właśnie w regexpach jest. pytajnik oznacza zero lub jedno wystąpienie tego, co stoi przed nim. a przed nim są 2 backslashe, co oznacza ciąg “\” który może być albo nie. a to dla tego że w ścieżce dysq jest: “\\server12\share” – co odpowiada regexpowi, który można by przeczytać “dwa slashe, potem jedno lub więcej wystąpień ciągu składającego się ze ze znaków alfabetu, cyfr lub kropek, po którym jest lub nie pojedyńczy slash”. no tak jest – jedno wystąpienie “server12\” i drugie “share”.

teraz jak to wykorzystać w kodzie:

      set file=fso.OpenTextFile(file) 
      fileBody=split(file.ReadAll,VBCrLf)
      for each line in fileBody
        if re.test(line) then 
         set matches = re.execute(line)
‘          for each match in matches
‘            wscript.echo match.value
‘          next
‘ same-same but different (: 
          wscript.echo matches(0).submatches(0)&" "&matches(0).submatches(1)
        end if
      next 

zmienna ‘file’ to gdzieś tam zdefiniowana nazwa pliq – nieważne. generalnie otwierany jest plik, powstały przy pomocy ‘net view >> somefile.log’, wczytywany do tablicy, w której kolejny wiersz to linia pliq. no i teraz zaczyna się wykorzystanie wyrażeń regularnych.

  • re.test(line) zwraca true/false – czyli czy znalazł dopasowanie czy nie. a więc jeśli linia zaczyna się ciągiem typu “x: \\server\share” to o to chodziło. jak nie – olej.
  • set matches = re.execute(line) - sam test niewiele daje. dla tego tworzony jest obiekt, do którego przypisywany jest wynik [kolekcja] z faktycznego ‘uruchomienia’ wyrażenia – trochę to redundantne bo niby sam test to już zrobił, ale trochę konieczne – to takie zabezpieczenie w stylu ochroną przed dzieleniem przez zero. można nie robić testu i po prostu wykonać execute i zobaczyć co zwraca matches.count – czyli ile jest trafień. do wyboru, do koloru
  • potem jest kilka wykomentowanych linijek, a to dla tego, że dalsza część kodu robi to samo, tylko bardziej uniwersalnie. ale zostawiłem, ponieważ to dwa sposoby wyświetlenia wyników – pierwszy ogólny:
  • for each match in matches – jak pisałem, zwracana jest kolekcja, a więc ‘dla każdego dopasowania w kolekcji’
  • wscript.echo match.value –  match.value to wartość dopasowania – całego – i dla tego ciężko coś z tym zrobić później.
  • wscript.echo matches(0).submatches(0)&" "&matches(0).submatches(1) – w tym konkretnym przypadq wynik na ekranie będzie dokładnie taki sam, ale możliwości są zupełnie inne. wyjaśnia się też tajemnica ‘zapamiętywanych zmiennych’ – które wyszuqje się za pomocą nawiasów (). w przykładzie w nawiasach były dwa dopasowania – litera dysku z dwukropkiem oraz sama ścieżka. i dokładnie to jest wypisywane – matches(0), ponieważ to pierwszy element kolekcji [i w tym przypadq jedyny – dokładnie ten, który był w powyżej wypisany jako całość] – a potem występuje ‘submatches(X)’ – co jest adekwatne do $1, $2 etc – oznacza numer ‘zapamiętaj zmiennej’ liczony od zera. a więc submatches(0) to np. ‘M:’ a submatches(1) to np. “\\server\share” dzięki temu można je wykorzystać w dowolnym momencie – choćby zamienić ich kolejność, wykonać operację na jednym z nich [np. uppercase]

regexpy mają wiele fajnych zastosowań – wszędzie tam, gdzie trzebaby w kodzie zrobić pierdylion if’ów, case’ów i innych wynalazków – które średnio się nadają do operacji na niezbyt przewidywalnych stringach. dzięki wyrażeniom regularnym można zdefiniować to w ludzkim języq.. chociaż wygląda totalnie nieludzko i mało podobnie do języka (; przykładem zastosowania są zasady normalizacji numerów telefonów – czy ktoś wpisze +48 czy 22 czy +4822 czy tylko numer telefonu, a może potem jest jakiś numer wewnętrzny? a jak firma jest w kilq lokalizacjach to prefixy będą inne, a czy numer telefonu ktoś wpisał jako 345-67-89 czy może 3456789 a może ze spacjami?… i tak dalej. a na wyjściu musi zawsze być znormalizowany numer telefonu dla danej lokalizacji. zapisuje się to bardzo prostymi wyrażeniami regularnymi w stylu “^((00|+)48)?(\d{3}.?\d{2}.?\d{2})(\d{4})?” q: pisząc to mam na myśli OCS, i tak na prawdę to wygląda tam dużo prościej.

reasumując – niewiarygodnie wygodne narzędzie, które może nie przydaje się na co dzień ale kiedy jest dla niego zastosowanie, robienie tego innymi metodami jest strzałem w kolana.

linki

ps. czemu nie w powerShell? bo siedzę tam, gdzie się teren jeszcze renderuje, i musiałem skleić coś na szybko. ale uh… trzeba będzie usiąść i do poweshella

n.

poniedziałek, 4 maja, 2009 - 16:43

powershell grep

Autor: nExoR | Kategorie: script/developer

w PS braqje czegoś aka grep. po krótkich poszukiwaniach można znaleźć polecenie ‘Select-String –pattern “czego szukam” ‘ ale po krótkich testach okazuje się, że to się zachowuje trochę niedeterministycznie… znaczy się… trzeba mieć pewność, że to, co zwraca inny cmdlet to string. wystarczy kilka doświadczeń typu:

  • get-childitem | Select-String –pattern “win” – działa ok i wypisze np. “Windows”
  • get-help | Select-String –pattern “syn” – już nie zadziała wedle oczekiwań
  • get-help get-childitem | Select-String –pattern “syn” – zadziała totalnie nie wedle oczekiwań

taki to dziwny zwierz. zaufać mu w każdym razie dość trudno w obecnej postaci. dla tego polecam przypomnieć sobie taki systemowy util, który polecam, bo działa deterministycznie:

PS C:\> findstr /?
Searches for strings in files.

FINDSTR [/B] [/E] [/L] [/R] [/S] [/I] [/X] [/V] [/N] [/M] [/O] [/P] [/F:file]
        [/C:string] [/G:file] [/D:dir list] [/A:color attributes] [/OFF[LINE]]
        strings [[drive:][path]filename[ …]]

n.

wtorek, 28 kwietnia, 2009 - 18:52

Backup SVN (Windows + Apache)

Autor: kfaz | Kategorie: script/developer

Jako, że nie da się backupować bezpośrednio repozytorii SVN będących on-line, trzeba było napisać prosty skrypt, który najpierw zrobi ich hotcopy a dopiero potem backup na zadaną lokalizację sieciową. Zamiast robienia backup set i używania ntbackup można spakować cały folder docelowy i przegrać go zwykłym xcopy, w sumie wyjdzie na to samo a pewnie będzie szybciej i prościej do odzyskiwania.

Środowisko:
Windows Server 2003
Apache 2.2 z modułem SVN

' SVNbackup.vbs
' Backups all SVN repositories from selected directory + Apache config
' Author Kuba Siatkowski http://w-files.pl/author/kfaz
' ver 1.0.1


optionexplicit Const FOR_READING = 1 Dim strReposFolder, colReposFolders, strBackupFolder, colBackupFolders, strBackupLocation, strApacheLocDim objFSO,WshShell, objReposFolder, objBackupFolder, objSubFolder, objSubBackupFolder, strBackupset, fileBackupset

strReposFolder = "C:\RepositorySVN"                                 ' place where all SVN repos are
strBackupFolder = "C:\backup\"                                      ' temp folder for local backups
strBackupLocation = "\\backupserver\backupshare\backupname.bkf"     ' place for backups
strApacheLoc = “C:\Apache\” ‘apache directory (SVN configs, plug-ins etc)
strBackupset = strBackupFolder&“backupset.bks”


Set objFSO = CreateObject("Scripting.FileSystemObject")
Set WshShell = WScript.CreateObject("WScript.Shell")
Set objReposFolder = objFSO.GetFolder(strReposFolder)
Set colReposFolders = objReposFolder.SubFoldersSet
objBackupFolder = objFSO.GetFolder(strBackupFolder)
Set colBackupFolders = objBackupFolder.SubFoldersSet
fileBackupset = objFSO.CreateTextFile(strBackupset, True)

'delete old backups from temp folder
For Each objSubBackupFolder In colBackupFolders


objSubBackupFolder.Delete True

Next

‘hotcopy all repos from reposdir and create backupset
For Each objSubFolder In colReposFolders

WshShell.run "svnadmin.exe hotcopy "&strReposFolder&"\"&objSubFolder.Name&" "&strBackupFolder&objSubFolder.Name, 1, true
fileBackupset.WriteLine ""&strBackupFolder&objSubFolder.Name&"\"

Next

'add Apache to backupset
fileBackupset.WriteLine ""&strApacheLoc fileBackupset.close ‘do the backup
WshShell.run "ntbackup.exe backup @"&strBackupset& " /n ""SVN Repos “&Now&""" /v:yes /r:no /rs:no /hc:off /m normal /j ""SvnBackup""/l:s /f "&strBackupLocation, , true

czwartek, 9 kwietnia, 2009 - 12:57

Czy programowanie może być zabawą?

Autor: nExoR | Kategorie: rec, script/developer

takie oto pytanie zawitało dzisiaj w moim RSS readerze, zadane przez GT – przepraszam Cię Grzesiu, że nie w komentarzach tylko tak tutaj – ale pytanie ciekawe, a odpowiedź zbyt długa, żeby ją wklepywać jako comment – a ping backa powinieneś dostać [jeśli masz włączonego]. nie traktuj tego więc jako atak – to czysta polemika (:

“A kto pamięta LOGO? Proste to było do bólu, ale uczyło myślenia.”

oj pamiętam ci ja logo, pamiętam – uczyłem się go na bosmanach 8. założeniem logo była edukacja i na początq lat 9o’  miało to sens. kilka lat temu [ok 4-5] miałem nieprzyjemność uczenia logo – takiego nowego, z innym edytorem, niby-obiektowego etc. mając porównanie czasów ‘wtedy’ oraz ‘dziś’ mogę śmiało powiedzieć – LOGO TO SYF. język nieprzemyślany, gdzie na siłę wtrącono część obiektowości, pozostawiając w wielu miejscach podejście strukturalne, totalnie zwalony edytor, który wręcz zmusza do zrobienia bałaganu w kodzie, ciężko cokolwiek znaleźć – po prostu masakra. jedyne czego można po logo oczekiwać to nauczenia się totalnie złych manier programowania, niespójności i raczej się można zrazić niż nauczyć. do dziś na murach można spotkać napisy ‘punk not dead’ a nawet czasem odbędzie się jakiś koncert – gdzie 8o% ludzi jest powyżej 4otki. z logo jest podobnie – należy pochylić czoło nad kawałkiem historii i zapomnieć.

“W systemie DOS, podobnie jak w ośmiobitowcach (nie wnikam czy było to Atari, Commodore, Spectrum czy jeszcze coś innego) proste środowisko programistyczne było dostępne od ręki. A teraz?”

a teraz od wieków w windzie jest WSH, od niedawna powershell, w linuxach bash… oj bez GUI? no to TCL … ale po co w ogóle szukać po jakiejś niszy? czemu nie Java lub .NET – pierwsze prawdziwie języki obiektowe? być może ponieważ:

“Pomijam już to, że środowiska programistyczne zazwyczaj są olbrzymimi pakietami oprogramowania, które zachowują się nieraz tak, jakby były samodzielnymi systemami.”
oraz
Pomijając kwestie środowiska, programowanie w XXI wieku nie jest tak proste jak kiedyś. Dawniej dało się napisać program mieszczący się w jednym pliku, bez tony #include i innych Using.

nie prawda. do napisania ‘hello world’ potrzebujesz dokładnie tylko samo kodu – no ok. z jednego includa trzeba dodać. i bardzo dobrze. ale jeśli chcesz coś narysować, napisać lub skorzystać np z sieci – kiedyś musiałeś napisać toooooonę kodu – teraz dołączasz bibliotekę, która i tak działa o niebo lepiej niż większość by to sama zrobiła. i jest przenośne. zamiast uczyć się ‘jak coś działa’ [np. przebijanie się przez RFC od TCP/IP] sqpiasz się na logice – w końcu developer nie musi być architektem. równie dobrze można powiedzieć, że najlepszy był assembler. po co mam pisać algorytm na rysowanie koła, skoro mogę po prostu napisać rysujOkrag(10) q:
co do kompilatora – nie trzeba instalować visual studio – może owszem, microsoft ma taką politykę, że .net kojarzy się z VS, ale przecież wystarczy dobry edytor z podkreślaniem składni [np. pspad] – zarówno do javy jak i .neta i zainstalowany framework/VM. nie jestem ‘na bieżąco’ ale są małe środowiska do obu tych języków – po szybkim googlaniu np. tutaj. małe, szybkie, do pierwszych zabaw wystarczą – wcale nie trzeba SQL ani pierdyliona dodatków.

Tylko, czy przypadkiem nie stało się tak, że zginęła w tym radość z napisania czegoś, co działa? Czy dzisiaj dziesięciolatek ma szansę siąść i napisać kilka albo kilkadziesiąt linii kodu, które zapytają o imię i wyświetlą okienko, w którym to imię zostanie wstawione w komunikat "Jasio umie programować!"?

imho – nie. co więcej – ma szansę to zrobić bez problemu, ponieważ to nie jest na tym etapie kwestia języka tylko nauczyciela oraz kompilatora. taka aplikacja to w javie tyle samo kodu w VB – a jeśli jest go więcej wizualnie, to i tak ‘sprytny edytor’ doda wszystko co potrzebne na początek – a co to oznacza można wytłumaczyć później.
różnica polega jednak na tym, że jak ktoś się zacznie uczyć języków strukturalnych, a już nie-daj-wielki-informatyku takich archaizmów jak BASIC, to potem będzie musiał się na nowo uczyć obiektowych. wiem – bo sam przez to przeszedłem i przełamanie sposobu myślenia jest dość bolesne. developerem nie zostałem [czego trochę żałuję, ale tak się potoczyło], ale miałem okazję kombinować w różnych wynalazkach – logo, basic, pascal, c, c++, java, .net, php, vbs+hta, sql, vba, fortran, c-MPI, shellowe cmd, bash itd – i po wszystkich przejściach, zakochałem się w obiektowości. dla tego z resztą tak dobrze gada mi się z AD a tak bardzo nie znoszę poronionego SQL. imho warto zainwestować czas od razu w coś, co będzie przyszłościowe, zamiast babrać się w oldschoolu. nie twierdzę, że to nie ma wartości edukacyjnych, ale to ślepa uliczka i pewne zderzenie z rzeczywistością jeśli ktoś w tym kierunq będzie podążał.

“Mówiąc w największym skrócie: Jestem za powrotem BASICa do łask!”

w-życiu-never! (;

jeśli chodzi o 1o latków – ale nie tylko – to polecam grę CeeBot – imho do osób, które chcą efekty zobaczyć najszybciej – docieranie poprzez fabułę jest najefektywniejszy – i nie tylko zobaczymy ‘jaś jest programistą’ ale w ciągu kilq chwil można sterować własnym robotem! Chciałem nawet robić z tego zajęcia, ale licencja edu była za droga na moją kieszeń, a uczelnia nie chciała wydawać ):

n.

środa, 8 kwietnia, 2009 - 19:19

Przenoszenie nieaktywnych kont do innego OU

Autor: kfaz | Kategorie: script/developer, windows

Trzeba było znaleźć wszystkich użytkowników, którzy nie logowali się od dłuższego czasu i przenieść ich do innego OU.
Problemy jakie się pojawiły to wartość atrybutu LastLogonTimeStamp, która jest specyficzna (liczba milisekund od epoki) i przenoszenie obiektów w AD. O ile pierwsze było proste do wygooglania o tyle z drugim strasznie ludzie kombinują, piszą miliony linii kodu i generalnie żadne z tych rozwiązań mi się nie podobało. Chwila samodzielnego kombinowania, trochę rzeźby i olśnienie w postaci, że PowerShell to przecież… shell :) i że działają w nim komendy commandlinowe takie jak np. dsmove :)

Poniżej skrypt, który znajduje wszystkich w danym OU , którzy nie logowali się od 14 miesięcy i przenosi ich od OU inactive. Minimalne wymagania: domena w trybie “Windows Server 2003”

# script finds all users in specified OU who haven’t logged for last n months # and moves theirs accounts to another OU # Author Kuba Siatkowski http://interkreacja.pl/
$howoldallowed = 14; #maximum time since last logon (months) $dom ="LDAP://OU=sourceou,DC=yourdomain,DC=com,DC=pl"; #search path $newparent ="OU=inactive,DC=yourdomain,DC=com,DC=pl"; #destination path for unused accounts #$Root = New-Object DirectoryServices.DirectoryEntry $strROOT $Root = New-Object DirectoryServices.DirectoryEntry $Dom $Searcher = New-Object DirectoryServices.DirectorySearcher $Searcher.SearchRoot = $root $searcher.Filter = (&(objectClass=User)(!(objectClass=Computer))); $users = $searcher.findAll(); $lastallowed = [DateTime]::Now.AddMonths($howoldallowed * (-1)); foreach ($user in $users) { if (!($user.Properties.lastlogontimestamp -eq $Null)){ $lastlogon = [DateTime]::FromFileTime([Int64]::Parse($user.Properties.lastlogontimestamp)); if (($lastlogon -lt $lastallowed)){ write-host $user.Properties.cn “; -NoNewLine; write-host $lastlogon ; -NoNewLine; write-host $user.Properties.distinguishedname; dsmove $de.distinguishedName -newparent $newparent } } else { write-host $user.Properties.cn never logged on; } }
środa, 8 kwietnia, 2009 - 16:07

Ustawianie msSFU30GidNumber dla wszystkich grup w domenie

Autor: kfaz | Kategorie: script/developer, windows

Linuxy potrzebują parametru msSFU30GidNumber żeby widziały grupy z Active Directory. Do tej pory pojedyńcze MsSFUGidy robiliśmy ręcznie z ADSIEdit, jednak kiedy przyszło ponad sto nowych grup to trzeba było to jakoś oskryptować.

Skrypt poniżej:

  1. znajduje maksymalny MsSFUGid w domenie
  2. wszystkim grupom, które nie mają msSFUGID przypisuje kolejne numery 

Jego wadą jest to, że dodaje Gidy wszystkim grupom ale to można zmienić np. poprzez ustawienie odpowiedniego roota przed drugą pętla.

$Root = New-Object DirectoryServices.DirectoryEntry $strROOT
$Searcher = New-Object DirectoryServices.DirectorySearcher
$Searcher.SearchRoot = $root
$searcher.Filter =  "(&(objectClass=Group))";
$numer = 0;
$gid ;
$groups = $searcher.findAll();
foreach ($group in $groups)
{
   $de = New-Object DirectoryServices.DirectoryEntry $group.Path;
   $gid = [int]$de.msSFU30GidNumber.ToString();
#  write-host $gid ";" -NoNewLine;
#  write-host $de.name;
   if ($numer -lt $gid )
   {
     $numer = $gid;
#    $numer;
   }
}
$numer++;

foreach ($group in $groups)
{
  $de = New-Object DirectoryServices.DirectoryEntry $group.Path;
  $gid = [int]$de.msSFU30GidNumber.ToString();
  if ($gid -eq 0)
  {
    $de.msSFU30GidNumber = $numer;
    $de.SetInfo();
    write-host $numer ";" -NoNewLine;
    write-host $de.name;
    $numer++;
  }
}

środa, 8 kwietnia, 2009 - 15:47

Pozwalanie użytkownikom na uruchamianie/zatrzymywanie serwisów

Autor: kfaz | Kategorie: HOWTO, script/developer, windows

Mamy na stacji zainstalowanego Apacha, Network Inspectora czy Flash Server i nie chcemy żeby chodziły one przez cały czas i bezsensownie zżerały nam zasoby. Chcemy pozwolić użytkownikowi na uruchamianie/zatrzymywanie serwisów i nie nadawać mu zbędnych uprawnień. Najprościej jest to zrobić ustawiając z poziomu domeny odpowiednią polisę która ustawi odpowiednie ACL na dany serwis (tak serwisy też mają ACL :o ).
Co jednak zrobić w momencie gdy komputer nie jest w domenie? Zawsze wydawało mi się, że wszystko da się ustawić w Local Security Policy. Windows + R wpisuję secpol.msc (albo gpedit.msc, jak kto woli ;) ) enter i nie ma serwisów :-o . Wszystko wskazuje na to, że nie da rady tego ustawić lokalnie jednak z pomocą przychodzi Security Configuraration and Analysis (dla nieświadomych start -> run -> mmc -> ctrl+m -> add -> Security Configuraration and Analysis ). Dodaję nową bazę, importuję template (dla bezpieczeństwa polecam setup security.inf), analizuję komputer, po czym kiedy już pokaże mi się drzewko wchodzę w System Services wybieram interesujący mnie serwis i ustawiam mu ACL’ki :) .
Ciekawe czemu jest to wycięte z interfejsu w secpol.msc? Po co wycieli coś co i tak da się ustawić? bez sensu…

Po tem jeszcze warto dać użytkownikom narzędzie pozwalające na wygodnie uruchamianie/zatrzymywanie serwisów. Może to być prosty batch wyglądający mniej więcej tak:
NET START "Nazwa serwisu"
albo tak:
NET STOP "Nazwa serwisu"

A gdybyśmy chcieli pisać to w Visual Basicu (np. po to żeby sprawdzać coś zanim nasz serwis wstanie, zrobić ładny interface graficzny itp. itd.) to przyda się ten kawałek kodu:

‘ Uruchom zatrzymaj serwis
option explicit
dim queryString
dim Service, ServiceSet

queryString = "select * from Win32_Service where Name=’Nazwa serwisu’ and State=’Stopped’"
Set ServiceSet = GetObject("winmgmts://.").ExecQuery(queryString)

if ServiceSet.Count <> 0 then
WScript.echo “Uruchamiam serwis”
for each Service in ServiceSet
Service.StartService()
next
else
WScript.echo “Jesteś kretynem, serwis już działa”
end if

niedziela, 22 marca, 2009 - 10:48

Jakie aliasy stworzyć w shellu?

Autor: cabi | Kategorie: HOWTO, script/developer

Poniższe pokazuje listę poleceń wraz z ich ilością wywolanych np. w bash albo ksh.

Jeśli jakieś rozbudowane polecenie wywołujesz często, może warto zrobić aliasa dla niego:

history|awk '{print $2}'|awk 'BEGIN {FS="|"} {print $1}'|sort|uniq -c|sort

sobota, 21 marca, 2009 - 16:39

MUI - script it

Ostatnio siedzę i bawię się windowsowym Multilingual User Interface. Posiłkując się tym oto artykułem zintegrowałem MUI z instalką na RISie. Ale tu pojawił się problem - jak niezbyt technicznym ludziom pokazać sposób zmiany języka? Tutorial? Nieeeeeee. Za dużo pracy ;) Idąc za radą NeXoRa “If it moves - script it” udało mi się z Kfaz’a pomocą spłodzić coś takiego:

Piczek.vbs

Set WshShell = WScript.CreateObject(”WScript.Shell“)

WshShell.run “regedit /s “”G:\Program Files\MUI\jap.reg”“”,1,true
WshShell.run "taskkill /F /IM explorer.exe“,1,true
WshShell.run "explorer.exe“,1,false

jap.reg

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Control Panel\Desktop]
"MUILanguagePending“=”00000415
"MultiUILanguageId“=”00000415

Ogólnie idea jest prosta. Podmień wpisy w rejestrze (znalezienie ich trwa krótką chwilę), zabij explorera i uruchom go w kontekście nowego UI. Co do kodów języków, to są one dostępne tutaj.