Get all suspended instances for specific application in BizTalk - powershell

In BizTalk Server Administration Console you can query for suspended service instances and then filter them by Application Name. I need such functionality without BTS Administration Console.
So far I've created Powershell script to get suspended instances:
$array = Get-WmiObject MSBTS_ServiceInstance `
-Namespace 'root\MicrosoftBizTalkServer' `
-Filter '(ServiceClass = 4 or ServiceClass = 1) `
and (ServiceStatus = 4 or ServiceStatus = 16)'
foreach ($element in $array)
{
Write-Host $element.InstanceID "-" $element.HostName "-" `
$element.ServiceStatus "-" $element.ServiceClass
}
If you run this script you'll get all suspended instances, but how to find out to what application they belong?
Any solution that uses PowerShell, WMI or C# is good for me.

I've used the Microsoft.BizTalk.Operations assembly ...
Add-Type -AssemblyName ('Microsoft.BizTalk.Operations, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL')
$dbServer = (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\BizTalk Server\3.0\Administration' 'MgmtDBServer').MgmtDBServer
$dbName = (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\BizTalk Server\3.0\Administration' 'MgmtDBName').MgmtDBName
$bo = New-Object Microsoft.BizTalk.Operations.BizTalkOperations $dbServer, $dbName
$serviceInstances = $bo.GetServiceInstances()
$tgt = "DeploymentFramework.Samples.HelloWorld"
foreach ($instance in $serviceInstances)
{
if ($instance.Application -ieq $tgt)
{
$completionStatus= $bo.TerminateInstance($instance.Id)
}
}
One thing I've not worked out ... Why does terminating a suspended (not resumable) service instance return Failed, yet it is terminated

Application name property is not exposed via MSBTS_ServiceInstance class. I believe the reason for that is, application concept was only introduced in BizTalk 2006 but the WMI API was present right from 2004.
I'm afraid, your only choice is to go directly to the database.

What version of BizTalk?
This works on BizTalk 2010:
$array = Get-WmiObject MSBTS_ServiceInstance `
-Namespace 'root\MicrosoftBizTalkServer' `
-Filter '(ServiceClass = 4 or ServiceClass = 1) `
and (ServiceStatus = 4 or ServiceStatus = 16)'
foreach ($element in $array)
{
Write-Host $element.ServiceName
}

Related

Powershell integration with Office365

I would like some comments on the integration code that I am developing... trying to integrate Office365 to Solarwinds:
import-Module Office365Alerts
$Username = 'XXXXX#XXX.XXX'
$Password = 'XXXXXXXXXXXXXXXX'
$credential = New-Object -TypeName pscredential -ArgumentList $Username, ($Password | ConvertTo-SecureString -AsPlainText -Force) -ErrorAction Stop
$alerts = Get-Office365ServiceHealth -Credential $credential -ErrorAction Stop | Select-Object -Property * | Where-Object Service -like '*Exchange*'
foreach($a in $alerts){
[regex]$regex = '\bCurrent status:\s?.*\s'
$Mess = $a.LatestMessage
if($Mess -match $regex){
foreach($m in $mess){
Write-Host "Message:Title: $($a.Title)"
Write-Host "Message:Impact: $($a.UserImpact)"
Write-Host "Message:Start Time: $($a.StartTime)"
Write-Host "Message:Last Update: $($a.LastUpdate)"
Write-Host "Message: $($Matches.Values)"
}
Write-Host "Statistic: 1"
}
}
if($a -eq $null){
Write-Host "Message: Service is Healthy"
Write-Host "Statistic: 0"
The SolarWinds Powershell monitors are limited to 10 returned metric pairs (message and statistic), if there are more than 10 alerts returned, it will break. AS you are returning 5 messages, which appear to be identical in foreach($a in $alerts) loop, they won't have unique names, also probably causing you problems.
Are you running the script in Local Host or Remote Host execution mode? IF you are running it on a host without the Office365 commandlets, it'll fail.
Have you enabled debug logging, within the template? It's under Advanced at the top of the template editing view. Logs can be found in ProgramData\SolarWinds\Logs\APM, take note of your templateID or its componentIDs, as the logs will be referenced by them.

Running powershell script in different OS

I am trying to run the below mentioned command in Server 2012 & it's pulling users from Administrators user group. But in Server 2008R2, it's pulling from entire domain
Get-WmiObject -Class Win32_GroupUser `
| where{$_.GroupComponent -like "*Administrators*"} `
|foreach {
$data = $_.PartComponent -split "\,"
$data[1].Remove(0,5).Replace('"','')
}
As you have guessed the issue is that win2008R2 has only PS 2.0.x. I think this command where{$_.GroupComponent -like "*Administrators*"} is not available at that version so it queries the whole AD as a fallback (that is a guess).
From your description I did not understand if you want to query local server or domain so I will enter both (all are functional on win2008R2 (PS version 2.0.50727)):
To query local admins and
#get servers by AD OU
If (!(Get-Module ActiveDirectory)) {
Import-Module ActiveDirectory
}
function get-localadmins{
[cmdletbinding()]
Param(
[string]$server
)
$group = get-wmiobject win32_group -ComputerName $server -Filter "LocalAccount=True AND SID='S-1-5-32-544'"
$query = "GroupComponent = `"Win32_Group.Domain='$($group.domain)'`,Name='$($group.name)'`""
$list = Get-WmiObject win32_groupuser -ComputerName $server -Filter $query
$list | %{$_.PartComponent} | % {$_.substring($_.lastindexof("Domain=") + 7).replace("`",Name=`"","\")}
}
get-localadmins 'your_server_name'
If your goal is to query the whole AD then you can use:
On windows 2008 R2 SP1 it can produce an error: System.DirectoryServices.AccountManagement.PrincipalOperationException: An error (1301) occurred while enumerating the groups. The group's SID could not be resolved.
You have to install a hotfix by Microsoft at: https://support.microsoft.com/en-us/help/2830145/sid-s-1-18-1-and-sid-s-1-18-2-cannot-be-mapped-on-windows-based-computers-in-a-domain-environment?wa=wsignin1.0%3Fwa%3Dwsignin1.0
The following code was taken from here: https://stackoverflow.com/a/8057025/6059896 (all credit to the author) - only changed the names of variables to fig my coding style.
$Recurse = $true
Add-Type -AssemblyName System.DirectoryServices.AccountManagement
$context_type = [System.DirectoryServices.AccountManagement.ContextType]::Domain
$group_principal_identity=[System.DirectoryServices.AccountManagement.GroupPrincipal]::FindByIdentity($ct,'Administrators')
$group.GetMembers($Recurse)

Powershell : How to get Antivirus product details

We have over 1500 servers. Windows 2003, 2008 and 2012. I have to gather the details of antivirus(Product Name & Version) on these servers.
There could be multiple antivirus product.
I am not sure powershell script will work on 2003 server.
So, far i tried below scripts but not got useful information.
$av = get-wmiobject -class "Win32_Product" -namespace "root\cimv2" `
-computername "." -filter "Name like '%antivirus%'"
Below script is working fine on client operating system.
$wmiQuery = "SELECT * FROM AntiVirusProduct"
$AntivirusProduct = Get-WmiObject -Namespace "root\SecurityCenter2" -Query $wmiQuery #psboundparameters # -ErrorVariable myError -ErrorAction 'SilentlyContinue'
Write-host $AntivirusProduct.displayName
Can anybody advise me on this?
I am trying to get the details of antivirus(Product & Version)
What do i need to do for win server 2003?
You were on the right path, the following Powershell script works.
function Get-AntiVirusProduct {
[CmdletBinding()]
param (
[parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
[Alias('name')]
$computername=$env:computername
)
#$AntivirusProducts = Get-WmiObject -Namespace "root\SecurityCenter2" -Query $wmiQuery #psboundparameters # -ErrorVariable myError -ErrorAction 'SilentlyContinue' # did not work
$AntiVirusProducts = Get-WmiObject -Namespace "root\SecurityCenter2" -Class AntiVirusProduct -ComputerName $computername
$ret = #()
foreach($AntiVirusProduct in $AntiVirusProducts){
#Switch to determine the status of antivirus definitions and real-time protection.
#The values in this switch-statement are retrieved from the following website: http://community.kaseya.com/resources/m/knowexch/1020.aspx
switch ($AntiVirusProduct.productState) {
"262144" {$defstatus = "Up to date" ;$rtstatus = "Disabled"}
"262160" {$defstatus = "Out of date" ;$rtstatus = "Disabled"}
"266240" {$defstatus = "Up to date" ;$rtstatus = "Enabled"}
"266256" {$defstatus = "Out of date" ;$rtstatus = "Enabled"}
"393216" {$defstatus = "Up to date" ;$rtstatus = "Disabled"}
"393232" {$defstatus = "Out of date" ;$rtstatus = "Disabled"}
"393488" {$defstatus = "Out of date" ;$rtstatus = "Disabled"}
"397312" {$defstatus = "Up to date" ;$rtstatus = "Enabled"}
"397328" {$defstatus = "Out of date" ;$rtstatus = "Enabled"}
"397584" {$defstatus = "Out of date" ;$rtstatus = "Enabled"}
default {$defstatus = "Unknown" ;$rtstatus = "Unknown"}
}
#Create hash-table for each computer
$ht = #{}
$ht.Computername = $computername
$ht.Name = $AntiVirusProduct.displayName
$ht.'Product GUID' = $AntiVirusProduct.instanceGuid
$ht.'Product Executable' = $AntiVirusProduct.pathToSignedProductExe
$ht.'Reporting Exe' = $AntiVirusProduct.pathToSignedReportingExe
$ht.'Definition Status' = $defstatus
$ht.'Real-time Protection Status' = $rtstatus
#Create a new object for each computer
$ret += New-Object -TypeName PSObject -Property $ht
}
Return $ret
}
Get-AntiVirusProduct
Output:
Product GUID : {B0D0C4F4-7F0B-0434-B825-1213C45DAE01}
Name : CylancePROTECT
Real-time Protection Status : Enabled
Computername : HOSTNAME
Product Executable : C:\Program Files\Cylance\Desktop\CylanceSvc.exe
Reporting Exe : C:\Program Files\Cylance\Desktop\CylanceSvc.exe
Definition Status : Up to date
Product GUID : {D68DDC3A-831F-4fae-9E44-DA132C1ACF46}
Name : Windows Defender
Real-time Protection Status : Unknown
Computername : HOSTNAME
Product Executable : windowsdefender://
Reporting Exe : %ProgramFiles%\Windows Defender\MsMpeng.exe
Definition Status : Unknown
Instead of relying on running processes, you could query the registry :
$computerList = "localhost", "localhost"
$filter = "antivirus"
$results = #()
foreach($computerName in $computerList) {
$hive = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey([Microsoft.Win32.RegistryHive]::LocalMachine, $computerName)
$regPathList = "SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall",
"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
foreach($regPath in $regPathList) {
if($key = $hive.OpenSubKey($regPath)) {
if($subkeyNames = $key.GetSubKeyNames()) {
foreach($subkeyName in $subkeyNames) {
$productKey = $key.OpenSubKey($subkeyName)
$productName = $productKey.GetValue("DisplayName")
$productVersion = $productKey.GetValue("DisplayVersion")
$productComments = $productKey.GetValue("Comments")
if(($productName -match $filter) -or ($productComments -match $filter)) {
$resultObj = [PSCustomObject]#{
Host = $computerName
Product = $productName
Version = $productVersion
Comments = $productComments
}
$results += $resultObj
}
}
}
}
$key.Close()
}
}
$results | ft -au
Example output :
Host Product Version Comments
---- ------- ------- --------
localhost Avast Free Antivirus 10.4.2233
localhost Avast Free Antivirus 10.4.2233
Would this work for you? It's written in PowerShell v2, so if you have that installed on your 2003 servers, it will run on all the servers. This code will give you a CSV of this data from whichever machines run the script that have a service with the description including the word "virus" (which I thought better than "antivirus" because some services use "anti-virus" instead). If they all have access to a shared resource, you can prepend that shared resource directory to the $Filename variable and it will name each report starting with that computer's name and dump your reports there.
invoke-command -computername Server01, Server02 -filepath c:\Scripts\get_av_info.ps1
Assuming the script is saved as c:\Scripts\get_av_info.ps1, that should run it on whatever machines you specify, or if you have a CSV of all the machines you want to run the script, ForEach it. I didn't try this, so I can't verify the remote invoking.
$Date = (Get-Date).ToString('yyyy-MM-dd')
$localhost = $env:computername
$Filename = "C:\" + $localhost + "_" + $Date + "_AV_FileInfo.csv"
$AV = get-process | ?{$_.Description -like "*virus*"}
$Process = ForEach($a in $AV){
$ID = $($a.Id)
get-process -Id $ID -FileVersionInfo
}
$Process | select "CompanyName","FileBuildPart","FileDescription","FileName","FileVersion","ProductName","ProductPrivatePart","ProductVersion","SpecialBuild" | Export-Csv $Filename -NoTypeInformation
There are a LOT of options, I just picked ones I thought you'd want. You could probably also combine the reports to one by adding a shared resource to the Filename and having it -Append, but you would run the risk of multiple servers trying to write to the file at the same time and failing to report at all.
You'll need to refine your results, of course. If you don't change anything, any machine where you run this will just drop a CSV called "COMPUTERNAME_DATE_AV_FileInfo.csv" at the root of it's C:\ drive.

How can you check for existing firewall rules using Powershell

So, I've got this script:
function Add-FirewallRule {
param(
$name,
$tcpPorts,
$appName = $null,
$serviceName = $null
)
$fw = New-Object -ComObject hnetcfg.fwpolicy2
$rule = New-Object -ComObject HNetCfg.FWRule
$rule.Name = $name
if ($appName -ne $null) { $rule.ApplicationName = $appName }
if ($serviceName -ne $null) { $rule.serviceName = $serviceName }
$rule.Protocol = 6 #NET_FW_IP_PROTOCOL_TCP
$rule.LocalPorts = $tcpPorts
$rule.Enabled = $true
$rule.Grouping = "#firewallapi.dll,-23255"
$rule.Profiles = 7 # all
$rule.Action = 1 # NET_FW_ACTION_ALLOW
$rule.EdgeTraversal = $false
if(*here*)
{
$fw.Rules.Add($rule)
}
}
and I want to be able to put something in the if() that will check and see if the rule already exists before it adds it. I'm not terribly familiar with powershell, so go easy on me :P
PowerShell Firewall example for SDL Microservices
Only create a new firewall rule if it does not already exist
$rules = Get-NetFirewallRule
$par = #{
DisplayName = ""
LocalPort = 80
Direction="Inbound"
Protocol ="TCP"
Action = "Allow"
}
$par.LocalPort = 8081
$par.DisplayName = "SDL Web 8 Stage Content Microservice on port $($par.LocalPort)"
if (-not $rules.DisplayName.Contains($par.DisplayName)) {New-NetFirewallRule #par}
$par.LocalPort = 8082
$par.DisplayName = "SDL Web 8 Stage Discovery Microservice on port $($par.LocalPort)"
if (-not $rules.DisplayName.Contains($par.DisplayName)) {New-NetFirewallRule #par"}
Why not just:
$r = Get-NetFirewallRule -DisplayName 'Docker Cluster Management Communications' 2> $null;
if ($r) {
write-host "found it";
}
else {
write-host "did not find it"
}
MSDN has some extensive documentation on the Windows Firewall API here:
http://msdn.microsoft.com/en-us/library/aa366449(v=vs.85).aspx
You'll want to start with instantiating the HNetCfg.FwMgr COM object -- this will give you access to query various existing rules via the HNetCfg.FwMgr.LocalPolicy.CurrentProfile.
There are several different types of rules: Authorized Applications, Globally Open Ports, ICMP settings, and "services." The INetFwProfile object (retrieved via the CurrentProfile) has properties that allow access to these rules.
http://msdn.microsoft.com/en-us/library/aa365327(v=vs.85).aspx
Update (2014-01-30): In Windows 8 and Windows Server 2012, there is a PowerShell module called NetSecurity, which contains the Get-NetFirewallRule command. You can use this command to discover which firewall rules are already defined. To add a new firewall rule, use the New-NetFirewallRule command in the same NetSecurity module.
This doesn't seem to be widely known. You can do a fast search of the firewall rules by going first to the filter commands, for example, to list the ones with 'chrome.exe' as the program. You can use a wildcard with -Program, even though it doesn't seem to be documented.
Get-NetFirewallApplicationFilter -Program *chrome.exe | Get-NetFirewallRule |
% Displayname
Google Chrome (mDNS-In)
Get-NetFirewallPortFilter | Where Localport -match 3389 | Get-NetFirewallRule |
% Displayname
Remote Desktop - User Mode (TCP-In)
Remote Desktop - User Mode (UDP-In)
This answer over on serverfault, which was based on this blog-post, might help:
Function Get-EnabledRules
{
Param($profile)
$rules = (New-Object -comObject HNetCfg.FwPolicy2).rules
$rules = $rules | where-object {$_.Enabled -eq $true}
$rules = $rules | where-object {$_.Profiles -bAND $profile}
$rules
}
$networkListManager = [Activator]::CreateInstance([Type]::GetTypeFromCLSID([Guid]"{DCB00C01-570F-4A9B-8D69-199FDBA5723B}"))
$connections = $networkListManager.GetNetworkConnections()
[int[] ] $connTypes = #()
$connTypes = ($connections | % {$_.GetNetwork().GetCategory()})
#$connTypes += 1
Write-Host $connTypes
$connTypes | ForEach-Object {Get-EnabledRules -profile $_ | sort localports,Protocol | format-table -wrap -autosize -property Name, #{Label="Action"; expression={$_.action}}, #{Label="Protocol"; expression={$_.protocol}}, localPorts,applicationname}
you will need to check the enabled rules in your 'if()' ..
You can do it in hacky way, so using Get-NetFirewallRule and surround it in try catch statement. If the rule doesn't exist, it will move us to catch statement so we can create a new rule there.
try {
$firewallRule = Get-NetFirewallRule -DisplayName PROGRAM -ErrorAction Stop
"Firewall rule already exist for program.exe" | Add-Content 'file.log'
}
catch {
if(-Not $firewallRule) {
New-NetFirewallRule -Program $ecfClient -Action Allow -Profile Any -DisplayName "PROGRAM"
"Firewall rule for ecfClient.exe succesffully created" | Add-Content 'file.log'
}
}
You can also check the value from the Get-NetFirewallRule, if the rule exists it will return true because variable isn't empty.
I know it's a dirty way for doing this, but when I was looking for the shortest way that really helped me.
Following up #Trevor Sullivian Suggestion here is test script which achieves the same using NetSecurity Module.
Import-Module NetSecurity
new-netfirewallrule -Action Allow -Direction Inbound -Enabled True -Protocol TCP -LocalPort <<Port>> -DisplayName <<Name>>

How to update existing IIS 6 Web Site using PowerShell

I am trying to create a PowerShell script that creates a new IIS 6 web site and sets things like App Pool, Wildcard application maps, ASP.NET version, etc.
After extensive search on the Internet I found a script that allows me to create a new Web Site but not to modify all the properties I need.
$newWebsiteName = "WebSiteName"
$newWebsiteIpAddress = "192.168.1.100"
$newWebSiteDirPath = "c:\inetpub\wwwroot\WebSiteName"
$iisWebService = Get-WmiObject -namespace "root\MicrosoftIISv2"
-class "IIsWebService"
$bindingClass = [wmiclass]'root\MicrosoftIISv2:ServerBinding'
$bindings = $bindingClass.CreateInstance()
$bindings.IP = $newWebsiteIpAddress
$bindings.Port = "80"
$bindings.Hostname = ""
$result = $iisWebService.CreateNewSite
($newWebsiteName, $bindings, $newWebSiteDirPath)
Any help on how to expand example above is greatly appreciated.
First of all, big thanks to jrista for pointing me in the right direction.
I also found this article very useful.
What follows here is a powershell script to create Application pool, Website and a SelfSsl certificate:
function CreateAppPool ([string]$name, [string]$user, [string]$password)
{
# check if pool exists and delete it - for testing purposes
$tempPool = gwmi -namespace "root\MicrosoftIISv2" -class "IISApplicationPoolSetting" -filter "Name like '%$name%'"
if (!($tempPool -eq $NULL)) {$tempPool.delete()}
# create Application Pool
$appPoolSettings = [wmiclass] "root\MicrosoftIISv2:IISApplicationPoolSetting"
$newPool = $appPoolSettings.CreateInstance()
$newPool.Name = "W3SVC/AppPools/" + $name
$newPool.WAMUsername = $user
$newPool.WAMUserPass = $password
$newPool.PeriodicRestartTime = 1740
$newPool.IdleTimeout = 20
$newPool.MaxProcesses = 1
$newPool.AppPoolIdentityType = 3
$newPool.Put()
}
function CreateWebSite ([string]$name, [string]$ipAddress, [string]$localPath, [string] $appPoolName, [string] $applicationName)
{
# check if web site exists and delete it - for testing purposes
$tempWebsite = gwmi -namespace "root\MicrosoftIISv2" -class "IISWebServerSetting" -filter "ServerComment like '%$name%'"
if (!($tempWebsite -eq $NULL)) {$tempWebsite.delete()}
# Switch the Website to .NET 2.0
C:\windows\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis.exe -sn W3SVC/
$iisWebService = gwmi -namespace "root\MicrosoftIISv2" -class "IIsWebService"
$bindingClass = [wmiclass]'root\MicrosoftIISv2:ServerBinding'
$bindings = $bindingClass.CreateInstance()
$bindings.IP = $ipAddress
$bindings.Port = "80"
$bindings.Hostname = ""
$iisWebService.CreateNewSite($name, $bindings, $localPath)
# Assign App Pool
$webServerSettings = gwmi -namespace "root\MicrosoftIISv2" -class "IISWebServerSetting" -filter "ServerComment like '%$name%'"
$webServerSettings.AppPoolId = $appPoolName
$webServerSettings.put()
# Add wildcard map
$wildcardMap = "*, c:\somewildcardfile.dll, 0, All"
$iis = [ADSI]"IIS://localhost/W3SVC"
$webServer = $iis.psbase.children | where { $_.keyType -eq "IIsWebServer" -AND $_.ServerComment -eq $name }
$webVirtualDir = $webServer.children | where { $_.keyType -eq "IIsWebVirtualDir" }
$webVirtualDir.ScriptMaps.Add($wildcardMap)
# Set Application name
$webVirtualDir.AppFriendlyName = $applicationName
# Save changes
$webVirtualDir.CommitChanges()
# Start the newly create web site
if (!($webServer -eq $NULL)) {$webServer.start()}
}
function AddSslCertificate ([string] $websiteName, [string] $certificateCommonName)
{
# This method requires for you to have selfssl on your machine
$selfSslPath = "\program files\iis resources\selfssl"
$certificateCommonName = "/N:cn=" + $certificateCommonName
$certificateValidityDays = "/V:3650"
$websitePort = "/P:443"
$addToTrusted = "/T"
$quietMode = "/Q"
$webServerSetting = gwmi -namespace "root\MicrosoftIISv2" -class "IISWebServerSetting" -filter "ServerComment like '$websiteName'"
$websiteId ="/S:" + $webServerSetting.name.substring($webServerSetting.name.lastindexof('/')+1)
cd -path $selfSslPath
.\selfssl.exe $addToTrusted $certificateCommonName $certificateValidityDays $websitePort $websiteId $quietMode
}
$myNewWebsiteName = "TestWebsite"
$myNewWebsiteIp = "192.168.0.1"
$myNewWebsiteLocalPath = "c:\inetpub\wwwroot\"+$myNewWebsiteName
$appPoolName = $myNewWebsiteName + "AppPool"
$myNewWebsiteApplicationName = "/"
$myNewWebsiteCertificateCommonName = "mynewwebsite.dev"
CreateAppPool $appPoolName "Administrator" "password"
CreateWebSite $myNewWebsiteName $myNewWebsiteIp $myNewWebsiteLocalPath $appPoolName $myNewWebsiteApplicationName
AddSslCertificate $myNewWebsiteName $myNewWebsiteCertificateCommonName
The $result object contains the path to the newly created IIsWebServer object. You can get access to the virtual directory, where you can configure more properties, by doing the following:
$w3svcID = $result.ReturnValue -replace "IIsWebServer=", ""
$w3svcID = $w3svcID -replace "'", ""
$vdirName = $w3svcID + "/ROOT";
$vdir = gwmi -namespace "root\MicrosoftIISv2"
-class "IISWebVirtualDir"
-filter "Name = '$vdirName'";
# do stuff with $vdir
$vdir.Put();
This is a useful PowerShell snippet.
I tried running this and I get problems with the delete tests. Delete does not work against the app pool when the site still exists. Surely you should run website delete test first.
# check if web site exists and delete it - for testing purposes
$tempWebsite = gwmi -namespace "root\MicrosoftIISv2"
-class "IISWebServerSetting"
-filter "ServerComment like '%$name%'"
if (!($tempWebsite -eq $NULL)) {$tempWebsite.delete()}
Run this first, then run the app pool deletion test.
I realise you have marked these as tests but surely it is useful to exit or delete if webs site exists.