wrote this small part of code to check if file exist and contains string pattern
try {
$SEL = Select-String -Path \\$serversPing\c$\Scripts\compare_result.txt -Pattern "no differences encountered" -ErrorAction SilentlyCOntinue
}catch{
$ErrorMessage = $_.Exception.Message
$FailedItem = $_.Exception.ItemName
}
Finally {
if ($SEL | Test-Path -ErrorAction SilentlyContinue){
#write-host $serversPing $SEL.Pattern
#write-host $serversPing $SEL
if ($SEL.Pattern -eq "no differences encountered")
{
$SoftCheckResult = "ok"
}
else
{
$SoftCheckResult ="Verify"
}
}
else{
$SoftCheckResult = "NotInScope"
}
}
But, it does not do what it should. First of all it partially recognize that path exist and secondly it does partially recognize pattern in txt file. Can you please help me?
I suspect that PATTER is partially recognizable on multiply server.(whitepaces etc) even so how to skip that?
Strange think is that it does not see that pattern is missing in file, it return
NotinScope instead Verify
Below file without this pattern
And below you can see normal pattern
Since you use plural in $serversPing, I suspect this variable comes from an earlier part of your code and contains a COLLECTION of servers.
I would change the order of checks and start with a test to see if the file exists on that server or not:
# As you mentioned a possible whitespace problem the pattern below uses regex `\s+` so multiple whitespace characters are allowed betwen the words.
$pattern = "no\s+differences\s+encountered"
foreach ($server in $serversPing) {
if (Test-Connection $server -Count 1 -Quiet) {
$filePath = Join-Path -Path "\\$server" -ChildPath 'c$\Scripts\compare_result.txt'
if (Test-Path $filePath -PathType Leaf) {
# -Quiet: Indicates that the cmdlet returns a Boolean value (True or False), instead of a MatchInfo object.
# The value is True if the pattern is found; otherwise, the value is False.
if (Select-String -Path $filePath -Pattern $pattern -Quiet) {
Write-Host "Pattern '$pattern' found in '$filePath'"
$SoftCheckResult = "ok"
}
else {
Write-Host "Pattern '$pattern' not found in '$filePath'"
$SoftCheckResult = "Verify"
}
}
else {
Write-Host "File '$filePath' not found"
$SoftCheckResult ="NotInScope"
}
}
else {
Write-Host "Server '$server' is off-line."
$SoftCheckResult ="OffLine"
}
}
I added a Test-Connection in the foreach loop to first see if the server is online or not. If you have checked that before and the $serversPing variable contains only servers that are online and reachable, you may skip that.
Concerning the -Path of the Select-String cmdlet, you should put the value between "" :
$SEL = Select-String -Path "\\$serversPing\c$\Scripts\compare_result.txt" -Pattern "no differences encountered" -ErrorAction SilentlyCOntinue
EDIT
This should do the trick :
try {
$SEL = Select-String -Path \\$serversPing\c$\Scripts\compare_result.txt -Pattern "no differences encountered" -ErrorAction SilentlyCOntinue
}catch{
$ErrorMessage = $_.Exception.Message
$FailedItem = $_.Exception.ItemName
}
Finally {
if ($SEL){
$SoftCheckResult = "ok"
}
else
{
$SoftCheckResult ="Verify"
}
}
try
{
$SEL = $null
$SEL = Select-String -Path \\$serversPing\c$\Scripts\compare_result.txt -Pattern "no differences encountered" -ErrorAction Stop
if ($SEL)
{
$SoftCheckResult = "ok"
}
else
{
$SoftCheckResult = "Verify"
}
}
catch
{
$ErrorMessage = $_.Exception.Message
$FailedItem = $_.Exception.ItemName
$SoftCheckResult = "NotInScope"
}
return $softCheckResult
Please try like below :
$SEL = "Fiile path location"
if ($SEL | Test-Path -ErrorAction SilentlyContinue){
if ($SEL Get-Content | Select-String -pattern "no differences encountered")
{
}
....
}
Related
I'm trying to add an image to an excel worksheet with powershell 5. and VSCode.
I get these errors:
C:\CC_SnapViews\EndToEnd_view\path is correct\file.bmp
does not exist (but it's there)
Multiple ambiguous overloads found for "AddPicture" and the argument
count: "2"
When I search the internet, this error isn't coming up in the search. I was following these examples:
addPicture
addPicture github
This is my code:
$xlsx = $result | Export-Excel -Path $outFilePath -WorksheetName $errCode -Autosize -AutoFilter -FreezeTopRow -BoldTopRow -PassThru # -ClearSheet can't ClearSheet every time or it clears previous data ###left off
$ws = $xlsx.Workbook.Worksheets[$errCode]
for ($row = 2 ;( $row -le $tempRowCount ); $row++)
{
#Write-Host $($ws.Dimension.Rows)
#Write-Host $($row)
$ws.Row($row).Height
$ws.Row($row).Height = 150
$ws.Row($row)[3]
$result.GetValue($row) #$ws.Row($row)[3]
$pictureName=$result[$row].PictureID
$pictureNamePath=$result[$row].ImageFileName
#place the image in spreadsheet
#https://github.com/dfinke/ImportExcel/issues/1041 https://github.com/dfinke/ImportExcel/issues/993
$drawingName = "$($pictureName)_Col3_$($row)" #Name_ColumnIndex_RowIndex
#Write-Host $image
Write-Host $drawingName
####
if($null -ne $pictureNamePath)
{
$image = Get-Image -imageFileName $pictureNamePath ###error pictureNamePath does not exist but it does
}
else
{
Write-Host "Did not find an image file for $pictureName in $pictureNamePath"
}
$picture = $ws.Drawings.AddPicture($pictureNamePath,$image) ###error message here
}
Any ideas why powershell thinks the image file doesn't exist?
Update:
I added some debug in the foreach for the rows:
for ($row = 2 ;( $row -le $tempRowCount ); $row++)
{
#Write-Host $($ws.Dimension.Rows)
#Write-Host $($row)
$ws.Row($row).Height
$ws.Row($row).Height = 150
$ws.Row($row)[3]
$result.GetValue($row) #prints entire row info
$pictureName=$result[$row].PictureID
$pictureNamePath=$result[$row].ImageFileName
if(Test-Path $pictureNamePath)
{
Write-Host "$($pictureNamePath) exists" ##prints ...filenamepath... exists (looks good)
}
Write-Host "pic path = $pictureNamePath" ##prints pic path = ..file name path... (looks good)
...
Update2:
Adding the Get-Image function:
Function Get-Image{
[cmdletbinding()]
Param ([string]$imageFileName)
Process
{
#find image file name to look for
if($imageFileName.Exists) #if($imageFile2.Exists)
{
[System.Drawing.Image] $image = [System.Drawing.Image]::FromFile($imageFileName) #may not need this step
#need to figure out which is correct if there's multiple images
return $image
}
else {
Write-Host "$($imageFileName) does not exist"
return $null
}
} #end Process
}# End of Function
I changed my function to use Test-Path instead and it sets the image now.
Function Get-Image{
[cmdletbinding()]
Param ([string]$imageFileName)
Process
{
#find image file name to look for
if(Test-Path $imageFileName) ###instead of Exists
{
[System.Drawing.Image] $image = [System.Drawing.Image]::FromFile($imageFileName) #may not need this step
#need to figure out which is correct if there's multiple images
return $image
}
else {
Write-Host "$($imageFileName) does not exist"
return $null
}
} #end Process
}# End of Function
So I have a powershell script that I wrote which crawls through a particular website and downloads all of the software hosted on the site to my local machine. The website in question is nirsoft.net, and I will include the full script below. Anyway, so I have this script that downloads all of the application files hosted on the website, when I notice something odd: while most of the file downloads completed successfully, there are several files that were not downloaded successfully, resulting in a corrupt file of 4KB:
For those of you who are familiar with Nirsoft's software, the tools are very powerful, but also constantly misidentified as dangerous because of the password cracking tools, so my guess as to why this is happening is that, since powershell's If I were to guess as to why this was happening, I would guess that, due to the fact that powershell's "Invoke-webrequest cmdlet" uses Internet Explorer's engine for its core functionality, Internet Explorer is flagging the files as dangerous and refusing to download them, thus causing powershell to fail to download the file. I confirmed this by trying to manually download each of the corrupt files using internet explorer, which marked them all as malicious. However, this is where things get strange. In order to bypass this limitation, I attempted a variety of other methods to download the file within my script, like using a pure dotnet object ( (New-object System.Net.WebClient).DownloadFile("url","file") ) and even some third party command line tools (wget for windows, wget in cygwin, etc), but no matter what I tried, not a single alternative method I used was able to download a non-corrupt file. So what I want to know is if there is a way around this, and I want to know why even third party tools are affected by this. Is there some kind of rule that any scripting tool has to use Internet Explorer's engine in order to connect to the internet or something? Thanks in advance. Oh, and one last thing before I post the script. Below is the url to one of the files that I am having difficulty in downloading via powershell, which you can use to run individual tests rather than the whole script:
enter link description here
And without further ado, here is the script. Thank again:
$VerbosePreference = "Continue"
$DebugPreference = "Continue"
$present = $true
$subdomain = $null
$prods = (Invoke-WebRequest "https://www.nirsoft.net/utils/index.html").links
Foreach ($thing in $prods)
{
If ($thing.Innertext -match "([A-Za-z]|\s)+v\d{1,3}\.\d{1,3}(.)*")
{
If ($thing.href.Contains("/"))
{
}
$page = Invoke-WebRequest "https://www.nirsoft.net/utils/$($thing.href)"
If ($thing.href -like "*dot_net_tools*")
{
$prodname = $thing.innerText.Trim().Split(" ")
}
Else
{
$prodname = $thing.href.Trim().Split(".")
}
$newlinks = $page.links | Where-Object {$_.Innertext -like "*Download*" -and ($_.href.endswith("zip") -or $_.href.endswith("exe"))}
# $page.ParsedHtml.title
#$newlinks.href
Foreach ($item in $newlinks)
{
$split = $item.href.Split("/")
If ($item.href -like "*toolsdownload*")
{
Try
{
Write-host "https://www.nirsoft.net$($item.href)"
Invoke-WebRequest "https://www.nirsoft.net$($item.href)" -OutFile "$env:DOWNLOAD\test\$($split[-1])" -ErrorAction Stop
}
Catch
{
Write-Host $thing.href -ForegroundColor Red
}
}
elseif ($item.href.StartsWith("http") -and $item.href.Contains(":"))
{
Try
{
Write-host "$($item.href)"
Invoke-WebRequest $item.href -OutFile "$env:DOWNLOAD\test\$($split[-1])" -ErrorAction Stop
}
Catch
{
Write-Host "$($item.href)" -ForegroundColor Red
}
}
Elseif ($thing.href -like "*/dot_net_tools*")
{
Try
{
Invoke-WebRequest "https://www.nirsoft.net/dot_net_tools/$($item.href)" -OutFile "$env:DOWNLOAD\test\$($split[-1])" -ErrorAction Stop
}
Catch
{
Write-Host $thing.href -ForegroundColor Red
}
}
Else
{
Try
{
Write-Host "https://www.nirsoft.net/utils/$($item.href)"
Invoke-WebRequest "https://www.nirsoft.net/utils/$($item.href)" -OutFile "$env:DOWNLOAD\test\$($item.href)" -ErrorAction Stop
}
Catch
{
Write-Host $thing.href -ForegroundColor Red
}
}
If ($item.href.Contains("/"))
{
If (!(Test-Path "$env:DOWNLOAD\test\$($split[-1])"))
{
$present = $false
}
}
Else
{
If (!(Test-Path "$env:DOWNLOAD\test\$($item.href)"))
{
$present = $false
}
}
}
}
}
If ($present)
{
Write-Host "All of the files were downloaded!!!" -ForegroundColor Green
}
Else
{
Write-Host "Not all of the files downloaded. Something went wrong." -ForegroundColor Red
}
You have two separate issues.
For anything Defender flags, it doesn't matter if you save it to disk with this or that. You could simply add an exclusion for the directory in Defender.
The other issue is pointed out by Guenther, you need to provide a referrer at least on some of the downloads. With the following changes I was able to download them all.
$VerbosePreference = "Continue"
$DebugPreference = "Continue"
$present = $true
$subdomain = $null
$path = c:\temp\downloadtest\
New-Item $path -ItemType Directory -ErrorAction SilentlyContinue | Out-Null
Add-MpPreference -ExclusionPath $path
$prods = (Invoke-WebRequest "https://www.nirsoft.net/utils/index.html").links
Foreach ($thing in $prods)
{
If ($thing.Innertext -match "([A-Za-z]|\s)+v\d{1,3}\.\d{1,3}(.)*")
{
If ($thing.href.Contains("/"))
{
}
$page = Invoke-WebRequest "https://www.nirsoft.net/utils/$($thing.href)"
If ($thing.href -like "*dot_net_tools*")
{
$prodname = $thing.innerText.Trim().Split(" ")
}
Else
{
$prodname = $thing.href.Trim().Split(".")
}
$newlinks = $page.links | Where-Object {$_.Innertext -like "*Download*" -and ($_.href.endswith("zip") -or $_.href.endswith("exe"))}
# $page.ParsedHtml.title
#$newlinks.href
Foreach ($item in $newlinks)
{
$split = $item.href.Split("/")
If ($item.href -like "*toolsdownload*")
{
Try
{
Write-host "https://www.nirsoft.net$($item.href)"
Invoke-WebRequest "https://www.nirsoft.net$($item.href)" -OutFile "$path\$($split[-1])" -ErrorAction Stop -Headers #{Referer="https://www.nirsoft.net$($item.href)"}
}
Catch
{
Write-Host $thing.href -ForegroundColor Red
}
}
elseif ($item.href.StartsWith("http") -and $item.href.Contains(":"))
{
Try
{
Write-host "$($item.href)"
Invoke-WebRequest $item.href -OutFile "$path\$($split[-1])" -ErrorAction Stop -Headers #{Referer="$($item.href)"}
}
Catch
{
Write-Host "$($item.href)" -ForegroundColor Red
}
}
Elseif ($thing.href -like "*/dot_net_tools*")
{
Try
{
Invoke-WebRequest "https://www.nirsoft.net/dot_net_tools/$($item.href)" -OutFile "$path\$($split[-1])" -ErrorAction Stop -Headers #{Referer="https://www.nirsoft.net/dot_net_tools/$($item.href)"}
}
Catch
{
Write-Host $thing.href -ForegroundColor Red
}
}
Else
{
Try
{
Write-Host "https://www.nirsoft.net/utils/$($item.href)"
Invoke-WebRequest "https://www.nirsoft.net/utils/$($item.href)" -OutFile "$path\$($item.href)" -ErrorAction Stop -Headers #{Referer="https://www.nirsoft.net/utils/$($item.href)"}
}
Catch
{
Write-Host $thing.href -ForegroundColor Red
}
}
If ($item.href.Contains("/"))
{
If (!(Test-Path "$path\$($split[-1])"))
{
$present = $false
}
}
Else
{
If (!(Test-Path "$path\$($item.href)"))
{
$present = $false
}
}
}
}
}
If ($present)
{
Write-Host "All of the files were downloaded!!!" -ForegroundColor Green
}
Else
{
Write-Host "Not all of the files downloaded. Something went wrong." -ForegroundColor Red
}
I'd also recommend you turn the download routine into a function that you can pass the relative URL portion so you don't have to repeat code several times.
I'm trying to make script to automaticly assign credidentials based on the group that was chose. I'm getting a lot of syntax errors. Can you help?
Function Add-OSCCredential
{
$target = Read-Host "Group number"
If($target)
{
If($target -eq 1)
{[string]$result = cmdkey /add:Group1 /user:Group1 /pass:Pass1}
[ElseIf($target -eq 2)
{[string]$result = cmdkey /add:Group2 /user:Group2 /pass:Pass2}]
{
[ElseIf($target -eq 3)
{[string]$result = cmdkey /add:Group3 /user:Group3 /pass:Pass3}]
{
If($result -match "The command line parameters are incorrect")
{Write-Error "Failed to add Windows Credential to Windows vault."}
ElseIf($result -match "CMDKEY: Credential added successfully")
{Write-Host "Credential added successfully."}
}
Else
{
Write-Error "Internet(network address) or username can not be empty,please try again."
Add-OSCCredential
}
}
Add-OSCCredential
I'd suggest you use a proper editor such as vscode which will give you lots of hints concerning bad syntax.
In your case there are a lot of [] and {} parenthesis that do not make sense.
Only considering the syntax of that function, the following should 'work':
Function Add-OSCCredential {
$target = Read-Host "Group number"
If ($target) {
If ($target -eq 1) {
[string]$result = cmdkey /add:Group1 /user:Group1 /pass:Pass1
}
ElseIf ($target -eq 2) {
[string]$result = cmdkey /add:Group2 /user:Group2 /pass:Pass2
}
ElseIf ($target -eq 3) {
[string]$result = cmdkey /add:Group3 /user:Group3 /pass:Pass3
}
If ($result -match "The command line parameters are incorrect") {
Write-Error "Failed to add Windows Credential to Windows vault."
}
ElseIf ($result -match "CMDKEY: Credential added successfully") {
Write-Host "Credential added successfully."
}
}
Else {
Write-Error "Internet(network address) or username can not be empty,please try again."
Add-OSCCredential
}
}
edit:
you'd most likely want to look into a ready-to-use PowerShell Module such as CredentialManager, this way you wouldn't have to fiddle with cmdkey.exe yourself.
The returned value for Read-Host is always a string, but you treat it like an integer in your tests.
For better readability, I suggest using a switch rather that yet another set of if..elseif..else statements.
Something like this:
function Add-OSCCredential {
$target = Read-Host "Enter Group number (1-3)"
if ($target -match '1|2|3') {
switch ([int]$target) {
1 {[string]$result = cmdkey /add:Group1 /user:Group1 /pass:Pass1}
2 {[string]$result = cmdkey /add:Group2 /user:Group2 /pass:Pass2}
3 {[string]$result = cmdkey /add:Group3 /user:Group3 /pass:Pass3}
}
if($result -match "The command line parameters are incorrect") {
Write-Error "Failed to add Windows Credential to Windows vault."
}
elseif ($result -match "Credential added successfully") {
Write-Host "Credential added successfully."
}
else {
Write-Warning $result
}
}
else {
Write-Warning "Group number must be either 1, 2 or 3. Please try again."
Add-OSCCredential
}
}
Add-OSCCredential
I'm writing a function for getting the Windows version using WMI object. But I wanted to add the Windows 10 ReleaseId ("1709") (from a registry key) into the object.
Is this a stupid idea? (It works, I just don't know if it's a smart thing to do.)
function Get-OSVersion {
[version]$OSVersion = (Get-WmiObject -Class Win32_OperatingSystem).Version
if ($OSVersion.Major -ge '10') {
$OSVersion | Add-Member -MemberType NoteProperty -Name ReleaseId -Value $([int]::Parse($(Get-ItemProperty -Path "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion" ReleaseId).ReleaseId)) -Force
}
return $OSVersion
}
$OSVersion = Get-OSVersion
if ($OSVersion -ge '6.1') {"At least Win7"} else {"Too old"}
if ($OSVersion.ReleaseID -ge '1703') {"At least 1703."} else {"Too old"}
Also, would it be unwise to overwrite the member "Revision" (value is always -1) instead of adding a new member "ReleaseId"?
To expand on my comment:
I wouldn't suggest changing a wmi class that you don't need to, but you're not doing that. I don't see anything wrong about your approach besides adding a member to a defined standard library class (System.Version) and doing a number comparison against a string.
What I would suggest doing is creating a [pscustomobject] with the members you need:
function Get-OSVersion {
$OSVersion = [version](Get-CimInstance -ClassName Win32_OperatingSystem).Version
if ($OSVersion.Major -ge 10) {
[pscustomobject]#{
Version = $OSVersion
ReleaseId = [int](Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion').ReleaseId
}
} else {
[pscustomobject]#{
Version = $OSVersion
}
}
}
In use:
$OS = Get-OSVersion
if ($OS.Version -ge [version]'6.1') {
'At least Win7'
} else {
'Too old'
}
if ($OS.ReleaseId -ge 1703) {
'At least 1703.'
} else {
'Too old'
}
To serve an alternative: Use a hashtable since it looks like you're just doing key/value accessing and comparisons without any method implementation.
function Get-OSVersion {
$OS = #{
Version = [version](Get-CimInstance -ClassName Win32_OperatingSystem).Version
}
if ($OS.Version.Major -ge 10) {
$OS['ReleaseId'] = [int](Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion').ReleaseId
}
return $OS
}
My recommendation would be to use calculated properties:
function Get-OSVersion {
Get-WmiObject -Class Win32_OperatingSystem |
Select-Object #{n='Version';e={[version]$_.Version}},
#{n='ReleaseId';e={
if (([version]$_.Version).Major -ge '10') {
[int](Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion').ReleaseId
}
}}
}
I'm trying to modify a working script, to make it modular. The purpose of the script is to connect to a DPM server, get the attached libraries, and inventory them. Once the inventory is done, the script marks the appropriate tapes as 'free'. The script is below
I have two problems. The first one has come and gone, as I've edited the script. When I run the script: .\script.ps1, Powershell says:
C:\it\test.ps1 : Cannot validate argument on parameter 'DPMLibrary'. The argument is null. Supply a non-null argument and try the command again.
At line:1 char:11
+ .\test.ps1 <<<<
CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,test.ps1
The second problem comes when I've just copied the functions into the shell. The Get-Libraries function works fine and returns the properties of the connected library. When I pass the parameter to Inventory-DPMLibrary, the inventory completes. When I pass the library parameter into the Update-TapeStatus function, I get an error that says
Bad argument to operator '-notmatch': parsing "slot" - Quantifier {x,y} follo
wing nothing..
At line:6 char:77
$tapes = Get-DPMTape -DPMLibrary $lib | Where {$_.Location -notmatch
<<<< " *slot *"} | Sort Location
CategoryInfo : InvalidOperation: (:) [], RuntimeException
? + FullyQualifiedErrorId : BadOperatorArgument
It looks like the $liblist parameter is null, even though the variable isn't. What gives?
Here is the script:
[CmdletBinding()]
param(
[ValidateSet("Fast","Full")]
[string]$InventoryType = 'Fast',
[string]$DPMServerName = 'server1'
)
Function Import-DPMModule {
Try {
Import-Module DataProtectionManager -ErrorAction Stop
}
Catch [System.IO.FileNotFoundException] {
Throw ("The DPM Powershell module is not installed or is not importable. The specific error message is: {0}" -f $_.Exception.Message)
}
Catch {
Throw ("Unknown error importing DPM powershell module. The specific error message is: {0}" -f $_.Exception.Message)
}
}
Function Get-Libraries {
Write-Verbose ("Getting list of libraries connected to {0}." -f $DPMServerName)
Try {
$libraries = Get-DPMLibrary $DPMServerName -ErrorAction Stop | Where {$_.IsOffline -eq $False}
}
Catch [Microsoft.Internal.EnterpriseStorage.Dls.Utils.DlsException] {
Write-Error ("Cannot connect to the DPM library. It appears that the servername is not valid. The specific error message is: {0}" -f $_.Exception.Message)
Return
}
Catch {
Write-Error ("Unknown error getting library. The specific error message is: {0}" -f $_.Exception.Message)
Return
}
Return $libraries
}
Function Inventory-DPMLibraries ($liblist) {
Foreach ($lib in $liblist) {
If ($InventoryType -eq "Fast") {
Write-Verbose ("Starting fast inventory on {0}" -f $lib)
$inventoryStatus = Start-DPMLibraryInventory -DPMLibrary $lib -FastInventory -ErrorAction SilentlyContinue
}
Else {
Write-Verbose ("Starting detailed inventory on {0}" -f $lib)
$inventoryStatus = Start-DPMLibraryInventory -DPMLibrary $lib -DetailedInventory -ErrorAction SilentlyContinue
}
While ($inventoryStatus.HasCompleted -eq $False) {
Write-Output ("Running {0} inventory on library: {1}" -f $InventoryType.ToLower(),$lib.UserFriendlyName)
Start-Sleep 5
}
If ($inventoryStatus.Status -ne "Succeeded") {
Throw ("Unknown error in inventory process. The specific error message is: {0}" -f $_.Exception.Message)
Return
}
}
}
Function Update-TapeStatus ($liblist) {
Foreach ($lib in $liblist) {
write-host ("in tapestatus. the lib is: {0}" -f $lib)
Write-Verbose ("Beginning the process to determine which tapes to mark 'free' on {0}" -f $lib)
Write-Verbose ("Getting list of tapes in {0}." -f $lib)
$tapes = Get-DPMTape -DPMLibrary $lib | Where {$_.Location -notmatch "*slot*"} | Sort Location
Foreach ($tape in $tapes) {
If ($tape.DisplayString -eq "Suspect") {
Write-Verbose ("Remove suspect tapes from the DPM database.")
Invoke-Command -ScriptBlock {osql -E -S server2 -d DPMDB_server1 -Q "UPDATE tbl_MM_ArchiveMedia SET IsSuspect = 0"} -whatif
Start-DPMLibraryInventory -DPMLibrary $lib -FastInventory -Tape $tape -whatif
}
#Run a full inventory on "unknown" tapes
#Make recyclable tapes "free"
If (($tape.DisplayString -notlike "Free*" -and $tape.DataSetState -eq "Recyclable") -or ($tape.DisplayString -like "Unrecognized")) {
Write-Output ("Marking the tape in slot {0} as free." -f $tape.Location)
Set-DPMTape $tape -Free -whatif
}
If ($tape.OMIDState -eq "Unknown") {
Write-Warning ("Unknown tape found in slot {0}. Beginning detailed inventory." -f $tape.location)
$inventoryStatus = Start-DPMLibraryInventory -DPMLibrary $lib -DetailedInventory -Tape $tape -whatif
While ($inventoryStatus.HasCompleted -eq $False) {Write-Output ("Running full inventory on the tape in slot {0} (label {1})" -f $tape.Location,$tape.Label); Start-Sleep 10}
}
}
}
}
#Calling functions
Try {
Import-DPMModule
}
Catch {
Write-Error $_
Exit
}
Try {
$liblist = Get-Libraries
}
Catch {
Write-Error $_
Exit
}
Try {
Inventory-DPMLibraries
}
Catch {
Write-Error $_
Exit
}
Update-TapeStatus $liblist
Thanks.
Your function Inventory-DPMLibraries expects a parameter ($liblist):
Function Inventory-DPMLibraries ($liblist) {
...
}
However, you don't supply that parameter when you call the function:
Try {
Inventory-DPMLibraries
}
Catch {
Write-Error $_
Exit
}
Change the above into this:
Try {
Inventory-DPMLibraries $liblist
}
Catch {
Write-Error $_
Exit
}