Set location to newly mounted disk image fails in PowerShell - windows

I'm trying to run the following code in a function in my script:
$result = Mount-DiskImage -ImagePath $imagepath -PassThru
$driveLetter = ($result | Get-Volume).DriveLetter
Set-Location "$($driveLetter):"
But it constantly fails with this error:
Set-Location : Cannot find drive. A drive with the name 'G' does not exist.
At C:\Users\Agent\BuildAgent\scripts\helpers.psm1:35 char:3
+ Set-Location "$($driveLetter):"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (G:String) [Set-Location], DriveNotFoundException
+ FullyQualifiedErrorId : DriveNotFound,Microsoft.PowerShell.Commands.SetLocationCommand
But after the script has terminated I can change the drive, no problem.
It might be timing related, but injecting a sleep (even a large one) before setting location, does not help.
Does anyone know about this issue?

Let's all up-vote the bug report.
Then, I think I have a workaround by manually adding the drive as a new PSDrive. I guess the New-PSDrive cmdlet can access the mounted drive even though others can't.
$mount = Mount-DiskImage $isoPath -PassThru
$driveLetter = ($mount | Get-Volume).DriveLetter
# Have to use New-PSDrive so other cmdlets in this session can see the new drive
New-PSDrive -Name $driveLetter -PSProvider FileSystem -Root "$($driveLetter):\"
// ...do things...
Dismount-DiskImage $mount.ImagePath

I can't try this but your command looks odd to me
Set-Location "$($driveLetter):"
have you tried
Set-Location "$driveLetter:"
without the parens

Related

Not able to use a function from another powershell file

I have the main.ps1 file where I am importing another file $dirpath\new.ps1 as below:
Import-module $dirpath\new.ps1 -force -ErrorAction SilentlyContinue -WarningAction SilentlyContinue
try {
$getval = invoke-command -cn $host -Credential $cred -ScriptBlock {
param($name)
get-myfunc $name
} -ArgumentList $name
} catch {
...
}
Both main.ps1 file and new.ps1 are existing under the same directory - $dirpath.
The new.ps1 looks as below:
Function global:get-myfunc{
PARAM(
[Parameter(Mandatory=$true,Position=0)][STRING]$name
)
write-host "$name"
}
Now, the main.ps1 file is throwing below error:
+ $getval = invoke-command -cn $host -Credential $cred -S ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (get-myfunc:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
I have tried renaming new.ps1 as new.psm1 then importing module as Import-module $dirpath\new.psm1 but it is still failing with same error.
I am using poweshell 5
First issue
The new.ps1 file isn't a module, just a regular script, so you can't/shouldn't use Import-Module for that.
Modules are not simply scripts with a different extension. For more information, see:
about Modules
How to Write a PowerShell Script Module
If you want to keep the current setup, dot source the script by replacing the Import-Module line with:
. $dirpath\new.ps1
This will execute the script and make define the function in the current scope.
If the script is located in the same folder as the calling script, you can further simplify the statement by using $PSScriptRoot:
. $PSScriptRoot\new.ps1
Second issue
Invoke-Command means you're running a scriptblock on a different host, which implies that it uses a different scope. That's why it can't find the get-myfunc function.
The modifying your statement to:
Invoke-Command
-ComputerName $host `
-Credential $cred `
-ScriptBlock ${Function:get-myfunc} `
-ArgumentList $name
For a more detailed explanation, see Run Local Functions Remotely in PowerShell.
That Won't work, because you are importing that Module into your local machine. But, the below command is executing in remote machine. That means you need install that module in remote machine and then you can use that module in the remote machine.
$getval = invoke-command -cn $host -Credential $cred -ScriptBlock {
param($name)
get-myfunc $name
Please follow below link for the solution

Install Offline Windows Updates(.msu) to remote servers

I'm trying to get a script together to remotely install some windows updates on some remote servers that are connected in an offline domain.
I have tried regular PS Remoting and after some research, I think what I am trying to do isnt supported by microsoft. When checking my event logs I have a bunch of these errors.
Edit
I wanted to add that I have tried running the .\Install2012R2.ps1 script from my local computer, modified to have the Invoke-Command in that and have it run the update portion of the original Install2012R2.ps1 and I would get the same errors.
I was hoping that by placing the script on each server that it would like that more.
End Edit
Windows update could not be installed because of error 2147942405 "Access is denied."
(Command line: ""C:\Windows\System32\wusa.exe" "C:\Updates\windows8.1-kb4556853-x64.msu" /quiet /norestart")
I have tried running Invoke-Command as credentialed to an administrator account on the servers but I have been having no luck and was looking for some advice if someone has maybe tried/done this before.
$Servers = #("V101-Test1","V101-Test2")
$Username = 'admin'
$Password = 'Password'#not actual password
$pass = ConvertTo-SecureString -AsPlainText $Password -Force
$Cred = New-Object System.Management.Automation.PSCredential -ArgumentList $Username,$pass
Get-PSSession | Remove-PSSession
New-PSSession -ComputerName $Servers
foreach($Server in $Servers){
Get-ChildItem -Path C:\Source\Temp -Recurse | Copy-Item -Destination "\\$Server\c$\Updates\" -Force
}
Invoke-Command $Servers -Credential $Cred -ScriptBlock{
& "C:\Updates\Install2012R2.ps1"
}
EDIT 2
Here is the actual install code of the Install2012R2.ps1 script
$updatedir= "./"
$files = Get-ChildItem $updatedir -Recurse
$msus = $files | ? {$_.extension -eq ".msu"}
$exes = $files | ? {$_.extension -eq ".exe"}
foreach ($file in $msus){
$KBCtr++
$fullname = $file.fullname
# Need to wrap in quotes as folder path may contain space
$fullname = "`"" + $fullname + "`""
$KBN = $fullname.split('-')[1]
# Need to wrap in quotes as folder path may contain space
$fullname = "`"" + $fullname + "`""
# Specify the command line parameters for wusa.exe
$parameters = $fullname + " /quiet /norestart"
# Start services and pass in the parameters
$install = [System.Diagnostics.Process]::Start( "wusa",$parameters )
$install.WaitForExit()
}
I'm not sure why wusa.exe is failing here with Access Denied, but here is a PowerShell-native approach you can try. If nothing else, it should give you a clearer indication via the captured error information as to what the underlying issue is:
Add-WindowsPackage -Path C:\Updates\OurHeroicUpdate.msu -Online -PreventPending -NoRestart
-Path is the path to the msu file
-Online tells Add-WindowsPackage to modify the currently "mounted image" (the running version) of Windows (as opposed to an offline disk image you could also apply it to)
-PreventPending prevents installing the msu if there is already a pending change, like needing to reboot for updates.
Add-WindowsPackage is part of the DISM module available under Windows PowerShell, and is the functional equivalent of dism /packagepath:"cabfile", although it can take an msu where dism.exe only allows a cab.

Delete children directories in powershell including symlinks

Currently experiencing issue, I'm currently doing this:
Get-ChildItem $PATH -Recurse -ErrorAction SilentlyContinue |
Where-Object {($_.Attributes -notmatch '\"Directory\"') -and
($_.LastWriteTime -lt (Get-Date).AddHours(-12))}|
Remove-Item -Force -Recurse
Now, it would delete fine IF I didn't have symlinks, but I do. I am getting this error:
Remove-Item : There is a mismatch between the tag specified in the request and the tag present in the reparse point
At line:1 char:184
+ ... ($_.LastWriteTime -lt (Get-Date).AddHours(-12))}| Remove-Item -Force
+ ~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Remove-Item], Win32Exception
+ FullyQualifiedErrorId : System.ComponentModel.Win32Exception,Microsoft.PowerShell.Commands.RemoveItemCommand
I'm unable to upgrade powershell to v6. It seems to be related to:https://github.com/powershell/powershell/issues/621#issuecomment-289230180
Anyone have a workaround?
Tested today on PowerShell 7 and unfortunately the issue is still there: PowerShell cannot delete symlink.
I had to delete the directory through an elevated prompt typing cmd /c rmdir /s /q C:\Users\Your_User_Name\Your_Folder_Name
This problem seems to be fixed in PS 6 (ref: https://github.com/powershell/powershell/issues/621)
In PS 5.1 one can work around it by using:
$(get-item $theSymlinkDir).Delete()
or as LotPings noted in the comments to the Q for this specific Foreach-Object loop:
|? LinkType -eq 'SymbolicLink'| % { $_.Delete() }

Invoke-Command Cannot Find Path But File Does Exist

I'm very new to Windows scripting and am having an issue with trying to execute a Powershell script located on a remote node.
It's a super simple HelloWorld script.
I'm setting up my session and issuing the remote invocation command like this ::
$session = New-PSSession -ComputerName DH2VCAUSPTCTX01.XXX.XXX.com -Credential XXX\XXX
Invoke-Command -Session $session -FilePath C:\Users\Public\EOD_CWx_Scripts\hello_world_PS.ps1
I keep getting this error ::
Invoke-Command : Cannot find path 'C:\Users\Public\EOD_CWx_Scripts\hello_world_PS.ps1' because it does not exist.
At line:1 char:1
+ Invoke-Command -Session $session -FilePath C:\Users\Public\EOD_CWx_Sc ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\Users\Public...lo_world_PS.ps1:String) [Invoke-Command], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.InvokeCommandCommand
This is a screen shot of the Remote node showing that the file does indeed exist ::
This is a screen shot of me attempting to invoke the Powershell script on the remote node ::
Like I said, I'm really new to Windows scripting.
Is there something that I'm missing when it comes to remotely invoking Powershell scripts?
For reference, I've been using this resource to try and figure out how to do this :: https://msdn.microsoft.com/en-us/powershell/reference/5.1/microsoft.powershell.core/invoke-command

Not able to call a PowerShell script from another script

I am trying to call a file enable.ps1 from another file begin.ps1. Both the files are in the same folder. So, I thought that may be I can use the following code for that purpose.
Here is the code I have written inside begin.ps1 for calling.
#
# begin.ps1
#
function MapDrives ($Message)
{
Write-Host Network drives does not exist till now. Trying again to connect
Write-Host ...............................................................
WriteInLogFile "Network drives does not exist till now. Trying again to connect"
$ScriptPath = Split-Path $MyInvocation.InvocationName
& "$ScriptPath\enable.ps1"
cmd /c pause | out-null
Start-Sleep -s 20
}
There is the PowerShell file I am trying to call: enable.ps1
I am using Visual studio 2015
Windows 7
PowerShell 5
both begin.ps1 and enable.ps1 are under same folder location which is this :
C:\Users\srijani.ghosh\Documents\visual studio 2015\Projects\test\test
Do you have any idea on how should I proceed on this ?
P.S : did some changes as suggested by Martin. Now the code looks like this:
function MapDrives ($Message)
{
Write-Host Network drives does not exist till now. Trying again to connect
Write-Host ...............................................................
WriteInLogFile "Network drives does not exist till now. Trying again to connect"
$ScriptPath = split-path -parent $MyInvocation.MyCommand.Definition
& "$ScriptPath\enable.ps1"
cmd /c pause | out-null
Start-Sleep -s 20
}
And, I am trying to run it in PowerShell ISE. It giving this error.
Network drives does not exist till now. Trying again to connect
...............................................................
& : The module 'param($Message)
Write-Host Network drives does not exist till now. Trying again to connect
Write-Host ...............................................................
WriteInLogFile "Network drives does not exist till now. Trying again to connect"
$ScriptPath = split-path -parent $MyInvocation.MyCommand.Definition
& "$ScriptPath' could not be loaded. For more information, run 'Import-Module param($Message)
Write-Host Network drives does not exist till now. Trying again to connect
Write-Host ...............................................................
WriteInLogFile "Network drives does not exist till now. Trying again to connect"
$ScriptPath = split-path -parent $MyInvocation.MyCommand.Definition
& "$ScriptPath'.
At C:\Users\srijani.ghosh\Documents\visual studio 2015\Projects\test\test\begin.ps1:45 char:7
+ & "$ScriptPath\enable.ps1"
+ ~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (param($Message)...cmd \enable.ps1:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CouldNotAutoLoadModule
You are doing it right. However it looks like $ScriptPath doesn't contain any value (as you see within the error message).
You probably have to replace
$ScriptPath = Split-Path $MyInvocation.InvocationName
with
$ScriptPath = split-path -parent $MyInvocation.MyCommand.Definition

Resources