En kollega till mig bad mig ordna fram en lista på alla servrar i domänen och lista deras ip-adresser från DNS:en. I detta fall räckte de med att filtrera alla datorkonton som börjar på S för att få fram endast servrar. Jag sparade listan "namn = ip-adress" men de går lika enkelt att skriva "namn;ip-adress" om man vill ha de kommaseparerat. Jag var tvungen att skriva en lite felhantering då en stor del av datorkontona inte fanns med i DNS:en.
Får tacka Ghost6Shell för den enkla och mycke användbara namnupplösningen!
http://nex6.blogspot.com/2009/02/using-powershell-to-reslove-host-name.html
--- Skript ---
Import-Module activedirectory
Get-ADComputerForEach-Object -Filter {Name -like "S*"} | {
$ServerName = $_.Name
try
{
$IP = [System.Net.Dns]::GetHostAddresses($ServerName)|
Select-Object IPAddressToString -ExpandProperty IPAddressToString
"$ServerName = $IP"
}
Catch
{
"$ServerName ="
}
} | Out-File -FilePath .\server_ip.txt
Hej och välkomna till min blogg om mina Microsoft Powershell erfarenheter. Här kommer jag skriva artiklar om hur Powershell skriptande har förgyllt min arbetsdag.
onsdag 21 december 2011
tisdag 20 december 2011
Hitta kataloger utan ägare.
Många miljöer som jag varit i har haft problem med att hantera avveckling av resurser vid avslut. Detta brukar visa sig när personalen slutar och de är dags att ta bort hemkatalogen. Om det inte finns fungerande rutiner för avveckling av användare brukar det ofta ligga hemkataloger kvar som ingen vill hantera. Jag skrev denna oneliner för att urskilja vilka kataloger som inte längre har en ägare som går att slå upp i domän eller i datorn.
Get-ChildItem C:\Temp |Where-object {$_.psIsContainer -eq $true}| get-acl | Select-Object Path, owner | where-object {$_.owner.StartsWith("O:S-1")}
Uppdatera till din katalogstruktur och prova. Obs det är en rad.
Get-ChildItem C:\Temp |Where-object {$_.psIsContainer -eq $true}| get-acl | Select-Object Path, owner | where-object {$_.owner.StartsWith("O:S-1")}
Uppdatera till din katalogstruktur och prova. Obs det är en rad.
Etiketter:
ACL,
Folder,
Microsoft Powershell,
Owner
måndag 12 december 2011
Ini-filer och Powershell
En sak som jag trodde skulle vara trivialt att lösa med Powershell, var att jobba med ini-filer. Det är inte så edge att arbeta med dem men det kan ändå krävas. Jag har grävt lite själv och hittat en lösning som använder WindowsApi för att läsa och skriva i en ini-fil.
Trist nog har jag inte kvar länken till artikeln som jag kopierade. Funktionerna som läser och skriver från och till ini-filer. Skriptet kan verka överdrivet för att endast läsa ini-filer men de fungerar bra. Jag provade själv med några sök och ersätt funktioner men i större miljöer är det väldigt plågsamt att inte ha en ytterst exakt lösning.
De är tre funktioner i skriptet.
Function Invoke-WindowsApi {
param(
[string] $dllName,
[Type] $returnType,
[string] $methodName,
[Type[]] $parameterTypes,
[Object[]] $parameters
)
$domain = [AppDomain]::CurrentDomain
$name = New-Object Reflection.AssemblyName 'PInvokeAssembly'
$assembly = $domain.DefineDynamicAssembly($name, 'Run')
$module = $assembly.DefineDynamicModule('PInvokeModule')
$type = $module.DefineType('PInvokeType', "Public,BeforeFieldInit")
$inputParameters = @()
$refParameters = @()
for($counter = 1; $counter -le $parameterTypes.Length; $counter++)
{
if($parameterTypes[$counter - 1] -eq [Ref])
{
$refParameters += $counter
$parameterTypes[$counter - 1] =
$parameters[$counter - 1].Value.GetType().MakeByRefType()
$inputParameters += $parameters[$counter - 1].Value
}
else
{
$inputParameters += $parameters[$counter - 1]
}
}
$method = $type.DefineMethod($methodName, 'Public,HideBySig,Static,PinvokeImpl',
$returnType, $parameterTypes)
foreach($refParameter in $refParameters)
{
[void] $method.DefineParameter($refParameter, "Out", $null)
}
$ctor = [Runtime.InteropServices.DllImportAttribute].GetConstructor([string])
$attr = New-Object Reflection.Emit.CustomAttributeBuilder $ctor, $dllName
$method.SetCustomAttribute($attr)
$realType = $type.CreateType()
$realType.InvokeMember($methodName, 'Public,Static,InvokeMethod', $null, $null,
$inputParameters)
foreach($refParameter in $refParameters)
{
$parameters[$refParameter - 1].Value = $inputParameters[$refParameter - 1]
}
}
Function Read-Ini {
param(
$file,
$category,
$key)
$returnValue = New-Object System.Text.StringBuilder 500
$parameterTypes = [string], [string], [string], [System.Text.StringBuilder], [int], [string]
$parameters = [string] $category, [string] $key, [string] "",
[System.Text.StringBuilder] $returnValue, [int] $returnValue.Capacity, [string] $file
[void] (Invoke-WindowsApi "kernel32.dll" ([UInt32]) "GetPrivateProfileString" $parameterTypes $parameters)
$returnValue.ToString()
}
Function Write-Ini {
param(
$file,
$category,
$key,
$value)
$parameterTypes = [string], [string], [string], [string]
$parameters = [string] $category, [string] $key, [string] $value, [string] $file
[void] (Invoke-WindowsApi "kernel32.dll" ([UInt32]) "WritePrivateProfileString" $parameterTypes $parameters)
}
Trist nog har jag inte kvar länken till artikeln som jag kopierade. Funktionerna som läser och skriver från och till ini-filer. Skriptet kan verka överdrivet för att endast läsa ini-filer men de fungerar bra. Jag provade själv med några sök och ersätt funktioner men i större miljöer är det väldigt plågsamt att inte ha en ytterst exakt lösning.
De är tre funktioner i skriptet.
- Invoke-WindowsApi
Som namnet säger så sköter denna funktion anropen mot Windows-api och i detta skript anropas av dom andra två Read-ini och write-ini funktionerna.
- Write-ini
Skriver till ini-filer.
Parametrar: Fil, kategori, nyckel, värde
ex:
Write-Ini "C:\Windows\win.ini" "Min sektion" "Test" "Värdet" - Read-ini
Läser ini-filer.
Parametrar: Fil, kategori, nyckel
Ex:
Read-ini "C:\Windows\win.ini" "Min sektion" "Test"
------Skript nedan------Lycka till!
Function Invoke-WindowsApi {
param(
[string] $dllName,
[Type] $returnType,
[string] $methodName,
[Type[]] $parameterTypes,
[Object[]] $parameters
)
$domain = [AppDomain]::CurrentDomain
$name = New-Object Reflection.AssemblyName 'PInvokeAssembly'
$assembly = $domain.DefineDynamicAssembly($name, 'Run')
$module = $assembly.DefineDynamicModule('PInvokeModule')
$type = $module.DefineType('PInvokeType', "Public,BeforeFieldInit")
$inputParameters = @()
$refParameters = @()
for($counter = 1; $counter -le $parameterTypes.Length; $counter++)
{
if($parameterTypes[$counter - 1] -eq [Ref])
{
$refParameters += $counter
$parameterTypes[$counter - 1] =
$parameters[$counter - 1].Value.GetType().MakeByRefType()
$inputParameters += $parameters[$counter - 1].Value
}
else
{
$inputParameters += $parameters[$counter - 1]
}
}
$method = $type.DefineMethod($methodName, 'Public,HideBySig,Static,PinvokeImpl',
$returnType, $parameterTypes)
foreach($refParameter in $refParameters)
{
[void] $method.DefineParameter($refParameter, "Out", $null)
}
$ctor = [Runtime.InteropServices.DllImportAttribute].GetConstructor([string])
$attr = New-Object Reflection.Emit.CustomAttributeBuilder $ctor, $dllName
$method.SetCustomAttribute($attr)
$realType = $type.CreateType()
$realType.InvokeMember($methodName, 'Public,Static,InvokeMethod', $null, $null,
$inputParameters)
foreach($refParameter in $refParameters)
{
$parameters[$refParameter - 1].Value = $inputParameters[$refParameter - 1]
}
}
Function Read-Ini {
param(
$file,
$category,
$key)
$returnValue = New-Object System.Text.StringBuilder 500
$parameterTypes = [string], [string], [string], [System.Text.StringBuilder], [int], [string]
$parameters = [string] $category, [string] $key, [string] "",
[System.Text.StringBuilder] $returnValue, [int] $returnValue.Capacity, [string] $file
[void] (Invoke-WindowsApi "kernel32.dll" ([UInt32]) "GetPrivateProfileString" $parameterTypes $parameters)
$returnValue.ToString()
}
Function Write-Ini {
param(
$file,
$category,
$key,
$value)
$parameterTypes = [string], [string], [string], [string]
$parameters = [string] $category, [string] $key, [string] $value, [string] $file
[void] (Invoke-WindowsApi "kernel32.dll" ([UInt32]) "WritePrivateProfileString" $parameterTypes $parameters)
}
fredag 25 november 2011
Egna menyval i ADUC (Active Dirtectory Users and Computers)
Ett sätt att förenkla exekveringen av ps-skript i ett ou(organizationalunit) exempelvis är att använda "DisplaySpecifiers". Jag har jobbat med ett uppdrag där vi byggde en rollbaserad rättighets-struktur. Den rollbaserade strukturen krävde många ou, grupper, och gpo(Group Policy Objects). Vi valde då att skapa menyval när administratörer högerklickar på ett ou i ADUC. ADUC skickar med sökvägen till de aktuell ou:t och jag använder de i skripten nedan.
I exemplet nedan startar jag en powershell promt i aktuellt ou. Detta exempel kräver Powershell 2.0 och möjligheten att använda moduler.
Använd ADSIedit.msc och och öppna
CN=organizationalUnit-Display,CN=409,CN=DisplaySpecifiers,CN=Configuration,DC=Lab,DC=local
Nyckel : adminContextMenu
* 409 engelska
* 41d svenska
Lägg till en ny rad med ditt skript.
4,PS i detta OU,PS-Here.cmd
- Nummer för sorteringen på menyn.
- Namnet som kommer synas på menyn.
- Namnet på de som kommer exekveras.
Exempel på cmd-filen: C:\Windows\System32\PS-Here.cmd
@echo off
PowerShell.exe -NoExit -File "C:\Skript\ps-here.ps1" %1
Exempel på ps-filen: C:\Skript\ps-here.ps1
Import-Module ActiveDirectory
$sPath = $args[0]
$sPath = $sPath.Substring($sPath.LastIndexOf("/")+1)
$sPath = "AD:\\" + $sPath
cd $sPath
Domänpartitionen måste synkroniseras och ADUC måste startas om innan menyerna syns.
Detta är endast ett exempel på vad som skulle kunna exekveras. I mitt fall har jag skapat flera olika funktioner kopplade till ou-strukturen. Lycka till.
fredag 18 november 2011
Uppdatera rättigheter på underkataloger.
Orsak: De finns ingen ändra rättighet på en katalog som ger möjligheten att byta namn. För ett namnbyte krävs två rättigheter.
1. "Delete" på katalogen som ska byta namn
2. "Create" på överordnad katalog.
Att kunna uppdatera ACL:er på en katalog eller som i detta fallet alla underkataloger på ett share, är en enkel uppgift med detta Powershellskriptet. I detta fallet som jag arbetade med gällde de hemkataloger och därför kunde jag inte använda arv av säkerhetsskäl.
Uppgift: Ett konto ska ha en rättighet på alla underkataloger utan att slå på arv.
När jag första gången körde skriptet märkte jag att de kontot som användes inte hade rättigheter till alla underkataloger. Jag använde "Try & Catch" för att fånga felen och i mitt fall kommer jag hantera dom katalogerna som inte lyckats senare.
Referens:
http://technet.microsoft.com/en-us/library/ff730951.aspx
Skript:
$ScriptPath = $MyInvocation.MyCommand.Path
$ScriptDir = split-path -parent $ScriptPath
$ScriptName = [system.io.path]::GetFilenameWithoutExtension($ScriptPath)
$sShare = file://filesrv01/homefolder$/usr
# Skapar ACE-objekt
$colRights = [System.Security.AccessControl.FileSystemRights]"Delete"
$InheritanceFlag = [System.Security.AccessControl.InheritanceFlags]::None
$PropagationFlag = [System.Security.AccessControl.PropagationFlags]::None
$objType =[System.Security.AccessControl.AccessControlType]::Allow
$objUser = New-Object System.Security.Principal.NTAccount("domain\user")
$objACE = New-Object System.Security.AccessControl.FileSystemAccessRule _
($objUser, $colRights, $InheritanceFlag, $PropagationFlag, $objType)
# Skapar Arrayer för loggning av resultat.
$FolErr = @()
$FolOK = @()
# Lista endast underkataloger och uppdaterar rättigheterna på dom.
Get-ChildItem $share | Where {$_.psIsContainer -eq $true} | foreach {
try {
$FolderName = $_.name
$objACL = $_ | Get-ACL
$objACL.AddAccessRule($objACE)
$_ | Set-Acl -AclObject $objACL
$FolOK += $_.name
}
# Fångar dom katalogerna som jag inte får läsa rättigheterna på.
catch [UnauthorizedAccessException]
{
"De gick inte att läsa rättigheterna på $FolderName"
$FolErr += $FolderName
}
}
# Bygger namn och sökväg till logfilerna.
$sshareName = $sShare.Split("\")[3]
$errfileName = "$ScriptDir\$sshareName" + "_Err.txt"
$okFileName = "$ScriptDir\$sshareName" + "_OK.txt"
# Summerar kataloger som är rättade och vilka som inte lyckats.
$FolErr | out-file -FilePath $errfileName
$FolOK | out-file -FilePath $okFileName
1. "Delete" på katalogen som ska byta namn
2. "Create" på överordnad katalog.
Att kunna uppdatera ACL:er på en katalog eller som i detta fallet alla underkataloger på ett share, är en enkel uppgift med detta Powershellskriptet. I detta fallet som jag arbetade med gällde de hemkataloger och därför kunde jag inte använda arv av säkerhetsskäl.
Uppgift: Ett konto ska ha en rättighet på alla underkataloger utan att slå på arv.
När jag första gången körde skriptet märkte jag att de kontot som användes inte hade rättigheter till alla underkataloger. Jag använde "Try & Catch" för att fånga felen och i mitt fall kommer jag hantera dom katalogerna som inte lyckats senare.
Referens:
http://technet.microsoft.com/en-us/library/ff730951.aspx
Skript:
$ScriptPath = $MyInvocation.MyCommand.Path
$ScriptDir = split-path -parent $ScriptPath
$ScriptName = [system.io.path]::GetFilenameWithoutExtension($ScriptPath)
$sShare = file://filesrv01/homefolder$/usr
# Skapar ACE-objekt
$colRights = [System.Security.AccessControl.FileSystemRights]"Delete"
$InheritanceFlag = [System.Security.AccessControl.InheritanceFlags]::None
$PropagationFlag = [System.Security.AccessControl.PropagationFlags]::None
$objType =[System.Security.AccessControl.AccessControlType]::Allow
$objUser = New-Object System.Security.Principal.NTAccount("domain\user")
$objACE = New-Object System.Security.AccessControl.FileSystemAccessRule _
($objUser, $colRights, $InheritanceFlag, $PropagationFlag, $objType)
# Skapar Arrayer för loggning av resultat.
$FolErr = @()
$FolOK = @()
# Lista endast underkataloger och uppdaterar rättigheterna på dom.
Get-ChildItem $share | Where {$_.psIsContainer -eq $true} | foreach {
try {
$FolderName = $_.name
$objACL = $_ | Get-ACL
$objACL.AddAccessRule($objACE)
$_ | Set-Acl -AclObject $objACL
$FolOK += $_.name
}
# Fångar dom katalogerna som jag inte får läsa rättigheterna på.
catch [UnauthorizedAccessException]
{
"De gick inte att läsa rättigheterna på $FolderName"
$FolErr += $FolderName
}
}
# Bygger namn och sökväg till logfilerna.
$sshareName = $sShare.Split("\")[3]
$errfileName = "$ScriptDir\$sshareName" + "_Err.txt"
$okFileName = "$ScriptDir\$sshareName" + "_OK.txt"
# Summerar kataloger som är rättade och vilka som inte lyckats.
$FolErr | out-file -FilePath $errfileName
$FolOK | out-file -FilePath $okFileName
Prenumerera på:
Inlägg (Atom)