Using CurrentDomain.SetData("APP_CONFIG_FILE") doesn't work in PowerShell ISE - .net-4.0

I'm attempting to use a .NET 4.0 assembly in PowerShell ISE, and trying to change the config file which is used via:
[System.AppDomain]::CurrentDomain.SetData("APP_CONFIG_FILE", $PathToConfig);
[Configuration.ConfigurationManager]::ConnectionStrings.Count always returns "1",and "[Configuration.ConfigurationManager]::ConnectionStrings[0].Name" always returns "LocalSqlServer", and that ConnectionString name is not in my ".config" file.
Note that executing the PowerShell script from a PowerShell command prompt functions as expected. It's just when I execute it from within PowerShell ISE, it doesn't work as expected.

It's because the path to app.config for PowerShell ISE has already been loaded and cached so changing the app.config path afterwards won't make a difference:
stackoverflow.com/q/6150644/222748
Here is an example script that will clear the cached path so it will work under PowerShell ISE:
[System.AppDomain]::CurrentDomain.SetData("APP_CONFIG_FILE", $PathToConfig)
Add-Type -AssemblyName System.Configuration
[Configuration.ConfigurationManager].GetField("s_initState", "NonPublic, Static").SetValue($null, 0)
[Configuration.ConfigurationManager].GetField("s_configSystem", "NonPublic, Static").SetValue($null, $null)
([Configuration.ConfigurationManager].Assembly.GetTypes() | where {$_.FullName -eq "System.Configuration.ClientConfigPaths"})[0].GetField("s_current", "NonPublic, Static").SetValue($null, $null)
[Configuration.ConfigurationManager]::ConnectionStrings[0].Name

Taking off [0] works for me.
([Configuration.ConfigurationManager].Assembly.GetTypes() | where {$_.FullName -eq "System.Configuration.ClientConfigPaths"}).GetField("s_current", "NonPublic, Static").SetValue($null, $null)

Related

How to capture all outputs from a powershell script?

I am working on script "executeAll.ps1" that would execute multiple "execute.ps1" scripts. I am trying to capture the outputs of each execute.ps1 window but the problem is that the script execute .sql commands from a dacpac and the PRINTS only shows in the powershell window but not in any of my output files.
I have tried having *>> in my executeAll script and Start-Transcript in execute.ps1, but neither of them shows the sql PRINTS.
Is there anything I can do about this, maybe a different approach I am unaware of?
I have access to the .ps1 files, but only a maybe on the .sql files.
Here is my code when executing the script:
Start-Process powershell "& .\execute.ps1 -dbserver $server -databasename $database -client $client *>> "".\output\$client.txt"""

Microsoft.Azure.IpSecurityRestriction not found in Azure PowerShell script

I am trying to run some PowerShell commands and my script is failing on the following line:
$ipsr = New-Object Microsoft.Azure.IpSecurityRestriction
The error is:
Cannot find type [Microsoft.Azure.IpSecurityRestriction]: verify that the assembly containing this type is loaded
I am trying to run this “inline” in an Azure PowerShell task as part of my deployment pipeline. Is this supported or do I need to first import an assembly?
I can reproduce your issue. First, it should be Microsoft.Azure.Management.WebSites.Models.IpSecurityRestriction, not Microsoft.Azure.IpSecurityRestriction, then make sure you have installed the Az.Websites powershell module, just use the command below.
Import-Module -Name Az.Websites
New-Object Microsoft.Azure.Management.WebSites.Models.IpSecurityRestriction
Besides, actually we import the module just for the Microsoft.Azure.Management.Websites.dll, so you can also use the command as below, check the path of your .dll file.
Add-Type -Path 'C:\Program Files\WindowsPowerShell\Modules\Az.Websites\1.1.0\Microsoft.Azure.Management.Websites.dll'
New-Object Microsoft.Azure.Management.WebSites.Models.IpSecurityRestriction

New-Item Behavior Changes When Using Runspace to Run Command Remotely

I am using VB.Net to open a Powershell runspace using WSManConnectionInfo. The connection works fine. I am trying to run a New-Item command in order to create a new virtual directory.
New-Item "IIS:\Sites\ExternalInventory FTP\TestVT" -Type VirtualDirectory -physicalPath "C:\"
The command works fine when running it locally on the server. However, when ran remotely through the runspace I get an error:
A parameter cannot be found that matches parameter name 'physicalPath'.
I initially tried to use use the New-WebVirtualDirectory command to create the virtual directory, but this led to other errors. I need to use New-Item.
What is causing the difference in behavior of the New-Item command, and how can I use it to create a new virtual directory through the runspace?
Note: I have tried other commands through the runspace and they seem to work as expected.
EDITS
I know that the New-Item command does not have the parameter "physicalPath" listed in the docs: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/new-item?view=powershell-6
The New-Item command is used in multiple places in the docs to create virtual directory with the physicalPath parameter. See links
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/new-item?view=powershell-6
https://forums.iis.net/t/1223546.aspx?New+WebVirtualDirectory+does+not+work+when+invoked+remotely+and+a+UNC+path+is+used
As pointed out in the comments, I needed to include the WebAdministration module in my script.
Thanks TheMadTechnitian

Recompose VM using vmware 5.5 power cli

How can I recompose a VM v1 with existing parent VM v2's snapshot s2 ?
After referring few documents, I saw command Send-LinkedCloneRecompose for recomposing VM.
I am trying this command as follows:
$myVM = 'v1'
$clone = Get-DesktopVM -Name $myVM
$pool = Get-Pool -pool_id $clone.pool_id
$date = Get-Date
$date = $date.AddSeconds(10)
Write-Host "Recomposing" $clone.name
Send-LinkedCloneRecompose -machine_id $clone.machine_id -parentVMPath $pool.parentVMPath -parentSnapshotPath $pool.parentVMSnapshotPath -schedule $date -forcelogoff $true | tee-object -variable vmState
Here I am getting error as Get-DesktopVM : The term 'Get-DesktopVM' is not recognized as the name of a
cmdlet, function, script file, or operable program. Check the spelling of the
name, or if a path was included, verify that the path is correct and try again.
I am getting the same error for powercli commandlets Get-Pool and Send-LinkedCloneRecompose as well.
I am using VMware VSphere power cli 5.5 release 2 patch 1.
Can anyone please help me in understanding the problem here ?
I missed to add
& "C:\Program Files\VMware\VMware View\Server\extras\PowerShell\add-snapin.ps1"
before executing above commands. So the commandlets were not recognized.

Can you remove an Add-ed Type in PowerShell again?

I'm currently writing a library in C# and was using PowerShell to quickly test it on some occasions. However, this prevents me from re-building the project as PowerShell obviously still has the DLL open.
Is there a way of unloading the DLL again after adding it with Add-Type? The documentation doesn't seem to have clues on that and the obvious candidate would be Remove-Type (which doesn't exist – there is only one command anyway with Type as its noun). It gets cumbersome to close PowerShell and do all the stuff of navigating to the build directory and adding the type again each time I want to rebuild.
Like the others say, this is a .NET behavior. Assemblies loaded into an AppDomain cannot be unloaded. Only the AppDomain can be unloaded, and powershell uses a single appdomain. I blogged a bit about this some years ago:
https://web.archive.org/web/20170707034334/http://www.nivot.org/blog/post/2007/12/07/WhyAppDomainsAreNotAMagicBullet
When I test like this, I usually keep a shell open and use a nested shell to do tests. start powershell, cd to bin location then run "powershell" to start nested shell (new process.) "exit" to start over, and run "powershell" again.
I find the simplest way to get around this problem is to wrap the Add-Type and the test code inside of a Start-Job. Start-Job will create a background process, and the type will be loaded there. Once you are done, the process goes away and you're free to retry.
Here's an example of how it looks:
$job = Start-Job -ScriptBlock {
Add-Type -path 'my.dll'
$myObj = new-object My.MyTestClassName
$result = $myObj.TestMethod
$result
}
Wait-Job $job
Receive-Job $job
The output from the test method will be echoed to the console.
If your assembly doesn't require a binding context you can do this:
$bytes = [System.IO.File]::ReadAllBytes("Path_To_Your_Dll.dll")
[System.Reflection.Assembly]::Load($bytes)
Here is a complete example that allows to run the Add-Type command as a background job so that the assembly is unloaded once it finishes:
# Start-Job will not preserve the working directory, so do it manually
# Other arguments can also be passed to the job this way
$cd = Split-Path $MyInvocation.MyCommand.Path
$jobParams = #{
'cd' = $cd
}
Start-Job -InputObject $jobParams -ScriptBlock {
cd $Input.cd
Add-Type -Path assembly.dll
} | Receive-Job -Wait -AutoRemoveJob
Receive-Job -Wait will make sure that the output of the job is received since otherwise it will be lost.
I have been facing to similar problem. It is not possible to unload a type/assembly (that's because it applies to .NET framework).
In .NET you can solve it if you crate a new application domain (System.AppDomain) and load the assembly into that domain. It is possible to unload the app domain and that unloads all the dlls as well.
I haven't tried it yet, because for me it is much simpler to close a tab in Console and open new one.
Visual Studio Code:
Settings -> Extensions -> PowerShell Configuration -> Debugging: Create Temporary Integrated Console
Check checkbox: "Determines whether a temporary PowerShell Integrated Console is created for each debugging sessions, usefull for debugging PowerShell classes and binary modules."