Cut variable into multiple Strings - string

I want to write a script that renames all NICs on a Server 2012 R2.
Currently it looks like this with each one:
$NIC = Get-WMIObject -Class Win32_NetworkAdapter -Filter "NetconnectionID='Embedded LOM 1 Port 1'"
$NIC.NetconnectionID = 'Physical 1'
$NIC.Put()
Now I want to use this for different Servers and therefore I have to get the NetconnectionID from a variable.
So far I have put the NICs into a variable:
$NICS = Get-NetAdapter | select name
Now when just issuing the command $NICS it shows the list of names, but since I want to rename however many of NICs I have individually I have to break the variable down into different strings. It would be awesome if it would even count the amount and then implement my script with an if statement or foreach!
But for now I would be happy with a solution to rename a specific amount (in my case it's four).

$NICS = Get-NetAdapter | select name
for ($i = 0; $i -lt $NICS.Count; $i++) {
Write-Host (($NICS[$i]) -replace("#{name=","") -replace("}",""))
}
That is a good starting point I think.

Use foreach for that:
$NICS = Get-NetAdapter | select name
foreach ($n in $nics)
{
write-host "Nick name " $n.name
}

Related

PowerShell :: Microsoft.Azure.Commands.Sql.Database.Model.AzureSqlDatabaseModel.DatabaseName [duplicate]

This question already has answers here:
How can you use an object's property in a double-quoted string?
(5 answers)
Closed 5 months ago.
I wrote a script that allows me to query the whole Azure database park:
#$ErrorActionPreference = 'SilentlyContinue'
# Connect to Azure
$azureAccount = Connect-AzAccount
# Get Azure Access Token (we will use this to query the databasees)
#$azureToken = Get-AzAccessToken -ResourceUrl https://database.windows.net
$access_token = (Get-AzAccessToken -ResourceUrl https://database.windows.net).Token
# Queries will be picked up from here
$folderPath = '.\Queries'
# Choose how to format each date ("yyyy-MM-dd") or ("yyyy-MM-dd HH:mm:ss")
$DateTime = (Get-Date).ToString("yyyy-MM-dd")
# List Azure Sunscriptions
Get-Azsubscription | ForEach-Object -Begin { $a = 1 } -Process {"$a $($_.Name)"; $a++}
$SubscriptionChoice = Read-Host -Prompt "Copy/paste the name of the Subscription that you want to investigate. If more than one separate them by a coma, Type `"All`" if you want to target all of them"
# Iterate into subscriptoins and print names
foreach ($gs in $SubscriptionChoice) {
Select-Azsubscription -Subscription "$gs" | Out-Null
Write-Host "Let's browse into Azure Sunscription: " -NoNewline
Write-Host (Get-AzContext).Subscription.Name -ForegroundColor green
# Fins all Azure SQL Server
Get-AzSqlServer | ForEach-Object -Begin { $a = 1 } -Process {"$a $($_.ServerName)"; $a++}
$SqlServerChoice = Read-Host -Prompt "Copy/paste the name of the SQL Server that you want to investigate. If more than one separate them by a coma, Type `"All`" if you want to target all of them"
if ($SqlServerChoice = "All"){
$SqlServerChoice = Get-AzSqlServer
}
Foreach ($server in $SqlServerChoice){
$DatabaseChoice = Get-AzSqlDatabase -ServerName $server.ServerName -ResourceGroupName $server.ResourceGroupName | Where-Object DatabaseName -NE "master"
Foreach ($database in $DatabaseChoice){
(Get-ChildItem $folderPath | sort-object {if (($i = $_.BaseName -as [int])) {$i} else {$_}} ).Foreach{
Invoke-Sqlcmd -ServerInstance $server.FullyQualifiedDomainName -Database $database.DatabaseName -AccessToken $access_token -InputFile $psitem.FullName | Export-Csv -Path ".\Results\$psitem.csv" -Append -NoTypeInformation
write-host "Executing $psitem on $database.DatabaseName"
}
}
}
}
However each time the query is executed against a database the Write-Hosts returns:
Executing DTU_to_vCore.sql on Microsoft.Azure.Commands.Sql.Database.Model.AzureSqlDatabaseModel.DatabaseName
Here a picture:
This Write-Hosts comes from the line:
write-host "Executing $psitem on $database.DatabaseName"
In which you can find the two variables:
$psitem : which is the name of the file that contains the query
$database.DatabaseName : which should be the database name but instead of printing the database name is printing Microsoft.Azure.Commands.Sql.Database.Model.AzureSqlDatabaseModel.DatabaseName
Why one of the two variable is not interpreted?
You need to encapsulate your variable property in a subexpression operator $().
write-host "Executing $psitem on $($database.DatabaseName)"
This is because only simple variables get expanded in an expandable string.
References
Only simple variable references can be directly embedded in an
expandable string. Variables references using array indexing or member
access must be enclosed in a subexpression.
Source: about_Quoting_Rules
Subexpression operator $( )
Returns the result of one or more statements. For a single result,
returns a scalar. For multiple results, returns an array. Use this
when you want to use an expression within another expression. For
example, to embed the results of command in a string expression.
PS> "Today is $(Get-Date)"
Today is 12/02/2019 13:15:20
PS> "Folder list: $((dir c:\ -dir).Name -join ', ')"
Folder list: Program Files, Program Files (x86), Users, Windows
Source: about_Operators

Powershell loop until the output is one line

What i am trying to achieve is that if the output is one line and that that line gets written away in a variable. This is the code i have right now:
Connect-AzureRmAccount
(get-azurermresourcegroup).ResourceGroupName
$filter = Read-Host -Prompt "Please filter to find the correct resource group"
$RGName = get-azurermresourcegroup | Where-Object { $_.ResourceGroupName -match $filter }
$RGName.resourcegroupname
this code filters one time and after that it writes all the lines away underneath each other so the results are this:
ResourceGroup-Test
ResourceGroup-Test-1
ResourceGroup-Test-2
but the preferred output is to keep filtering until one is left
Out-GridView
but the preferred output is to keep filtering until one is left
Depending on what the running user chooses for filters this could be a punishing approach / needlessly complicated. If you only want one result how about we instead use something like Out-GridView to allow the user to select one result from their chosen filter.
$filter = Read-Host -Prompt "Please filter to find the correct resource group"
$RGName = get-azurermresourcegroup |
Where-Object { $_.ResourceGroupName -match $filter } |
Out-GridView -OutputMode Single
$RGName.resourcegroupname
You could have used -PassThru but that allows for multiple selections. -OutputMode Single. So this would still have the potential for making a huge selection set if $filter was too vague but this is a simple way to ensure you get one result. Another caveat is that the user could click Cancel. So you might still need some loop logic: do{..}until{}. That depends on how resilient you want to make this process.
Choice
If Out-GridView is not your speed. Another option would be to make a dynamic choice system using $host.ui.PromptForChoice. The following is an example that allows users to choose a subfolder from a collection.
$possibilities = Get-ChildItem C:\temp -Directory
If($possibilities.Count -gt 1){
$title = "Folder Selection"
$message = "Which folder would you like to use?"
# Build the choices menu
$choices = #()
For($index = 0; $index -lt $possibilities.Count; $index++){
$choices += New-Object System.Management.Automation.Host.ChoiceDescription ($possibilities[$index]).Name
}
$options = [System.Management.Automation.Host.ChoiceDescription[]]$choices
$result = $host.ui.PromptForChoice($title, $message, $options, 0)
$selection = $possibilities[$result]
}
$selection
You should be able to adapt that into your code much in the same way that I suggested with Out-GridView. Be careful though about this approach. Too many options will clutter the screen.

Powershell script to pull remote pc serial number then match against an xlsx file then match against another and output only needed info

hey im trying to build a powershell script that will pull a serial number from a remote pc and then match that against an xlsx file which would then match a column against another xlsx file i have gotten to the point where i can pull the remote sn and have everything put in to a csv output but i am having issues matching the data then filtering based on the match and then outputting only what i need im new to scripting so im pretty sure its more my lack of experiance than anything else this is my code so far
$computers = Get-Content c:\script\computerlist.txt
Get-wmiobject Win32_Bios -ComputerName $computers | Select-Object __SERVER, SerialNumber| Format-Table |out-file C:\script\computerinfo.txt
$computerinfo = Import-Excel C:\script\compDB.xlsx
$userinfo = Import-Excel C:\script\userDB.xlsx
$Computerinfo[2].SERIAL -eq
$Computerinfo[2].DATE_ADDED
$Computerinfo[2].OS
$Computerinfo[2].MODEL
$Computerinfo[2].USER
$userinfo[2].NAME_FIRST
$userinfo[2].NAME_LAST
$userinfo[2].NT_USERID
''
'Computer Info'
'----------'
$computerinfo ,$userinfo | Format-Table - | Out-File c:\script\computerinfo.csv
First you need to save the wmi information to a variable:
$WMIinfo = Get-wmiobject Win32_Bios -ComputerName $computers | Select-Object __SERVER, SerialNumber
Then you would need to loop through the spreadsheet and compare to data in Computer spreadsheet. If it matches loop through user spreadsheet for match:
foreach ($CompEntry in $Computerinfo) {
if ($WMIinfo.serial -eq $CompEntry.serial) {
foreach ($UserEntry in $userinfo) {
if ($UserEntry.NT_USERID -eq $CompEntry.USER) {
#output information you want here
}
}
}
I'll try to help you get there.
I created an Excel file called Serial.xslx. Here's what it looks like
SerialNumber DeployedTo
212 Ham
4M24N32 Stephen
I then import this as $list.
$list = import-excel C:\temp\serial.xlsx
Next,to get the Win32_Bios info, so I can grab the SerialNumber property.
$bios = get-WmiObject Win32_Bios
Finally, I'll filter through the $list (which contains the Excel file), and find a row which has a SerialNumber that matches this computers serial number. If I find a matching one, then I grab the .DeployedTo value for that record.
$user = $list | Where SerialNumber -eq $bios.SerialNumber | Select -ExpandProperty DeployedTo
All that remains is to demonstrate that it works.
"the computer with serial $($bios.SerialNumber) is deployed to $user"
>the computer with serial 4M24N32 is deployed to Stephen
Now, you've got two separate excel files, so I would either manually join them into one, or repeat this same basic approach.

Return duplicate names (including partial matches)

Excel guy here that occasionally turns to automating powershell via vba.
I tried to solve https://stackoverflow.com/q/36538022/641067 (now closed) and couldn't get there with my basic powershell knowledge and googlefu alone.
In essence the problem the OP presented is:
There are a list of names in a text file.
Aim is to capture only those names that occurr at least once (so discard unique names, see point (3)).
Names occurring at least once include partial matches, ie Will and William can be considered duplicates and should be retained. Whereas Bill is not a duplicate of William.
I tried various approaches including
Group
Compare-Object see example below
But I was stymied by part (3). I suspect that a loop is required to do this but am curious whether there is a direct Powershellapproach,
Looking forward to hearing from the experts.
what I tried
$a = Get-Content "c:\temp\in.txt"
$b = $a | select -unique
[regex] $a_regex = ‘(?i)(‘ + (($a |foreach {[regex]::escape($_)}) –join “|”) + ‘)’
$c = $b -match $a_regex
Compare-object –referenceobject $c -IncludeEqual $a
Following testscript using a loop would work for the rules you outlined and looks foolproof to me
$t = ('first', 'will', 'william', 'williamlong', 'unique', 'lieve', 'lieven')
$s = $t | sort-object
[String[]]$r = #()
$i = 0;
while ($i -lt $s.Count - 1) {
if ($s[$i+1].StartsWith($s[$i])) {
$r += $s[$i]
$r += $s[$i+1]
}
$i++
}
$r | Sort-Object -Unique
and following testscript using a regex might get you started.
$content = "nomatch`nevenmatch1`nevenmatch12`nunevenmatch1`nunevenmatch12`nunevenmatch123"
$string = (($content.Split("`n") | Sort-Object -Unique) -join "`n")
$regex = [regex] '(?im)^(\w+)(\n\1\w+)+'
$matchdetails = $regex.Match($string)
while ($matchdetails.Success) {
$matchdetails.Value
$matchdetails = $matchdetails.NextMatch()
}

PowerShell: retrieve number of applications in AppPool

How to retrieve the number of applications associated with a specific IIS AppPool via PowerShell command?
We can see the associated applications manually using:
Get-Item IIS:\AppPools\AppPoolName
However, if we manually want to select the Applications column, it is not possible. Also, the Applications column is not listed within | Get-Member *.
Why is the column not listed?
How to find the number of applications associated with a specific IIS AppPool using PowerShell?
The trick is: PowerShell established so-called "view definition files" which tell PowerShell how to format objects (e.g. whether the object is formatted as a a list or a table, which columns are displayed, etc.). Those files can be found at C:\Windows\System32\WindowsPowerShell\v1.0 and are all ending in .format.ps1xml.
To answer the original question: The file C:\Windows\System32\WindowsPowerShell\v1.0\Modules\WebAdministration\iisprovider.format.ps1xml contains the view definition for the AppPool type which defines a calculated column looking like this:
<TableColumnItem>
<ScriptBlock>
$pn = $_.Name
$sites = get-webconfigurationproperty "/system.applicationHost/sites/site/application[#applicationPool=`'$pn`'and #path='/']/parent::*" machine/webroot/apphost -name name
$apps = get-webconfigurationproperty "/system.applicationHost/sites/site/application[#applicationPool=`'$pn`'and #path!='/']" machine/webroot/apphost -name path
$arr = #()
if ($sites -ne $null) {$arr += $sites}
if ($apps -ne $null) {$arr += $apps}
if ($arr.Length -gt 0) {
$out = ""
foreach ($s in $arr) {$out += $s.Value + "`n"}
$out.Substring(0, $out.Length - 1)
}
</ScriptBlock>
</TableColumnItem>
This answers why the column itself is not a member of the AppPool type. The second question can be easily answered now extracting the necessary code from the "scriptlet" above:
$applicationsInAppPoolCount = #(Get-WebConfigurationProperty `"/system.applicationHost/sites/site/application[#applicationPool=`'$appPool`'and #path!='/']"` "machine/webroot/apphost" -name path).Count
I dealt with this same issue for many hours until finally arriving at the solution. The answer from D.R. was very helpful but it was not working for me. After some tweaks, I came up with the code below which retrieves the number of applications in an app pool.
I noticed that this part of the code nd #path!='/' threw off the count.
$appPool = "REPLACE ME with a value from your app pool"
#(Get-WebConfigurationProperty "/system.applicationHost/sites/site/application[#applicationPool=`'$appPool`']" "machine/webroot/apphost" -name path).Count
I ended up with the following Code (basically the same as above, but differently formatted)
$appPools = Get-ChildItem –Path IIS:\AppPools
foreach ($apppool in $apppools) {
$appoolName = $apppool.Name
[string] $NumberOfApplications = (Get-WebConfigurationProperty "/system.applicationHost/sites/site/application[#applicationPool='$appoolName']" "machine/webroot/apphost" -name path).Count
Write-Output "AppPool name: $appoolName has $NumberOfApplications applications"
}
I recently came across this post searching for ways to get the active Application Pools. The information provided above was great, but I kept digging to see if there was another way get this information. I was able to find a way to do this through Get-IISSite, which I used the following:
Get-IISSite | Select-Object -ExpandProperty Applications | Select-Object Path,ApplicationPoolName
I tested this on a server that only had one website, but if there are multiple sites on the server, you could also add VirtualDirectories for the Select.
I also had a need to just get a unique list of the Application Pools being used, so I did the following:
$appPoolInfo = Get-IISSite | Select-Object -ExpandProperty Applications | Select-Object Path,ApplicationPoolName
$appPoolInfo | Select-Object -Unique ApplicationPoolName
This gives what you are looking in an array.
Import-Module WebAdministration;
Get-ChildItem IIS:\AppPools >> AppPoolDetails.txt;
$appPoolDetails = Get-Content .\AppPoolDetails.txt;
$w = ($appPoolDetails |Select-String 'State').ToString().IndexOf("State");
$w = $w -1;
$res1 = $appPoolDetails | Foreach {
$i=0;
$c=0; `
while($i+$w -lt $_.length -and $c++ -lt 1) {
$_.Substring($i,$w);$i=$i+$w-1}}
Write-Host "First Column---";
$res1.Trim();
$j = $w + 1;
$w = ($appPoolDetails |Select-String 'Applications').ToString().IndexOf("Applications");
$w = $w -$j;
$res2 = $appPoolDetails | Foreach {
$i=$j;
$c=0; `
while($i+$w -lt $_.length -and $c++ -lt 1) {
$_.Substring($i,$w);$i=$i+$w-1}}
Write-Host "Second Column---";
$res2.Trim();
$lineLength=0
$appPoolDetails | Foreach {
if($lineLength -lt $_.TrimEnd().Length )
{
$lineLength = $_.TrimEnd().Length;
#Write-Host $lineLength;
}
}
$j = ($appPoolDetails | Select-String 'Applications').ToString().IndexOf("Applications");
$w = $lineLength;
$w = $w -$j;
#Write-Host $j $w;
$res3 = $appPoolDetails | Foreach {
$i=$j;
$c=0; `
while($i+$w -lt $_.length -and $c++ -lt 1) {
$_.Substring($i,$w);$i=$i+$w-1}}
Write-Host "Third Column---";
$res3;

Resources