简体   繁体   English

如何在Powershell中创建动态变量,例如日期/时间等

[英]How to create a dynamic variable in Powershell, sucha as date/time etc

Hi i am not exactly sure if my wording is right but i need a variable which contains current date/time whenever i write data to log ; 嗨,我不确定我的措辞是否正确,但是每当我将数据写入日志时,我都需要一个包含当前日期/时间的变量; how can i do that without initializing everytime.Currently everytime i need a update i use these both statements jointly.Is there an other way of doing this? 我怎么做而不必每次都初始化。目前每次我需要更新时,我会同时使用这两个语句。还有另一种方法吗?

$DateTime = get-date  | select datetime
Add-Content $LogFile -Value "$DateTime.DateTime: XXXXX"

please do let me know if any questions or clarifications regarding my question. 请让我知道是否有任何疑问或有关我的问题的说明。

This script make the real Dynamic variable in Powershell ( Thanks to Lee Holmes and his Windows PowerShell Cookbook The Complete Guide to Scripting Microsoft's Command Shell, 3rd Edition ) 该脚本在Powershell中生成真正的Dynamic变量(感谢Lee Holmes和他的Windows PowerShell Cookbook The Complete Guide to Scripting Microsoft's Command Shell, 3rd Edition

##############################################################################
##
## New-DynamicVariable
##
## From Windows PowerShell Cookbook (O'Reilly)
## by Lee Holmes (http://www.leeholmes.com/guide)
##
##############################################################################

<#

.SYNOPSIS

Creates a variable that supports scripted actions for its getter and setter

.EXAMPLE

PS > .\New-DynamicVariable GLOBAL:WindowTitle `
     -Getter { $host.UI.RawUI.WindowTitle } `
     -Setter { $host.UI.RawUI.WindowTitle = $args[0] }

PS > $windowTitle
Administrator: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
PS > $windowTitle = "Test"
PS > $windowTitle
Test

#>

param(
    ## The name for the dynamic variable
    [Parameter(Mandatory = $true)]
    $Name,

    ## The scriptblock to invoke when getting the value of the variable
    [Parameter(Mandatory = $true)]
    [ScriptBlock] $Getter,

    ## The scriptblock to invoke when setting the value of the variable
    [ScriptBlock] $Setter
)

Set-StrictMode -Version 3

Add-Type @"
using System;
using System.Collections.ObjectModel;
using System.Management.Automation;

namespace Lee.Holmes
{
    public class DynamicVariable : PSVariable
    {
        public DynamicVariable(
            string name,
            ScriptBlock scriptGetter,
            ScriptBlock scriptSetter)
                : base(name, null, ScopedItemOptions.AllScope)
        {
            getter = scriptGetter;
            setter = scriptSetter;
        }
        private ScriptBlock getter;
        private ScriptBlock setter;

        public override object Value
        {
            get
            {
                if(getter != null)
                {
                    Collection<PSObject> results = getter.Invoke();
                    if(results.Count == 1)
                    {
                        return results[0];
                    }
                    else
                    {
                        PSObject[] returnResults =
                            new PSObject[results.Count];
                        results.CopyTo(returnResults, 0);
                        return returnResults;
                    }
                }
                else { return null; }
            }
            set
            {
                if(setter != null) { setter.Invoke(value); }
            }
        }
    }
}
"@

## If we've already defined the variable, remove it.
if(Test-Path variable:\$name)
{
    Remove-Item variable:\$name -Force
}

## Set the new variable, along with its getter and setter.
$executioncontext.SessionState.PSVariable.Set(
    (New-Object Lee.Holmes.DynamicVariable $name,$getter,$setter))

There's a Set-StrictMode -Version 3 but you can set it as -Version 2 if you can load framework 4.0 in your powershell V2.0 session as explained Here 有一个Set-StrictMode -Version 3但是如果可以在powershell V2.0会话中加载框架4.0,则可以将其设置为-Version 2,如此处所述

The use for the OP is: OP的用途是:

 New-DynamicVariable -Name GLOBAL:now -Getter { (get-date).datetime }

Here the Lee Holmes's evaluation (where it is clear what is the real flaw) about the method I used in my other answer: 在这里,李·福尔摩斯(Lee Holmes)对我在其他答案中使用的方法的评估(很明显是真正的缺陷):

Note
There are innovative solutions on the Internet that use PowerShell's debugging facilities to create a breakpoint that changes a variable's value whenever you attempt to read from it. While unique, this solution causes PowerShell to think that any scripts that rely on the variable are in debugging mode. This, unfortunately, prevents PowerShell from enabling some important performance optimizations in those scripts.

Why not use: 为什么不使用:

Add-Content $LogFile -Value "$((Get-Date).DateTime): XXXXX"

This gets the current datetime every time. 每次获取当前日期时间。 Notice that it's inside $( ) which makes powershell run the expression(get the datetime) before inserting it into the string. 注意,它在$( ) ,这使powershell在将表达式插入字符串之前运行表达式(获取日期时间)。

wrap your two commands in function so you will have just one call ? 将两个命令包装在函数中,这样您将只有一个调用?

function add-log{
(param $txt)
$DateTime = get-date  | select -expand datetime
Add-Content $LogFile -Value "$DateTime: $txt"
}

Besides these other ways (which frankly I would probably use instead - except the breakpoint approach), you can create a custom object with a ScriptProperty that you can provide the implementation for: 除了这些其他方式(坦率地说,我可能会改用其他方式-除断点方法外),还可以使用ScriptProperty创建自定义对象,并为以下内容提供实现:

$obj = new-object pscustomobject
$obj | Add-Member ScriptProperty Now -Value { Get-Date }
$obj.now

Using PsBreakPoint : 使用PsBreakPoint

$act= @'
$global:now = (get-date).datetime
'@
$global:sb = [scriptblock]::Create($act)
$now = Set-PSBreakpoint -Variable now -Mode Read -Action $global:sb

calling $now returns current updated datetime value 调用$now返回当前更新的日期时间值

One liner: 一班轮:

$now = Set-PSBreakpoint -Variable now -Mode Read -Action { $global:now = (get-date).datetime }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM