在PowerShell中从内存中删除类

Vid*_*ous 9 powershell class

我创建了一个名为"Application"的类,并将其加载到我的主脚本中:

Import-Module -NAME "C:\PowerShell_Scripts\Class\Application.ps1" -GLOBAL -FORCE;
Run Code Online (Sandbox Code Playgroud)

但是,如果我更改类文件并在PowerShell ISE中运行代码,则不会应用任何更改.即使我使用了-FORCE,它几乎就像是在类中仍然在内存中.

我还尝试在加载模块之前删除该模块,并发生同样的问题:

Remove-Module "Application" -ErrorAction Ignore -FORCE;
Import-Module -NAME "C:\PowerShell_Scripts\Class\Application.ps1" -GLOBAL -FORCE;
Run Code Online (Sandbox Code Playgroud)

如果我在主脚本中进行单个字符更改,则会重新加载该类!但我不应该修改主脚本来强制PowerShell重新加载类,这看起来很傻.

有没有办法从内存中删除Application类(如果存在)?

注意:只有函数的文件工作文件.这仅适用于类导入.

添加:在控制台中,如果我运行Remove-Module命令它运行成功但我仍然可以创建新对象:

$appDetails = [Application]::new($applicationID);
Run Code Online (Sandbox Code Playgroud)

对我来说没有意义......

主要内容:

# Application Details
# -----------------
  #ID
  $applicationID     = 1;

############################################
#
# Load Supporting Scripts
#
############################################

try
{
    Remove-Module "Application" -ErrorAction Ignore -FORCE;
    Remove-Module "Common" -ErrorAction Ignore -FORCE;
    Remove-Module "ServerData" -ErrorAction Ignore -FORCE;

    Import-Module -NAME "C:\PowerShell_Scripts\Common.ps1" -GLOBAL -FORCE;
    Import-Module -NAME "C:\PowerShell_Scripts\ServerData.ps1" -GLOBAL -FORCE;
    Import-Module -NAME "C:\PowerShell_Scripts\Class\Application.ps1" -GLOBAL -FORCE;
}
catch
{
    Write-Host "`nError: Cannot load required PowerShell scripts. Ensure C:\PowerShell_Scripts\ exists and has the required files." -ForegroundColor Red;

    EXIT;
}

############################################
#
# Load the SharePoint Snapin Module.
#
############################################

LoadSharePointModule;
############################################
#
# Display component details to user.
#
############################################

#Create object of "Application" to get app details based on the ID.
$appDetails = [Application]::new($applicationID);

Write-Host "Ending ......";
Run Code Online (Sandbox Code Playgroud)

申请分类文件

Class Application
{
    #Class Properties
    [STRING] $appName;

    [INT32] $appID;
    [INT32] $versionMajor;
    [INT32] $versionOS;
    [INT32] $versionCentraAdmin;
    [INT32] $versionMain;
    [INT32] $versionGUI;
    [INT32] $versionWorkflow;
    [INT32] $versionForm;
    [INT32] $versionVS;
    [INT32] $versionOther;
    [INT32] $versionFull;

    [OBJECT] $spDevSite;
    [OBJECT] $versionList;

    #Constructor: Setup class properties.
    Application ([INT32] $appID)
    {
        Write-Host "`nGathering application details ..." -ForegroundColor Yellow;

        try
        {
            #Get the SharePoint Developer site Object.
            $this.spDevSite = Get-SPWeb -ErrorAction Stop $GLOBAL:spDevURL;
        }
        catch
        {
            Write-Host "`nUnable to connect to SharePoint Developer site!: $($GLOBAL:spDevURL)";

            #EXIT;
        }

        #Assign class property.
        $this.appID = $appID;
    }

}
Run Code Online (Sandbox Code Playgroud)

我故意设置$ GLOBAL的URL:spDevURL; 这样构造函数就无法进行此测试.它正常失败并显示

Write-Host "`nUnable to connect to SharePoint Developer site!: $($GLOBAL:spDevURL)";
Run Code Online (Sandbox Code Playgroud)

但是,如果我对此行进行更改并运行脚本,则不会应用更改.

alx*_*x9r 12

已知问题

PowerShell 5.0和5.1中存在一个已知问题,可以解释此行为. 2016年11月,东博王在PowerShell 6团队中承认这个问题.他写了以下内容:

"模块分析结果存储在缓存中,模块文件路径为密钥,PSModuleInfo对象为值.缓存条目未根据模块文件的LastWriteTime正确无效,因此重用了相同的缓存值. "

换句话说,PowerShell 5.0,5.1和6.0在内存中保留(并使用)旧的类副本.

启示

如果您不对其进行补偿,则此问题会导致使用PowerShell类进行开发时出现相当大的问题.我编写了一个测试,涵盖了大约100个类重新加载很重要的场景.模糊地说,在大约17个场景中,PowerShell 5.0和5.1不会在应该的时候重新加载类.这意味着在编辑中使用相同的会话会产生解释器将缓存相同或类似类的重复副本的真实可能性.这使得行为变得不可预测,并导致奇怪的结果,不能麻烦.

解决方法

我发现使用PowerShell类仍然可以高效地开发.当项目涉及PowerShell解释器可能认为已更改的源代码的PowerShell类时,您只需在新的PowerShell会话中执行每个测试运行.执行此操作的常规方法是通过调用powershell.exe以下方法从PowerShell控制台调用test命令:

powershell.exe -Command { Invoke-Pester }
Run Code Online (Sandbox Code Playgroud)

如果你有严格的单元测试,这不是一个非常低效的测试编辑测试周期.如果您需要单步执行代码,则每次进行编辑时都需要启动ISE的全新副本.

通过这种解决方法,我发现这个bug的生产力影响是可管理的.我开发这个这个完全使用此解决办法.每个项目都涉及大量涉及PowerShell类的代码.