using below snippet :
#loop until we have found the newly added domain
$Stop=''
while (-not $Stop)
{
$stop = Get-AzureADDomain -Name $direct_routing_domain -ErrorAction Ignore | Out-Null
if (!$stop)
{
Write-Host "Domain is not provisioned yet - retrying in 60 seconds..." -ForegroundColor Yellow
Start-Sleep -Seconds 60
}
}
Write-Host "Domain is provisioned " -ForegroundColor Green
The output gives an error on stdout:
Get-AzureADDomain : Error occurred while executing GetDomain
Code: Request_ResourceNotFound
...
So here comes the question: how can I surpress this output ? I believe that | out-null should be enough. Or is this a bug in AzureAd 2.0.0 module ?
Out-Null does not ignore errors. Out-Null redirects stdout (known as stream #1) to null. You can try doing a try catch (catch provides easy exceptions handling)
try {}
catch {}
doc. https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_try_catch_finally?view=powershell-5.1
or redirect an error stream to void
Write-Error "ASD" 2>$null
doc. https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_redirection?view=powershell-5.1
You can use this:
$stop = $true
try {Get-AzureADDomain -Name $direct_routing_domain}
catch {
$stop = $false
}
OR
$stop = $true
$domain = Get-AzureADDomain | Where-Object {$_.Name -eq $direct_routing_domain}
if ($null -eq $domain) {
$stop = $false
}
You can use a try{}..catch{} on this, but remember to add -ErrorAction Stop (not 'Ignore') to the cmdlet to ensure also non-terminating exceptions are caught in the catch block:
# loop until we have found the newly added domain
$isProvisioned = $false
while (-not $isProvisioned) {
try {
$isProvisioned = [bool](Get-AzureADDomain -Name $direct_routing_domain -ErrorAction Stop)
}
catch { $isProvisioned = $false }
if (!$isProvisioned) {
Write-Host "Domain is not provisioned yet - retrying in 60 seconds..." -ForegroundColor Yellow
Start-Sleep -Seconds 60
}
}
Write-Host "Domain is provisioned " -ForegroundColor Green
Related
I would like to ask question about how I should proceed or how I should fix the code.
My problem is that I need my code to write into the Path three different paths for Logstash, Kibana and ElasticSearch, but I have no idea how to do it. It returns always the same error about missing ")" error
Here's the whole code ¨
[CmdletBinding(SupportsShouldProcess=$true)]
param(
[string]$NewLocation.GetType($ElasticSearch)
[string]$ElasticSearch = "C:\Elastic_Test_Server\elasticsearch\bin"
[string]$Kibana = "C:\Elastic_Test_Server\kibana\bin"
[string]$Logstash = "C:\Elastic_Test_Server\logstash\bin"
)
Begin
{
#Je potřeba spustit jako Administrátor
$regPath = "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"
$hklm = [Microsoft.Win32.Registry]::LocalMachine
Function GetOldPath()
{
$regKey = $hklm.OpenSubKey($regPath, $FALSE)
$envpath = $regKey.GetValue("Path", "", [Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames)
return $envPath
}
}
Process
{
# Win32API errory
$ERROR_SUCCESS = 0
$ERROR_DUP_NAME = 34
$ERROR_INVALID_DATA = 13
$NewLocation = $NewLocation.Trim();
If ($NewLocation -eq "" -or $NewLocation -eq $null)
{
Exit $ERROR_INVALID_DATA
}
[string]$oldPath = GetOldPath
Write-Verbose "Old Path: $oldPath"
# Zkontroluje zda cesta již existuje
$parts = $oldPath.split(";")
If ($parts -contains $NewLocation)
{
Write-Warning "The new location is already in the path"
Exit $ERROR_DUP_NAME
}
# Nová cesta
$newPath = $oldPath + ";" + $NewLocation
$newPath = $newPath -replace ";;",""
if ($pscmdlet.ShouldProcess("%Path%", "Add $NewLocation")){
# Přidá to přítomné session
$env:path += ";$NewLocation"
# Uloží do registru
$regKey = $hklm.OpenSubKey($regPath, $True)
$regKey.SetValue("Path", $newPath, [Microsoft.Win32.RegistryValueKind]::ExpandString)
Write-Output "The operation completed successfully."
}
Exit $ERROR_SUCCESS
}
Thank you for your help.
I really think you could simplify this a lot, unless I have misunderstood. Apologies, I am not currently on a Windows machine so can't test this.
function Add-ESPath {
# Create an array of the paths we wish to add.
$ElasticSearch = #(
"C:\Elastic_Test_Server\elasticsearch\bin",
"C:\Elastic_Test_Server\kibana\bin",
"C:\Elastic_Test_Server\logstash\bin"
)
# Collect the current PATH string and split it out in to an array
$CurrentPath = [System.Environment]::GetEnvironmentVariable("PATH")
$PathArray = $CurrentPath -split ";"
# Loop though the paths we wish to add.
foreach ($Item in $ElasticSearch) {
if ($PathArray -notcontains $Item) {
$PathArray += $Item
}
else {
Write-Output -Message "$Item is already a member of the path." # Use Write-Warning if you wish. I see it more as a notification here.
}
}
# Set the path.
$PathString = $PathArray -join ";"
Try {
[System.Environment]::SetEnvironmentVariable("PATH", $PathString)
exit 0
}
Catch {
Write-Warning -Message "There was an issue setting PATH on this machine. The path was:" # Use $env:COMPUTERNAME here perhaps instead of 'this machine'.
Write-Warning -Message $PathString
Write-Warning -Message $_.Exception.Message
exit 1
}
}
Add-ESPath
Perhaps you want to add some kind of log file rather than writing messages/warnings to the console. You can use Add-Content for this.
I long time ago i wrote some functions to add a path to system path + their is an check if the path is already inside the system path. And i also did an elevation check so when i use this function and i forgot to elevate my powershell that i get a warning. Its a different approach, I hope it will help you.
I only use the begin {} proccess{} statements for when i want to write a function that excepts pipeline inputs. So its if you want to write a function that will work as the following:
$paths = #("C:\Elastic_Test_Server\elasticsearch\bin", "C:\Elastic_Test_Server\kibana\bin")
$paths | my-append-these-to-system-path-function
Elevation check:
function G-AmIelevated($warningMessage){
if([bool](([System.Security.Principal.WindowsIdentity]::GetCurrent()).groups -match "S-1-5-32-544")){
return $true
}else{
write-host "not elevated $warningMessage" -ForegroundColor Red
return $false
}
}
append something to system path with check if its already inside system path:
function G-appendSystemEnvironmentPath($str){
if(test-path $str){
if(!((Get-Itemproperty -path 'hklm:\system\currentcontrolset\control\session manager\environment' -Name Path) -like "*$str*")){
write-host "`t $str exists...`n adding $str to environmentPath" -ForegroundColor Yellow
if(G-AmIelevated){
write-host `t old: (Get-Itemproperty -path 'hklm:\system\currentcontrolset\control\session manager\environment' -Name Path).Path
Set-ItemProperty -path 'hklm:\system\currentcontrolset\control\session manager\environment' `
-Name Path `
-Value "$((Get-Itemproperty -path 'hklm:\system\currentcontrolset\control\session manager\environment' -Name Path).Path);$str"
write-host `t new: (Get-Itemproperty -path 'hklm:\system\currentcontrolset\control\session manager\environment' -Name Path).Path
write-host `t restart the computer for the changes to take effect -ForegroundColor Red
write-host `t `$Env:Path is the merge of System Path and User Path This function set the system path
write-host `t $str appended to environmet variables. -ForegroundColor Green
}else{
write-host `t rerun ise in elevated mode -ForegroundColor Red
}
}else{
write-host "`t $str is in system environmenth path"
}
}else{
write-host `t $str does not exist
}
}
G-appendSystemEnvironmentPath -str "C:\Elastic_Test_Server\elasticsearch\bin"
G-appendSystemEnvironmentPath -str "C:\Elastic_Test_Server\kibana\bin"
G-appendSystemEnvironmentPath -str "C:\Elastic_Test_Server\logstash\bin"
Client doesn't want to upgrade, because they don't want anything to
break.
The code that I need to work on their machine is below. Right now
this script will not work because it's made to work for PowerShell 3.0 and above
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12; (new-object Net.WebClient).DownloadString("https://api.agent.alienvault.cloud/osquery-api/us-east-1/bootstrap?flavor=powershell") | iex; install_agent -controlnodeid <Agent ID>
How can this be rewritten to accomplish the same thing?
Now if you know of a simpler way to work around this issue, that will help greatly.
new-module -name install_agent -scriptblock {
function AgentDoStart() {
$kServiceName = "osqueryd"
$osquerydService = Get-WmiObject -Class Win32_Service -Filter "Name='$kServiceName'"
if ($osquerydService) {
Start-Service $kServiceName
Write-Host "'$kServiceName' system service is started." -foregroundcolor Cyan
return 1
} else {
Write-Host "'$kServiceName' is not an installed system service." -foregroundcolor Yellow
return 0
}
}
function AgentDoStop() {
$kServiceName = "osqueryd"
$osquerydService = Get-WmiObject -Class Win32_Service -Filter "Name='$kServiceName'"
if ($osquerydService) {
Stop-Service $kServiceName
Start-Sleep -s 1
$proc = Get-Process osqueryd -ErrorAction SilentlyContinue
if ($proc) {
Write-Host "osqueryd still running, killing processes"
Stop-Process -Force -Name osqueryd
}
Write-Host "'$kServiceName' system service is stopped." -foregroundcolor Cyan
return 1
} else {
Write-Host "'$kServiceName' is not an installed system service." -foregroundcolor Yellow
return 0
}
}
Function Install-Project() {
param(
[string]$apikey="",
[string]$controlnodeid="",
[string]$hostid="",
[string]$assetid=""
)
Install-Project-Internal -apikey $apikey -controlnodeid $controlnodeid -hostid $hostid -assetid $assetid
Write-Host "See install.log for details" -ForegroundColor Cyan
}
Function Download-And-Install-Sysmon() {
#===================================================
#1. Download Sysmon
#===================================================
$source = "https://download.sysinternals.com/files/Sysmon.zip"
Write-Host "Downloading Sysmon from $source" -ForegroundColor Cyan
$file = "$($env:TEMP)\Sysmon.zip"
Invoke-WebRequest $source -OutFile $file
#===================================================
#2. Clean & Prepare Sysmon installation target
#===================================================
$targetondisk = "$($env:USERPROFILE)\Documents\Sysmon\"
Write-Host "Preparing Sysmon target path $($targetondisk)" -ForegroundColor Cyan
Remove-Item $targetondisk -Recurse -ErrorAction Ignore
# Suppress output, but not errors:
[void](New-Item -ItemType Directory -Force -Path $targetondisk)
If (-Not (Test-Path -Path $targetondisk)) {
Write-Error "Skipping Sysmon... Destination path $($targetondisk) does not exist."
} Else {
#===================================================
#3. Unzip Sysmon
#===================================================
Unblock-File -Path $file
Write-Host "Uncompressing the Zip file to $($targetondisk)" -ForegroundColor Cyan
$FoundExtractionAssembly = 0
try {
# Load preferred extraction method's assembly (.NET 4.5 or later)
# Write-Host "Using preferred extraction method..."
Add-Type -As System.IO.Compression.FileSystem -ErrorAction Stop
$FoundExtractionAssembly = 1
}
catch [System.Exception] {
# Write-Host "Preferred extraction method not found. Attempting fall-back method..."
}
If ($FoundExtractionAssembly) {
[IO.Compression.ZipFile]::ExtractToDirectory($file, $targetondisk)
} Else {
# Fall-back method, may fail in sessions lacking access to interactive shell
$continue_flag = 1
try {
$shell_app = New-Object -COMObject "Shell.Application"
} catch {
Write-Error "Could not create Shell.Application object"
$continue_flag = 0
}
if ($continue_flag) {
$zip_file = $shell_app.namespace($file)
$destination = $shell_app.namespace($targetondisk)
if ($destination -ne $null) {
$destination.Copyhere($zip_file.items(), 0x10)
}
}
}
}
#===================================================
#3. Download Sysmon Config File
#===================================================
$source = "https://www.alienvault.com/documentation/resources/downloads/sysmon_config_schema4_0.xml"
Write-Host "Downloading Sysmon config file from $source" -ForegroundColor Cyan
$destination = [System.IO.Path]::GetTempFileName()
Invoke-WebRequest $source -OutFile $destination
#===================================================
#3. Install Sysmon
#===================================================
Write-Host "Installing Sysmon from $source" -ForegroundColor Cyan
If ( (get-childitem $destination).length -eq 0 ) {
$command = "& '$targetondisk\sysmon' -accepteula -h md5 -n -l -i"
Write-Host "Not using an additional Sysmon configuration file" -ForegroundColor Cyan
}
Else {
$command = "& '$targetondisk\sysmon' -accepteula -h md5 -n -l -i '$destination'"
Write-Host "Sysmon configuration file to use $destination" -ForegroundColor Cyan
}
Write-Host "Installing Sysmon with command $command" -ForegroundColor Cyan
iex $command
}
Function Install-Project-Internal() {
param(
[string]$apikey="",
[string]$controlnodeid="",
[string]$hostid="",
[string]$assetid=""
)
If (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) {
Write-Error "You do not have Administrator rights to run this script!`nPlease re-run this script as an Administrator!"
Return
}
If ($PSVersionTable.PSVersion.Major -lt 3) {
Write-Error "This script must be run using Powershell version 3 or higher. You have version $PSVersionTable.PSVersion.Major installed"
Return
}
$kServiceName = "osqueryd"
$BASE = "$($env:SYSTEMDRIVE)\Program Files\osquery"
$OLDBASE = "$($env:SYSTEMDRIVE)\ProgramData\osquery"
$secretfile = $(Join-Path $BASE "secret")
$flagfile = $(Join-Path $BASE "osquery.flags")
if ([string]::IsNullOrEmpty($hostid)) {
$hostid = $assetid
}
if ([string]::IsNullOrEmpty($apikey)) {
$apikey = $controlnodeid
}
if ([string]::IsNullOrEmpty($apikey)) {
if ([System.IO.File]::Exists("$secretfile")) {
$apikey = [IO.File]::ReadAllText("$secretfile").Trim()
}
}
if ([string]::IsNullOrEmpty($apikey)) {
# check old location in ProgramData
$oldsecretfile = $(Join-Path $OLDBASE "secret")
if ([System.IO.File]::Exists("$oldsecretfile")) {
$apikey = [IO.File]::ReadAllText("$oldsecretfile").Trim()
}
}
if ([string]::IsNullOrEmpty($apikey)) {
Write-Warning "You must supply either the -apikey or -controlnodeid parameters to identify your agent account"
return
}
# use TLS 1.2
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Download-And-Install-Sysmon
#===================================================
#4. Download and install osquery
#===================================================
try {
AgentDoStop
} catch {
Write-Error "Did not stop osqueryd service. Hopefully, this is fine."
}
Write-Host "Downloading installer"
$webclient = New-Object System.Net.WebClient
$webclient.DownloadFile("https://prod-usm-saas-agent-config.s3.amazonaws.com/repo/windows/alienvault-agent-20.01.0203.0301.msi", "$env:TEMP\alienvault-agent.msi")
Write-Host "Installing"
try {
Start-Process C:\Windows\System32\msiexec.exe -ArgumentList "/i $env:TEMP\alienvault-agent.msi ALLUSERS=1 /qn /l*v .\install.log" -wait
echo "INSTALLATION SUCCESSFULLY COMPLETED" >> .\install.log
} catch {
echo "INSTALLATION ERROR (ERRORLEVEL=%ERRORLEVEL%)" >> .\install.log
Write-Error "INSTALLATION ERROR (ERRORLEVEL=%ERRORLEVEL%)"
Return
}
# If the install directory doesn't exist, bail
if (![System.IO.Directory]::Exists("$BASE")) {
echo "Installation directory does not exist: $BASE" >> .\install.log
Write-Error "Installation directory does not exist: $BASE"
Return
}
# $osquerydService = Get-WmiObject -Class Win32_Service -Filter "Name='osqueryd'"
# if ($osquerydService) {
# Write-Host "Service exists, uninstalling"
# try {
# Stop-Service $kServiceName
# AgentDoStop
#
# Write-Host "Found '$kServiceName', stopping the system service..."
# Start-Sleep -s 5
# Write-Host "System service should be stopped."
# $osquerydService.Delete()
# Write-Host "System service '$kServiceName' uninstalled." -foregroundcolor Cyan
# } catch {
# Write-Error "Did not uninstall osqueryd service. Hopefully, it's not already installed."
# }
# }
Write-Host "Writing secret"
[IO.File]::WriteAllLines("$secretfile", $apikey)
# if hostid is not specified, try to extract from flag file
if ([string]::IsNullOrEmpty($hostid)) {
if ([System.IO.File]::Exists($flagfile)) {
$match = (Select-String -Path $flagfile -Pattern "specified_identifier=(.*)")
if ($match.Matches.Groups.success) {
$hostid = $match.Matches.Groups[1].Value.Trim()
Write-Host "Detected and re-using previously selected host id from ${flagfile}: $hostid"
} else {
Write-Host "Existing host id not found in ${flagfile}"
}
}
}
# if still not found, check old ProgramData location
if ([string]::IsNullOrEmpty($hostid)) {
$oldflagfile = $(Join-Path $OLDBASE "osquery.flags")
if ([System.IO.File]::Exists($oldflagfile)) {
$match = (Select-String -Path $oldflagfile -Pattern "specified_identifier=(.*)")
if ($match.Matches.Groups.success) {
$hostid = $match.Matches.Groups[1].Value.Trim()
Write-Host "Detected and re-using previously selected host id from ${oldflagfile}: $hostid"
} else {
Write-Host "Existing host id not found in ${oldflagfile}"
}
}
}
echo "Creating flag file"
copy $BASE\osquery.flags.example $flagfile
Write-Host "Setting host identifier"
# if still no hostid, use generated default
if ([string]::IsNullOrEmpty($hostid)) {
$hostid="00000000-8019-46ae-b324-685a63cb327a"
}
$output = "--tls_hostname=api.agent.alienvault.cloud/osquery-api/us-east-1", "--host_identifier=specified", "--specified_identifier=$hostid"
[IO.File]::AppendAllLines([string]$flagfile, [string[]]$output)
# add customer certs if present
$custpem = "$($env:SYSTEMROOT)\System32\drivers\etc\osquery_customer_certs.pem"
if ([System.IO.File]::Exists($custpem)) {
Write-Host "Adding customer certs"
type "$custpem" >> "$BASE\certs\certs.pem"
}
# start service
if (-NOT (AgentDoStop)) {
return
}
AgentDoStart
Write-Host "Deleting installer"
del $env:TEMP\alienvault-agent.msi
if (($BASE -ne $OLDBASE) -And [System.IO.Directory]::Exists($OLDBASE)) {
Write-Host "renaming old ProgramData/osquery directory"
move "$OLDBASE" "$($OLDBASE).renamed"
}
}
set-alias install_agent -value Install-Project
export-modulemember -alias 'install_agent' -function 'Install-Project'
}
If you remove this from "Function Install-Project-Internal"
If ($PSVersionTable.PSVersion.Major -lt 3) {
Write-Error "This script must be run using Powershell version 3 or higher. You have version $PSVersionTable.PSVersion.Major installed"
Return
}
Does it work? And if not, what is the error?
I have a script which starts a process only after specific service is running.
It's a loop that's trying to Get-Service its status.
I can't find how to limit loop by time.
The part where I'm stuck:
#add Start button
$button_start = New-Object System.Windows.Forms.Button
$button_start.Location = New-Object System.Drawing.Size(25,70)
$button_start.Size = New-Object System.Drawing.Size(240,32)
$button_start.TextAlign = "MiddleCenter"
$button_start.font = New-Object System.Drawing.Font("Segoe UI",14,[System.Drawing.FontStyle]::Regular)
$button_start.BackColor = "seashell"
$button_start.Text = "Start"
$button_start.Add_Click({
#add statement
while ((Get-Service -ComputerName $textBox_IP.text -ServiceName wscsvc).Status -ne "Running") {
# Pause before next check
Start-Sleep -Seconds 1
}
#only then..
Start-Process -FilePath "C:\Users\username\Desktop\software.exe" -verb RunAs -ArgumentList $textBox_IP.text
})
$Form_remoteControl.Controls.Add($button_start)
I've tried internet searching information on network without any success.
Define a time limit and check if the current time exceeds that limit.
$limit = (Get-Date).AddMinutes(5)
while (... -or (Get-Date) -le $limit) {
Start-Sleep -Seconds 1
}
If you want to skip starting the external program when the service still isn't running after that add another check after the loop upon which you return:
if ((Get-Service ...).Status -ne "Running") {
return
}
This is an example how to stop a service and wait until it is stopped or timeout applies.
You can modify to start a service.
Function StopService ($serv)
{
Write-Host "Config service " $serv " ..."
$service = Get-Service $serv -ErrorAction SilentlyContinue
if ($service)
{
if($service.status -eq "running")
{
write-host "Stop service" $serv
Stop-Service $serv -Force
# Wait until service is stopped (max. 1 minute)
$acttime = 0
$waittime = 100
$maxtime = 60000
$TestService = Get-Service $serv
While($TestService | Where-Object {$_.Status -eq 'Running'})
{
Start-Sleep -m $waittime
$acttime += $waittime
if ($acttime -gt $maxtime)
{
write-host "ERROR: Service" $serv " could not be stopped!" -ForegroundColor Red
return $False
}
}
}
else
{
write-host "Service already stopped!" -ForegroundColor Green
return $True
}
}
else
{
write-host "Service not installed" -ForegroundColor Green
return $True
}
}
I recommend you not using any polling While loops (with Start-Sleep cmdlets) in a Windows forms interface. It will stall your interface for important form events as button clicks etc.
Instead, I would anticipate on the Windows.Forms Timer class by creating a timer event and take appropriate checks and actions after a certain time period (e.g. a new Start-Process depending on a service state).
I've got a Powershell script that stops an IIS website and corresponding app pool and then deletes the app logs (log4net logs). Here is the script snippet:
stop-website -name "MyWebsite"
stop-webapppool -name "MyWebsite"
del c:\inetpub\MyWebsite\logs\*.*
The problem is stop-website and stop-webapppool seem to return before the website is completely shutdown which results in the delete failing saying the file is being used by another process:
del : Cannot remove item C:\inetpub\MyWebsite\logs\App.log: The process cannot access the file 'C:\inetpub\MyWebsite\logs\App.log' because it is being used by another process.
If I add a 10 second sleep between the stop commands and the del command then the logs are deleted successfully. This is very hackish though and not reliable. Is there a way to force the stop-website/stop-webapppool commands to not return until the website/apppool is completely stopped?
Thanks.
Implemented solution from the below link. I will wait ~60 seconds and then kill the IIS process if it hasn't stopped.
https://greenfinch.ie/blog/powershellscript.html
"Stopping IIS site [$name]" >> $logFile
stop-website -name $name
"Stopping app pool [$name]" >> $logFile
stop-webapppool -name $name
$sleepTime = 5
$processId = $TRUE
while ($processId)
{
$processId = Get-WmiObject -Class win32_process -filter "name='w3wp.exe'" |
?{ ($_.CommandLine).Split("`"")[1] -eq $name } |
%{ $_.ProcessId }
if ($sleepTime -gt 60)
{
"Waited [$sleepTime] sec for process [$processId] to stop and it is still running. Killing it." >> $logFile
Stop-Process $processId
break
}
if ($processId)
{
"App pool [$name] is running with process ID: [$processId]. Sleeping for [$sleepTime] sec and then checking again." >> $logFile
Start-Sleep -s $sleepTime
$sleepTime = $sleepTime + 10
}
}
You can use these two commands to check the status of the website/app, say after 10 seconds, then use an If statement to delete logs only when the status returned is stopped
Get-WebsiteState -name "MyWebsite"
Get-WebAppPoolState -name "MyWebsite"
This loop should help you too
$currentRetry = 0;
$success = $false;
do{
$status = Get-WebAppPoolState -name "MyWebsite"
if ($status -eq "Stopped"){
<....your code here....>
$success = $true;
}
Start-Sleep -s 10
$currentRetry = $currentRetry + 1;
}
while (!$success -and $currentRetry -le 4)
Updated Apr 24, 2019
Based on comment and current cmdlet document, it appears the return type is indeed an object. Thus presumably can be handled as commented or the line snippet below. Author no longer have access to Windows Server environment therefore did not directly modify original answer nor able to test the update
if ($status.Value -eq "Stopped")
After you run 'Stop-WebAppPool' the state of the WebAppPool will be "Stopping" and it may take a few seconds before the state of the WebAppPool is actually "Stopped".
Here is a little function to help with the WebAppPoolState
function Stop-AppPool ($webAppPoolName,[int]$secs) {
$retvalue = $false
$wsec = (get-date).AddSeconds($secs)
Stop-WebAppPool -Name $webAppPoolName
Write-Output "$(Get-Date) waiting up to $secs seconds for the WebAppPool '$webAppPoolName' to stop"
$poolNotStopped = $true
while (((get-date) -lt $wsec) -and $poolNotStopped) {
$pstate = Get-WebAppPoolState -Name $webAppPoolName
if ($pstate.Value -eq "Stopped") {
Write-Output "$(Get-Date): WebAppPool '$webAppPoolName' is stopped"
$poolNotStopped = $false
$retvalue = $true
}
}
return $retvalue
}
you can run this function using e.g.
Stop-AppPool "MyWebsite" 30
and check the return-value to see if the WebAppPool has stopped within the given seconds
The simplest way to stop the app pool and get it into Stopped state is to use appcmd.exe. It will return when the app pool is really stopped or you'll get an error
Just do this on PowerShell:
& $env:windir\system32\inetsrv\appcmd.exe stop apppool /apppool.name:"YourAppPoolName"
When your AppPool is correctly stooped you'll get this message:
"YourAppPoolName" successfully stopped
I fix the #user4531 code It would be failed if the app pool is stopped before :
function Stop-AppPool ($webAppPoolName,[int]$secs) {
$retvalue = $false
$wsec = (get-date).AddSeconds($secs)
$pstate = Get-WebAppPoolState -Name $webAppPoolName
if($pstate.Value -eq "Stopped") {
Write-Output "WebAppPool '$webAppPoolName' is stopped already"
return $true
}
Stop-WebAppPool -Name $webAppPoolName
Write-Output "$(Get-Date) waiting up to $secs seconds for the WebAppPool '$webAppPoolName' to stop"
$poolNotStopped = $true
while (((get-date) -lt $wsec) -and $poolNotStopped) {
$pstate = Get-WebAppPoolState -Name $webAppPoolName
if ($pstate.Value -eq "Stopped") {
Write-Output "WebAppPool '$webAppPoolName' is stopped"
$poolNotStopped = $false
$retvalue = $true
}
}
return $retvalue
}
It can use like this :
Stop-AppPool "SSO" 30
Here is how I did it with Get-IISServerManager.
$manager = Get-IISServerManager
$site = $manager.Sites["mySiteName"]
if($site.State -ne "Stopped") {
$site.Stop()
}
while ($site.State -ne "Stopped") {
"waiting 1 second for site to stop..."
Start-Sleep -s 1
}
"site stopped"
$topDC1="10.254.90.17"
$topDC2="10.225.224.17"
$topDC3="10.110.33.32"
$topDC4="10.88.100.10"
$DomainName="office.adroot.company.net"
TRY{
$hostname = [System.Net.DNS]::GetHostByName($topDC1).HostName.toupper()
$ipaddress = [System.Net.Dns]::GetHostAddresses($DomainName) | select IPAddressToString -ExpandProperty IPAddressToString
# I want the below to loop foreach ip in the object, ns it against all 4 topDC's, then output each result :(
$NS1 = nslookup $ipaddress[0] $topDC1
Write-host $NS1
}
Catch{
write-host "error"
}
Here is my dirty code so far (just to keep it simple)
I am trying to automate this:
NSLOOKUP office.adroot.company.net
put the results into an object
for each ip in results, do an NSLOOKUP against our top level DC's.
find which DC's haven't been cleaned up after decommission (still in dns)
$DCList="10.254.90.17","10.225.224.17","10.110.33.32","10.88.100.10"
$DomainName="office.adroot.blorg.net","pcd.blorg.ca","blorg.ca","percom.adroot.blorg.net", "blorg.blorg.net","ibg.blorg.net","sacmcm.adroot.blorg.net","sysdev.adroot.blorg.net","adroot.blorg.net"
TRY{
foreach ($DomainNameItem in $DomainName){
Write-Host ""
Write-Host ""
Write-Host "Looking UP result"$DomainNameItem -foreground yellow
Write-Host ""
$hostname = [System.Net.DNS]::GetHostByName($DCListItem).HostName.toupper()
$ipaddress = [System.Net.Dns]::GetHostAddresses($DomainNameItem).IPAddressToString
foreach ($ip in $ipaddress){
Write-Host ""
Write-Host "Looking UP result"$ip -foreground green
foreach ($topdns in $DCList){
$RESULTS = nslookup $ip $topdns
Write-host $RESULTS
}
}
}
}
Catch{
write-host "error"
}
Write-Host ""
Write-Host ""
pause
Got it! This will save me tonnes of work determining if a DNS cleanup is necessary. Thanks guys, I'm learning just how great Powershell can be :)
Try this:
$topDomainControllers = #("10.254.90.17", "10.225.224.17", "10.110.33.32", "10.88.100.10")
$DomainName="office.adroot.company.net"
try {
$hostname = [System.Net.Dns]::GetHostByName($topDC1).HostName.ToUpper()
$ipAddresses = [System.Net.Dns]::GetHostAddresses($DomainName) |
select -ExpandProperty IPAddressToString
foreach ($ipAddress in $ipAddresses) {
$nslookupResult = nslookup $ipAddress
$foundIp = $nslookupResult[1] -match "^\D*(\d+\.\d+\.\d+\.\d+)$"
if ($foundIp -eq $false) {
continue
}
$domainController = $Matches[1]
if ($topDomainControllers.Contains($domainController)) {
Write-Output -Verbose "Found domain controller match for $domainController"
break
} else {
Write-Output -Verbose "No match found for domain controller $domainController"
}
}
} catch {
Write-Output "An error has occured: $_"
}