Parancsmag létrehozása adattár eléréséhez
Ez a szakasz bemutatja, hogyan hozhat létre olyan parancsmagokat, amelyek a tárolt adatokhoz férnek hozzá egy Windows PowerShell szolgáltatón keresztül. Ez a parancsmagtípus a Windows PowerShell-Windows PowerShell-es futtatás Windows PowerShell-szolgáltatói infrastruktúráját használja, ezért a parancsmag osztályának a System.Management.Automation.PSCmdlet alaposztályból kell származtatva lennie.
Az Select-Str ismertetett parancsmag megkeresheti és kiválaszthatja a sztringeket egy fájlban vagy objektumban. A sztring azonosításához használt minták explicit módon, a parancsmag paraméterén vagy implicit módon a paraméteren Path
keresztül is Script
meghatározhatóak.
A parancsmag úgy lett kialakítva, hogy a System.Management.Automation.Provider.IcontentcmdletproviderWindows PowerShell-szolgáltatót használja. A parancsmag például megadhatja a fájlrendszerszolgáltatót vagy a változószolgáltatót, amelyet a Windows PowerShell. További információ a Windows PowerShell-szolgáltatókról: Designing Your Windows PowerShell provider..
A parancsmagosztály meghatározása
A parancsmag létrehozásának első lépése mindig a parancsmag elnevezése és a parancsmagot megvalósító .NET-osztály deklarációja. Ez a parancsmag bizonyos sztringeket észlel, így az itt kiválasztott művelet neve "Select", amelyet a System.Management.Automation.Verbscommon osztály határoz meg. Az "Str" főnév azért használatos, mert a parancsmag sztringeket használ. Az alábbi deklarációban figyelje meg, hogy a parancsmag ige és főnév is megjelenik a parancsmagosztály nevében. A jóváhagyott parancsmagokkal kapcsolatos további információkért lásd: Parancsmagok parancsmagnevei.
A parancsmag .NET-osztályának a System.Management.Automation.PSCmdlet alaposztályból kell származtatva lennie, mivel biztosítja a Windows PowerShell-Windows PowerShell-futtatás számára az Windows PowerShell-szolgáltatói infrastruktúra elérhetővé Windows PowerShell támogatását. Vegye figyelembe, hogy ez a parancsmag a reguláris .NET-keretrendszer osztályokat is használja, például System.Text.Regularexpressions.Regex.
A következő kód a parancsmag osztálydefiníciója Select-Str parancsmaghoz.
[Cmdlet(VerbsCommon.Select, "Str", DefaultParameterSetName="PatternParameterSet")]
public class SelectStringCommand : PSCmdlet
Ez a parancsmag egy alapértelmezett paraméterkészletet határoz meg úgy, hogy hozzáadja az DefaultParameterSetName
attribútum kulcsszót az osztálydeklarációhoz. Ha a paraméter nincs megadva, a rendszer az PatternParameterSet
alapértelmezett Script
paraméterkészletet használja. További információt erről a paraméterkészletről a következő szakaszban, a és a paraméter Pattern
Script
vitafórumában láthat.
Adatelérési paraméterek meghatározása
Ez a parancsmag számos olyan paramétert határoz meg, amelyek lehetővé teszik a felhasználó számára a tárolt adatokhoz való hozzáférést és vizsgálatokat. Ezek a paraméterek tartalmaznak egy paramétert, amely jelzi az adattár helyét, egy paramétert, amely meghatározza a keresésben használni szükséges mintát, valamint számos más paramétert, amely támogatja Path
a Pattern
keresések hajtható végre.
Megjegyzés
További információ a paraméterek meghatározásának alapjairól: Paraméterek hozzáadása parancssori bemenet feldolgozásához.
A Path paraméter deklarása
Az adattár megtalálásához a parancsmagnak egy Windows PowerShell elérési utat kell használnia az adattár eléréséhez tervezett Windows PowerShell-szolgáltató azonosításához. Ezért meghatároz egy sztringtömb típusú paramétert, amely Path
jelzi a szolgáltató helyét.
[Parameter(
Position = 0,
ParameterSetName = "ScriptParameterSet",
Mandatory = true)]
[Parameter(
Position = 0,
ParameterSetName = "PatternParameterSet",
ValueFromPipeline = true,
Mandatory = true)]
[Alias("PSPath")]
public string[] Path
{
get { return paths; }
set { paths = value; }
}
private string[] paths;
Vegye figyelembe, hogy ez a paraméter két különböző paraméterkészlethez tartozik, és rendelkezik aliasokkal.
Két System.Management.Automation.Parameterattribute attribútum deklarálja, hogy a paraméter a és a Path
ScriptParameterSet
attribútumhoz PatternParameterSet
tartozik. A paraméterkészletekkel kapcsolatos további információkért lásd: Adding Parameter Sets to a Cmdlet (Paraméterkészletek hozzáadása parancsmaghoz).
A System.Management.Automation.Aliasattribute attribútum deklarál egy aliast a PSPath
Path
paraméterhez. Az alias deklarált használata erősen ajánlott, hogy konzisztens legyen más, a Windows PowerShell parancsmagokkal. AWindows PowerShell-útvonalakkal kapcsolatos további információkért lásd a PowerShell elérésiút-fogalmakat a How Windows PowerShell Works (A PowerShell elérésiút-fogalmai) Windows PowerShell.
A mintaparaméter deklarása
A kereshető minták megadásához ez a parancsmag egy sztringek tömbjeként megadott Pattern
paramétert deklarál. Pozitív eredményt ad vissza, ha a minták bármelyike megtalálható az adattárban. Vegye figyelembe, hogy ezek a minták lefordított reguláris kifejezések tömbjén vagy literális keresések helyettesítő karakteres mintái tömbjén fordíthatóak le.
[Parameter(
Position = 1,
ParameterSetName = "PatternParameterSet",
Mandatory = true)]
public string[] Pattern
{
get { return patterns; }
set { patterns = value; }
}
private string[] patterns;
private Regex[] regexPattern;
private WildcardPattern[] wildcardPattern;
Ha ez a paraméter meg van adva, a parancsmag az alapértelmezett paraméterkészletet PatternParameterSet
használja. Ebben az esetben a parancsmag az itt megadott mintákat használja a sztringek kiválasztásához. Ezzel szemben a paraméter is használható a mintákat tartalmazó Script
szkriptek biztosítanak. A Script
és paraméterek két külön Pattern
paraméterkészletet határoznak meg, így kölcsönösen kizárják egymást.
Keresési támogatási paraméterek deklarása
Ez a parancsmag a következő támogatási paramétereket határozza meg, amelyek a parancsmag keresési képességeinek módosítására használhatók.
A paraméter megad egy szkriptblokkot, amely egy alternatív keresési mechanizmust biztosít Script
a parancsmaghoz. A szkriptnek tartalmaznia kell az egyeztetéshez használt mintákat, és vissza kell adnunk egy System.Management.Automation.PSObject objektumot. Vegye figyelembe, hogy ez a paraméter az egyedi paraméter is, amely azonosítja ScriptParameterSet
a paraméterkészletet. Amikor a Windows PowerShell látja ezt a paramétert, csak a paraméterkészlethez tartozó ScriptParameterSet
paramétereket használja.
[Parameter(
Position = 1,
ParameterSetName = "ScriptParameterSet",
Mandatory = true)]
public ScriptBlock Script
{
set { script = value; }
get { return script; }
}
ScriptBlock script;
A paraméter egy kapcsolóparaméter, amely azt jelzi, hogy a parancsmagnak pontosan meg kell-e egyeznie a megadott SimpleMatch
mintákkal. Amikor a felhasználó megadja a paramétert a parancssorban ( ), a parancsmag a megadott true
mintákat használja. Ha a paraméter nincs megadva ( ), a false
parancsmag reguláris kifejezéseket használ. A paraméter alapértelmezett értéke false
.
[Parameter]
public SwitchParameter SimpleMatch
{
get { return simpleMatch; }
set { simpleMatch = value; }
}
private bool simpleMatch;
A paraméter egy kapcsolóparaméter, amely azt jelzi, hogy CaseSensitive
a kis- és nagybetűket megkülönböztető keresés történik-e. Amikor a felhasználó megadja a paramétert a parancssorban ( ), a parancsmag kis- és nagybetűs karaktereket keres a true
minták összehasonlíthatóságakor. Ha a paraméter nincs megadva ( ), a parancsmag nem tesz különbséget false
a kis- és nagybetűk között. Például a "MyFile" és a "myfile" is pozitív találatként lenne visszaadva. A paraméter alapértelmezett értéke false
.
[Parameter]
public SwitchParameter CaseSensitive
{
get { return caseSensitive; }
set { caseSensitive = value; }
}
private bool caseSensitive;
A és a paraméter azonosítja azokat az elemeket, amelyek kifejezetten ki vannak zárva a keresésből, vagy Exclude
Include
amelyek szerepelnek a keresésben. Alapértelmezés szerint a parancsmag az adattár összes elemében keres. A parancsmag által végzett keresés korlátozására azonban ezek a paraméterek használhatók a keresésbe foglalni vagy kihagyni szükséges elemek explicit jelzésére.
[Parameter]
public SwitchParameter CaseSensitive
{
get { return caseSensitive; }
set { caseSensitive = value; }
}
private bool caseSensitive;
[Parameter]
[ValidateNotNullOrEmpty]
public string[] Include
{
get
{
return includeStrings;
}
set
{
includeStrings = value;
this.include = new WildcardPattern[includeStrings.Length];
for (int i = 0; i < includeStrings.Length; i++)
{
this.include[i] = new WildcardPattern(includeStrings[i], WildcardOptions.IgnoreCase);
}
}
}
internal string[] includeStrings = null;
internal WildcardPattern[] include = null;
Paraméterkészletek deklarása
Ez a parancsmag két paraméterkészletet használ ( és , amely az alapértelmezett beállítás) az adatelérésben használt két ScriptParameterSet
PatternParameterSet
paraméterkészlet neveként. PatternParameterSet
A az alapértelmezett paraméterkészlet, és a paraméter megadásakor Pattern
lesz használva. ScriptParameterSet
Akkor használatos, ha a felhasználó alternatív keresési mechanizmust ad meg a Script
paraméterrel. A paraméterkészletekkel kapcsolatos további információkért lásd: Adding Parameter Sets to a Cmdlet (Paraméterkészletek hozzáadása parancsmaghoz).
A bemeneti feldolgozási módszerek felülbírálása
A parancsmagok a System.Management.Automation.PSCmdlet osztály egy vagy több bemeneti feldolgozási metódusát felül kell bírálni. A bemeneti feldolgozási metódusokkal kapcsolatos további információkért lásd: Creating Your First Cmdlet (Az első parancsmag létrehozása).
Ez a parancsmag felülírja a System.Management.Automation.Cmdlet.BeginProcessing metódust, hogy lefordított reguláris kifejezések tömbje indításakor létre legyen hozva. Ez növeli a teljesítményt olyan keresések során, amelyek nem egyszerű egyeztetést használnak.
protected override void BeginProcessing()
{
WriteDebug("Validating patterns.");
if (patterns != null)
{
foreach(string pattern in patterns)
{
if (pattern == null)
ThrowTerminatingError(new ErrorRecord(
new ArgumentNullException(
"Search pattern cannot be null."),
"NullSearchPattern",
ErrorCategory.InvalidArgument,
pattern)
);
}
WriteVerbose("Search pattern(s) are valid.");
// If a simple match is not specified, then
// compile the regular expressions once.
if (!simpleMatch)
{
WriteDebug("Compiling search regular expressions.");
RegexOptions regexOptions = RegexOptions.Compiled;
if (!caseSensitive)
regexOptions |= RegexOptions.Compiled;
regexPattern = new Regex[patterns.Length];
for (int i = 0; i < patterns.Length; i++)
{
try
{
regexPattern[i] = new Regex(patterns[i], regexOptions);
}
catch (ArgumentException ex)
{
ThrowTerminatingError(new ErrorRecord(
ex,
"InvalidRegularExpression",
ErrorCategory.InvalidArgument,
patterns[i]
));
}
} //Loop through patterns to create RegEx objects.
WriteVerbose("Pattern(s) compiled into regular expressions.");
}// If not a simple match.
// If a simple match is specified, then compile the
// wildcard patterns once.
else
{
WriteDebug("Compiling search wildcards.");
WildcardOptions wildcardOptions = WildcardOptions.Compiled;
if (!caseSensitive)
{
wildcardOptions |= WildcardOptions.IgnoreCase;
}
wildcardPattern = new WildcardPattern[patterns.Length];
for (int i = 0; i < patterns.Length; i++)
{
wildcardPattern[i] =
new WildcardPattern(patterns[i], wildcardOptions);
}
WriteVerbose("Pattern(s) compiled into wildcard expressions.");
}// If match is a simple match.
}// If valid patterns are available.
}// End of function BeginProcessing().
Ez a parancsmag felülbírálja a System.Management.Automation.Cmdlet.ProcessRecord metódust is a felhasználó által a parancssorban kiválasztott sztringek feldolgozásához. Egyéni objektum formájában írja a sztringkiválasztás eredményeit egy privát MatchString metódus hívásával.
protected override void ProcessRecord()
{
UInt64 lineNumber = 0;
MatchInfo result;
ArrayList nonMatches = new ArrayList();
// Walk the list of paths and search the contents for
// any of the specified patterns.
foreach (string psPath in paths)
{
// Once the filepaths are expanded, we may have more than one
// path, so process all referenced paths.
foreach(PathInfo path in
SessionState.Path.GetResolvedPSPathFromPSPath(psPath)
)
{
WriteVerbose("Processing path " + path.Path);
// Check if the path represents one of the items to be
// excluded. If so, continue to next path.
if (!MeetsIncludeExcludeCriteria(path.ProviderPath))
continue;
// Get the content reader for the item(s) at the
// specified path.
Collection<IContentReader> readerCollection = null;
try
{
readerCollection =
this.InvokeProvider.Content.GetReader(path.Path);
}
catch (PSNotSupportedException ex)
{
WriteError(new ErrorRecord(ex,
"ContentAccessNotSupported",
ErrorCategory.NotImplemented,
path.Path)
);
return;
}
foreach(IContentReader reader in readerCollection)
{
// Reset the line number for this path.
lineNumber = 0;
// Read in a single block (line in case of a file)
// from the object.
IList items = reader.Read(1);
// Read and process one block(line) at a time until
// no more blocks(lines) exist.
while (items != null && items.Count == 1)
{
// Increment the line number each time a line is
// processed.
lineNumber++;
String message = String.Format("Testing line {0} : {1}",
lineNumber, items[0]);
WriteDebug(message);
result = SelectString(items[0]);
if (result != null)
{
result.Path = path.Path;
result.LineNumber = lineNumber;
WriteObject(result);
}
else
{
// Add the block(line) that did not match to the
// collection of non matches , which will be stored
// in the SessionState variable $NonMatches
nonMatches.Add(items[0]);
}
// Get the next line from the object.
items = reader.Read(1);
}// While loop for reading one line at a time.
}// Foreach loop for reader collection.
}// Foreach loop for processing referenced paths.
}// Foreach loop for walking of path list.
// Store the list of non-matches in the
// session state variable $NonMatches.
try
{
this.SessionState.PSVariable.Set("NonMatches", nonMatches);
}
catch (SessionStateUnauthorizedAccessException ex)
{
WriteError(new ErrorRecord(ex,
"CannotWriteVariableNonMatches",
ErrorCategory.InvalidOperation,
nonMatches)
);
}
}// End of protected override void ProcessRecord().
Tartalom elérése
A parancsmagnak meg kell nyitnia a Windows PowerShell által jelzett szolgáltatót, hogy hozzáfér az adatokhoz. A rendszer a runspace System.Management.Automation.Sessionstate objektumát használja a szolgáltatóhoz való hozzáféréshez, a parancsmag System.Management.Automation.PSCmdlet.Invokeprovider* tulajdonsága pedig a szolgáltató megnyitásához. A tartalomhoz való hozzáférést a megnyitott szolgáltató System.Management.Automation.Providerintrinsics objektumának lekérése biztosítja.
Ez a Select-Str parancsmag a System.Management.Automation.Providerintrinsics.Content* tulajdonság segítségével teszi elérhetővé a vizsgálható tartalmat. Ezután meg tudja hívni a System.Management.Automation.Contentcmdletproviderintrinsics.Getreader* metódust, és át tudja adni a Windows PowerShell elérési útját.
Kódminta
Az alábbi kód a parancsmag ezen verziójának megvalósítását Select-Str be. Vegye figyelembe, hogy ez a kód tartalmazza a parancsmag osztályát, a parancsmag által használt privát metódusokat, valamint a Windows PowerShell regisztráláshoz használt beépülő modul kódját. További információ a parancsmag regisztrálásról: Building the Cmdlet.
//
// Copyright (c) 2006 Microsoft Corporation. All rights reserved.
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
using System;
using System.Text.RegularExpressions;
using System.Collections;
using System.Collections.ObjectModel;
using System.Management.Automation;
using System.Management.Automation.Provider;
using System.ComponentModel;
namespace Microsoft.Samples.PowerShell.Commands
{
#region SelectStringCommand
/// <summary>
/// This cmdlet searches through PSObjects for particular patterns.
/// </summary>
/// <remarks>
/// This cmdlet can be used to search any object, such as a file or a
/// variable, whose provider exposes methods for reading and writing
/// content.
/// </remarks>
[Cmdlet(VerbsCommon.Select, "Str", DefaultParameterSetName="PatternParameterSet")]
public class SelectStringCommand : PSCmdlet
{
#region Parameters
/// <summary>
/// Declare a Path parameter that specifies where the data is stored.
/// This parameter must specify a PowerShell that indicates the
/// PowerShell provider that is used to access the objects to be
/// searched for matching patterns. This parameter should also have
/// a PSPath alias to provide consistency with other cmdlets that use
/// PowerShell providers.
/// </summary>
/// <value>Path of the object(s) to search.</value>
[Parameter(
Position = 0,
ParameterSetName = "ScriptParameterSet",
Mandatory = true)]
[Parameter(
Position = 0,
ParameterSetName = "PatternParameterSet",
ValueFromPipeline = true,
Mandatory = true)]
[Alias("PSPath")]
public string[] Path
{
get { return paths; }
set { paths = value; }
}
private string[] paths;
/// <summary>
/// Declare a Pattern parameter that specifies the pattern(s)
/// used to find matching patterns in the string representation
/// of the objects. A positive result will be returned
/// if any of the patterns are found in the objects.
/// </summary>
/// <remarks>
/// The patterns will be compiled into an array of wildcard
/// patterns for a simple match (literal string matching),
/// or the patterns will be converted into an array of compiled
/// regular expressions.
/// </remarks>
/// <value>Array of patterns to search.</value>
[Parameter(
Position = 1,
ParameterSetName = "PatternParameterSet",
Mandatory = true)]
public string[] Pattern
{
get { return patterns; }
set { patterns = value; }
}
private string[] patterns;
private Regex[] regexPattern;
private WildcardPattern[] wildcardPattern;
/// <summary>
/// Declare a Script parameter that specifies a script block
/// that is called to perform the matching operations
/// instead of the matching performed by the cmdlet.
/// </summary>
/// <value>Script block that will be called for matching</value>
[Parameter(
Position = 1,
ParameterSetName = "ScriptParameterSet",
Mandatory = true)]
public ScriptBlock Script
{
set { script = value; }
get { return script; }
}
ScriptBlock script;
/// <summary>
/// Declare a switch parameter that specifies if the pattern(s) are used
/// literally. If not (default), searching is
/// done using regular expressions.
/// </summary>
/// <value>If True, a literal pattern is used.</value>
[Parameter]
public SwitchParameter SimpleMatch
{
get { return simpleMatch; }
set { simpleMatch = value; }
}
private bool simpleMatch;
/// <summary>
/// Declare a switch parameter that specifies if a case-sensitive
/// search is performed. If not (default), a case-insensitive search
/// is performed.
/// </summary>
/// <value>If True, a case-sensitive search is made.</value>
[Parameter]
public SwitchParameter CaseSensitive
{
get { return caseSensitive; }
set { caseSensitive = value; }
}
private bool caseSensitive;
/// <summary>
/// Declare an Include parameter that species which
/// specific items are searched. When this parameter
/// is used, items that are not listed here are omitted
/// from the search.
/// </summary>
[Parameter]
[ValidateNotNullOrEmpty]
public string[] Include
{
get
{
return includeStrings;
}
set
{
includeStrings = value;
this.include = new WildcardPattern[includeStrings.Length];
for (int i = 0; i < includeStrings.Length; i++)
{
this.include[i] = new WildcardPattern(includeStrings[i], WildcardOptions.IgnoreCase);
}
}
}
internal string[] includeStrings = null;
internal WildcardPattern[] include = null;
/// <summary>
/// Declare an Exclude parameter that species which
/// specific items are omitted from the search.
/// </summary>
///
[Parameter]
[ValidateNotNullOrEmpty]
public string[] Exclude
{
get
{
return excludeStrings;
}
set
{
excludeStrings = value;
this.exclude = new WildcardPattern[excludeStrings.Length];
for (int i = 0; i < excludeStrings.Length; i++)
{
this.exclude[i] = new WildcardPattern(excludeStrings[i], WildcardOptions.IgnoreCase);
}
}
}
internal string[] excludeStrings;
internal WildcardPattern[] exclude;
#endregion Parameters
#region Overrides
/// <summary>
/// If regular expressions are used for pattern matching,
/// then build an array of compiled regular expressions
/// at startup. This increases performance during scanning
/// operations when simple matching is not used.
/// </summary>
protected override void BeginProcessing()
{
WriteDebug("Validating patterns.");
if (patterns != null)
{
foreach(string pattern in patterns)
{
if (pattern == null)
ThrowTerminatingError(new ErrorRecord(
new ArgumentNullException(
"Search pattern cannot be null."),
"NullSearchPattern",
ErrorCategory.InvalidArgument,
pattern)
);
}
WriteVerbose("Search pattern(s) are valid.");
// If a simple match is not specified, then
// compile the regular expressions once.
if (!simpleMatch)
{
WriteDebug("Compiling search regular expressions.");
RegexOptions regexOptions = RegexOptions.Compiled;
if (!caseSensitive)
regexOptions |= RegexOptions.Compiled;
regexPattern = new Regex[patterns.Length];
for (int i = 0; i < patterns.Length; i++)
{
try
{
regexPattern[i] = new Regex(patterns[i], regexOptions);
}
catch (ArgumentException ex)
{
ThrowTerminatingError(new ErrorRecord(
ex,
"InvalidRegularExpression",
ErrorCategory.InvalidArgument,
patterns[i]
));
}
} //Loop through patterns to create RegEx objects.
WriteVerbose("Pattern(s) compiled into regular expressions.");
}// If not a simple match.
// If a simple match is specified, then compile the
// wildcard patterns once.
else
{
WriteDebug("Compiling search wildcards.");
WildcardOptions wildcardOptions = WildcardOptions.Compiled;
if (!caseSensitive)
{
wildcardOptions |= WildcardOptions.IgnoreCase;
}
wildcardPattern = new WildcardPattern[patterns.Length];
for (int i = 0; i < patterns.Length; i++)
{
wildcardPattern[i] =
new WildcardPattern(patterns[i], wildcardOptions);
}
WriteVerbose("Pattern(s) compiled into wildcard expressions.");
}// If match is a simple match.
}// If valid patterns are available.
}// End of function BeginProcessing().
/// <summary>
/// Process the input and search for the specified patterns.
/// </summary>
protected override void ProcessRecord()
{
UInt64 lineNumber = 0;
MatchInfo result;
ArrayList nonMatches = new ArrayList();
// Walk the list of paths and search the contents for
// any of the specified patterns.
foreach (string psPath in paths)
{
// Once the filepaths are expanded, we may have more than one
// path, so process all referenced paths.
foreach(PathInfo path in
SessionState.Path.GetResolvedPSPathFromPSPath(psPath)
)
{
WriteVerbose("Processing path " + path.Path);
// Check if the path represents one of the items to be
// excluded. If so, continue to next path.
if (!MeetsIncludeExcludeCriteria(path.ProviderPath))
continue;
// Get the content reader for the item(s) at the
// specified path.
Collection<IContentReader> readerCollection = null;
try
{
readerCollection =
this.InvokeProvider.Content.GetReader(path.Path);
}
catch (PSNotSupportedException ex)
{
WriteError(new ErrorRecord(ex,
"ContentAccessNotSupported",
ErrorCategory.NotImplemented,
path.Path)
);
return;
}
foreach(IContentReader reader in readerCollection)
{
// Reset the line number for this path.
lineNumber = 0;
// Read in a single block (line in case of a file)
// from the object.
IList items = reader.Read(1);
// Read and process one block(line) at a time until
// no more blocks(lines) exist.
while (items != null && items.Count == 1)
{
// Increment the line number each time a line is
// processed.
lineNumber++;
String message = String.Format("Testing line {0} : {1}",
lineNumber, items[0]);
WriteDebug(message);
result = SelectString(items[0]);
if (result != null)
{
result.Path = path.Path;
result.LineNumber = lineNumber;
WriteObject(result);
}
else
{
// Add the block(line) that did not match to the
// collection of non matches , which will be stored
// in the SessionState variable $NonMatches
nonMatches.Add(items[0]);
}
// Get the next line from the object.
items = reader.Read(1);
}// While loop for reading one line at a time.
}// Foreach loop for reader collection.
}// Foreach loop for processing referenced paths.
}// Foreach loop for walking of path list.
// Store the list of non-matches in the
// session state variable $NonMatches.
try
{
this.SessionState.PSVariable.Set("NonMatches", nonMatches);
}
catch (SessionStateUnauthorizedAccessException ex)
{
WriteError(new ErrorRecord(ex,
"CannotWriteVariableNonMatches",
ErrorCategory.InvalidOperation,
nonMatches)
);
}
}// End of protected override void ProcessRecord().
#endregion Overrides
#region PrivateMethods
/// <summary>
/// Check for a match using the input string and the pattern(s)
/// specified.
/// </summary>
/// <param name="input">The string to test.</param>
/// <returns>MatchInfo object containing information about
/// result of a match</returns>
private MatchInfo SelectString(object input)
{
string line = null;
try
{
// Convert the object to a string type
// safely using language support methods
line = (string)LanguagePrimitives.ConvertTo(
input,
typeof(string)
);
line = line.Trim(' ','\t');
}
catch (PSInvalidCastException ex)
{
WriteError(new ErrorRecord(
ex,
"CannotCastObjectToString",
ErrorCategory.InvalidOperation,
input)
);
return null;
}
MatchInfo result = null;
// If a scriptblock has been specified, call it
// with the path for processing. It will return
// one object.
if (script != null)
{
WriteDebug("Executing script block.");
Collection<PSObject> psObjects =
script.Invoke(
line,
simpleMatch,
caseSensitive
);
foreach (PSObject psObject in psObjects)
{
if (LanguagePrimitives.IsTrue(psObject))
{
result = new MatchInfo();
result.Line = line;
result.IgnoreCase = !caseSensitive;
break;
} //End of If.
} //End ForEach loop.
} // End of If if script exists.
// If script block exists, see if this line matches any
// of the match patterns.
else
{
int patternIndex = 0;
while (patternIndex < patterns.Length)
{
if ((simpleMatch &&
wildcardPattern[patternIndex].IsMatch(line))
|| (regexPattern != null
&& regexPattern[patternIndex].IsMatch(line))
)
{
result = new MatchInfo();
result.IgnoreCase = !caseSensitive;
result.Line = line;
result.Pattern = patterns[patternIndex];
break;
}
patternIndex++;
}// While loop through patterns.
}// Else for no script block specified.
return result;
}// End of SelectString
/// <summary>
/// Check whether the supplied name meets the include/exclude criteria.
/// That is - it's on the include list if the include list was
/// specified, and not on the exclude list if the exclude list was specified.
/// </summary>
/// <param name="path">path to validate</param>
/// <returns>True if the path is acceptable.</returns>
private bool MeetsIncludeExcludeCriteria(string path)
{
bool ok = false;
// See if the file is on the include list.
if (this.include != null)
{
foreach (WildcardPattern patternItem in this.include)
{
if (patternItem.IsMatch(path))
{
ok = true;
break;
}
}
}
else
{
ok = true;
}
if (!ok)
return false;
// See if the file is on the exclude list.
if (this.exclude != null)
{
foreach (WildcardPattern patternItem in this.exclude)
{
if (patternItem.IsMatch(path))
{
ok = false;
break;
}
}
}
return ok;
} //MeetsIncludeExcludeCriteria
#endregion Private Methods
}// class SelectStringCommand
#endregion SelectStringCommand
#region MatchInfo
/// <summary>
/// Class representing the result of a pattern/literal match
/// that is passed through the pipeline by the Select-Str cmdlet.
/// </summary>
public class MatchInfo
{
/// <summary>
/// Indicates if the match was done ignoring case.
/// </summary>
/// <value>True if case was ignored.</value>
public bool IgnoreCase
{
get { return ignoreCase; }
set { ignoreCase = value; }
}
private bool ignoreCase;
/// <summary>
/// Specifies the number of the matching line.
/// </summary>
/// <value>The number of the matching line.</value>
public UInt64 LineNumber
{
get { return lineNumber; }
set { lineNumber = value; }
}
private UInt64 lineNumber;
/// <summary>
/// Specifies the text of the matching line.
/// </summary>
/// <value>The text of the matching line.</value>
public string Line
{
get { return line; }
set { line = value; }
}
private string line;
/// <summary>
/// Specifies the full path of the object(file) containing the
/// matching line.
/// </summary>
/// <remarks>
/// It will be "inputStream" if the object came from the input
/// stream.
/// </remarks>
/// <value>The path name</value>
public string Path
{
get { return path; }
set
{
pathSet = true;
path = value;
}
}
private string path;
private bool pathSet;
/// <summary>
/// Specifies the pattern that was used in the match.
/// </summary>
/// <value>The pattern string</value>
public string Pattern
{
get { return pattern; }
set { pattern = value; }
}
private string pattern;
private const string MatchFormat = "{0}:{1}:{2}";
/// <summary>
/// Returns the string representation of this object. The format
/// depends on whether a path has been set for this object or
/// not.
/// </summary>
/// <remarks>
/// If the path component is set, as would be the case when
/// matching in a file, ToString() returns the path, line
/// number and line text. If path is not set, then just the
/// line text is presented.
/// </remarks>
/// <returns>The string representation of the match object.</returns>
public override string ToString()
{
if (pathSet)
return String.Format(
System.Threading.Thread.CurrentThread.CurrentCulture,
MatchFormat,
this.path,
this.lineNumber,
this.line
);
else
return this.line;
}
}// End class MatchInfo
#endregion
#region PowerShell snap-in
/// <summary>
/// Create a PowerShell snap-in for the Select-Str cmdlet.
/// </summary>
[RunInstaller(true)]
public class SelectStringPSSnapIn : PSSnapIn
{
/// <summary>
/// Create an instance of the SelectStrPSSnapin class.
/// </summary>
public SelectStringPSSnapIn()
: base()
{
}
/// <summary>
/// Specify the name of the PowerShell snap-in.
/// </summary>
public override string Name
{
get
{
return "SelectStrPSSnapIn";
}
}
/// <summary>
/// Specify the vendor of the PowerShell snap-in.
/// </summary>
public override string Vendor
{
get
{
return "Microsoft";
}
}
/// <summary>
/// Specify the localization resource information for the vendor.
/// Use the format: SnapinName,VendorName.
/// </summary>
public override string VendorResource
{
get
{
return "SelectStrSnapIn,Microsoft";
}
}
/// <summary>
/// Specify the description of the PowerShell snap-in.
/// </summary>
public override string Description
{
get
{
return "This is a PowerShell snap-in for the Select-Str cmdlet.";
}
}
/// <summary>
/// Specify the localization resource information for the description.
/// Use the format: SnapinName,Description.
/// </summary>
public override string DescriptionResource
{
get
{
return "SelectStrSnapIn,This is a PowerShell snap-in for the Select-Str cmdlet.";
}
}
}
#endregion PowerShell snap-in
} //namespace Microsoft.Samples.PowerShell.Commands;
A parancsmag kiépítése
A parancsmagok megvalósítása után regisztrálnia kell azt a Windows PowerShell egy Windows PowerShell beépülő modulon keresztül. További információ a parancsmagok regisztrálásról: How to Register Cmdlets, Providers, and Host Applications (Parancsmagok, szolgáltatók és gazdaalkalmazások regisztrálása).
A parancsmag tesztelése
Miután regisztrálta a parancsmagot a Windows PowerShell, a parancssorban futtatva tesztelheti. Az alábbi eljárással tesztelheti a Select-Str parancsmagot.
Indítsa Windows PowerShell, majd keresse meg a Notes fájlban a ".NET" kifejezéssel kiegészítve a sorok előfordulásait. Vegye figyelembe, hogy az elérési út neve körüli idézőjelek csak akkor szükségesek, ha az elérési út egynél több szóból áll.
select-str -Path "notes" -Pattern ".NET" -SimpleMatch=$false
Az alábbi kimenet jelenik meg.
IgnoreCase : True LineNumber : 8 Line : Because Windows PowerShell works directly with .NET objects, there is often a .NET object Path : C:\PowerShell-Progs\workspace\Samples\SelectStr\notes Pattern : .NET IgnoreCase : True LineNumber : 21 Line : You should normally define the class for a cmdlet in a .NET namespace Path : C:\PowerShell-Progs\workspace\Samples\SelectStr\notes Pattern : .NET
A Notes fájlban keressen sorokat az "over" szóval, majd bármely más szöveggel együtt. A
SimpleMatch
paraméter az alapértelmezett értéketfalse
használja. A keresés nemérzékeny, mert a paraméter értékeCaseSensitive
false
.select-str -Path notes -Pattern "over*" -SimpleMatch -CaseSensitive:$false
Az alábbi kimenet jelenik meg.
IgnoreCase : True LineNumber : 45 Line : Override StopProcessing Path : C:\PowerShell-Progs\workspace\Samples\SelectStr\notes Pattern : over* IgnoreCase : True LineNumber : 49 Line : overriding the StopProcessing method Path : C:\PowerShell-Progs\workspace\Samples\SelectStr\notes Pattern : over*
Keressen a Notes fájlban egy reguláris kifejezés mintájaként. A parancsmag betűrendbe szedett karaktereket és zárójelek közötti üres szóközöket keres.
select-str -Path notes -Pattern "\([A-Za-z:blank:]" -SimpleMatch:$false
Az alábbi kimenet jelenik meg.
IgnoreCase : True LineNumber : 1 Line : Advisory Guidelines (Consider Following) Path : C:\PowerShell-Progs\workspace\Samples\SelectStr\notes Pattern : \([A-Za-z:blank:] IgnoreCase : True LineNumber : 53 Line : If your cmdlet has objects that are not disposed of (written to the pipeline) Path : C:\PowerShell-Progs\workspace\Samples\SelectStr\notes Pattern : \([A-Za-z:blank:]
Végezzen megkülönbözteti a kis- és nagybetűket a Notes fájlban, és keressen rá a "Parameter" szó előfordulásaira.
select-str -Path notes -Pattern Parameter -CaseSensitive
Az alábbi kimenet jelenik meg.
IgnoreCase : False LineNumber : 6 Line : Support an InputObject Parameter Path : C:\PowerShell-Progs\workspace\Samples\SelectStr\notes Pattern : Parameter IgnoreCase : False LineNumber : 30 Line : Support Force Parameter Path : C:\PowerShell-Progs\workspace\Samples\SelectStr\notes Pattern : Parameter
Keresse meg a változókhoz Windows PowerShell változókat, amelyek 0 és 9 között numerikus értékeket tartalmaznak.
select-str -Path * -Pattern "[0-9]"
Az alábbi kimenet jelenik meg.
IgnoreCase : True LineNumber : 1 Line : 64 Path : Variable:\MaximumHistoryCount Pattern : [0-9]
Egy szkriptblokk használatával keressen a SelectStrCommandSample.cs fájlban a "Pos" sztringre. A szkript cmatch függvénye a kis- és a nagy- és a kis- és a nagy- és a nagy- és a kis- és a nagy- és kis- és a nagy
select-str -Path "SelectStrCommandSample.cs" -Script { if ($args[0] -cmatch "Pos"){ return $true } return $false }
Az alábbi kimenet jelenik meg.
IgnoreCase : True LineNumber : 37 Line : Position = 0. Path : C:\PowerShell-Progs\workspace\Samples\SelectStr\SelectStrCommandSample.cs Pattern :
Lásd még:
Új parancsmag Windows PowerShell létrehozása
Az első parancsmag létrehozása
Rendszermódosító parancsmag létrehozása
Saját Windows PowerShell megtervezése
Az Windows PowerShell működése
Parancsmagok, szolgáltatók és gazdaalkalmazások regisztrálása