powershell - how to auto add and remove dhcp reservation with csv - csv

my client.csv format is:
ScopeId,Name,ClientId,Ipaddress
10.10.10.0,Computer1,1a-1b-1c-1d-1e-1f,10.10.10.10
10.10.10.0,Computer2,2a-2b-2c-2d-2e-2f,10.10.10.11
10.10.10.0,Computer3,3a-3b-3c-3d-3e-3f,10.10.10.12
my client.csv format (when the user's ClientID is null):
ScopeId,Name,ClientId,Ipaddress
10.10.10.0,Computer1,1a-1b-1c-1d-1e-1f,10.10.10.10
10.10.10.0,Computer2,2a-2b-2c-2d-2e-2f,10.10.10.11
10.10.10.0,Computer3,,10.10.10.12
and then run my powershell with my csv,auto add dhcp server reservations is successful,but when the user's ClientID is null ,powershell could not auto remove dhcp server rereservations,my powershell script has some problem?
$ComputerName="WIN-OO4RE715BV8.test.com"
if (!$args) {
Write-Host "client.csv"
}
ELSE
{
$dhcpdata=Import-CSV $args
foreach ($dhcp in $dhcpdata){
$ScopeId=$dhcp.ScopeId
$Name=$dhcp.Name
$ClientId=$dhcp.ClientId
$IPAddress=$dhcp.IPAddress
if ($ClientId -eq $null) {
Remove-DhcpServerv4Reservation -ScopeId $ScopeId -Name $Name -ClientId $ClientId -IPAddress $IPAddress
}
Add-DhcpServerv4Reservation -ScopeId $ScopeId -Name $Name -ClientId $ClientId -IPAddress $IPAddress
}
}

$ComputerName="WIN-JA5I029SJFM.test.com"
if(!$args){
Write-Host "client.csv"
}
ELSE
{
$dhcpdata=Import-CSV $args
foreach ($dhcp in $dhcpdata){
$ScopeId=$dhcp.ScopeId
$Name=$dhcp.Name
$ClientId=$dhcp.ClientId
$IPAddress=$dhcp.IPAddress
Add-DhcpServerv4Reservation -ScopeId $ScopeId -Name $Name -ClientId $ClientId -
IPAddress $IPAddress
if(!$ClientId)
{
echo Remove-DhcpServerv4Reservation -ComputerName "$ComputerName" -IPAddress
$IPAddress
Remove-DhcpServerv4Reservation -ComputerName "$ComputerName" -IPAddress
$IPAddress
}
}
}

Related

Trying to use remote variable in If-Condition within ScriptBlock using PowerShell

I am trying to use below code to remove the groups from Active Directory. I am maintaining an input file for the list of servers. the input file is in the local machine and trying to use the content of the file inside the ScriptBlock using ($Using:variablename) after taking a remote session.
I am getting the content[file content] of the variable inside the ScriptBlock which is defined outside the ScriptBlock. The issue is the if condition [if($serverlist -ne $null)] is satisfying even if the variable is empty. The code is entering into if block even if the variable $serverlist is null, instead it has to take else block.
Could you please help me on this.
$adserver = Read-Host -Prompt "Please enter AD server details"
$adserver
$askcredential = $host.ui.PromptForCredential("Need credentials", "Please enter your user name and password.", "", "NetBiosUserName")
$credential = New-Object System.Management.Automation.PsCredential($askcredential.UserName,$askcredential.Password)
$session = New-PSSession -ComputerName "$adserver" -Credential $credential
#$command = (Get-ADForest).domains
$addomain = Read-Host -Prompt "Please enter the Domain"
$servers = Get-Content "D:\Bhargavi\Windows-Decommission\$addomain\servers.txt"
#Invoke-Command -ComputerName $adserver -Authentication Default -Credential $credential -ScriptBlock {
Invoke-Command -Session $session -ScriptBlock {
#$addomain = Read-Host -Prompt "Please enter the Domain"
#$servers = Get-Content "D:\Bhargavi\Windows-Decommission\$addomain\servers.txt"
#Param($domainname,$serverlist)
$serverlist = $Using:servers
$domainname = $Using:addomain
Write-Host "the list is $serverlist"
Write-Host "the domain is $domainname"
if($serverlist -ne $null)
{
Write-Host "Found the data in the input file. Proceeding to remove the groups."
foreach ($server in $serverlist)
{
write-host "Server Name is: $server"
$mgserver = "MG-$server"
$mggroup = Get-ADGroup -Filter { Name -like $mgserver }
$mggroup
if($mggroup -ne $null)
{
Get-ADGroup -Filter { Name -like $mgserver } #| Remove-ADGroup -Confirm:$False
$mggroupconfirm = Get-ADGroup -Filter { Name -like $mgserver }
if($mggroupconfirm -eq $null)
{
Write-Host "$mgserver is removed from $domainname"
#Set-Content -Path "D:\Bhargavi\Windows-Decommission\$domainname\servers.txt" -Value (get-content -Path "D:\Bhargavi\Windows-Decommission\$domainname\servers.txt" | Select-String -Pattern "$server" -NotMatch)
}
else
{
Write-Host "$mgserver is not removed. Please try again."
}
}
else{Write-Host "There is no group called $mgserver in $domainname domain "}
}
}
else
{
DO
{
$val = Read-Host -Prompt "Do you want to enter servername ? Enter yes or no"
if($val -eq "yes")
{
$entermgserver = Read-Host -Prompt "Please enter the server name"
$entermgserver
$mgserver = "MG-$entermgserver"
$mgserver
$mggroup = Get-ADGroup -Filter { Name -like $mgserver }
$mggroup
if($mggroup -ne $null)
{
#Write-Host "$mggroup is not null"
Get-ADGroup -Filter { Name -like $mgserver } #| Remove-ADGroup -Confirm:$False
$mggroupconfirm = Get-ADGroup -Filter { Name -like $mgserver }
if($mggroupconfirm -eq $null)
{
Write-Host "$mgserver is removed"
}
else
{
Write-Host "$mgserver is not removed. Please try again."
}
}
else{Write-Host "The is no group called $mgserver in $domainname domain"}
}
}until ($val -eq "no")
}
} ### End Script Block
Clear-Content "D:\Bhargavi\Windows-Decommission\$addomain\servers.txt"
Remove-PSSession -Session $session

Binding the SSL certificate to my site works in powershell ise in admin mode but not from PowerShell 7 in admin mode

I am trying to bind the SSL certificate to my site. If I run the script from PowerShell ise in admin mode it works fine however, when I run from PowerShell 7 in admin mode, it does not bind the certificate to the site. I am using the below section in my script:
#Add SSL Certificate
if(($Protocol -eq "https") -and ($Port) -and ($AddConfiguration))
{
$newWebBindingCmd = "New-WebBinding -Name '$Name' -Protocol 'https' -Port '$port' -SslFlags 1"
$getWebBindingCmd = "Get-WebBinding -Name '$Name' -Port '$port'"
if($IPAddress)
{
$newWebBindingCmd += " -IPAddress '$IpAddress'"
$getWebBindingCmd += " -IPAddress '$IpAddress'"
}
If($hostname)
{
$newWebBindingCmd += " -HostHeader '$hostname'"
}
if (-not([string]::IsNullOrEmpty($CertificateKey)))
{
$cert = Get-ChildItem 'Cert:\LocalMachine\My' | where {($_.Subject -like "*$CertificateKey*") -or ($_.Thumbprint -like "*$CertificateKey*")};
if($cert -ne $null)
{
write-host 'Certificate Found';
$CommandLines = "Import-Module WebAdministration;$newWebBindingCmd;"
$createhttpsbinding = Execute-CommandLines -Commandlines $CommandLines.ToString();
if($createhttpsbinding -eq $true)
{
write-host 'https binding created successfully';
}
$CommandLines = "Import-Module WebAdministration;
`$httpsbinding = $getWebBindingCmd -Protocol 'https';
if(`$httpsbinding)
{
`$httpsbinding.AddSslCertificate(`$cert.GetCertHashString(), 'my');
write-host 'Added SslCertificate successfully';
}";
$addSslCertificate = Execute-CommandLines -Commandlines $CommandLines.ToString();
if($addSslCertificate -eq $true)
{
$CommandLines = "Import-Module WebAdministration;$getWebBindingCmd -Protocol 'http' | Remove-WebBinding;"
write-host 'SslCertificate installed. Removing http binding..';
}
else
{
$CommandLines = "Import-Module WebAdministration;$getWebBindingCmd -Protocol 'https' | Remove-WebBinding;"
write-host 'SslCertificate could not be installed. Removing https binding..';
}
$result = Execute-CommandLines -Commandlines $CommandLines.ToString()
if($result -eq $true)
{
Log -color Green "Binding Properties set successfully for WebService '$Name'"
}
else
{
Log -color Red "Binding Properties could not be set for WebService '$Name'"
}
}
else
{
Log -color Red "Certificate with CertificateKey '$CertificateKey' is not found!"
}
}
}

Azure PowerShell Runbook with nested function

I have a Azure PowerShell Runbook where I use SharePoint-PnP Cmdlets, which is working totally fine. But I have a problem with a function call. To mention, the script is working fine locally, but not in the Azure Runbook.
$SPCredentials = Get-AutomationPSCredential -Name 'ServiceAccount'
Connect-PnPOnline -Url $SPUrl -Credentials $SPCredentials
$SPList = New-PnPList -Title "$($ObjektNr)-$($ObjektName)" -Template DocumentLibrary -OnQuickLaunch -EnableContentTypes
Write-Output "Bibliothek erstellt"
Add-PnPContentTypeToList -List $SPList -ContentType $SPCTName -DefaultContentType
Write-Output "Inhaltstyp hinzugefügt"
Remove-PnPContentTypeFromList -List $SPList -ContentType "Dokument"
Write-Output "Inhaltstyp entfernt"
Set-PnPList -Identity $SPList -EnableContentTypes $false -EnableVersioning $true -EnableMinorVersions $false
Write-Output "Listeneinstellungen vorgenommen"
$SPList = Get-PnPList -Identity "$($ObjektNr)-$($ObjektName)"
$SPRootFolder = "$($SPList.RootFolder.Name)/"
Write-Output "Neue Bibliothek abgerufen"
$SPTerms = Get-PnPTerm -TermSet $SPTermSet -TermGroup $SPTermGroup -IncludeChildTerms -Recursive
Write-Output "Terms abgerufen"
Function getTerms($Terms)
{
Write-Output "Funktion ausgeführt"
Foreach ($Term in $Terms)
{
If ($Term.PathOfTerm.Contains(";"))
{
Add-PnPFolder -Name $Term.Name -Folder "$($SPRootFolder)$($Term.PathOfTerm.Substring(0, $Term.PathOfTerm.LastIndexOf(";")).Replace(";","/"))"
$values = #()
$splitTerms = $Term.PathOfTerm.Split(";")
$count = $splitTerms.Count - 1
For ($i=0; $i -le $count; $i++)
{
If ($i -eq 0)
{
$values += "$($SPTermGroup)|$($SPTermSet)|$($splitTerms[$i])"
}
Else
{
$values += "$($values[-1])|$($splitTerms[$i])"
}
}
Set-PnPDefaultColumnValues -List $SPList -Field "Metadaten" -Value $values -Folder "$($Term.PathOfTerm.Replace(";","/"))"
}
else
{
Add-PnPFolder -Name $Term.Name -Folder $SPRootFolder
Set-PnPDefaultColumnValues -List $SPList -Field "Metadaten" -Value $Term.Id -Folder $Term.Name
}
If ($Term.Terms.Count -gt 0)
{
getTerms($Term.Terms)
}
}
}
getTerms($SPTerms)
The problem now is where I call the function getTerms within the function getTerms (the fourth line from the bottom). It seems after calling that function again, the whole script starts from the beginning, instead of only the function with the parameters.
Thanks for any help!
Regards,
Mark
Ideally it shouldn't start from the beginning! To double check, I would recommend you to add write-output lines just before and after you call getTerms function (i.e., near 4th line from the bottom) and also just before actual getTerms function. And then validate whether the content you provided in those write-output lines are printed in expected order or not.
Also, I would suggest you to try below approach to see if your issue gets resolved.
Function getTerms($Terms)
{
Write-Output "Funktion ausgeführt"
Foreach ($Term in $Terms)
{
If ($Term.PathOfTerm.Contains(";"))
{
Add-PnPFolder -Name $Term.Name -Folder "$($SPRootFolder)$($Term.PathOfTerm.Substring(0, $Term.PathOfTerm.LastIndexOf(";")).Replace(";","/"))"
$values = #()
$splitTerms = $Term.PathOfTerm.Split(";")
$count = $splitTerms.Count - 1
For ($i=0; $i -le $count; $i++)
{
If ($i -eq 0)
{
$values += "$($SPTermGroup)|$($SPTermSet)|$($splitTerms[$i])"
}
Else
{
$values += "$($values[-1])|$($splitTerms[$i])"
}
}
Set-PnPDefaultColumnValues -List $SPList -Field "Metadaten" -Value $values -Folder "$($Term.PathOfTerm.Replace(";","/"))"
}
else
{
Add-PnPFolder -Name $Term.Name -Folder $SPRootFolder
Set-PnPDefaultColumnValues -List $SPList -Field "Metadaten" -Value $Term.Id -Folder $Term.Name
}
If ($Term.Terms.Count -gt 0)
{
getTerms($Term.Terms)
}
}
}
Function main()
{
$SPCredentials = Get-AutomationPSCredential -Name 'ServiceAccount'
Connect-PnPOnline -Url $SPUrl -Credentials $SPCredentials
$SPList = New-PnPList -Title "$($ObjektNr)-$($ObjektName)" -Template DocumentLibrary -OnQuickLaunch -EnableContentTypes
Write-Output "Bibliothek erstellt"
Add-PnPContentTypeToList -List $SPList -ContentType $SPCTName -DefaultContentType
Write-Output "Inhaltstyp hinzugefügt"
Remove-PnPContentTypeFromList -List $SPList -ContentType "Dokument"
Write-Output "Inhaltstyp entfernt"
Set-PnPList -Identity $SPList -EnableContentTypes $false -EnableVersioning $true -EnableMinorVersions $false
Write-Output "Listeneinstellungen vorgenommen"
$SPList = Get-PnPList -Identity "$($ObjektNr)-$($ObjektName)"
$SPRootFolder = "$($SPList.RootFolder.Name)/"
Write-Output "Neue Bibliothek abgerufen"
$SPTerms = Get-PnPTerm -TermSet $SPTermSet -TermGroup $SPTermGroup -IncludeChildTerms -Recursive
Write-Output "Terms abgerufen"
getTerms($SPTerms)
}
main()

Values are not updated in a PowerShell function

I made a code to get some variables and values from a TXT file. The code looks like that, and it works as expected:
Get-Content "C:\Temp\File.txt" | ? {$_ -match "="} | % {
$Item = $_.Split('=')
if (Test-Path Variable:\$($Item[0])) {
Set-Variable -Name $Item[0] -Value $Item[1]
Write-Host $Item[0] $Item[1]
} else {
New-Variable -Name $Item[0] -Value $Item[1] -Force
}
}
Write-Host $IPaddress
Write-Host $Hostname
The file.txt looks like that:
IPaddress=192.168.1.100
Hostname=server01
So from this example, I get the variables $IPaddress and $Hostname with their values from the TXT file.
However, as I need to use this this code quite often, or because the values in the TXT file are updated, or to get it from a different TXT files, I included it in a function:
function GetInfo {
Param(
[string]$FilePath
)
Get-Content $FilePath | ? {$_ -match "="} | % {
$Item = $_.Split('=')
if (Test-Path Variable:\$($Item[0])) {
Set-Variable -Name $Item[0] -Value $Item[1]
Write-Host $Item[0] $Item[1]
} else {
New-Variable -Name $Item[0] -Value $Item[1] -Force
}
}
}
GetInfo -FilePath "C:\Temp\File.txt"
Write-Host $IPaddress
Write-Host $Hostname
And here is the issue! First time I execute the script no worries, the variables and values are gotten properly. However, if I modify the values in the TXT file (for example the IP address changes to 192.168.1.200) and execute the script again, I can see in the function itself that the new IP is gotten properly from the Write-Host $Item[0] $Item[1], but at the end, the value of $IPaddress will not be updated (Write-Host $IPaddress will still display 192.168.1.100).
The scope of the variables should be declared as global. That can be done in Set-Variable method like below,
function GetInfo {
Param(
[string]$FilePath
)
Get-Content $FilePath | ? {$_ -match "="} | % {
$Item = $_.Split('=')
if (Test-Path Variable:\$($Item[0])) {
Set-Variable -Name $Item[0] -Value $Item[1] -Scope global
#Write-Host $Item[0] $Item[1]
} else {
New-Variable -Name $Item[0] -Value $Item[1] -Force
}
}
}
GetInfo -FilePath "C:\Temp\File.txt"
Write-Host $IPaddress
Write-Host $Hostname
In the above code you can see that i have mentioned the scope as global. Try that one. It should solve your issue.
Set-Variable -Name $Item[0] -Value $Item[1] -Scope global

try-catch bypassing a step

I have a script that tests connection to a list of servers, and if contactable, gets the status of a service, and puts the results into three variables, $Computer, $Ping (True/False), and $Service (Running or Stopped).
The output is in a hashtable but I can only get to show the servers that ARE contactable, and not the ones that cannot be contactable.
I have placed a try/catch in the $Ping block, as well as -ErrorAction Stop, so that it doesn't attempt to run the $Service script, and instead go to the next $Computer in the array. I think I am trying to do two things at once that are conflicting each other:
add the variables to the #Splat and
don't process any further.
There are actually many more remote registry queries in my script, which will be irrelevant if the $Computer cannot be contactable, but I have shortened it for this post.
Function Get-Ping {
$Servers = (gc "c:\temp\test.txt")
foreach ($Computer in $Servers) {
Write-Host
Write-Host "---------------------------------"
Write-Host "QUERYING $Computer"
Write-Host
Write-Host "Performing ping test..."
try {
$Ping = Test-Connection $Computer -Count 1 -ErrorAction Stop
} catch {
Write-Warning "Cannot Ping $Computer"
Write-Host "Trying next computer..."
Write-Host
continue
}
if ($Ping) {$Ping="$True"}
Write-Host $Computer "can be pinged"
$svcRRStopped = $false
if ($Computer -ne $env:COMPUTERNAME) {
Write-Host "Check RemoteRegistry status..."
}
$svcRR = Get-Service -ComputerName $Computer -Include RemoteRegistry
$SelectSplat = #{
Property = (
'Computer',
'Ping',
'Service'
)}
New-Object -TypeName PSObject -Property #{
Computer=$Computer
Ping=$Ping
Service=$svcRR.status
} | Select-Object #SelectSplat
}
}
$results = Get-Ping
$tableFragment = $results | Select 'Computer','Ping','Service'
$tableFragment
Don't make things more complicated than they need to be.
function Get-Ping {
Get-Content 'C:\temp\test.txt' | ForEach-Object {
$isAvailable = [bool](Test-Connection $_ -Count 1 -EA SilentlyContinue)
if ($isAvailable) {
$rreg = Get-Service -Computer $_ -Name RemoteRegistry |
Select-Object -Expand Status
} else {
$rreg = 'n/a'
}
New-Object -Type PSObject -Property #{
Computer = $_
Ping = $isAvailable
Service = $rreg
}
}
}
Get-Ping
You can simply use the -Quiet Parameter:
Test-Connection $_ -Count 1 -Quiet