Skip to Content

IT nieuczesane.
category

Category: DevOps/Scripting

skrypty, programy, command line i inne

wypisywanie wartości pliku – powershell

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.

Ku pamięci – usuwanie Forefront Client Security

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

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

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

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

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

FTM nie usuwa kolejki

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

n.

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 FilesSCCMConsoleExtensionsWOL.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 szperan
ia 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< font color="#808080">
        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 \Srv1rootSMSsite_LAB gdzie Srv1 to nazwa serwera SCCM, a LAB to trzyliterowy kod site’u. Najciekawsze klasy są w gałęzi – SMS_GroupSMS_G_System_Current*

Powershell portable

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/

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:scriptsfrmwrkdotnetfx35.exe /qb /norestart",1,true ‚.NET 3.5   
Wait "msiexec.exe","Administrator"   
Wait "setup.exe","Administrator"   
WshShell.run "C:scriptsfrmwrkdotnetfx35SP1.exe /qb /norestart",1,true ‚.NET 3.5 SP1   
Wait "msiexec.exe","Administrator"   
Wait "setup.exe","Administrator"   
‚Windows Installer 4.5   
WshShell.run "C:scriptsWindowsInstallerWindowsXP-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:Windowsregedit.exe /s c:scriptsstage2.reg",1,true   
WshShell.run "c:scriptsshutdown.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 = ""   
      &#16
0;
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_MACHINESOFTWAREMicrosoftWindows NTCurrentVersionWinlogon]  
"DefaultDomainName"
="PJWSTK"  
"DefaultUserName"
="Administrator"  
"DefaultPassword"
="StandardoweHasloAdmina"  
"AutoAdminLogon"
="3"  
"ForceAutoLogon"
="1"  

[HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRun]  
"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:scriptsfixmsdtc.cmd",0,true  
‚zatrzymanie usługi Automatic Updates – nie chcemy, żeby jakiś inny setup chodził w tle i nam coś popsuł :)  
WshShell.run "c:scriptsupdatesstop.cmd",1,true  
WshShell.run "P:DbMicrosoftMsSQL2008devsetup.exe /q /CONFIGURATIONFILE=P:DbMicrosoftMsSQL2008devConfigurationFile.ini",0,true  
Wait "setup.exe","Administrator"  
‚znów MSDTC – same kłopoty z tą usługą :/  
WshShell.run "c:scriptsfixmsdtc.cmd",0,true  
‚autologin do stage 3  
WshShell.run "c:Windowsregedit.exe /s c:scriptsstage3.reg",1,true  
WshShell.run "c:scriptsshutdown.exe -r -t 30 -f"< font color="#000000">,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:InstalkiMICROSOFTDevelopervisual_studio_2008Setupsetup.exe /UnattendFile P:InstalkiMICROSOFTDevelopervisual_studio_20082008v3.ini",0,true  
Wait "setup.exe","Administrator"  
WshShell.run "cmd /c""echo y|gpupdate /force """,1,true  
WshShell.run "c:winntshutdown.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

skrypt mapujący dyski sieciowe

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 HKCUNetwork:


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:!\.rootDefault: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.

AD Powershell na WS2003/2008 (bez R2)

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