Powershell Format Arrays to two dimensional Arrays - arrays

i had a problem a few days ago where my script that is supposed to extract all hostnames from an AD OU and then check for the space used and free space on disks for every single host. Since this is the first time i do something with powershell i ran into many problems. The Problem that i got now is that the script cant find the hostnames listed in an array. I think i found out why it wont work because it uses the wrong hostname.
Error message i get for every hostname:
Write-Warning : Es wurde kein Positionsparameter gefunden, der das Argument "#{Name=BUCHHOLZMVZ}" akzeptiert.
In Zeile:16 Zeichen:5
+ Write-Warning "Server " $server "nicht erreichbar"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Write-Warning], ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.WriteWarningCommand
When i only use the command to get all hostnames of all servers i get:
Name
----
someserver
someserver1
someserver2
(and so on...)
Here is the script:
$servers = Get-ADComputer -Filter * -SearchBase "OU=ServerOU, DC=somedomain, DC=somedomain, DC=somedomain" | Select-Object Name
$allDisks = foreach ($server in $servers)
{
try {
Get-WmiObject Win32_LogicalDisk -ComputerName $server -Filter DriveType=3 -ErrorAction Stop |
Select-Object #{'Name'='ComputerName'; 'Expression'={$server}},
DeviceID,
#{'Name'='Size'; 'Expression'={[math]::truncate($_.size / 1GB)}},
#{'Name'='Freespace'; 'Expression'={[math]::truncate($_.freespace / 1GB)}}
}
catch {
Write-Warning "Server " $server "nicht erreichbar"
Continue
}
}
$allDisks |Export-Csv C:\Servers.csv -NoTypeInformation

Use the following for your first line:
$servers = Get-ADComputer -Filter * -SearchBase "OU=ServerOU, DC=somedomain, DC=somedomain, DC=somedomain" |
Select-Object -Expand Name
Using Select-Object without -Expand or -ExpandProperty outputs an object that contains properties and values. If you only want to output values of the selected properties you must use -Expand or member access ($servers.Name).

Related

Powershell Get-mailboxdatabase and Create Shared Mailbox Script

I have some basic Powershell knowledge and i am trying to revise an existing script on our Service Desk to make a shared mailbox in Exchange 2010.
The current version was setup so the user can input the database to assign the mailbox to.
The revised version i am trying to do is suppose to pull the Databases and display the size of each database. Then the idea is the user can simply input a number value to represent a database, rather than writing out the whole database.
So after doing some research i tried out the following;
$mailboxname=Read-Host “Enter mailbox name”
$alias=Read-Host “Enter Email Alias”
$User=$alias + "#domain.com"
Get-MailboxDatabase -Server "Server" -Status | Where-Object {$_.name -like "Database*"} | Sort-Object -Descending -Property #{Expression = "name"; Descending = $true} | Select Name,Databasesize
$script:ChosenDatabase=Get-MailboxDatabase
function Get-MailboxDatabase
{
$database=Read-Host "Enter database using a value of 1 to 4 to add the mailbox to"
Switch ($database)
{
1 {$Chosendatabase="Database-1"}
2 {$Chosendatabase="Database-2"}
3 {$Chosendatabase="Database-3"}
4 {$Chosendatabase="Database-4"}
}
return $Chosendatabase
}
New-mailbox -shared -Name $mailboxname -alias $alias -UserPrincipalName $User -OrganizationalUnit "Domain.com/Resources-OU" -Database $Chosendatabase
Get-mailbox -Identity $User | ft DisplayName,Database
read-host "hit enter to close window"
This kinda works, but it doesn't show the Mailbox Database and as can be seen in the example below it did a double up of the readhost to enter the database
Enter mailbox name: testscript2
Enter Email Alias: testscript2
Enter database using a value of 1 to 4 to add the mailbox to: 2
Enter database using a value of 1 to 4 to add the mailbox to: 2
Name Alias ServerName ProhibitSendQuota
---- ----- ---------- -----------------
testscript2 testscript2 Server unlimited
DisplayName Database
----------- --------
testscript2 Database-2
hit enter to close window:
So i found Show output before Read-Host, which i tried out to see if this will help show the mailboxdatabase before inputting a value.
Changed;
Get-MailboxDatabase -Server "Server" -Status | Where-Object {$_.name -like "Database*"} | Sort-Object -Descending -Property #{Expression = "name"; Descending = $true} | Select Name,Databasesize
To;
$getDB=Get-MailboxDatabase -Server "Server" -Status | Where-Object {$_.name -like "Database*"} | Sort-Object -Descending -Property #{Expression = "name"; Descending = $true} | Select Name,Databasesize | Out-String;
Write-Host $getDB
But got the following errors
Enter mailbox name: testScript
Enter Email Alias: testscript
Name DatabaseSize
---- ------------
Database-4 762.8 GB
Database-3 376.3 GB
Database-2 249.3 GB
Database-1 829.8 GB
Cannot process argument transformation on parameter 'Database'. Cannot convert the
"System.Collections.ArrayList" value of type
"System.Collections.ArrayList" to type "Microsoft.Exchange.Configuration.Tasks.DatabaseIdParameter".
+ CategoryInfo : InvalidData: (:) [New-Mailbox], ParameterBindin...mationException
+ FullyQualifiedErrorId : ParameterArgumentTransformationError,New-Mailbox
+ PSComputerName : Domain.com
The operation couldn't be performed because object 'testscript#domain.com' couldn't be found on
'Domain.com'.
+ CategoryInfo : NotSpecified: (:) [Get-Mailbox], ManagementObjectNotFoundException
+ FullyQualifiedErrorId : 8D2D2EF6,Microsoft.Exchange.Management.RecipientTasks.GetMailbox
+ PSComputerName : Domain.com
hit enter to close window:
Is anybody able to help shed some light on what i am doing wrong and why I am getting a double of the read-host.
Figured this problem out awhile ago and thought to post the solution here.
My mistake was the function was incorrect and shouldn't of been named
function Get-MailboxDatabase
This caused the issue as i was creating a function using an existing cmdlet name (DERP)
I changed my script to the following
$data = Get-MailboxDatabase -Server "Server" -Status | Where-Object {$_.name -like "DATABASE*"} | Sort-Object -Property #{Expression = "name"} | Select Name,Databasesize | ft | Out-String
function WORK
{
Write-host $data
Write-host "Pick the database with the lowest size"
Write-host
$database=Read-Host "Enter the database using a value of 1 to 4 to add the mailbox to"
Switch ($database)
{
1 {$Chosendatabase="DATABASE-1"}
2 {$Chosendatabase="DATABASE-2"}
3 {$Chosendatabase="DATABASE-3"}
4 {$Chosendatabase="DATABASE-4"}
}
return $Chosendatabase
}
$date=Get-Date -format d
$mailboxname=Read-Host “Enter the mailbox name”
$alias=Read-Host “Enter Email Alias”
$User=$alias + "#domain.com"
$ticket=Read-Host "Enter the Ticket number"
$notes="Mailbox created - $ticket - $date"
Read-Host "hit enter to Continue"
$script:ChosenDatabase = WORK
New-mailbox -shared -Name $mailboxname -alias $alias -UserPrincipalName $User -OrganizationalUnit "domain.com/Resources-OU" -Database $Chosendatabase
Set-user -identity $alias -notes "$Notes"
##This command is to make sure a copy of sent emails are stored on the shared mailbox as well as the senders mailbox
Set-MailboxSentItemsConfiguration -Identity $alias -SendAsItemsCopiedTo SenderAndFrom -SendOnBehalfOfItemsCopiedTo SenderAndFrom
##bring back confirmation the script has done as tended
Get-mailbox -Identity $User | ft DisplayName,Database
Get-mailboxsentitemsconfiguration -Identity $alias
read-host "hit enter to close window"
This has been working fine for us for the past few months

How to pass AD computer names to array?

I am trying to Set-ADComputer on all machines matching the filter that is added to the $servers array. But it's not working. I guess it has something to do with passing an object to a string, but I can't get my head around it. Anyone's got a golden tip?
#Get gateway
$gateway = "MGMT01"
$gatewayObject = Get-ADComputer -Identity $gateway
#Get servers
$servers=#(Get-ADComputer -Filter {OperatingSystem -like "Windows Server*"} -Properties Name | select name | ft -HideTableHeaders)
#Create list of servers
Out-File -FilePath c:\adcomputers.txt -InputObject $servers
#Set WAC delegation
ForEach ($server in $servers)
{
$nodeObject = Get-ADComputer -Identity $server
Set-ADComputer -Identity $nodeObject -PrincipalsAllowedToDelegateToAccount $gatewayObject
}
Errors:
Get-ADComputer : Cannot bind parameter 'Identity'. Cannot convert the "Microsoft.PowerShell.Commands.Internal.Format.FormatEndData" value of type "Microsoft.PowerShell.C
ommands.Internal.Format.FormatEndData" to type "Microsoft.ActiveDirectory.Management.ADComputer".
At C:\Users\SA.****\Desktop\inventorize-honolulu-incl-sso.ps1:7 char:40
+ $nodeObject = Get-ADComputer -Identity $server
+ ~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Get-ADComputer], ParameterBindingException
+ FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.ActiveDirectory.Management.Commands.GetADComputer
Set-ADComputer : Cannot validate argument on parameter 'Identity'. The argument is null. Provide a valid value for the argument, and then try running the command again.
At C:\Users\SA.****\Desktop\inventorize-honolulu-incl-sso.ps1:8 char:26
+ Set-ADComputer -Identity $nodeObject -PrincipalsAllowedToDelegateToAc ...
+ ~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Set-ADComputer], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.ActiveDirectory.Management.Commands.SetADComputer
To output your list of servers to a text file, all you need is this:
Get-ADComputer -Filter {OperatingSystem -like "Windows Server*"} |
Select-Object -ExpandProperty Name |
Out-File "c:\adcomputers.txt"
Bill_Stewart had the right idea, it just didn't fit in exactly with the way you're doing things.
It's the ft -HideTableHeaders that's messing up your array. Use select -ExpandProperty instead:
$servers=#(Get-ADComputer -Filter {OperatingSystem -like "Windows Server*"} -Properties Name | select -ExpandProperty name)
That will give you an array of plain strings, as you seem to want.
Your Get-ADComputer line is an expression problem, you are missing () in {}. Your example works fine after fixing that.
$servers=#(Get-ADComputer -Filter {(OperatingSystem -like "Windows Server*")} -Properties Name | select name | ft -HideTableHeaders)

Pulling a list of entries from Registry key and checking them for anything that is contained in an array

I am using the following code to try and pull a list of installed software on a system and check for certain entries within the list, so far I have managed to get the software list to run as desired using the following code:
$path = 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*'
Get-ChildItem $path | Get-ItemProperty | Select-Object DisplayName
if (ItemProperty -Name -eq ('Wacom Tablet')) {
start notepad.exe
}
I would like this to be an array that references the DisplayName list, but I get the following error:
ItemProperty : Cannot find path 'C:\WINDOWS\system32\Wacom Tablet' because it
does not exist.
At C:\Users\username\Documents\Scripts\win10test.ps1:39 char:5
+ if (ItemProperty -Name -eq ('Wacom Tablet')) {
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\WINDOWS\system32\Wacom Tablet:String) [Get-ItemProperty], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetItemPropertyCommand
How could I achieve this?
ItemProperty is expanded to Get-ItemProperty, so your if condition
ItemProperty -Name -eq ('Wacom Tablet')
becomes
Get-ItemProperty -Name -eq -Path ('Wacom Tablet')
meaning that your code is trying to get a property -eq from an item Wacom Tablet in the current working directory (in your case apparently C:\WINDOWS\system32).
What you seem to want to do is something like this:
Get-ChildItem $path | Get-ItemProperty |
Where-Object { $_.DisplayName -eq 'Wacom Tablet'} |
ForEach-Object {
# do stuff
}
or like this:
$prop = Get-ChildItem $path | Get-ItemProperty |
Select-Object -Expand DisplayName
if ($prop -eq 'Wacom Tablet') {
# do stuff
}

ConvertFrom-StringData fails casting to Hashtable

I just tried to adapt the scripting guy's example to read data from a textfile and parse a hashtable using ConvertFrom-StringData:
$PSVersionTable.PSVersion;
[String] $loginsFileName = "$HOME\Logins.txt";
Get-Content $loginsFileName;
[Hashtable] $logins = Get-Content -Path $loginsFileName | ConvertFrom-StringData;
Write-Host got $logins.count lines from $loginsFileName;
$logins.GetEnumerator() | Sort-Object Name;
I got screwed up:
Major Minor Build Revision
----- ----- ----- --------
3 0 -1 -1
Lisa=GanzGeheim
Susanne=ganzgeheim
Fritz=geheim
Hans=Geheim
Der Wert "System.Object[]" vom Typ "System.Object[]" kann nicht in den Typ "System.Collections.Hashtable" konvertiert werden.
In Zeile:11 Zeichen:1
+ [Hashtable] $logins = Get-Content -Path $loginsFileName | ConvertFrom-StringData ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : MetadataError: (:) [], ArgumentTransformationMetadataException
+ FullyQualifiedErrorId : RuntimeException
got 0 lines from E:\Users\Christian\Logins.txt
My guess: The piping goes wrong. I tried to stress out that Get-Content delivers an array by embracing (Get-Content -Path $loginsFileName) – without any bettering. Can anybody please give me some hint?
Sorry about misleading you earlier. The issue you are having is that you are getting an array of single key hashtables because of Get-Content. For what I think you are looking for you should read in the file as one string. Assuming you have at least PowerShell v3:
$logins = Get-Content -Path $loginsFileName -Raw | ConvertFrom-StringData;
This was you get one single hashtable as supposed to an array of hashtables. This gets me once and a while since PowerShell groups the output well.
-Raw is a feature of 3.0. If you do not have access to 3.0 than either of these solutions would suffice.
$logins = Get-Content -Path $loginsFileName | Out-String | ConvertFrom-StringData;
$logins = ((Get-Content -Path $loginsFileName) -join "`r`n") | ConvertFrom-StringData;

Powershell - Unable to Compare Strings Output from Sharepoint List

After extracting a list from SharePoint, I need to validate each Item against its BRTeam value. Here is the script:
cls
if((Get-PSSnapin | Where {$_.Name -eq "Microsoft.SharePoint.PowerShell"}) -eq $null) {
Add-PSSnapin Microsoft.SharePoint.PowerShell;
}
$sourceWebUrl = "http://theoracle/WorkingHere/"
$sourceListName = "Policies & Procedures"
$spSourceWeb = Get-SPWeb $sourceWebUrl
$spSourceList = $spSourceWeb.Lists[$sourceListName]
$spSourceItems = $spSourceList.Items
$spSourceItems | ForEach-Object {
Write-Host $_['Name']
Write-Host $_['BRTeam']
}
The code works fine in terms of getting the data and writing the required items to the host.
However, if I add the following If-Statement to validate the items, I am seeing an error:
if ($_['BRTeam'].Contains('HR')) {
Write-Host $_['Name']
Write-Host $_['BRTeam']
}
I have also tried replacing the Boolean check with $x -contains 'HR' after assigning $x = $_['BRTeam'], but this returns no output (no error either). Error below:
Method invocation failed because [Microsoft.SharePoint.Taxonomy.TaxonomyFieldValue] doesn't contain a method named 'Contains'.
At line:21 char:9
+ if ($_['BRTeam'].Contains('HR')) {
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
Can anyone let me know what I am missing here?
I was able to resolve this by using the -Match operator instead:
$spSourceItems | ForEach-Object {
#Write-Host $_['ID']
#Write-Host $_['Workflow Started']
$x = $_['BRTeam']
if ($_['BRTeam'] -Match 'HR') {
Write-Host $_['Name']
}
}
If I am concerned that some other BRTeams may contain HR without actually being HR, I could also perform a -NotMatch against all the other departments.
E.g.:
$spSourceItems | ForEach-Object {
#Write-Host $_['ID']
#Write-Host $_['Workflow Started']
$x = $_['BRTeam']
if ($_['BRTeam'] -Notmatch 'Accounts' -And $_['BRTeam'] -Notmatch 'IT') {
Write-Host $_['Name']
}
}

Resources