Battle.net: NagaByrd#2844
#jehaderbijmoetenzijn
pr0mpt - It never hurts to help!
Zal eens kijken voor de slidesJazzy schreef op dinsdag 25 november 2014 @ 17:25:
In ieder geval staan de slides online: http://www.expertslive.nl/
Volgend jaarpr0mpt schreef op dinsdag 25 november 2014 @ 15:52:
Volgens mij alleen een paar foto'tjes, maar geen video gezien...
#jehaderbijmoetenzijn
Battle.net: NagaByrd#2844
Situatie:
2 Exchange servers waarop ik wat rechten gekregen heb (aanmaken mailbox, export van e-mail, SMTP adres aanmaken e.d.). Normaliter start ik een PowerShell Window, open een tekstbestandje waar de commando's in staan, copy & paste, voer uit en klaar
Maar dat kan ook anders, anders zou het geen automatisering heten
Zoektocht:
Een PowerShell script te maken met een aantal "keuze menu's" erin:
Hoofdmenu:
- "Verbind naar Server 1."
- "Verbind naar Server 2"
Submenu:
- "Opdracht 1 op Server 1"
- "Opdracht 2 op Server 1"
- "Remove-PsSession -ID op Server 1"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
| Function Show-Menu {
Param(
[Parameter(Position=0,Mandatory=$True,HelpMessage="Powershell Exchange Connection")]
[ValidateNotNullOrEmpty()]
[string]$Menu,
[Parameter(Position=1)]
[ValidateNotNullOrEmpty()]
[string]$Title="Menu",
[switch]$ClearScreen
)
if ($ClearScreen) {Clear-Host}
#build the menu prompt
$menuPrompt=$title
#add a return
$menuprompt+="`n"
#add an underline
$menuprompt+="-"*$title.Length
$menuprompt+="`n"
#add the menu
$menuPrompt+=$menu
Read-Host -Prompt $menuprompt
} #end function
#define a menu here string
$menu=@"
1 Server 1
2 Server 2
Q Quit
Select a task by number or Q to quit
"@
#Keep looping and running the menu until the user selects Q (or q).
Do {
#use a Switch construct to take action depending on what menu choice
#is selected.
Switch (Show-Menu $menu "Powershell Exchange Connection" -clear) {
"1" {$s = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://Server1/powershell
$r = Import-PSSession $s
sleep -seconds 5
}
"2" {$s = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://Server2/powershell
$r = Import-PSSession $s
sleep -seconds 5
}
"Q" {Write-Host "Goodbye" -ForegroundColor Cyan
Return
}
Default {Write-Warning "Invalid Choice. Try again."
sleep -milliseconds 750}
} #switch
} While ($True) |
Er kan met succes een connectie gemaakt worden naar Server1 middels de New-PsSession.
Issue/Vraag:
Hoe kan ik nu een submenu tonen in de Import-PsSession waarbij er een aantal voorgedefinieerde commando's staan als "Opdracht 1 op Server 1" / "Opdracht 2 op Server 1" (Zoals een Get-AdUser of Enable-Mailbox)?
Volgens mij zou je dan bij regel 43 (waar je "1" hebt voor menu item 1) het submenu toe moeten voegen.Dwazer schreef op maandag 16 maart 2015 @ 13:42:
Issue/Vraag:
Hoe kan ik nu een submenu tonen in de Import-PsSession waarbij er een aantal voorgedefinieerde commando's staan als "Opdracht 1 op Server 1" / "Opdracht 2 op Server 1" (Zoals een Get-AdUser of Enable-Mailbox)?
Menu's in PS is nou niet echt mijn favoriete onderdeel - vooral omdat je ook bv een GUI item zou kunnen maken hiervoor.
Als ik het script zo doorlees dan komt dit nou ook niet echt over als een flexibel menu.
(overigens vind ik persoonlijk dat je als Exchange admin niet met menu's moet werken maar gewoon PS commando's zal moeten typen, maar dat is uiteraard een andere discussie welke verder niet in dit topic thuishoort)
[ Voor 14% gewijzigd door Killah_Priest op 16-03-2015 14:16 ]
Hier kun je dan een functie voor maken, die een nieuwe user aanmaakt (met naam johndoe), compleet met mailbox.
MCSE NT4/2K/2K3, MCTS, MCITP, CCA, CCEA, CCEE, CCIA, CCNA, CCDA, CCNP, CCDP, VCP, CEH + zwemdiploma A & B
Het is beter om 3 functies aan te maken en als parameter de server te gebruiken dan met submenu's te werken.
Doe-opdracht1 -computername server1
Je kan je parameters verplicht maken, validatepattern op toepassen zodat enkel die servers kunnen aangeroepen worden.
Of je kan zelf pipeline toepassen met cmdletbinding
server1, server2 | remove-PSSession
Als je dan niet telkens wil naar het pad van je script gaan voordat je het kan uitvoeren,
kan je misschien een module overwegen en daarbij een manifest schrijven. (google is je vriend).
Bij het openen van een PS sessie worden de functies modules dan automatisch ingeladen.
Active directory doet dat bijvoorbeeld als je get-aduser, get-adcomputer,... aanroept.
edit:typo
Battle.net: NagaByrd#2844
Volgens mij worden alleen gecompileerde modules automatisch geladen : bij script modules werkt dit helaas niet (lang leve je psprofile dus)nagasy schreef op maandag 16 maart 2015 @ 15:21:
Zoals Killah_Priest en Question Mark reeds zeggen.
Het is beter om 3 functies aan te maken en als parameter de server te gebruiken dan met submenu's te werken.
Doe-opdracht1 -computername server1
Je kan je parameters verplicht maken, validatepattern op toepassen zodat enkel die servers kunnen aangeroepen worden.
Of je kan zelf pipeline toepassen met cmdletbinding
server1, server2 | remove-PSSession
Als je dan niet telkens wil naar het pad van je script gaan voordat je het kan uitvoeren,
kan je misschien een module overwegen en daarbij een manifest schrijven. (google is je vriend).
Bij het openen van een PS sessie worden de functies modules dan automatisch ingeladen.
Active directory doet dat bijvoorbeeld als je get-aduser, get-adcomputer,... aanroept.
edit:typo
Wij maken hier nochtans gebruik van scriptmodules (samen met modulemanifsten) op een 2008 R2 omgeving.Killah_Priest schreef op dinsdag 17 maart 2015 @ 18:08:
[...]
Volgens mij worden alleen gecompileerde modules automatisch geladen : bij script modules werkt dit helaas niet (lang leve je psprofile dus)
PSversion draait op de 4.0 (en ik dacht dat vanaf de 3.0 modules automatisch opgehaald worden als ze zich bevinden in de $env:psmodulepath).
Bij aanpassingen in de module, kunnen andere collega's, na het opnieuw openen van een PS sessie, de functies onmiddellijk gebruiken. Dit kunnen nieuwe of aangepaste functies zijn. Dit zonder van elke collega een specifiek PSprofile te definiëren.
Misschien dat het impliciet toegepast wordt op het globaal PS profile? Maar dat durf ik niet met zekerheid zeggen.
Battle.net: NagaByrd#2844
Ik heb het zelf nu uitgebreid getest, mede ivm het zelf ontwikkelen van modules (zowel compiled als gewone script modules) en het blijkt hem in een correcte manifest etc te zitten. Als deze correct zijn opgemaakt dan werken dus ook de scriptmodules met auto import.nagasy schreef op woensdag 18 maart 2015 @ 08:23:
[...]
Wij maken hier nochtans gebruik van scriptmodules (samen met modulemanifsten) op een 2008 R2 omgeving.
PSversion draait op de 4.0 (en ik dacht dat vanaf de 3.0 modules automatisch opgehaald worden als ze zich bevinden in de $env:psmodulepath).
Bij aanpassingen in de module, kunnen andere collega's, na het opnieuw openen van een PS sessie, de functies onmiddellijk gebruiken. Dit kunnen nieuwe of aangepaste functies zijn. Dit zonder van elke collega een specifiek PSprofile te definiëren.
Misschien dat het impliciet toegepast wordt op het globaal PS profile? Maar dat durf ik niet met zekerheid zeggen.
Nog een leuke handigheid van PS : je kunt gewoon C# sourcecode via get-content -raw en daarna add-type toevoegen. Daarna kun je via new-object verder. Ik gebruik dit vaak om even snel de output van dingen te testen die ik schrijf (in PS even snel een method uitvoeren om te kijken wat voor waardes ik precies terugkrijg is vaak sneller als compilen enzo).
De classes uit dll bestanden zijn ook (mits ze public zijn) via add-type en new object te gebruiken.
In ps5 kun je zelfs in powershell zelf classes maken.
Verwijderd
Helaas is het komende evenement van de DuPSUG op 26 Mei al uitverkocht (70 tickets binnen 7 dagen!)... maar de sessies zullen opgenomen worden en komen op YouTube op het DuPSUG kanaal: YouTube: DuPSUG
So...stay tuned ;-)
[Te koop: 3D printers] [Website] Agile tools: [Return: retrospectives] [Pokertime: planning poker]
Ik heb hier een test-versie van windows 8 met powershell-versie 3.
Ik heb ondertussen nu al verschillende pogingen gedaan in Powershell om dit mogelijk te maken, maar zonder enig succes. Hieronder een aantal pogingen:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| $ComputerName = "LocalHost"
$Hive = "CurrentUser"
$Key = "Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel"
$MyComputer = "{20D04FE0-3AEA-1069-A2D8-08002B30309D}"
$UserFiles = "{59031a47-3f72-44a7-89c5-5595fe6b30ee}"
$Kind = [Microsoft.Win32.RegistryValueKind]
$RegHive = [Microsoft.Win32.RegistryHive]$hive
$RegKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($RegHive,$ComputerName)
$MyComputerValue = ($RegKey.OpenSubKey($Key)).GetValue($MyComputer)
$UserFilesValue = ($RegKey.OpenSubKey($Key)).GetValue($UserFiles)
if ($MyComputerValue -eq $null -or $MyComputerValue -eq 1)
{
$Computer = $regKey.OpenSubKey($Key,$true)
$Computer.SetValue($MyComputer, 0,$Kind::DWord)
}
if ($UserFilesValue -eq $null -or $UserFilesValue -eq 1)
{
$User = $regKey.OpenSubKey($Key,$true)
$User.SetValue($UserFiles, 0,$Kind::DWord)
} |
poging 2 via aanmaak van een registersleutel met de bijhorende CLSID
1
| #new-item -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Desktop\NameSpace\{20D04FE0-3AEA-1069-A2D8-08002B30309D}" - Value "Deze Computer" |
Maar geen enkele van deze codes blijken iets van verandering te geven.
iemand die kan helpen?
Waarom wil je iconen op de desktop plaatsen?RainerSGF schreef op zondag 03 mei 2015 @ 22:08:
Ik wil het mogelijks maken om voornamelijk in Windows 8 via een powershell-script een aantal iconen op het bureaublad te plaatsen zoals 'Deze Computer' en 'Mijn Doucmenten'.
Ik heb hier een test-versie van windows 8 met powershell-versie 3.
Ik heb ondertussen nu al verschillende pogingen gedaan in Powershell om dit mogelijk te maken, maar zonder enig succes. Hieronder een aantal pogingen:
code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20$ComputerName = "LocalHost" $Hive = "CurrentUser" $Key = "Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel" $MyComputer = "{20D04FE0-3AEA-1069-A2D8-08002B30309D}" $UserFiles = "{59031a47-3f72-44a7-89c5-5595fe6b30ee}" $Kind = [Microsoft.Win32.RegistryValueKind] $RegHive = [Microsoft.Win32.RegistryHive]$hive $RegKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($RegHive,$ComputerName) $MyComputerValue = ($RegKey.OpenSubKey($Key)).GetValue($MyComputer) $UserFilesValue = ($RegKey.OpenSubKey($Key)).GetValue($UserFiles) if ($MyComputerValue -eq $null -or $MyComputerValue -eq 1) { $Computer = $regKey.OpenSubKey($Key,$true) $Computer.SetValue($MyComputer, 0,$Kind::DWord) } if ($UserFilesValue -eq $null -or $UserFilesValue -eq 1) { $User = $regKey.OpenSubKey($Key,$true) $User.SetValue($UserFiles, 0,$Kind::DWord) }
poging 2 via aanmaak van een registersleutel met de bijhorende CLSID
code:
1#new-item -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Desktop\NameSpace\{20D04FE0-3AEA-1069-A2D8-08002B30309D}" - Value "Deze Computer"
Maar geen enkele van deze codes blijken iets van verandering te geven.
iemand die kan helpen?
Ik zou de snelkoppelingen gewoon kopieren vanaf ee share, zo maak je het jezelf onnodig moeilijk. Stel je de rechten van de share wel goed in zodat iedereen die erbij erbij moet.
Je hoeft het trouwens niet per se te scripten, wat jij wil kan ook met Group Policy in Windows 8:
http://blogs.technet.com/...ws-8-and-windows-8-1.aspx
[ Voor 6% gewijzigd door Turdie op 03-05-2015 22:21 ]
Komen ze net zo snel online als na de vorige DuPSUG?Verwijderd schreef op woensdag 08 april 2015 @ 14:15:
Ben ik want doelloos aan het browsen, kom ik dit topic tegen.
Helaas is het komende evenement van de DuPSUG op 26 Mei al uitverkocht (70 tickets binnen 7 dagen!)... maar de sessies zullen opgenomen worden en komen op YouTube op het DuPSUG kanaal: YouTube: DuPSUG
So...stay tuned ;-)
Freelance (Microsoft) Cloud Consultant & Microsoft Certified Trainer
Voordat je verder naar je PS code gaat kijken : werkt hetgeen jij wilt bereiken wel als je handmatig de betreffende regkeys aanmaakt?RainerSGF schreef op zondag 03 mei 2015 @ 22:08:
Ik wil het mogelijks maken om voornamelijk in Windows 8 via een powershell-script een aantal iconen op het bureaublad te plaatsen zoals 'Deze Computer' en 'Mijn Doucmenten'.
Ik heb hier een test-versie van windows 8 met powershell-versie 3.
Ik heb ondertussen nu al verschillende pogingen gedaan in Powershell om dit mogelijk te maken, maar zonder enig succes. Hieronder een aantal pogingen:
code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20$ComputerName = "LocalHost" $Hive = "CurrentUser" $Key = "Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel" $MyComputer = "{20D04FE0-3AEA-1069-A2D8-08002B30309D}" $UserFiles = "{59031a47-3f72-44a7-89c5-5595fe6b30ee}" $Kind = [Microsoft.Win32.RegistryValueKind] $RegHive = [Microsoft.Win32.RegistryHive]$hive $RegKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($RegHive,$ComputerName) $MyComputerValue = ($RegKey.OpenSubKey($Key)).GetValue($MyComputer) $UserFilesValue = ($RegKey.OpenSubKey($Key)).GetValue($UserFiles) if ($MyComputerValue -eq $null -or $MyComputerValue -eq 1) { $Computer = $regKey.OpenSubKey($Key,$true) $Computer.SetValue($MyComputer, 0,$Kind::DWord) } if ($UserFilesValue -eq $null -or $UserFilesValue -eq 1) { $User = $regKey.OpenSubKey($Key,$true) $User.SetValue($UserFiles, 0,$Kind::DWord) }
poging 2 via aanmaak van een registersleutel met de bijhorende CLSID
code:
1#new-item -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Desktop\NameSpace\{20D04FE0-3AEA-1069-A2D8-08002B30309D}" - Value "Deze Computer"
Maar geen enkele van deze codes blijken iets van verandering te geven.
iemand die kan helpen?
Wat me wel opvalt is dat je in het eerste script CurrentUser aanroept en in het tweede LocalMachine.
Je tweede poging met "new-item" is wel de manier waarom ik het zou doen btw.
Systeemiconen zoals de Prullenbak en Network Neighbourhood kan je volgens mij niet 1:1 kopiëren.mufana schreef op donderdag 07 mei 2015 @ 20:12:
Ik zou de iconen ook gewoon vanaf een share kopieren. Je maakt het jezelf erg ingewikkeld. Als het simpel kan moet je het simpel oplossen. En als je jezelf echt niet kun inhouden kun je de kopieer actie wel scripten.
Verwijderd
In VBscript lijkt het mij niet zo moeilijk:RainerSGF schreef op zondag 03 mei 2015 @ 22:08:
Ik wil het mogelijks maken om voornamelijk in Windows 8 via een powershell-script een aantal iconen op het bureaublad te plaatsen zoals 'Deze Computer' en 'Mijn Doucmenten'.
Ik heb hier een test-versie van windows 8 met powershell-versie 3.
Ik heb ondertussen nu al verschillende pogingen gedaan in Powershell om dit mogelijk te maken, maar zonder enig succes. Hieronder een aantal pogingen:
http://www.tek-tips.com/viewthread.cfm?qid=896749
En PowerShell en de bekende door VBscript gebruikte com objects werken erg goed.
Voorbeeld powershell com objects script van mij om de recycle bin en recent van een user te legen:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| # FreshStart.ps1
# Author: Stacheldraht
# Version: 1.0 - 2015-05-07 Windows 7 Only
# ---------------------------------------------------------
# (8). File system directory that contains the user's most recently used documents.
# (10). Virtual folder that contains the objects in the user's Recycle Bin.
$myShell = New-Object -ComObject Shell.Application
$myNameSpaceTarget = @(8,10)
ForEach($myNameSpace in $myNameSpaceTarget){
$mySpecialFolder = $myShell.NameSpace($myNameSpace)
ForEach ($myItem In $mySpecialFolder.Items()){
Remove-Item -Path $myItem.Path -Recurse -Force
}
} |
Heb me net nog kunnen inschrijven, ie die dan wel geldig?Verwijderd schreef op woensdag 08 april 2015 @ 14:15:
Ben ik want doelloos aan het browsen, kom ik dit topic tegen.
Helaas is het komende evenement van de DuPSUG op 26 Mei al uitverkocht (70 tickets binnen 7 dagen!)... maar de sessies zullen opgenomen worden en komen op YouTube op het DuPSUG kanaal: YouTube: DuPSUG
So...stay tuned ;-)
Nu kort ' vervelend probleem: ik heb een hoop Properties nodig en krijg maar de helft
1
| $Users = @(Get-ADUser -Filter * -Server $SelectedDomain -Credential $Credentials -Properties sAMAccountname, personalTitle, givenName, sn, displayName, mail, title, streetAddress, postalCode, l, c, co, company, wWWHomePage, telephoneNumber, mobile, facsimileTelephoneNumber) |
Gevraagd en gekregen onder elkaar, met een X voor wat mist.
1
2
| sAMAccountname, personalTitle, givenName, sn, displayName, mail, title, streetAddress, postalCode, l, c, co, company, wWWHomePage, telephoneNumber, mobile, facsimileTelephoneNumber sAMAccountName, X , givenName, sn, displayName, X , title, streetAddress, postalCode, X, X, X , company, X , X , X , X |
OK, blijkbaar zit niet alles van ADSI in de Extended Properties en zijn sowieso de namen niet gelijk
[ Voor 11% gewijzigd door YellowOnline op 22-05-2015 10:19 ]
Get-ADUser <username> -properties *
??
PS: Er is nog 1 DUPSUG ticket voor 26 mei beschikbaar: http://www.dupsug.com/?p=1065
[ Voor 33% gewijzigd door punisher007 op 22-05-2015 10:21 ]
Nee - ik had mij, ten onrechte, zo blijkt, op ADSI gebaseerd. Goed idee om te spieken met *punisher007 schreef op vrijdag 22 mei 2015 @ 10:20:
Krijg je wel de gewenste info wel te zien met:
Get-ADUser <username> -properties *
??
PS: Er is nog 1 DUPSUG ticket voor 26 mei beschikbaar: http://www.dupsug.com/?p=1065
Probeer eens volgende:YellowOnline schreef op vrijdag 22 mei 2015 @ 10:02:
TS voor 't eerst sinds lang terug. Ik ben bezig met een interessant GUI tool, waarover later (=enkele dagen) meer.
Nu kort ' vervelend probleem: ik heb een hoop Properties nodig en krijg maar de helft
C#:
1 $Users = @(Get-ADUser -Filter * -Server $SelectedDomain -Credential $Credentials -Properties sAMAccountname, personalTitle, givenName, sn, displayName, mail, title, streetAddress, postalCode, l, c, co, company, wWWHomePage, telephoneNumber, mobile, facsimileTelephoneNumber)
Gevraagd en gekregen onder elkaar, met een X voor wat mist.
code:
1 2 sAMAccountname, personalTitle, givenName, sn, displayName, mail, title, streetAddress, postalCode, l, c, co, company, wWWHomePage, telephoneNumber, mobile, facsimileTelephoneNumber sAMAccountName, X , givenName, sn, displayName, X , title, streetAddress, postalCode, X, X, X , company, X , X , X , X
OK, blijkbaar zit niet alles van ADSI in de Extended Properties en zijn sowieso de namen niet gelijk
1
| $Users = @(Get-ADUser -Properties * -Server $SelectedDomain -Credential $Credentials | select-object sAMAccountname, personalTitle, givenName, sn, displayName, mail, title, streetAddress, postalCode, l, c, co, company, wWWHomePage, telephoneNumber, mobile, facsimileTelephoneNumber) |
Filter gebruik je om de OU in je ADboom te selecteren. Mag je weglaten.
Battle.net: NagaByrd#2844
Dat zou niet werken om dezelfde reden als boven: de properties die Get-ADUser vraagt komen niet overeen met ADSI. Die worden onderweg ergens omgezet of zo. Volgende code werkt perfect:nagasy schreef op vrijdag 22 mei 2015 @ 10:33:
[...]
Probeer eens volgende:
C#:
1 $Users = @(Get-ADUser -Properties * -Server $SelectedDomain -Credential $Credentials | select-object sAMAccountname, personalTitle, givenName, sn, displayName, mail, title, streetAddress, postalCode, l, c, co, company, wWWHomePage, telephoneNumber, mobile, facsimileTelephoneNumber)
Filter gebruik je om de OU in je ADboom te selecteren. Mag je weglaten.
1
2
3
4
5
6
| $ForestUsers = @() ForEach ($SelectedDomain in $SelectedDomains) { $Users = @(Get-ADUser -Filter * -Server $SelectedDomain -Credential $Credentials -Properties CanonicalName, SID, SamAccountName, GivenName, Surname, DisplayName, Mail, Title, StreetAddress, PostalCode, City, Country, Company, HomePage, OfficePhone, MobilePhone, Fax ) $ForestUsers = $ForestUsers + $Users } |
Edit:
PS. Die Filter staat daar nu nog onbenut. Mijn script moet deze attributen kunnen opvragen in Forests, Domains en OUs, vandaar
PPS. Oh ja, heb nog een paar attributen veranderd intussen.
[ Voor 35% gewijzigd door YellowOnline op 22-05-2015 11:01 ]
Beide opties geven hier dezeldfe resultaten. Met en zonder te pipen.
en door dit te doen komt alles gewoon via 1 lijn in een csv.
1
| $bla = get-aduser -Properties * | select-object * | export-csv -Path D:\test.csv -NoTypeInformation |
Nu, als je code maar werkt
edit: moet mijn browser refreshen voordat ik reageer. Blijkbaar heb je je code ingekort. Negeer het pipelinevoorstel
[ Voor 17% gewijzigd door nagasy op 22-05-2015 11:27 ]
Battle.net: NagaByrd#2844
Of Get-Member.YellowOnline schreef op vrijdag 22 mei 2015 @ 10:24:
[...]
Nee - ik had mij, ten onrechte, zo blijkt, op ADSI gebaseerd. Goed idee om te spieken met *
Get-ADuser NAAM | gm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
| $SmtpClient = new-object system.net.mail.smtpClient($SmtpClient) $MailMessage = New-Object system.net.mail.mailmessage $SmtpClient.Host = "smtpserver" $MailMessage.from = ($ServerName + "mailadres@domein.com") $MailMessage.To.add("ontvanger@domein.com") $MailMessage.Subject = "File check" #Check if files ouder dan 5 minuten in de folders uit de .txt staan $date = (get-date).AddMinutes(-5) foreach($path in get-content "C:\Scripts\servers_path.txt") { if ((Test-Path -path $path)) { $item = get-childitem $path *.* | where-object {$_.LastWriteTime -lt $date} $item | Select FullName, Name, LastWriteTime if ($item) { $MailMessage.Body += "$path `n" $MailMessage.Body += "$item `n`n" $MailMessage.Body += "--------------------------------------------------------------------------------------------------`n" } } elseif (!(Test-Path $path)) { } } $SmtpClient.Send($MailMessage) |
Als je het script uitvoert dan stuurt hij ten alle tijden een email, maar negeert wat onder de elseif staat wanneer er inderdaad geen bestanden te vinden zijn en stuurt een lege email.
Carnavalmarkt.nl - Gratis adverteren met carnaval- en feestartikelen
Dan heb je nog steeds -Properties * nodig voor extended attributes, ander krijg je enkel de default attributes. Ten bewijze:Roamor schreef op vrijdag 22 mei 2015 @ 12:14:
[...]
Of Get-Member.Gebruik ik echt vaak om te zien welke properties een object heeft;
Get-ADuser NAAM | gm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| PS C:\Users\Administrator\Desktop> Get-ADUser Administrator | Get-Member TypeName: Microsoft.ActiveDirectory.Management.ADUser Name MemberType Definition ---- ---------- ---------- Contains Method bool Contains(st Equals Method bool Equals(Syst GetEnumerator Method System.Collectio GetHashCode Method int GetHashCode( GetType Method type GetType() ToString Method string ToString( Item ParameterizedProperty Microsoft.Active DistinguishedName Property System.String Di Enabled Property System.Boolean E GivenName Property System.String Gi Name Property System.String Na ObjectClass Property System.String Ob ObjectGUID Property System.Nullable` SamAccountName Property System.String Sa SID Property System.Security. Surname Property System.String Su UserPrincipalName Property System.String Us |
1
| $Users = @(Get-ADUser -Filter 'Enabled -EQ $True' -Server $SelectedDomain -Credential $Credentials -Properties CanonicalName, SID, SamAccountName, GivenName, Surname, DisplayName, Mail, Title, StreetAddress, PostalCode, City, Country, Company, HomePage, OfficePhone, MobilePhone, Fax) |
-> Alle data in $Users klopt
Voor elk domein gaat er een $Users in $ForestUsers
1
| $ForestUsers = $ForestUsers + $Users |
-> Alle data in $ForestUsers klopt
Wanneer ik de output transformeer door Select-Object...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| $FinalData = $ForestUsers | Select-Object @{Name="Domain";Expression={$_.CanonicalName.Split("/")[0]}},` @{Name="SID";Expression={$_.SID}},` @{Name="User";Expression={$_.sAMAccountname}},` @{Name="First Name";Expression={$_.GivenName}},` @{Name="Last Name";Expression={$_.Surname}},` @{Name="Display Name";Expression={$_.DisplayName}},` @{Name="E-Mail";Expression={$_.Mail}},` @{Name="Job Title";Expression={$_.Title}},` @{Name="Address";Expression={$_.StreetAddress}},` @{Name="Postal Code";Expression={$_.PostalCode}},` @{Name="City";Expression={$_.City}},` @{Name="Country";Expression={$_.Country}},` @{Name="Company";Expression={$_.Company}},` @{Name="Website";Expression={$_.HomePage}},` @{Name="Phone";Expression={$_.OfficePhone}},` @{Name="Mobile";Expression={$_.MobilePhone}},` @{Name="Fax";Expression={$_.Fax}} $FinalData | Export-CSV $TempDataFromAD -Delimiter ";" -Encoding UTF8 -NoTypeInformation |
... dan krijg ik Microsoft.ActiveDirectory.Management.ADPropertyValueCollection voor alle waarden nà Country. Nochtans waren die geen arrayobjecten (volgend de documentatie zelfs gewoon String). Ook valt er niets te indexeren.
Zwaar gecensureerd screenshotje:

Ja, ik bouw een app rond de CSV
Het bizarre is dat ik het in mijn console niet kan reproduceren - enkel in het script... en de enige relevante code heb ik hier gepost.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| PS C:\Users\Administrator\Desktop> $FinalData[1] Domain : tweakers.net SID : S-X-X-XX-XXXXXXXX-XXXXXXXXX-XXXXXXXXXX-XXX User : Administrator First Name : Administrator Last Name : Display Name : Administrator E-Mail : administrator@tweakers.net Job Title : Blablabla Address : Blablabla Postal Code : 10000 City : Berlin Country : Germany Company : Blablabla Website : about:blank Phone : 000000 Mobile : 000000 Fax : 000000 |
Als ik dat exporteer ziet mijn CSV er ook in orde uit. Hier de headers:
1
| Domain,"SID","User","First Name","Last Name","Display Name","E-Mail","Job Title","Address","Postal Code","City","Country","Company","Website","Phone","Mobile","Fax" |
Quid?
[ Voor 24% gewijzigd door YellowOnline op 22-05-2015 14:01 ]
? er staat geen code tussen je elseif blok, en als ik de rest van je code zo zie dan klop het toch dat hij te allen tijde een mail verstuurt?Wom schreef op vrijdag 22 mei 2015 @ 12:21:
Wat doe ik verkeerd? Maakt niet uit wat ik uitvoer in mijn elseif, het wordt gewoon genegeerd. Iemand een idee met een verse blik op mijn gepruts?
C#:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 $SmtpClient = new-object system.net.mail.smtpClient($SmtpClient) $MailMessage = New-Object system.net.mail.mailmessage $SmtpClient.Host = "smtpserver" $MailMessage.from = ($ServerName + "mailadres@domein.com") $MailMessage.To.add("ontvanger@domein.com") $MailMessage.Subject = "File check" #Check if files ouder dan 5 minuten in de folders uit de .txt staan $date = (get-date).AddMinutes(-5) foreach($path in get-content "C:\Scripts\servers_path.txt") { if ((Test-Path -path $path)) { $item = get-childitem $path *.* | where-object {$_.LastWriteTime -lt $date} $item | Select FullName, Name, LastWriteTime if ($item) { $MailMessage.Body += "$path `n" $MailMessage.Body += "$item `n`n" $MailMessage.Body += "--------------------------------------------------------------------------------------------------`n" } } elseif (!(Test-Path $path)) { } } $SmtpClient.Send($MailMessage)
Als je het script uitvoert dan stuurt hij ten alle tijden een email, maar negeert wat onder de elseif staat wanneer er inderdaad geen bestanden te vinden zijn en stuurt een lege email.
Kun je nader verklaren wat je nu bedoelt?
En als je dit probeert?YellowOnline schreef op vrijdag 22 mei 2015 @ 13:52:
Een interessantere vraag: waarom krijg ik "Microsoft.ActiveDirectory.Management.ADPropertyValueCollection" te zien? Je zou denken: "omdat het een array is". Wel, euh, volg even mee:
etc.......
https://social.technet.mi...5/getaduser-directreports dus de waarde -join.
[ Voor 12% gewijzigd door @r!k op 22-05-2015 14:25 . Reden: bijgewerkte post ]
Een hele rij microsoft certificeringen.
[ Voor 99% gewijzigd door @r!k op 22-05-2015 14:24 . Reden: dubbelpost.... :( ]
Een hele rij microsoft certificeringen.
Ik heb het wat anders geformat om het leesbaar te maken.Wom schreef op vrijdag 22 mei 2015 @ 12:21:
Wat doe ik verkeerd? Maakt niet uit wat ik uitvoer in mijn elseif, het wordt gewoon genegeerd. Iemand een idee met een verse blik op mijn gepruts?
C#:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 $SmtpClient = new-object system.net.mail.smtpClient($SmtpClient) $MailMessage = New-Object system.net.mail.mailmessage $SmtpClient.Host = "smtpserver" $MailMessage.from = ($ServerName + "mailadres@domein.com") $MailMessage.To.add("ontvanger@domein.com") $MailMessage.Subject = "File check" $date = (get-date).AddMinutes(-5) foreach($path in get-content "C:\Scripts\servers_path.txt") { if ((Test-Path -path $path)) { $item = get-childitem $path *.* | where-object {$_.LastWriteTime -lt $date} $item | Select FullName, Name, LastWriteTime if ($item) { $MailMessage.Body += "$path `n" $MailMessage.Body += "$item `n`n" $MailMessage.Body += "--------------------------------------------------------------------------------------------------`n" } } elseif (!(Test-Path $path)) { } } $SmtpClient.Send($MailMessage)
Als je het script uitvoert dan stuurt hij ten alle tijden een email, maar negeert wat onder de elseif staat wanneer er inderdaad geen bestanden te vinden zijn en stuurt een lege email.
1) maak van $item eens 'n array zodat je een .Count kan doen en je code niet breekt als er eens 1 element uit je GCI komt
1
| $item = @(get-childitem $path *.* | where-object {$_.LastWriteTime -lt $date}) |
2) er staat ook niets in je ElseIf
3) Natuurlijk wordt een mail verzonden: ongeacht wat er gebeurt eindigt je script met
1
| $SmtpClient.Send($MailMessage) |
Probeer het eens zo (copy/paste):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| $SmtpClient = New-Object System.Net.Mail.SmtpClient($SmtpClient) $MailMessage = New-Object System.Net.Mail.MailMessage $SmtpClient.Host = "smtpserver" $MailMessage.From = ($ServerName + "mailadres@domein.com") $MailMessage.To.Add("ontvanger@domein.com") $MailMessage.Subject = "File check" $Date = (Get-Date).AddMinutes(-5) ForEach($Path in ()Get-Content "C:\Scripts\servers_path.txt") { If ((Test-Path -Path $Path)) { $Item = @(Get-Childitem $Path *.* | Where-Object {$_.LastWriteTime -LT $date}) $Item | Select-Object FullName, Name, LastWriteTime If ($Item) { $MailMessage.Body += "$Path `n" $MailMessage.Body += "$Item `n`n" $MailMessage.Body += "--------------------------------------------------------------------------------------------------`n" } } ElseIf (!(Test-Path $path)) { } $SmtpClient.Send($MailMessage) } |
4) euh, wat hoop je te bereiken met die "$item | Select" etc? Dat wordt nergens heen gestuurd
Dat is wat je met arrays kan doen ja. Alleen: er is geen array in de voorgaande stappen en ik zie niet hoe mijn expression er een array van kan maken. Vandaar dat ik het niet begrijp@r!k schreef op vrijdag 22 mei 2015 @ 14:18:
[...]
En als je dit probeert?
https://social.technet.mi...5/getaduser-directreports dus de waarde -join.
[ Voor 23% gewijzigd door YellowOnline op 22-05-2015 15:22 ]
Carnavalmarkt.nl - Gratis adverteren met carnaval- en feestartikelen
Omdat je mijn edits misschien gemist hebt:Wom schreef op vrijdag 22 mei 2015 @ 14:54:
Bedankt, ik ben me er van bewust dat er niks in de elseif staat, maar had dat wegglaten om onnodige code te voorkomen. Ik ga er mee aan de slag
1) Als iets een array kan zijn, maak er expliciet een array van - in casu " $Item = @(Get-Childitem $Path *.* | Where-Object {$_.LastWriteTime -LT $date})"
2) ElseIf is inderdaad leeg, dus daar kan niet veel gebeuren.
3) Je SMTP-commando staat op de verkeerde plek - waar het nu staat wordt het altijd uitgevoerd
4) Je hebt daar een variabele $item die gepiped wordt naar Select(-Object) maar daarna wordt daar niets meer mee aangevangen - tenzij je enkel de bedoeling had het in de console te zien.
Bedoeling was op eerst een CSV bestand als input te hebben, waar ik bepaalde velden uit wilde trekken om die in de mail te gebruiken, maar heb dat anders opgelost.
Heb je voorbeeld gebruikt en dat lijkt te werken, nogmaals bedankt
Carnavalmarkt.nl - Gratis adverteren met carnaval- en feestartikelen
Waarom maak je overigens geen gebruik van de Send-MailMessage cmdlet?Wom schreef op vrijdag 22 mei 2015 @ 15:19:
Mijn bedoeling was inderdaad dat er altijd een mail gestuurd zou worden. De Elseif zou dan gebruikt worden om iets als $MailMessage.Subject = "Pad klopt niet" oid te versturen. Echter wil ik maar 1 email en niet voor elke regel in de file een mail krijgen, vandaar het statement op het einde van het script.
Bedoeling was op eerst een CSV bestand als input te hebben, waar ik bepaalde velden uit wilde trekken om die in de mail te gebruiken, maar heb dat anders opgelost.
Heb je voorbeeld gebruikt en dat lijkt te werken, nogmaals bedankt
https://technet.microsoft.com/en-us/library/hh849925.aspx
Hardcore Powershell Mode!
[ Voor 14% gewijzigd door @r!k op 01-06-2015 15:46 ]
Een hele rij microsoft certificeringen.
Ik maak GUIs met PoSh, wat toch al redelijk hardcore is, maar zo gek om ...@r!k schreef op maandag 01 juni 2015 @ 15:17:
Dan vind ik deze toch leuker.
Hardcore Powershell Mode!
1
| $ExecutionContext.InvokeCommand.CommandNotFoundAction = { Stop-Computer -Force } |
... ben ik nog niet
Dat is wel een tamelijk harde manier om geen syntaxfouten meer te maken.
Zouden ze moeten implementeren bij elke beginnerscursus programmeren ^^
Battle.net: NagaByrd#2844
Nou, met de juiste tools is een GUI in elkaar slepen in PoSh net zo makkelijk als in C# of VB.NET.YellowOnline schreef op maandag 01 juni 2015 @ 16:36:
[...]
Ik maak GUIs met PoSh, wat toch al redelijk hardcore is, maar zo gek om ...
code:
1$ExecutionContext.InvokeCommand.CommandNotFoundAction = { Stop-Computer -Force }
... ben ik nog niet
Meekoh is ook absoluut geen voorstander van GUI's maken met PoSh
Computer says no
Nee, PoSh is er inderdaad niet voor gemaakt, maar ik merk dat zelfs admin mijn tools sneller gebruiken wanneer ze een GUI hebben dan wanneer ze command line zijn.Meekoh schreef op maandag 01 juni 2015 @ 16:44:
[...]
Nou, met de juiste tools is een GUI in elkaar slepen in PoSh net zo makkelijk als in C# of VB.NET.
Meekoh is ook absoluut geen voorstander van GUI's maken met PoSh![]()
En PoSh is ook de enige taal die ik ken. Vroeg of laat leer ik wel eens C#, aangezien ik dat wel vaak port naar PoSh.
Ach ja, ik werk dan weer meer met Workflows en DSC. Daar kun je bij voorbaat al geen GUI maken.YellowOnline schreef op maandag 01 juni 2015 @ 16:46:
[...]
Nee, PoSh is er inderdaad niet voor gemaakt, maar ik merk dat zelfs admin mijn tools sneller gebruiken wanneer ze een GUI hebben dan wanneer ze command line zijn.
En PoSh is ook de enige taal die ik ken. Vroeg of laat leer ik wel eens C#, aangezien ik dat wel vaak port naar PoSh.
Computer says no
De flexibiliteit maakt het zo'n krachtig middel. Jammer er nog steeds veel systeembeheerders) te beroerd zijn om zich er eventjes in te verdiepen, het bied zoveel meerwaarde aan het vak.
Het maakt het leven inderdaad stukken relaxter bij repeterende actiesKillah_Priest schreef op maandag 01 juni 2015 @ 22:43:
De flexibiliteit maakt het zo'n krachtig middel. Jammer er nog steeds veel systeembeheerders) te beroerd zijn om zich er eventjes in te verdiepen, het bied zoveel meerwaarde aan het vak.
Any errors in spelling, tact, or fact are transmission errors.
scheidt het kaf van het korenKillah_Priest schreef op maandag 01 juni 2015 @ 22:43:
Ik ben door Powershell juist meer met c# gaan doen, hoewel PS toch wel mijn voorkeur heeft. Vooral het feit dat je gewoon c# sourcecode kan runnen dmv add-type is erg handig (vooral als je tegen beperkingen in PS aanloopt dan kun je gewoon een stuk c# code embedden in base64 om toch je doel te bereiken).
De flexibiliteit maakt het zo'n krachtig middel. Jammer er nog steeds veel systeembeheerders) te beroerd zijn om zich er eventjes in te verdiepen, het bied zoveel meerwaarde aan het vak.
Wees juist blij. 13 in dozijn "Systeem beheerders" en maar enkele "goede"
Newton's 3rd law of motion. Amateur moraalridder.
Ze zijn er nog mee bezig en zijn er nog niet uit, maar je zou bijvoorbeeld kunnen denken aan iets zoals een geavanceerde Out-Gridview met -passthru
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
| #XML importeren...
PS C:\ $xmlData = [xml](Get-Content $xmlFilePath)
PS C:\ $usrNew = ($xmlData.FileZillaServer.Users.User | Where-Object {$_.Name -EQ "TemplateUser"}).Clone()
PS C:\ $usrNew.Permissions.Permission.Option
#Voilà, hier is de data
Name #text
---- -----
FileRead 1
FileWrite 0
FileDelete 0
FileAppend 0
DirCreate 0
DirDelete 0
DirList 1
DirSubdirs 1
IsHome 1
AutoCreate 0
#En nu die attributes veranderen...
PS C:\> $usrNew.Permissions.Permission.Option[0] = 1
PS C:\> $usrNew.Permissions.Permission.Option[1] = 1
PS C:\> $usrNew.Permissions.Permission.Option[2] = 1
PS C:\> $usrNew.Permissions.Permission.Option[3] = 1
PS C:\> $usrNew.Permissions.Permission.Option[4] = 0
PS C:\> $usrNew.Permissions.Permission.Option[5] = 0
PS C:\> $usrNew.Permissions.Permission.Option[6] = 1
PS C:\> $usrNew.Permissions.Permission.Option[7] = 1
#Hey, die zijn niet gewijzigd?
PS C:\> $usrNew.Permissions.Permission.Option
Name #text
---- -----
FileRead 1
FileWrite 0
FileDelete 0
FileAppend 0
DirCreate 0
DirDelete 0
DirList 1
DirSubdirs 1
IsHome 1
AutoCreate 0 |
denk dat je eerder $usrNew.Permissions.Permission.Option.innerXML wilt gebruiken.
Maar daarvoor moeten we eigenlijk ook even weten hoe XML zelf eruit ziet.
Computer says no
Hmz, ik zal eens kijken naar die innerXML. Voor de volledige XML, als we de niet-relevante delen weglaten:Meekoh schreef op woensdag 03 juni 2015 @ 10:03:
ik twijfel of je options wel een array is.
denk dat je eerder $usrNew.Permissions.Permission.Option.innerXML wilt gebruiken.
Maar daarvoor moeten we eigenlijk ook even weten hoe XML zelf eruit ziet.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
| <?xml version="1.0"?> <FileZillaServer> <Settings> </Settings> <Groups> </Groups> <Users> <User Name="Tweaker"> <Option Name="Pass">33n0f4nd3r3H4shc0d3</Option> <Option Name="Group"> </Option> <Option Name="Bypass server userlimit">0</Option> <Option Name="User Limit">0</Option> <Option Name="IP Limit">0</Option> <Option Name="Enabled">1</Option> <Option Name="Comments"> </Option> <Option Name="ForceSsl">0</Option> <Option Name="8plus3">0</Option> <IpFilter> <Disallowed/> <Allowed/> </IpFilter> <Permissions> <Permission Dir="\\een.of.ander.pad\enzovoort"> <Option Name="FileRead">1</Option> <Option Name="FileWrite">1</Option> <Option Name="FileDelete">1</Option> <Option Name="FileAppend">0</Option> <Option Name="DirCreate">1</Option> <Option Name="DirDelete">1</Option> <Option Name="DirList">1</Option> <Option Name="DirSubdirs">1</Option> <Option Name="IsHome">1</Option> <Option Name="AutoCreate">0</Option> </Permission> </Permissions> <SpeedLimits ServerUlLimitBypass="0" UlLimit="10" UlType="0" ServerDlLimitBypass="0" DlLimit="10" DlType="0"> <Download/> <Upload/> </SpeedLimits> </User> </Users> </FileZillaServer> |
1
| $usrNew.Permissions.Permission.Option[0] = 1 |
1
| $usrNew.Permissions.Permission.Option.fileread = 1 |
[ Voor 31% gewijzigd door @r!k op 03-06-2015 10:29 ]
Een hele rij microsoft certificeringen.
Heb het net even getest en je moet inderdaadYellowOnline schreef op woensdag 03 juni 2015 @ 10:17:
[...]
Hmz, ik zal eens kijken naar die innerXML. Voor de volledige XML, als we de niet-relevante delen weglaten:
1
| $usrNew.Permissions.Permission.Option[0].innerXml = 0 |
doen, dan werkt het wel.
Let op dan is het In Memory veranderd NIET IN DE XML FILE!
Computer says no
Hopelijk gaan ze dit ook daadwerkelijk doorvoeren.
Een hele rij microsoft certificeringen.
Uiteraard enkel in het geheugenMeekoh schreef op woensdag 03 juni 2015 @ 10:29:
[...]
Heb het net even getest en je moet inderdaad
code:
1 $usrNew.Permissions.Permission.Option[0].innerXml = 0
doen, dan werkt het wel.
Let op dan is het In Memory veranderd NIET IN DE XML FILE!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| #region OBJECT If (!(Test-Path "\\$FZServer\$FZDataShare\$ftpGroup\$ftpUsername")){$Null = New-Item -ItemType Directory -Path "\\$FZServer\$FZDataShare\$ftpGroup\$ftpUsername"} If (!(Test-Path "\\$FZServer\$FZDataShare\$ftpGroup\$ftpUsername\1")){$Null = New-Item -ItemType Directory -Path "\\$FZServer\$FZDataShare\$ftpGroup\$ftpUsername\1"} If (!(Test-Path "\\$FZServer\$FZDataShare\$ftpGroup\$ftpUsername\2")){$Null = New-Item -ItemType Directory -Path "\\$FZServer\$FZDataShare\$ftpGroup\$ftpUsername\2"} If (!(Test-Path "\\$FZServer\$FZDataShare\$ftpGroup\$ftpUsername\3")){$Null = New-Item -ItemType Directory -Path "\\$FZServer\$FZDataShare\$ftpGroup\$ftpUsername\3"} If (!(Test-Path "\\$FZServer\$FZDataShare\$ftpGroup\$ftpUsername\4")){$Null = New-Item -ItemType Directory -Path "\\$FZServer\$FZDataShare\$ftpGroup\$ftpUsername\4"} $usrNew = ($xmlData.FileZillaServer.Users.User | Where-Object {$_.Name -EQ "TemplateUser"}).Clone() $usrNew.Name = $ftpUsername $usrNew.SelectSingleNode("Option[@Name='Pass']").InnerText = hashMeAPassword $ftpPassword $usrNew.SelectSingleNode("Option[@Name='Enabled']").InnerText = 1 $usrNew.SelectSingleNode("Option[@Name='Comments']").InnerText = "Created by $env:username on $(Get-Date -Format "yyyy/MM/dd hh:mm:ss")" $usrNew.Permissions.Permission.Dir = "$FZServer\$FZDataShare\$ftpGroup\$ftpUsername" $usrNew.Permissions.Permission.Option[0].InnerXML = 1 $usrNew.Permissions.Permission.Option[1].InnerXML = 1 $usrNew.Permissions.Permission.Option[2].InnerXML = 1 $usrNew.Permissions.Permission.Option[3].InnerXML = 1 $usrNew.Permissions.Permission.Option[4].InnerXML = 1 $usrNew.Permissions.Permission.Option[5].InnerXML = 0 $usrNew.Permissions.Permission.Option[6].InnerXML = 1 $usrNew.Permissions.Permission.Option[7].InnerXML = 1 $Null = $xmlData.DocumentElement.Users.AppendChild($usrNew) $xmlData.Save($xmlFilePath) #endregion OBJECT "$(Get-Date -format yyyy-MM-dd_HH:mm:ss) Reloading FileZilla configuration" | Out-File "C:\Temp\New-FileZillaUser.log" -Encoding UTF8 -Append -Force Reload-FZConfiguration |
Maar kijk eens, kijk eens:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
| PS C:\Users\YellowOnline\Desktop> $usrNew.Permissions.Permission.Option Name #text ---- ----- FileRead 1 FileWrite 0 FileDelete 0 FileAppend 0 DirCreate 0 DirDelete 0 DirList 1 DirSubdirs 1 IsHome 1 AutoCreate 0 PS C:\Users\YellowOnline\Desktop> $usrNew.Permissions.Permission.Option[0].InnerXML = 1 PS C:\Users\YellowOnline\Desktop> $usrNew.Permissions.Permission.Option[1].InnerXML = 1 PS C:\Users\YellowOnline\Desktop> $usrNew.Permissions.Permission.Option[2].InnerXML = 1 PS C:\Users\YellowOnline\Desktop> $usrNew.Permissions.Permission.Option[3].InnerXML = 1 PS C:\Users\YellowOnline\Desktop> $usrNew.Permissions.Permission.Option[4].InnerXML = 1 PS C:\Users\YellowOnline\Desktop> $usrNew.Permissions.Permission.Option[5].InnerXML = 0 PS C:\Users\YellowOnline\Desktop> $usrNew.Permissions.Permission.Option[6].InnerXML = 1 PS C:\Users\YellowOnline\Desktop> $usrNew.Permissions.Permission.Option[7].InnerXML = 1 PS C:\Users\YellowOnline\Desktop> $usrNew.Permissions.Permission.Option Name #text ---- ----- FileRead 1 FileWrite 1 FileDelete 1 FileAppend 1 DirCreate 1 DirDelete 0 DirList 1 DirSubdirs 1 IsHome 1 AutoCreate 0 |
Het enige wat ontbrak was dus .innerXml. Dankuwel, Meekoh.
Goed idee. Nu nog Tweakers overtuigen van een PoSh lexer. Laatste keer dat ik dat vroeg, 2 jaar geleden, was het antwoord dat ik er zelf een moet aanleveren - maar ik ken mij in lexers helemaal niet uit [ik begin langzaam aan te verduitsen...] ken niets van lexers@r!k schreef op woensdag 03 juni 2015 @ 10:36:
Hier ook maar even. June Blender rogers is een feature request bij microsoft gestart om ook powershell example code te krijgen op msdn pagina's. Er kan hier op gestemd worden.
Hopelijk gaan ze dit ook daadwerkelijk doorvoeren.
[ Voor 6% gewijzigd door YellowOnline op 03-06-2015 11:28 ]
Graag gedaan.YellowOnline schreef op woensdag 03 juni 2015 @ 10:36:
[...]
Het enige wat ontbrak was dus .innerXml. Dankuwel, Meekoh.
[...]
Goed idee. Nu nog Tweakers overtuigen van een PoSh lexer. Laatste keer dat ik dat vroeg, 2 jaar geleden, was het antwoord dat ik er zelf een moet aanleveren - maar ik ken mijn in lexers helemaal niet uit
Computer says no
1
| Get-ADUser $user.SamAccountName -Server $RemoteServer -Credential $Credentials -Properties Mail |
Ik heb een groot forest, vandaar de noodzaak voor -server. Elke user duurt +/- 20 seconden. Dat duurt aardig lang als je zo een paar duizend users moet doen
Edit: 20 seconden was optimistisch...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| PS H:\> Measure-Command {Get-ADUser administrator -Server $Server -Credential $Credentials -Properties Ma
il}
Days : 0
Hours : 0
Minutes : 1
Seconds : 32
Milliseconds : 624
Ticks : 926241015
TotalDays : 0,00107203821180556
TotalHours : 0,0257289170833333
TotalMinutes : 1,543735025
TotalSeconds : 92,6241015
TotalMilliseconds : 92624,1015 |
[ Voor 26% gewijzigd door YellowOnline op 03-06-2015 12:47 ]
Wat gebeurt er als je de parameter -searchbase gebruikt en enkel je gebruikersOU definieert?
1
| PS C:\> Get-ADUser -Filter * -SearchBase "OU=Finance,OU=UserAccounts,DC=FABRIKAM,DC=COM" |
[ Voor 65% gewijzigd door nagasy op 03-06-2015 12:36 ]
Battle.net: NagaByrd#2844
Welke van de 100 OUs? Het zijn niet eens dezelfde OUs in de 14 domeinen of zo.nagasy schreef op woensdag 03 juni 2015 @ 12:35:
[...]
Wat gebeurt er als je de parameter -searchbase gebruikt en enkel je gebruikersOU definieert?
C#:
1 PS C:\> Get-ADUser -Filter * -SearchBase "OU=Finance,OU=UserAccounts,DC=FABRIKAM,DC=COM"
Ik zou zeggen de bovenliggende OU voor al je gebruikers.
Kan je niet op één domein testen om te zien of er snelheidswinst is?
Steek het desnoods in een Measure-Command?
Kan je anders geen workflow maken en per domein de get-aduser met -searchbase afgaan?
Ik neem aan dat de volgorde van de gebruiker niet uitmaakt.
Lijkt me wel omslachtig als dsquery wel onmiddellijk resultaten geeft.
Battle.net: NagaByrd#2844
Computer says no
Dat wint niet bepaald een schoonheidsprijs: nog los van het feit dat dit een de facto dump van de hele AD DB is (...ik heb het al eens gedaan) blijven de dingen zo niet bepaald up to date. Vooral omdat ik net een script geschreven heb dat de user attributes (meer bepaald telefoonnummers en adres) goed moet zetten van al die gebruikers.Meekoh schreef op woensdag 03 juni 2015 @ 13:18:
Wat je ook zou kunnen doen is in 1x alle users ophalen en dan in memory daarin je user opzoeken.
Een hele rij microsoft certificeringen.
De echte vraag is natuurlijk:Meekoh schreef op woensdag 03 juni 2015 @ 13:18:
Wat je ook zou kunnen doen is in 1x alle users ophalen en dan in memory daarin je user opzoeken.
Dat zou ik ook wel interessant vinden om te weten. Work-around zou mooi zijn natuurlijk, maar dat neemt niet weg dat dit een logische vraag is.YellowOnline schreef op woensdag 03 juni 2015 @ 12:00:
heeft iemand een verklaring waarom dit een eeuwigheid duurt?
3.0. Maar de DCs zijn bijna allemaal Win2003. Wat -LDAPFilter betreft, oordeel zelf:@r!k schreef op woensdag 03 juni 2015 @ 13:35:
Welke versie van Powershell gebruik je? Wellicht dat de query op een nieuwere versie sneller gaat? Anders gebruikmaken van ldapfilter?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| PS H:\> Measure-Command {Get-ADUser -LDAPFilter "(samAccountName=Administrator)" -Server $Server -Credential $Credentials}
Days : 0
Hours : 0
Minutes : 0
Seconds : 59
Milliseconds : 505
Ticks : 595051946
TotalDays : 0,000688717530092593
TotalHours : 0,0165292207222222
TotalMinutes : 0,991753243333333
TotalSeconds : 59,5051946
TotalMilliseconds : 59505,1946 |
Los van de "waarom" vraag is een work-around inderdaad ook welkomJazzy schreef op woensdag 03 juni 2015 @ 13:41:
[...]
De echte vraag is natuurlijk:
[...]
Dat zou ik ook wel interessant vinden om te weten. Work-around zou mooi zijn natuurlijk, maar dat neemt niet weg dat dit een logische vraag is.
Misschien is de verklaring dat de PoSh-cmdlets via AD Web Services verlopen op die Server 2003s en dat de lijnen gewoon te traag zijn. Al spreken we hier over een paar 100 KB.
[ Voor 7% gewijzigd door YellowOnline op 03-06-2015 13:45 ]
True, true...Jazzy schreef op woensdag 03 juni 2015 @ 13:41:
[...]
De echte vraag is natuurlijk:
[...]
Dat zou ik ook wel interessant vinden om te weten. Work-around zou mooi zijn natuurlijk, maar dat neemt niet weg dat dit een logische vraag is.
Mogelijke verklaringen:
- property die je zoekt is niet geindexeerd (lijkt me sterk bij SamAccount, maar misschien die mail property)
- Powershell versie.
Computer says no
De machine waarvandaan je die query doet, zit die in hetzelfde domein?
Je zegt dat bijna al je DC's 2003 zijn, hoe heb je die activedirectory module werkend gekregen dan? Mijn query is tegen 2008 R2 machines. Wellicht dat dat iets verklaart. Om het op 2003 werkend te krijgen heb je een webgateway of iets dergelijks nodig (ben de exacte benaming even vergeten)
[ Voor 37% gewijzigd door @r!k op 03-06-2015 13:51 ]
Een hele rij microsoft certificeringen.
Neen, maar is geen verschil als ik direct op de DC hetzelfde commando uitvoer voor het domein van die DC eigenlijk. Wat meteen mijn idee van ADWS uitsluit.@r!k schreef op woensdag 03 juni 2015 @ 13:49:
Zelfde commando duurt hier 4.8 seconden, zonder ldapfilter 5,2. Ik gebruik alleen die credentials optie niet. En ik kan toch wel zeggen dat ik het tegen een behoorlijk grote AD query.
De machine waarvandaan je die query doet, zit die in hetzelfde domein?
Je zegt dat bijna al je DC's 2003 zien, hoe heb je die activedirectory module werkend gekregen dan?
Als je eerst richting de ADWS moet en dan weer terug dan kan ik me wel iets aan vertraging voorstellen. Heb je een 2008 DC beschikbaar waar je het op kunt proberen?YellowOnline schreef op woensdag 03 juni 2015 @ 13:51:
[...]
Neen, maar is geen verschil als ik direct op de DC hetzelfde commando uitvoer voor het domein van die DC eigenlijk. Wat meteen mijn idee van ADWS uitsluit.
Een hele rij microsoft certificeringen.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| $objDomain = New-Object System.DirectoryServices.DirectoryEntry("LDAP://dc=leuk,dc=domein,dc=local")
$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
$colProplist = "Mail"
foreach ($i in $colPropList)
{
$objSearcher.PropertiesToLoad.Add($i)
}
$user = "pietje puk"
$strFilter = "(&(objectCategory=User)(name=$($user)))"
$objSearcher.SearchRoot = $objDomain
$objSearcher.PageSize = 1000
$objSearcher.Filter = $strFilter
$objSearcher.SearchScope = "Subtree"
$colResults = $objSearcher.FindAll() |
Computer says no
Verwijderd
Wikipedia: Modulair rekenen
1
2
3
4
5
| $myEmployees = @("Henk","Linda","Jan","Jose")
$myModulus = $myEmployees.Length
$myWeekNumber = Get-Date -UFormat %V
$myResult = $myWeekNumber % $myModulus
Write-OutPut "Week Number: $($myWeekNumber) Employee Name: $($myEmployees[$myResult])" |
Ik nog eens voortgewerkt aan mijn achterliggende code. Iemand moet mij dit verklaren:Meekoh schreef op woensdag 03 juni 2015 @ 14:01:
of gebruik het .Net framework. Heb ik ook vroeger gedaan toen get-aduser nog niet bestond.
code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18$objDomain = New-Object System.DirectoryServices.DirectoryEntry("LDAP://dc=leuk,dc=domein,dc=local") $objSearcher = New-Object System.DirectoryServices.DirectorySearcher $colProplist = "Mail" foreach ($i in $colPropList) { $objSearcher.PropertiesToLoad.Add($i) } $user = "pietje puk" $strFilter = "(&(objectCategory=User)(name=$($user)))" $objSearcher.SearchRoot = $objDomain $objSearcher.PageSize = 1000 $objSearcher.Filter = $strFilter $objSearcher.SearchScope = "Subtree" $colResults = $objSearcher.FindAll()
1
| Get-ADUser -Filter $ADFilter -Server $SelectedDomain -Credential $Credentials -Properties Enabled, CanonicalName, SID, SamAccountName, LastLogon, GivenName, Surname, DisplayName, Mail, Description, Title, StreetAddress, PostalCode, City, Country, Company, HomePage, OfficePhone, HomePhone, MobilePhone, Fax) |
1
2
3
4
5
| Days : 0 Hours : 2 Minutes : 28 Seconds : 10 Milliseconds : 372 |
Versus
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
| $ForestUsers = @()
$Forest = [System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest()
ForEach ($Domain in $Forest.Domains)
{
$domainDN = $Domain.GetDirectoryEntry().distinguishedName
$NumDays = 0
$currentDate = [System.DateTime]::Now
$currentDateUtc = $currentDate.ToUniversalTime()
$lltstamplimit = $currentDateUtc.AddDays(- $NumDays)
$lltIntLimit = $lltstampLimit.ToFileTime()
#$objstalesearcher = New-Object System.DirectoryServices.DirectorySearcher([ADSI]'')
$objstalesearcher = New-Object System.DirectoryServices.DirectorySearcher([ADSI]"LDAP://$domainDN")
$objstalesearcher.filter = "(&(objectCategory=person)(objectClass=user)(lastLogonTimeStamp<=" + $lltIntLimit + "))"
$users = $objstalesearcher.FindAll() | Select-Object `
@{e={$_.properties.distinguishedName};n='Domain'},`
@{e={$_.properties.distinguishedName};n='Distinguished Name'},`
@{e={$_.properties.samaccountname};n='Username'},`
@{e={[datetime]::FromFileTimeUtc([int64]$_.properties.lastlogontimestamp[0])};n='Last Logon'},`
@{e={[string]$adspath=$_.properties.adspath;$account=[ADSI]$adspath;$account.psbase.invokeget('AccountDisabled')};n='Account Is Disabled'},`
@{e={$_.properties.givenName};n='GivenName'},`
@{e={$_.properties.sn};n='Surname'},`
@{e={$_.properties.displayName};n='DisplayName'},`
@{e={$_.properties.mail};n='Mail'},`
@{e={$_.properties.description};n='Description'},`
@{e={$_.properties.title};n='Title'},`
@{e={$_.properties.streetAddress};n='StreetAddress'},`
@{e={$_.properties.postalCode};n='PostalCode'},`
@{e={$_.properties.l};n='City'},`
@{e={$_.properties.c};n='Country'},`
@{e={$_.properties.company};n='Company'},`
@{e={$_.properties.wWWHomePage};n='HomePage'},`
@{e={$_.properties.telephoneNumber};n='OfficePhone'},`
@{e={$_.properties.homePhone};n='HomePhone'},`
@{e={$_.properties.mobile};n='MobilePhone'},`
@{e={$_.properties.facsimileTelephoneNumber};n='Fax'}
$ForestUsers = $ForestUsers + $Users
} |
1
2
3
4
5
| Days : 0 Hours : 0 Minutes : 2 Seconds : 38 Milliseconds : 216 |
Negeer de kleine verschillen (ik verander meer dan enkel het mechanisme...), maar leg mij uit waarom dat zo'n groot onderscheid is voor hetzelfde resultaat? 2.5 uur vs 2.5 minuten! Daar ben ik toch teleurgesteld in de AD-Module.
Edit: nog een verschil is dat de AD cmdlets AD Web Services gebruiken en de .net methode niet. Er is denk ik een goede mogelijkheid dat dit nogal veel slechter performt dan native methodes.
http://blogs.msdn.com/b/a...eb-services-overview.aspx
[ Voor 60% gewijzigd door SteeringWheel op 29-07-2015 13:17 ]
A forum post should be like a skirt. Long enough to cover the subject material, but short enough to keep things interesting.
Dat is ook mijn eigen vermoeden, alleen al omdat de DCs in de meeste domeinen die ik beheer nog 2003 zijn en AD Web Services apart geïnstalleerd is om die machines met PoSh aan te kunnen spreken.SteeringWheel schreef op woensdag 29 juli 2015 @ 13:10:
[...]Er is denk ik een goede mogelijkheid dat dit nogal veel slechter performt dan native methodes.
http://blogs.msdn.com/b/a...eb-services-overview.aspx
Nou ik ben daar zelf ook nog niet 100% achter. Echter het grootste verschil dat ik kan bedenken tussen de twee is dat Get-ADUser gebruik maakt van de ADWS (Active Directory Web Services) en het andere script gewoon een LDAP query doet.YellowOnline schreef op woensdag 29 juli 2015 @ 12:17:
[...]
Negeer de kleine verschillen (ik verander meer dan enkel het mechanisme...), maar leg mij uit waarom dat zo'n groot onderscheid is voor hetzelfde resultaat? 2.5 uur vs 2.5 minuten! Daar ben ik toch teleurgesteld in de AD-Module.
Blijkbaar voegen die Webservices een zekere overhead toe aan het hele proces.
Computer says no
Dat is toch wel een gigantisch verschil. Om uit te lezen ben ik volledig op LDAP overgeschakeld. Misschien moet ik hetzelfde doen voor wegschrijven (wat nu nog met Set-ADUser gebeurt).Meekoh schreef op woensdag 29 juli 2015 @ 15:27:
[...]
Nou ik ben daar zelf ook nog niet 100% achter. Echter het grootste verschil dat ik kan bedenken tussen de twee is dat Get-ADUser gebruik maakt van de ADWS (Active Directory Web Services) en het andere script gewoon een LDAP query doet.
Blijkbaar voegen die Webservices een zekere overhead toe aan het hele proces.
Zijn er eigenlijk nog mensen die in een forest met vele domeinen werken? Anders share ik wel eens de code van mijn zelfgeknutselde programma. Screenshotjes hieronder. Een prijs voor GFX zal het niet krijgen, maar het is toch verdomd handig.


[ Voor 20% gewijzigd door YellowOnline op 29-07-2015 16:01 ]
Een hele rij microsoft certificeringen.
Of hard-coded domain forest admin credentials@r!k schreef op dinsdag 04 augustus 2015 @ 08:42:
Let er wel goed op bij het sharen dat je geen vertrouwelijke data in het script heb staan zoals servernamen of bedrijfsnaam etc.
[ Voor 10% gewijzigd door YellowOnline op 04-08-2015 09:53 ]
Als dat alles is, online gooien die hapYellowOnline schreef op dinsdag 04 augustus 2015 @ 09:52:
[...]
Of hard-coded domain forest admin credentialsIk schakel wel op Get-Credentials over binnenkort.
Als ik iets online gooi zorg ik er eigenlijk altijd voor dat er niks hardcoded in staat maar dat alle benodigde informatie via het script wordt opgehaald. Domeinnaam e.d. kun je laten invoeren maar ook gewoon uit laten lezen via de cmdlets. Voor output probeer een parameter erin te bakken waarmee je zelf een path op kunt geven.
Een hele rij microsoft certificeringen.
Als ik de credentials buiten beschouwing laat is het enige hard-coded de forest root - het is uiteindelijk een programma gebouwd voor mijn omgeving. De domeinen in die root worden uiteraard gegenereerd. Output is met een save-knop. Het is een GUI-programma tenslotte. Ik probeer vandaag iets online te gooien. 't Zal wel op een externe host zijn, want mijn programma heeft meer lijnen code dan ik hier posten kan.@r!k schreef op dinsdag 04 augustus 2015 @ 10:57:
[...]
Als dat alles is, online gooien die hap![]()
Als ik iets online gooi zorg ik er eigenlijk altijd voor dat er niks hardcoded in staat maar dat alle benodigde informatie via het script wordt opgehaald. Domeinnaam e.d. kun je laten invoeren maar ook gewoon uit laten lezen via de cmdlets. Voor output probeer een parameter erin te bakken waarmee je zelf een path op kunt geven.
Geen oneliner?YellowOnline schreef op dinsdag 04 augustus 2015 @ 11:09:
[...]
Als ik de credentials buiten beschouwing laat is het enige hard-coded de forest root - het is uiteindelijk een programma gebouwd voor mijn omgeving. De domeinen in die root worden uiteraard gegenereerd. Output is met een save-knop. Het is een GUI-programma tenslotte. Ik probeer vandaag iets online te gooien. 't Zal wel op een externe host zijn, want mijn programma heeft meer lijnen code dan ik hier posten kan.
Een hele rij microsoft certificeringen.
Ik heb het ingekort tot 1325 lijnen.
Hier, Powershellers: probeer dit eens uit in jullie forest. Ik ben benieuwd eigenlijk. Het is geen afgewerkt product, dus verwacht bugs. Dramatische zaken zijn niet echt mogelijk. De foutmeldingen van 2 ontbrekende afbeeldingen zijn normaal aangezien ik die ter anonymisering gesloopt heb
Code: http://poshcode.org/5963
PS. Vergeet niet de variabele $ForestName = "microsoft.com" aan te passen aan je eigen omgeving natuurlijk.
PPS. En ik kom er net achter dat niet iedereen een $WorkingPath = $ENV:HOMESHARE heeft. Maak daar $WorkingPath = $ENV:TEMP van of zo.
[ Voor 18% gewijzigd door YellowOnline op 04-08-2015 21:26 ]
Query took 25.9928605 seconds
3780 row(s)
A forum post should be like a skirt. Long enough to cover the subject material, but short enough to keep things interesting.
Single Domain is de meerwaarde nogal beperktSteeringWheel schreef op dinsdag 04 augustus 2015 @ 14:39:
hij doet het hoor, single domain forest:
Query took 25.9928605 seconds
3780 row(s)
- Filters wat gebruiksvriendelijker maken
- Log autoscroll
Om je code iets in te korten (uitgaande van PS3 of hoger) :YellowOnline schreef op dinsdag 04 augustus 2015 @ 12:14:
[...]
Ik heb het ingekort tot 1325 lijnen.
Hier, Powershellers: probeer dit eens uit in jullie forest. Ik ben benieuwd eigenlijk. Het is geen afgewerkt product, dus verwacht bugs. Dramatische zaken zijn niet echt mogelijk. De foutmeldingen van 2 ontbrekende afbeeldingen zijn normaal aangezien ik die ter anonymisering gesloopt heb
Code: http://poshcode.org/5963
- De System assembly hoef je niet in te laden, dat doet PS automatisch
- System.Data wordt als het goed is ook automatisch geladen
Het deel in je code mbt het zoeken naar een alternatief voor Set-ADUser : bekijk eens System.DirectoryServices.AccountManagement.
Om bv properties van het current AD account te zien (handig in user scripts) doe je het volgende :
1
2
| add-type -AssemblyName System.DirectoryServices.AccountManagement [System.DirectoryServices.AccountManagement.UserPrincipal]::Current |
Je krijgt hier btw ook mooie objecten voor terug ipv met de DirectorySearcher van System.DirectoryServices.
Verder over PS5 (want ik lees hier nog weinig over in dit topic) : ik ben erg blij met de new() method in de .NET classes, scheelt weer het gebruik van new-object (voor mij blijft de code zo overzichtelijk EN erg makkelijk om iets te porten naar C# op die manier).
De kleuren in de automatische syntax highlighting vind ik daarentegen weer een beetje ongelukkig gekozen ten opzichte van ISE (bv groen voor een variable terwijl dit in ISE standaard rood is, strings hebben een bepaalde kleur groen welke lastig te lezen is op de standaard achtergrond, laat staan als je je PS window transparant hebt gemaakt in Win10)
[ Voor 20% gewijzigd door Killah_Priest op 04-08-2015 19:53 ]
Wat je alternatieve code betreft: de vraag is hoe dit gemakkelijk werkt. Ik ben in domein Y van forest X en mijn scipt werk in domeinen [A...O] van forest Z. Authenticatie is dus een belangrijk issue en zowel DirectorySearcher als AD cmdlets kunnen daar goed mee om. Met de output van DirectorySearcher ben ik trouwens tevreden. Eerst heb ik het geprobeerd met dsget en dat was een ramp inzake text scraping. Maar ik zal er eens naar kijken, alleen al omdat ik een alternatief nodig heb om weg te schrijven.Killah_Priest schreef op dinsdag 04 augustus 2015 @ 19:47:
[...]
Om je code iets in te korten (uitgaande van PS3 of hoger) :
- De System assembly hoef je niet in te laden, dat doet PS automatisch
- System.Data wordt als het goed is ook automatisch geladen
Het deel in je code mbt het zoeken naar een alternatief voor Set-ADUser : bekijk eens System.DirectoryServices.AccountManagement.
Om bv properties van het current AD account te zien (handig in user scripts) doe je het volgende :
code:
1 2 add-type -AssemblyName System.DirectoryServices.AccountManagement [System.DirectoryServices.AccountManagement.UserPrincipal]::Current
Je krijgt hier btw ook mooie objecten voor terug ipv met de DirectorySearcher van System.DirectoryServices.
Ik heb net nog een fout ontdekt:
1
| YELLOW.NET/Guest/Users |
Die System.Assembly is een restant van de IDE (Powershell Studio) die ik gebruik om de GUI te bouwen.
Die volgorde klopt niet denk ik
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
| Function Convert-DNtoEMail ([string]$DN) { [string]$EMail = $DN Return $EMail; } Function Get-DN ($FQDN) { $FQDNArray = $FQDN.Split(".") $Separator = "," For ($x = 0; $x -LT $FQDNArray.Length ; $x++) { If ($x -EQ ($FQDNArray.Length - 1)) { $Separator = "" } [string]$DN += "DC=" + $FQDNArray[$x] + $Separator } Return $DN } Function Get-FQDN ($x) { #OK, this is quick and dirty $y = $x -Split "DC=" $a = $y | Select-Object -Skip 1 | % {$_.Replace(",",".")} $b = $a + $y[0] -Replace "CN=","/" -Replace "OU=","/" -Replace ",","" #to do: escaped commas \, -> regex $b = -join $b $b } |
New-Object is de PoSh-methode en .New() de .NET-methode. Vergeljkbaar met -Split en .Split(). Zelf gebruik ik ze ook door elkaar, maar een purist kan beargumenteren dat de eerste methode de enige echte goeie is voor PoSh en de tweede eigenlijk geen PoSh meer is maar C#. Maar ach, een kniesoor die daar om maalt.Verder over PS5 (want ik lees hier nog weinig over in dit topic) : ik ben erg blij met de new() method in de .NET classes, scheelt weer het gebruik van new-object (voor mij blijft de code zo overzichtelijk EN erg makkelijk om iets te porten naar C# op die manier).
De ISE van Windows heb ik trouwens nog nooit gebruikt. Die valt wat licht uit in vergelijking met commerciele producten.De kleuren in de automatische syntax highlighting vind ik daarentegen weer een beetje ongelukkig gekozen ten opzichte van ISE (bv groen voor een variable terwijl dit in ISE standaard rood is, strings hebben een bepaalde kleur groen welke lastig te lezen is op de standaard achtergrond, laat staan als je je PS window transparant hebt gemaakt in Win10)
[ Voor 12% gewijzigd door YellowOnline op 04-08-2015 21:38 ]
Ik merk wel dat ik tegenwoordig steeds vaker rechtstreeks .net aanroep en steeds minder cmdlets gebruik. Het is dat het allemaal ook zo verschrikkelijk makkelijk kan met PS. Ook de Exchange web API aanroepen via PS (en vervolgens subscriben op een newMail event en daar weer triggers aan hangen) is vrij simpel te doen.
Mijn plan om ooit nog eens te maken (en alle code heb ik in feite al verspreid over tig scripts welke ik in de loop der tijd gebouwd heb) : automatisch user creation script dmv HR die een onboard form mailed. EWS via PS aanroepen om een mailbox te monitoren op specifieke subjects. Daarna attachment met de user info van het onboard Xlsx form processen (waarbij een xml file op een centrale locatie zeg maar de "map" is mbt welke groepen etc bij welke functies behoren).
(Helaas is een web based oplossing daar waarschijnlijk een stuk geschikter voor en in feite ook vrij snel gemaakt)
Dit. Ik gebruik PoSh graag voor dingen waar het eigenlijk niet meer voor gemaakt is, alleen al omdat het de enige taal is waar ik echt wat in kan bouwen, maar wat jij daar zegt kan echt veel gemakkelijker via een web interface.Killah_Priest schreef op woensdag 05 augustus 2015 @ 01:48:
[...]
(Helaas is een web based oplossing daar waarschijnlijk een stuk geschikter voor en in feite ook vrij snel gemaakt)
Nu is dat natuurlijk heel mooi meegenomen maar de uitbreiding is gewoon heel erg goed. Kijk maar eens op powertheshell.com .
Een hele rij microsoft certificeringen.
Voor het maken van een GUI is Sapien PowerShell Studio inderdaad wel handig, maar dat doe ik nagenoeg nooit
Dat gaat hoor. Kwestie van een C++ library te installeren. Hier:

Aangezien ik mijn programmaatje moet uitbreiden met de mogelijkheid om nieuwe gebruikers aan te maken ben ik aan de slag gegaan met DirectoryServices. Tot dusver heb ik het probleem dat ik verwachtte: authenticatie. Ondanks correcte credentials krijg ik me niet verbondenKillah_Priest schreef op dinsdag 04 augustus 2015 @ 19:47:
[...]
Om je code iets in te korten (uitgaande van PS3 of hoger) :
- De System assembly hoef je niet in te laden, dat doet PS automatisch
- System.Data wordt als het goed is ook automatisch geladen
Het deel in je code mbt het zoeken naar een alternatief voor Set-ADUser : bekijk eens System.DirectoryServices.AccountManagement.
Om bv properties van het current AD account te zien (handig in user scripts) doe je het volgende :
code:
1 2 add-type -AssemblyName System.DirectoryServices.AccountManagement [System.DirectoryServices.AccountManagement.UserPrincipal]::Current
Je krijgt hier btw ook mooie objecten voor terug ipv met de DirectorySearcher van System.DirectoryServices.
Verder over PS5 (want ik lees hier nog weinig over in dit topic) : ik ben erg blij met de new() method in de .NET classes, scheelt weer het gebruik van new-object (voor mij blijft de code zo overzichtelijk EN erg makkelijk om iets te porten naar C# op die manier).
De kleuren in de automatische syntax highlighting vind ik daarentegen weer een beetje ongelukkig gekozen ten opzichte van ISE (bv groen voor een variable terwijl dit in ISE standaard rood is, strings hebben een bepaalde kleur groen welke lastig te lezen is op de standaard achtergrond, laat staan als je je PS window transparant hebt gemaakt in Win10)
1
2
3
4
5
6
7
| PS H:\> New-Object System.DirectoryServices.DirectoryEntry("LDAP://OU=NEWYORK Users,DC=NEWYORK,DC=MICROSOFT,DC=COM"
, 'MICROSOFT\Administrator', 'I<3BillG@t3s')
format-default : The following exception occurred while retrieving member "distinguishedName": "Logon failure: unknown
user name or bad password.
"
+ CategoryInfo : NotSpecified: (:) [format-default], ExtendedTypeSystemException
+ FullyQualifiedErrorId : CatchFromBaseGetMember,Microsoft.PowerShell.Commands.FormatDefaultCommand |
Ik kijk wel verder. Misschien moet ik de vorm van de parameters wijzigen of zo.
Overigens haat ik maandagen. Ik kijk al een kwartier op deze code en snap nog altijd niet wat mijn logische fout is. Want het zal wel aan mij liggen en niet aan Powershell.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| PS H:\> Test-DotNet35 -EQ $True
True
PS H:\> If (Test-DotNet35 -NE $True)
>> {
>> Throw "I hate Mondays"
>> #[System.Windows.Forms.MessageBox]::Show(".NET 3.5 could not be detected","Prerequisite failed",[System.Windows.Forms
.MessageBoxButtons]::OK,[System.Windows.Forms.MessageBoxIcon]::Error)
>> #Exit;
>> }
>>
I hate Mondays
At line:3 char:1
+ Throw "I hate Mondays"
+ ~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (I hate Mondays:String) [], RuntimeException
+ FullyQualifiedErrorId : I hate Mondays
PS H:\> |
Haal ik weer TRUE en FALSE door elkaar? Nee toch?