Running a script as a different user

Hello folks,
I have this script which works well. It runs against a target, as the local admin account of that target, and it scans a file and tells me the disk mode. When I run it, it prompts me for the password, which I enter and away it goes. Here is the script:

#Check_PVS_Mode.ps1
#Checks if PVS target is in R/W mode or not
$Computer = Read-Host -Prompt "What PVS target do you want to check the Disk Mode on?"
$UserName = "$computer\localadmin"

Invoke-Command -Computername  $Computer -credential $username -ScriptBlock {
	$File = "$env:SystemDrive\Personality.ini"
	Write-Host "Write the PVS mode ('standard' or 'private') of the target machine to the screen"
	if ( Test-Path $File ) {
		if ( Select-String -Path $File -pattern "`_DiskMode`=S") {
			Write-Host "The current machine is a PVS target device running in STANDARD (Read only) mode"
							} else {
								Write-Host "The current machine is a PVS target device running in PRIVATE (Read/Write) mode"
									}
							} else {
								Write-Host "The current machine is not a PVS target device"
									}
}

I am trying to automate it by not having to enter the password. I have the password stored in an encrypted vault. This script is supposed to grab that password from the vault and apply it so it passes it for login. The script executes and gives me the results, but it creates a local profile of my own account that is running the script. I check those variables and they are correct as far as the name and PW. any ideas why this is not running as the local account?

#Check_PVS_Mode.ps1
#Checks if PVS target is in R/W mode or not
$Computer = Read-Host -Prompt "What PVS target do you want to check the Disk Mode on?"
$vaultpassword = (Import-CliXml C:\Tools\MSVault\vaultpassword.xml).Password
Unlock-SecretStore -Password $vaultpassword

$UserName = "$Computer\localadmin"
$UserPW = Get-SecretInfo -Name Secret1 -Vault SecretStore | Get-Secret -AsPlainText
$Both = "$UserName,$UserPW"
$Credential = [pscredential]::new($Both)

    Invoke-Command -Computername $Computer -credential ($Credential)  -ScriptBlock {
$File = "$env:SystemDrive\Personality.ini"
Write-Host "Write the PVS mode ('standard' or 'private') of the target machine to the screen"
if ( Test-Path $File ) {
    if ( Select-String -Path $File -pattern "`_DiskMode`=S") {
        Write-Host "The current machine is a PVS target device running in STANDARD (Read only) mode"
    } else {
        Write-Host "The current machine is a PVS target device running in PRIVATE (Read/Write) mode"
           }
} else {
    Write-Host "The current machine is not a PVS target device"
}
}

Thanks for any help!

Do you want to run this script by hand or should it run automatically by a scheduled task?

Are both computers member of an AD domain?

This is meant to run manually

Yes both computers are part of the same domain.

Thanks,

Matt

Then it’s the easiest approach to use domain account who is member of the administrators group on the remote computer. Don’t use local accounts. And it even get’s easier when the account you’re running this script is member of that group as well.

If not - you have to encrypt the logon credentials and save them with Export-CliXML and re-import them with Import-CliXML with the same account on the same machine. Otherwise it will not work

Alternatively you could create a scheduled task and configure it to run with the proper account for the remote access. Then you can allow any account on the local computer to run that task on demand.

My issue is I cant leave a trail on the remote computer. There are a number of Domain accounts in the local admins group, but none of them have profiles on the machine, never logged in interactively.

The local admin account however does have a profile, so I can use that account. I’ve used this technique of retrieving the vault password on demand using my domain account, so I think it should work using a local admin account.

Thanks,

Matt

I ended up solving this like so:

#Check_PVS_Mode_auto.ps1
#Checks if PVS target is in R/W mode or not
#Reads encypted password from file
#Run this to create encrypted PW file:
#Read-Host -assecurestring | convertfrom-securestring | out-file c:\temp\itscript\pvs\mysecurestring.txt

$Computer = Read-Host -Prompt "What PVS target do you want to check the Disk Mode on?"

$UserName = "$Computer\localadmin"
$PW = Get-Content 'c:\temp\itscript\pvs\mysecurestring.txt' | ConvertTo-SecureString
$Cred = New-Object -typename System.Management.Automation.PSCredential ($Username,$PW)

    Invoke-Command -Computername $Computer -credential $Cred -ScriptBlock {
$File = "$env:SystemDrive\Personality.ini"

if ( Test-Path $File ) {
    if ( Select-String -Path $File -pattern "`_DiskMode`=S") {
        Write-Host "`n$Using:Computer is in STANDARD (Read only) mode`n" -foregroundcolor yellow
    } else {
        Write-Host "`n$Using:Computer is in PRIVATE (Read/Write) mode`n" -foregroundcolor yellow
           }
} else {
    Write-Host "`n$Using:Computer is not a PVS target device`n" -foregroundcolor red
}
}

Thanks,
Matt

Since you’re actually just want to access a file on the remote computer why don’t you use a UNC path to access the administrative share of the remote computer? … \\remoteComputer\c$\Personality.ini … this way you don’t even need to logon to the remote computer. :wink: Another way could be to access the remote registry. This way you wouldn’t need to logon to the remote computer as well.

May I ask why?

If that works for you … great. :+1:t4: :slight_smile:

Olaf,
Thanks. Even though I got it working, Ill try re-writing the script using UNC path as it seems like it will do the job with less code.

These are master images we are working on so the tech team will complain if they see various account profiles created, so to avoid that we use the local admin account.

Thanks again,
Matt

If they don’t like these profiles they could easily remove them … even without loggin on and creating a profile …
:wink:

I’d exect this to be their duty preparing the master images for provisioning.
:smirk:

Yes, they may do that…but I would prefer if I fly under the radar either way.

Here is the UNC version, tested and it works:

#Check_PVS_Mode_UNC.ps1
#Checks if PVS target C:\Temp\ITScript\PVS\servers.txt are in R/W mode or not using UNC path

cls
$ComputerList = Get-content 'C:\Temp\ITScript\PVS\servers.txt'
Write-host "This is the list of computers you are executing against:`n"
$ComputerList
$answer = Read-Host -Prompt "`nProceed with this list? Y/N"

If ($answer -eq 'Y') { 
Foreach ($ComputerName in $ComputerList) {
  
$File = "\\$ComputerName\c$\Personality.ini"

if ( Test-Path $File ) {
    if ( Select-String -Path $File -pattern "_DiskMode=S") {
        Write-Host "`n$ComputerName is in STANDARD (Read only) mode`n" -foregroundcolor yellow
    } else {
        Write-Host "`n$ComputerName is in PRIVATE (Read/Write) mode`n" -foregroundcolor yellow
           }
} else {
    Write-Host "`n$ComputerName is not a PVS target device`n" -foregroundcolor red
}
}
}
Else {
Invoke-Item "C:\Temp\ITScript\PVS\servers.txt"
}

Nice. :+1:t4:

May I recommend some tweaks anyway? I’d prefer to have the output a little more “technical” and less “prosa”.

$ComputerList = Get-content 'C:\Temp\ITScript\PVS\servers.txt'
Write-host "This is the list of computers you are executing against:`n"
$ComputerList
$answer = Read-Host -Prompt "`nProceed with this list? Y/N"

If ($answer -eq 'Y') {
    $Result = 
    Foreach ($ComputerName in $ComputerList) {
        $ResultHashtable = @{
            ComputerName     = $ComputerName
            Online           = $false
            PVS_TargetDevice = $false
            DiskMode         = 'PRIVATE (Read/Write)'
        }

        if (Test-Connection -ComputerName $ComputerName -Count 1 -Quiet) {
            $ResultHashtable.Online = $true
            $File = '\\{0}\c$\Personality.ini' -f $ComputerName

            if ( Test-Path $File ) {
                $ResultHashtable.PVS_TargetDevice = $true
                if ( Select-String -Path $File -Pattern "_DiskMode=S") {
                    $ResultHashtable.DiskMode = 'STANDARD (Read only)'
                }
            }
            else {
                $ResultHashtable.DiskMode = 'n/a'
            }
        }
        else {
            $ResultHashtable.PVS_TargetDevice = 'n/a'
            $ResultHashtable.DiskMode = 'n/a'
        }
        [PSCustomObject]$ResultHashtable
    }
}
Else {
    Invoke-Item 'C:\Temp\ITScript\PVS\servers.txt'
}
$Result

This way you get an array of objects you can even use for further steps like exporting the data to a CSV or whatever further steps you may come up with. :wink:

2 Likes

Yea I really like that output, thanks Olaf.

I am now trying to add a bit of data to the output, but not having much luck.

I would like to add the Diskversion to the array.

Can anyone point out what Im doing wrong here? I get no output for my $diskversion

#Check_PVS_Mode_UNC_Object.ps1
#This script creates an array of objects showing diskmode

$computerList = Get-content 'C:\Temp\ITScript\PVS\servers.txt'
Write-host "This is the list of computers you are checking disk mode on:`n"
$computerList
$answer = Read-Host -Prompt "`nProceed with this list? Y/N"

If ($answer -eq 'Y') {
    $result =
    foreach ($computername in $computerlist) {
        $resultHashtable = @{
            ComputerName     = $computername
            Online           = $false
            PVS_TargetDevice = $false
            DiskMode         = 'PRIVATE (Read/Write)'
			DiskVersion		 = $diskversion
        }

        if (Test-Connection -ComputerName $computername -Count 1 -Quiet) {
            $resulthashtable.Online = $true
            $file = '\\{0}\c$\Personality.ini' -f $computername
			$diskversion = Get-content -Path $file | Where-Object {$_ -like "$DiskName=*"}
            if ( Test-Path $file ) {
                $resulthashtable.PVS_TargetDevice = $true
                if ( Select-String -Path $file -Pattern "_DiskMode=S") {
                    $resulthashtable.DiskMode = 'STANDARD (Read only)'
					$resulthashtable.DiskVersion = $diskversion
				}
			}
            else {
                $resulthashtable.DiskMode = 'n/a'
				$resulthashtable.DiskVersion = $diskversion
			}
        }
        else {
            $resulthashtable.PVS_TargetDevice = 'n/a'
            $resulthashtable.DiskMode = 'n/a'
		}
        [PSCustomObject]$resulthashtable
    }
}
else {
    Invoke-Item 'C:\Temp\ITScript\PVS\servers.txt'
}
$result

Thanks!

Got it working:

#Check_PVS_Mode_UNC_Object.ps1
#This script creates an array of objects showing diskmode

$computerList = Get-content 'C:\Temp\ITScript\PVS\servers.txt'
Write-host "This is the list of computers you are checking disk mode on:`n"
$computerList
$answer = Read-Host -Prompt "`nProceed with this list? Y/N"

If ($answer -eq 'Y') {
    $result =
    foreach ($computername in $computerlist) {
        $resultHashtable = @{
            ComputerName     = $computername
            Online           = $false
            PVS_TargetDevice = $false
            DiskMode         = 'PRIVATE (Read/Write)'
			DiskVersion		 = $diskversion
        }

        if (Test-Connection -ComputerName $computername -Count 1 -Quiet) {
            $resulthashtable.Online = $true
            $file = '\\{0}\c$\Personality.ini' -f $computername
			$diskversion = Get-content -Path $file | Where-Object {$_ -like '$DiskName=*'}
            if ( Test-Path $file ) {
                $resulthashtable.PVS_TargetDevice = $true
                if ( Select-String -Path $file -Pattern "_DiskMode=S") {
                    $resulthashtable.DiskMode = 'STANDARD (Read only)'
					$resulthashtable.DiskVersion = "$diskversion"
				}
			}
            else {
                $resulthashtable.DiskMode = 'n/a'
				$resulthashtable.DiskVersion = "$diskversion"
			}
        }
        else {
            $resulthashtable.PVS_TargetDevice = 'n/a'
            $resulthashtable.DiskMode = 'n/a'
		}
        [PSCustomObject]$resulthashtable
    }
}
else {
    Invoke-Item 'C:\Temp\ITScript\PVS\servers.txt'
}
$result

ok its not quite working correctly.

When I have a computer in the list that has the DiskMode as Private, the output is not right, the diskname is incorrect, it appears to be using the diskname of the previous record.

Not having much luck figuring out the logic problem. Here is wat I have now:

#Check_PVS_Mode_UNC_Object.ps1
#This script creates an array of objects showing diskmode

$computerList = Get-content 'C:\Temp\ITScript\PVS\servers.txt'
Write-host "This is the list of computers you are checking disk mode on:`n"
$computerList
$answer = Read-Host -Prompt "`nProceed with this list? Y/N"

If ($answer -eq 'Y') {
    $result =
    foreach ($computername in $computerlist) {
        $resultHashtable = @{
            ComputerName     = $computername
            Online           = $false
            PVS_TargetDevice = $false
            DiskMode         = 'PRIVATE (Read/Write)'
			DiskVersion		 = $diskversion
        }
		
		if (Test-Connection -ComputerName $computername -Count 1 -Quiet) {
            $resulthashtable.Online = $true
            $file = '\\{0}\c$\Personality.ini' -f $computername
			
            if ( Test-Path $file ) {
                $resulthashtable.PVS_TargetDevice = $true
				$diskversion = Get-content -Path $file | Where-Object {$_ -like '$DiskName=*'}
				
                if ( Select-String -Path $file -Pattern "_DiskMode=S") {
                    $resulthashtable.DiskMode = 'STANDARD (Read only)'
					$resulthashtable.DiskVersion = $diskversion
				}
			}
            else {
				$resulthashtable.DiskMode = 'n/a'
				$resulthashtable.DiskVersion = $diskversion
			}
        }
        else {
            $resulthashtable.PVS_TargetDevice = 'n/a'
            $resulthashtable.DiskMode = 'n/a'
			$resulthashtable.DiskVersion = 'n/a'
		}
        [PSCustomObject]$resulthashtable
    }
}
else {
    Invoke-Item 'C:\Temp\ITScript\PVS\servers.txt'
}
$result

lol, NOW it works:

#Check_PVS_Mode_UNC_Object.ps1
#This script creates an array of objects showing diskmode

$computerList = Get-content 'C:\Temp\ITScript\PVS\servers.txt'
Write-host "This is the list of computers you are checking disk mode on:`n"
$computerList
$answer = Read-Host -Prompt "`nProceed with this list? Y/N"

If ($answer -eq 'Y') {
    $result =
    foreach ($computername in $computerlist) {
        $resultHashtable = @{
            ComputerName     = $computername
            Online           = $false
            PVS_TargetDevice = $false
            DiskMode         = 'PRIVATE (Read/Write)'
			DiskVersion		 = ''
        }
		
		if (Test-Connection -ComputerName $computername -Count 1 -Quiet) {
            $resulthashtable.Online = $true
            $file = '\\{0}\c$\Personality.ini' -f $computername
			
            if ( Test-Path $file ) {
                $resulthashtable.PVS_TargetDevice = $true
				$diskversion = Get-content -Path $file | Where-Object {$_ -like '$DiskName=*'}
				
                if ( Select-String -Path $file -Pattern "_DiskMode=S") {
                    $resulthashtable.DiskMode = 'STANDARD (Read only)'
					$resulthashtable.DiskVersion = $diskversion
				}
			
            else {
				$resulthashtable.DiskMode = 'PRIVATE (Read/Write)'
				$resulthashtable.DiskVersion = $diskversion
			}
			}
        }
        else {
            $resulthashtable.PVS_TargetDevice = 'n/a'
            $resulthashtable.DiskMode = 'n/a'
			$resulthashtable.DiskVersion = 'n/a'
		}
        [PSCustomObject]$resulthashtable
    }
}
else {
    Invoke-Item 'C:\Temp\ITScript\PVS\servers.txt'
}
$result

To debug a non working code means basically to inspect the used variables at some certain points during the runtime of the script or at least output them to the console to see what’s going on.

Here you have something to start with

Can someone explain how this part works?

A hashtable is being cast into a pscustomobject. This allows you to reference object properties like $resulthashtable.diskmode.

How does the script reference those object properties before the hashtable is cast to a pscustomobject, ie the first pass through the script?

Thanks,

Matt

I’m not sure if I get what your question is actually about.

The following help topics and blog posts might help: