Value does not fall within the expected range powershell job creation - powershell

I wrote some code on my Windows 7 administration machine, where it just worked fine. Now I want to run it from a console - commandline with administration access from a client machine on Windows 10.
The script throws the error when it tries to Register the task through the COM-Object of the Task-Scheduler:
Value does not fall within the expected range:
# Aufruf in der command line mit
# powershell.exe -file C:\Workspace\controlling-macros\TaskCreator.ps1
$path = "C:\Workspace\controlling-macros\FullWorkbookPathsMR.csv"
$csv = Import-CSV -Path $path -Delimiter ";" | % {
# The name of the scheduled task
[string]$TaskName = "$($_.reportsource) - $($_.reportname) - $($_.reportid)"
# The description of the task
[string]$TaskDescr = "Hello, it's you again! I am $($_.reportname) and I will get started, when Report ID $($_.reportid) is fired. Have a nice day!"
# The Task Action command
$TaskCommand0 = "cmd"
$TaskCommand1 = "`"C:\Program Files (x86)\Microsoft Office\Office14\EXCEL.EXE`""
# The Task Action command argument
$TaskArg = "/c C:\Windows\System32\taskkill.exe /F /IM EXCEL.EXE"
$TaskArg1 = "$($_.fullpath)"
# attach the Task Scheduler com object
$service = new-object -ComObject("Schedule.Service")
# connect to the local machine.
# http://msdn.microsoft.com/en-us/library/windows/desktop/aa381833(v=vs.85).aspx
$service.Connect()
$rootFolder = $service.GetFolder("\")
$TaskDefinition = $service.NewTask(0)
$TaskDefinition.RegistrationInfo.Description = "$TaskDescr"
$TaskDefinition.Settings.Enabled = $true
$TaskDefinition.Settings.AllowDemandStart = $true
$triggers = $TaskDefinition.Triggers
#http://msdn.microsoft.com/en-us/library/windows/desktop/aa383915(v=vs.85).aspx
$trigger = $triggers.Create(0) # Creates an "On an event" trigger
$trigger.Subscription = "<QueryList><Query Id='0'><Select Path='Application'>*[System[Provider[#Name='$($_.reportsource)'] and EventID='$($_.reportid)']]</Select></Query></QueryList>"
# "*[System[Provider[#Name='$reporttype'] and EventID=$reportid]]"
# http://msdn.microsoft.com/en-us/library/windows/desktop/aa381841(v=vs.85).aspx
$Action = $TaskDefinition.Actions.Create(0)
$action.Path = "$TaskCommand0"
$action.Arguments = "$TaskArg"
$Action = $TaskDefinition.Actions.Create(0)
$action.Path = "$TaskCommand1"
$action.Arguments = "$TaskArg1"
#http://msdn.microsoft.com/en-us/library/windows/desktop/aa381365(v=vs.85).aspx
$rootFolder.RegisterTaskDefinition("$TaskName", $TaskDefinition, 6, "System", $null, 5) # <<--- here the error occurs
Write-Host $($_.sequence) $($_.reportsource) $($_.reportname) $($_.reportid) $($_.fullpath) "task created successfully."
}
why no data is piped to the variables?

I know this seems basic but I would start by matching Powershell versions first as different versions of Powershell do compile some code differently as well as some cmdlets just do not work in older versions.

In new-scheduledtasksettingsset there is a compatibility switch (v1, vista, win7, win8).

Related

Can I change powershell version to 7 with "Run PowerShell script" action on Power Automate Desktop?

Can I change powershell version to 7 on "Run PowerShell script" action?
If I can, how?
I know this post but I couldn't find if I can change the version PAD execute.
https://powerusers.microsoft.com/t5/Power-Automate-Desktop/Powershell-and-other-script-SUPPORTED-VERSION/td-p/1501322
I already installed powershell version7.
I'd like to use "-UseQuotes" option on "Export-Csv".
FYI, my PSVersion is here.
PSVersion 5.1.19041.1320
Thank you,
I also checked registry about PAD but There is noregistry to manage powershell
This is a bit ugly but it will get the job done.
I have this very basic flow, it just runs the PS script and outputs the results in a message box.
Throw this into the PowerShell task and then view the output.
$psVersion = (Get-Host).Version.Major
if ($psVersion -ne 7) {
$processInfo = New-Object System.Diagnostics.ProcessStartInfo
$processInfo.FileName = "C:\Program Files\PowerShell\7\pwsh.exe"
$processInfo.RedirectStandardError = $true
$processInfo.RedirectStandardOutput = $true
$processInfo.UseShellExecute = $false
$processInfo.Arguments = $MyInvocation.MyCommand.Definition
$process = New-Object System.Diagnostics.Process
$process.StartInfo = $processInfo
$process.Start() | Out-Null
$process.WaitForExit()
$stdout = $process.StandardOutput.ReadToEnd()
$stderr = $process.StandardError.ReadToEnd()
Write-Host $stdout
} else {
# Your logic goes here!
Write-Host "PowerShell Version = $psVersion"
}
You should get this ...
Essentially, it's checking for the version and if it's not version 7, it will launch PowerShell 7 and then retrieve the output.
Take note of the file path for PS7, you may need to change that or you may be able to simplify it. I've gone with the full path to make sure it works.

My PowerShell task scheduler script is showing a runtime exception error when running

When I run the following script to create a Scheduled Task, I receive the error
Bad type(Exception de HRESULT : 0x80020005 (DISP_E_TYPEMISMATCH))
$u = "domain\$env:username"
$p = "SomePassword"
$UserPass = ConvertTo-SecureString $p -AsPlainText -Force
$TaskName = "ML"
$TaskDescr = "Descriptor"
$TaskCommand = "$pos\$nm"
$TaskStartTime = [datetime]::Now.AddMinutes(5)
$service = new-object -ComObject("Schedule.Service")
$service.Connect()
$rtFr = $service.GetFolder("\")
$TaskDefinition = $service.NewTask(0)
$TaskDefinition.RegistrationInfo.Description = "$TaskDescr"
$TaskDefinition.Settings.Enabled = $true
$TaskDefinition.Settings.AllowDemandStart = $true
$triggers = $TaskDefinition.Triggers
$dd = "T"
$vv = "yyyy-MM-dd"
$xx = "HH:mm:ss"
$pr = "$vv$dd$xx"
$trigger = $triggers.Create(9)
$trigger.StartBoundary = $TaskStartTime.ToString($pr)
$trigger.Enabled = $true
$Action = $TaskDefinition.Actions.Create(0)
$action.Path = "$TaskCommand"
$rtFr.RegisterTaskDefinition("$TaskName",$TaskDefinition,6,$u,$UserPass,5)
There is too much to say about your script but let's focus on your issue:
Exception from HRESULT: 0x80020005 (DISP_E_TYPEMISMATCH)
This error is caused by the fact that $rtFr.RegisterTaskDefinition parameter for the password requires clear text, not encrypted string. So change your script as follow:
Use $p instead of $UserPass
Change trigger type from 9 to 1 (see below why)
Change logon type from 5 to 6 (see below why)
Modifications:
# Change these lines
$trigger = $triggers.Create(9)
$rtFr.RegisterTaskDefinition("$TaskName",$TaskDefinition,6,$u,$UserPass,5)
# To this
$trigger = $triggers.Create(1)
$rtFr.RegisterTaskDefinition($TaskName,$TaskDefinition,6,$u,$p,6)
refs:
https://learn.microsoft.com/en-us/windows/win32/taskschd/taskfolder-registertaskdefinition
https://learn.microsoft.com/en-us/windows/win32/taskschd/triggercollection-create
This is enough for your script to be executed without errors
...
Now, if you don't change the trigger type from 9 to 1, you will encounter this error:
Exception from HRESULT: 0x80070005 (E_ACCESSDENIED)
You are trying to create a task that will be executed at logon ($trigger = $triggers.Create(9)), which requires administrative privileges. So you must run your script from an elevated Powershell session (run as Administrator)
And finally, if you don't change the logon type from 5 to 6, you will encounter this error:
(XX,XX):UserId: At :XX char:XX
You are trying to create a task with a logon type TASK_LOGON_SERVICE_ACCOUNT, without specifying which service account to use. Also you are passing username and password parameters to create the task, they should be empty/null.
# Change this line
$rtFr.RegisterTaskDefinition($TaskName,$TaskDefinition,6,$u,$p,6)
# To this
$TaskDefinition.Principal.UserId = "S-1-5-18" # i.e Local System Account
$rtFr.RegisterTaskDefinition($TaskName,$TaskDefinition,6,$null,$null,5)
Conclusion:
So I don't know what you are trying to achieve but you must be consistent with all parameters for the task creation to execute properly.
I would advise you to use SCHTASKS.exe instead of the COM object, it will be easier, less complex and it's available on Windows 7 and higher versions.

Self Elevating Script + Execution Policy

I'm trying to use the following code from th question "PowerShell: Running a command as Administrator" to not only self elevate my script to run automatically in an Administrator-level PowerShell, but also for the Administrator-level PowerShell session to be run with an ExecutionPolicy level of RemoteSigned. I'm assuming that I need to use something like -ExecutionPolicy RemoteSigned in $newProcess.Arguments but am completely lost as to if this is the case, and if it is then what the syntax do I use to create the the multiple arguments?
# Get the ID and security principal of the current user account
$myWindowsID = [System.Security.Principal.WindowsIdentity]::GetCurrent();
$myWindowsPrincipal = New-Object System.Security.Principal.WindowsPrincipal($myWindowsID);
# Get the security principal for the administrator role
$adminRole = [System.Security.Principal.WindowsBuiltInRole]::Administrator;
# Check to see if we are currently running as an administrator
if ($myWindowsPrincipal.IsInRole($adminRole)) {
# We are running as an administrator, so change the title and background colour to indicate this
$Host.UI.RawUI.WindowTitle = $myInvocation.MyCommand.Definition + "(Elevated)";
$Host.UI.RawUI.BackgroundColor = "DarkBlue";
Clear-Host;
} else {
# We are not running as an administrator, so relaunch as administrator
# Create a new process object that starts PowerShell
$newProcess = New-Object System.Diagnostics.ProcessStartInfo "PowerShell";
# Specify the current script path and name as a parameter with added scope and support for scripts with spaces in it's path
$newProcess.Arguments = "& '" + $script:MyInvocation.MyCommand.Path + "'"
# Indicate that the process should be elevated
$newProcess.Verb = "runas";
# Start the new process
[System.Diagnostics.Process]::Start($newProcess);
# Exit from the current, unelevated, process
Exit;
}
# Run your code that needs to be elevated here...
Write-Host -NoNewLine "Press any key to continue...";
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown");
$newProcess.Arguments is indeed where you add the relevant parameters. However, you may want to run the script via the parameter -File instead of using the call operator (&) in an implicit -Command parameter.
$newProcess = New-Object Diagnostics.ProcessStartInfo 'powershell.exe'
$newProcess.Arguments = '-ExecutionPolicy RemoteSigned -File "' +
$script:MyInvocation.MyCommand.Path + '"'
$newProcess.Verb = 'runas'
[Diagnostics.Process]::Start($newProcess)

Getting error output from a powershell 2.0 script running as a task

TL:DR actual question is at the bottom
I'm trying to troubleshoot a Powershell v1.0 script issue. The script basically downloads a file from an FTP site and puts it on a remote server via UNC and emails the success or failure of the task.
The script runs as a task with a generic ID that is a Domain Admin but is not used to log into systems so the server it runs off of does not contain a profile for it.
If I do a runas for that user and execute the script via command line it works flawlessly. However, if I try to run it as a task it runs then exits instantly. If I open a runas command prompt and run the scheduled task vi at he command line all I get back is:
SUCCESS: Attempted to run the scheduled task "Task Name".
I've tried writing variable values to a text file to see what is going on but it never writes even when I write them as the very first step of execution.
What I want to do is capture any script error messages you would normally see when trying to run the script and/or write the variable information to a text file.
Is there any way to do this? BTW I doing via calling powershell with the following arguments:
-file -ExecutionPolicy Bypass "d:\datscript\myscript.ps1"
-I've tried -command instead of -file.
-I've tried "d:\datscript\myscript.ps1 5>&1 test.txt"
-I've tried "d:\datscript\myscript.ps1 9>&1 test.txt"
-I've tried "d:\datscript\myscript.ps1 | out-file d:\datscript\test.txt"
Nothing worked. I'm sure I can fix whatever bug I have but I'm banging my head against the wall trying to get some kind of failure info.
--Update: Here is a copy of the script minus details--
#-------------------------------------------------------------------------------------------------------------------------------------------------------------
#
#Variable Declaration
#
#$path = Path on local server to downlaod DAT to
#$olddat = Old/last DAT downloaded
#$currentdat = Next DAT number
#$ftpsite = McAfee FTP site. Update if path changes
#$ftpuser = FTP user (anon login)
#$ftppass = FTP password (anon login)
#$tempstring = Manipulation variable
#$gotdat = Boolean if updated DAT exists
#$success = Status if a new DAT exists and has been downloaded (used for email notification).
#$thetime = Variable use dto hold time of day manipulation.
$path = "\\myservername\ftproot\pub\mcafee\datfiles\"
$olddat = ""
$currentdat =""
$ftpsite = "ftp://ftp.nai.com/virusdefs/4.x/"
$ftpuser = "something"
$ftppass = "anything"
$tempstring =""
$gotdat = "False"
$success = ""
$thetime = ""
#
#Normalized functions handles UNC paths
#
function Get-NormalizedFileSystemPath
{
<#
.Synopsis
Normalizes file system paths.
.DESCRIPTION
Normalizes file system paths. This is similar to what the Resolve-Path cmdlet does, except Get-NormalizedFileSystemPath also properly handles UNC paths and converts 8.3 short names to long paths.
.PARAMETER Path
The path or paths to be normalized.
.PARAMETER IncludeProviderPrefix
If this switch is passed, normalized paths will be prefixed with 'FileSystem::'. This allows them to be reliably passed to cmdlets such as Get-Content, Get-Item, etc, regardless of Powershell's current location.
.EXAMPLE
Get-NormalizedFileSystemPath -Path '\\server\share\.\SomeFolder\..\SomeOtherFolder\File.txt'
Returns '\\server\share\SomeOtherFolder\File.txt'
.EXAMPLE
'\\server\c$\.\SomeFolder\..\PROGRA~1' | Get-NormalizedFileSystemPath -IncludeProviderPrefix
Assuming you can access the c$ share on \\server, and PROGRA~1 is the short name for "Program Files" (which is common), returns:
'FileSystem::\\server\c$\Program Files'
.INPUTS
String
.OUTPUTS
String
.NOTES
Paths passed to this command cannot contain wildcards; these will be treated as invalid characters by the .NET Framework classes which do the work of validating and normalizing the path.
.LINK
Resolve-Path
#>
[CmdletBinding()]
param (
[Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
[Alias('PSPath', 'FullName')]
[string[]]
$Path,
[switch]
$IncludeProviderPrefix
)
process
{
foreach ($_path in $Path)
{
$_resolved = $_path
if ($_resolved -match '^([^:]+)::')
{
$providerName = $matches[1]
if ($providerName -ne 'FileSystem')
{
Write-Error "Only FileSystem paths may be passed to Get-NormalizedFileSystemPath. Value '$_path' is for provider '$providerName'."
continue
}
$_resolved = $_resolved.Substring($matches[0].Length)
}
if (-not [System.IO.Path]::IsPathRooted($_resolved))
{
$_resolved = Join-Path -Path $PSCmdlet.SessionState.Path.CurrentFileSystemLocation -ChildPath $_resolved
}
try
{
$dirInfo = New-Object System.IO.DirectoryInfo($_resolved)
}
catch
{
$exception = $_.Exception
while ($null -ne $exception.InnerException)
{
$exception = $exception.InnerException
}
Write-Error "Value '$_path' could not be parsed as a FileSystem path: $($exception.Message)"
continue
}
$_resolved = $dirInfo.FullName
if ($IncludeProviderPrefix)
{
$_resolved = "FileSystem::$_resolved"
}
Write-Output $_resolved
}
} # process
} # function Get-NormalizedFileSystemPath
#
#Get the number of the exisiting DAT file and increment for next DAT if the DAT's age is older than today.
# Otherwise, exit the program if DATs age is today.
#
$tempstring = "xdat.exe"
$env:Path = $env:Path + ";d:\datscript"
$path2 ="d:\datscript\debug.txt"
add-content $path2 $path
add-content $path2 $olddat
add-content $path2 $currentdat
add-content $path2 $success
add-content $path2 " "
$path = Get-NormalizedFileSystemPath -Path $path
Set-Location -Path $path
$olddat = dir $path | %{$_.Name.substring(0, 4) }
$olddatfull = "$olddat" + "$tempstring"
if ( ((get-date) - (ls $olddatfull).LastWriteTime).day -lt 1)
{
#***** Commented out for testing!
# exit
}
$currentdat = [INT] $olddat
$currentdat++
$currentdat = "$currentdat" + "$tempstring"
add-content $path2 $olddat
add-content $path2 $currentdat
add-content $path2 $success
add-content $path2 " "
#
#Connect to FTP site and get a current directory listing.
#
[System.Net.FtpWebRequest]$ftp = [System.Net.WebRequest]::Create($ftpsite)
$ftp.Method = [System.Net.WebRequestMethods+FTP]::ListDirectoryDetails
$response = $ftp.getresponse()
$stream = $response.getresponsestream()
$buffer = new-object System.Byte[] 1024
$encoding = new-object System.Text.AsciiEncoding
$outputBuffer = ""
$foundMore = $false
#
# Read all the data available from the ftp directory stream, writing it to the
# output buffer when done. After that the buffer is searched to see if it cotains the expected
# lastest DAT.
#
do
{
## Allow data to buffer for a bit
start-sleep -m 1000
## Read what data is available
$foundmore = $false
$stream.ReadTimeout = 1000
do
{
try
{
$read = $stream.Read($buffer, 0, 1024)
if($read -gt 0)
{
$foundmore = $true
$outputBuffer += ($encoding.GetString($buffer, 0, $read))
}
} catch { $foundMore = $false; $read = 0 }
} while($read -gt 0)
} while($foundmore)
$gotdat = $outputbuffer.Contains($currentdat)
$target = $path + $currentdat
#
# Downloads DATs and cleans up old DAT file. Returns status of the operation.
# Return 1 = success
# Return 2 = Latest DAT not found and 4pm or later
# Return 3 = DAT available but did not download or is 0 bytes
# Return 4 = LatesT DAT not found and before 4pm
#
$success = 0
if ($gotdat -eq "True")
{
$ftpfile = $ftpsite + $ftppath + $currentdat
write-host $ftpfile
write-host $target
$ftpclient = New-Object system.Net.WebClient
$uri = New-Object System.Uri($ftpfile)
$ftpclient.DownloadFile($uri, $target)
Start-Sleep -s 30
if ( ((get-date) - (ls $target).LastWriteTime).days -ge 1)
{
$success = 3
}
else
{
$testlength = (get-item $target).length
if( (get-item $target).length -gt 0)
{
Remove-Item "$olddatfull"
$success = 1
}
else
{
$success = 3
}
}
}
else
{
$thetime = Get-Date
$thetime = $thetime.Hour
if ($thetime -ge 16)
{
$success = 2
}
else
{
$success = 4
exit
}
}
#
# If successful download (success = 1) run push bat
#
if ($success -eq 1)
{
Start-Process "cmd.exe" "/c c:\scripts\mcafeepush.bat"
}
#Email structure
#
#Sends result email based on previous determination
#
#SMTP server name
$smtpServer = "emailserver.domain.com"
#Creating a Mail object
$msg = new-object Net.Mail.MailMessage
#Creating SMTP server object
$smtp = new-object Net.Mail.SmtpClient($smtpServer)
$msg.From = "email1#domain.com"
$msg.ReplyTo = "email2#domain.com"
$msg.To.Add("email2#domain.com")
switch ($success)
{
1 {
$msg.subject = "McAfee Dats $currentdat successful"
$msg.body = ("DAT download completed successfully. Automaton v1.0")
}
2 {
$msg.subject = "McAfee DATs Error"
$msg.body = ("Looking for DAT $currentdat on the FTP site but I coud not find it. Human intervention may be required. Automaton v1.0")
}
3 {
$msg.subject = "McAfee DATs Error"
$msg.body = ("$currentdat is available for download but download has failed. Human intervention will be required. Automaton v1.0")
}
default {
$msg.subject = "DAT Automaton Error"
$msg.body = ("Something broke with the McAfee automation script. Human intervention will be required. Automaton v1.0")
}
}
#Sending email
$smtp.Send($msg)
#Needed to keep the program from exiting too fast.
Start-Sleep -s 30
#debugging stuff
add-content $path2 $olddat
add-content $path2 $currentdat
add-content $path2 $success
add-content $path2 " "
Apparently you have an error in starting Powershell, either because execution policy is different on the Powershell version you start, or on the account, or there is an access error on the scheduled task. To gather actual error, you can launch a task like so:
cmd /c "powershell.exe -file d:\datscript\myscript.ps1 test.txt 2>&1" >c:\windows\temp\test.log 2&>1
This way if there would be an error on starting Powershell, it will be logged in the c:\windows\temp\test.log file. If the issue is in execution policy, you can create and run (once) a task with the following:
powershell -command "Get-ExecutionPolicy -List | out-file c:/windows/temp/policy.txt; Set-ExecutionPolicy RemoteSigned -Scope LocalMachine -Force"
Running a task under the account you plan to run your main task will first get the policies in effect (so that if setting machine-level policy won't help, you'll know what scope to alter) and set machine-level policy to "RemoteSigned", the least restrictive level beyond allowing every script (highly not recommended, there are encoder scripts written on Powershell that can ruin your data).
Hope this helps.
UPDATE: If that's not policy, there might be some errors in properly writing the parameters for the task. You can do this: Create a .bat file with the string that launches your script and redirects output to say test1.txt, then change the scheduled task to cmd.exe -c launcher.bat >test2.txt, properly specifying the home folder. Run the task and review both files, at least one of them should contain an error that prevents your script from launching.

Powershell to install .\file errors, but when given full location C:\Users.... doesn't error

I have a script below that errors when trying to access a file, however if I change the location of the .msi file in the -argumentlist to a full address it succeeds, but I can't have it run like that as the address will change when I submit it to be packaged for SCCM deployment.
Function Get-OSCComputerOU
{
$ComputerName = $env:computername
$Filter = "(&(objectCategory=Computer)(Name=$ComputerName))"
$DirectorySearcher = New-Object System.DirectoryServices.DirectorySearcher
$DirectorySearcher.Filter = $Filter
$SearcherPath = $DirectorySearcher.FindOne()
$DistinguishedName = $SearcherPath.GetDirectoryEntry().DistinguishedName
$OUName = ($DistinguishedName.Split(","))[1]
$OUMainName = $OUName.SubString($OUName.IndexOf("=")+1)
$OUMainName
}
$strOU = Get-OSCComputerOU
$strTrueOU=$strOU.split('_')[1]
$strCSV=Import-Csv \\SERVER\SHARE\FOLDER\CSV.csv
$strRoomChannel=$strCSV | where {$_.Room -eq $strTrueOU} | % channel
IF ($strRoomChannel){
$strRoomFoundArg="/i .\Installers\MSI.msi CHANNEL=$strRoomChannel"
Start-Process msiexec -ArgumentList $strRoomFoundArg -wait
} ELSE {
msg * "Channel is missing, and can not install correctly, please call tech support on Ext: to have this rectified, it's a quick fix."
}
When I use a full address such as below, it installs fine.....what's the deal.
Function Get-OSCComputerOU
{
$ComputerName = $env:computername
$Filter = "(&(objectCategory=Computer)(Name=$ComputerName))"
$DirectorySearcher = New-Object System.DirectoryServices.DirectorySearcher
$DirectorySearcher.Filter = $Filter
$SearcherPath = $DirectorySearcher.FindOne()
$DistinguishedName = $SearcherPath.GetDirectoryEntry().DistinguishedName
$OUName = ($DistinguishedName.Split(","))[1]
$OUMainName = $OUName.SubString($OUName.IndexOf("=")+1)
$OUMainName
}
$strOU = Get-OSCComputerOU
$strTrueOU=$strOU.split('_')[1]
$strCSV=Import-Csv \\SERVER\SHARE\FOLDER\CSV.csv
$strRoomChannel=$strCSV | where {$_.Room -eq $strTrueOU} | % channel
IF ($strRoomChannel){
$strRoomFoundArg="/i C:\Users\USERNAME\Desktop\Installers\MSI.msi CHANNEL=$strRoomChannel"
Start-Process msiexec -ArgumentList $strRoomFoundArg -wait
} ELSE {
msg * "Channel is missing, and can not install correctly, please call tech support on Ext: to have this rectified, it's a quick fix."
}
I get this error:
The difference between the two is that '.' is going to be resolved by the process you are calling, msiexec, which, like most processes, is going to use the process's CurrentDirectory for '.', which is different than the current location in PowerShell. You can see the difference if you compare Get-Location and [Environment]::CurrentDirectory] in PowerShell. They will be different if you start powershell and change the directory using Set-Location (aka cd).
The solution is to resolve the path in PowerShell before sending it over to msiexec:
$path = Convert-Path .\Installers\MSI.msi
$strRoomFoundArg = "/i `"$path`" CHANNEL=$strRoomChannel"
Start-Process msiexec -ArgumentList $strRoomFoundArg -wait
Turns out the script wasn't happy with the .\ in front of the MSI file.
If I kept the .\ I would get the error.
If I removed the .\ and just had MSI.msi then it worked fine.
I failed to mention that I had changed the active directory to my desktop to execute the script, my apologies #mike z
Thank you very much for your input however.