在PowerShell中从内存中删除类 [英] Remove Class from Memory in PowerShell

查看:92
本文介绍了在PowerShell中从内存中删除类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个名为应用程序的类,并将其加载到我的主脚本中:

I've created a class called "Application" and loaded it in my main script with:

Import-Module -NAME "C:\PowerShell_Scripts\Class\Application.ps1" -GLOBAL -FORCE;

但是,如果我更改类文件并运行代码在PowerShell ISE中,未应用任何更改。即使我已经使用了-FORCE,该类似乎仍在内存中。

However if I ONLY make changes to the class file and run the code in PowerShell ISE none of the changes are applied. It's almost as if the class is still in memory even though I've used -FORCE.

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

I've also tried to remove the module before loading it and the same issue happens:

Remove-Module "Application" -ErrorAction Ignore -FORCE;
Import-Module -NAME "C:\PowerShell_Scripts\Class\Application.ps1" -GLOBAL -FORCE;

如果我在主脚本中进行了单个字符更改,那么它将重新加载该类!但是我不必修改主脚本来强制PowerShell重新加载类,这似乎很愚蠢。

If I make a single character change in my main script then it reloads the class! But I shouldn't have to modify the main script to force PowerShell to reload the class, that just seems silly.

有没有办法从内存中删除Application类

Is there a way to remove the Application class from memory if it exists?

注意:仅包含功能的文件可以工作。这仅适用于Class导入。

NOTE: Files with just functions in them work file. This only applies to Class imports.

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

Addition: In the console, if I run the Remove-Module command it runs successfully but I can STILL create new objects with:

$appDetails = [Application]::new($applicationID);

对我来说没有意义...

Doesn't make sense to me...

主脚本:

# 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 ......";

应用程序类文件

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;
    }

}

我故意为$ GLOBAL:spDevURL;因此构造函数无法通过此测试。它通常会失败并显示

I have deliberately set the URL for $GLOBAL:spDevURL; so that the Constructor fails for this test. It fails normally and displays

Write-Host "`nUnable to connect to SharePoint Developer site!: $($GLOBAL:spDevURL)";

但是如果我对此行进行了更改并运行了脚本,则不会应用更改。 / p>

But if I make a change to this line and run the script, the change is not applied.

推荐答案

已知问题



PowerShell 5.0中存在一个已知问题和5.1解释了此行为。 问题已得到确认。 .com / daxian-dbw rel = noreferrer> DongBo Wang 于2016年11月在PowerShell 6团队中工作。他写道:

The Known Issue

There is a known issue in PowerShell 5.0 and 5.1 that explains this behavior. The issue was acknowledged by DongBo Wang on the PowerShell 6 team in November 2016. He wrote the following:


模块分析结果存储在缓存中,其中模块文件路径作为键,而PSModuleInfo对象作为值。基于模块文件的LastWriteTime,缓存条目未正确失效,因此相同缓存的值将被重用。

"The module analysis result is stored in a cache with the module file path as the key and the PSModuleInfo object as the value. The cache entries are not properly invalidated based on the LastWriteTime of the module file, and thus same cached value got reused."

换句话说,PowerShell 5.0、5.1和6.0将类的旧副本保留(并使用)在

In other words, PowerShell 5.0, 5.1, and 6.0 keeps (and uses) old copies of classes in memory when it shouldn't.

如果您使用PowerShell类,则此问题会导致相当大的开发问题不赔偿。我写了测试,它涵盖了大约100种重要的类重载场景。大概地说,在大约17种情况下,PowerShell 5.0和5.1不会在应有的情况下重新加载该类。这意味着在编辑中使用相同的会话会产生很大的可能性,解释器将缓存相同或相似类的重复副本。这会使行为变得不可预测,并导致无法解决的奇怪结果。

This issue causes considerable problems for development using PowerShell classes if you do not compensate for it. I wrote a test that covers about 100 of the scenarios where class reloading is important. Vaguely speaking, in about 17 of those scenarios PowerShell 5.0 and 5.1 doesn't reload the class when it should. This means using the same session across edits creates a real likelihood the interpreter will have cached duplicate copies of the same or similar classes. That makes behavior unpredictable and causes strange results that cannot be troubleshot.

我发现您可以使用PowerShell类进行开发仍然可以提高工作效率。当项目涉及PowerShell类,其解释器 可能认为其源已更改时,您只需要在新的PowerShell会话中执行每个测试运行。惯用的方法是通过调用 powershell.exe 从PowerShell控制台调用测试命令:

I have found that you can still be productive developing using PowerShell classes. You just need to perform each test run in a fresh PowerShell session when a project involves PowerShell classes whose source the PowerShell interpreter may consider to have changed. The customary way to do this is to invoke your test command from your PowerShell console by invoking powershell.exe:

powershell.exe -Command { Invoke-Pester }

如果您有严格的单元测试,那么这将是效率极低的测试-编辑-测试周期。如果需要单步执行代码,则每次进行编辑时都需要启动ISE的新副本。

That's not a terribly inefficient test-edit-test cycle if you've got tight unit tests. If you need to step through code, you'll need to launch a fresh copy of ISE each time you make an edit.

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

With this workaround, I have found the productivity impact of this bug to be manageable. I developed this and this entirely using this workaround. Each of those projects involve a significant amount of code involving PowerShell classes.

这篇关于在PowerShell中从内存中删除类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆