Command not found when execute powershell script from IIS - powershell

I have a script that gets the citrix sessions for a relation on our platform.
The problem is that when I run the script from the console on the webserver, the executing of the script is succesfull and the result is as expected.
When I run the script from my website (hosted on IIS) the result is as follows:
"The term 'Get-XASession' is not recognized as the name of a cmdlet, function, script file, or operable program."
This is the script:
#----------------------------------------------------------
# PARAMS TO CALL SCRIPT WITH
#----------------------------------------------------------
Param(
[string]$relationId,
[string]$xaVersion,
[string]$xaServer
)
#----------------------------------------------------------
# LOAD ASSEMBLIES AND MODULES
#----------------------------------------------------------
try
{
Import-Module "C:\Program Files\Citrix\XenApp 6.5 Server SDK\Citrix.XenApp.Sdk.ps1"
. "D:\scripts\include\functions.ps1"
}
catch
{
return "[ERROR]`t Import module XenApp 6.5 Server SDK gives an error $($_.Exception)"
}
#----------------------------------------------------------
#START
#----------------------------------------------------------
Set-ExecutionPolicy Unrestricted
try
{
if ($xaVersion -eq "XA65")
{
$sessions = Get-XASession -ComputerName $xaServer | Where-Object { $_.AccountName -like "ASPECT\$relationId*" }
$listSessions = #()
foreach($se in $sessions)
{
New-Object psobject -Property #{AccountName = $se.AccountName; SessionId = $se.SessionId; Name = $se.BrowserName; ClientName = $se.ClientName; ServerName = $se.ServerName; LogonTime = $se.LogonTime; Status = $se.State}
}
return $listSessions
}
}
catch
{
return "[ERROR]`t Sessies ophalen voor gebruiker $samAccountName met XAversie $xaVersion gives the following error $($_.Exception)"
}
The identity of the IIS Application Pool is the same as the identity that I used to run the script from the console.
That user has all the rights it needs to access the Citrix XenApp module.
The wierd thing is, when I say Get-Command Get-XASession -neq $null then the script says, hé I know that command lets go to execute it. When it is going to execute it then the sripts says, huh Get-XASession? never hurt of.
I spent hours and hours and I don't have a clue.
Please help me!

jisaak did put me in the right direction.
Dot sourcing could be the answer but that gives an error about user interaction.
This is wat I did: I opened the module and copied everything except the write-host lines into my script. I did run it and guess what, it works!
So if you experience the same problem as me:
1. try dot sourcing
2. try to copy the content of the module into your script.
All credits go to jisaak (Y) :)

Related

Check if given process is running with elevated right with powershell and Get-WmiObject

I have to following part of my script:
$active_processes = (Get-WmiObject -Class Win32_Process | where path -like $path | Select-Object -ExpandProperty Path | split-path -leaf | Select-Object -Unique)
It's working fine but I need to check if the process I get after all the script is running with elevated rights to launch another process with elevated rights if neccesary so it can interact with said process. I don't see any information about elevated rights with Get-WmiObject, I was wondering if I'm missing it or if there's another way to get that information
I don't need to run the powershell script as administrator. What I need is to find ff any executable requires elevated rights when launched and I need to find this information via powershell.
After some research on how windows knows if it needs admin to run an executable, I concluded that there are a couple ways but the most recommended and reliable is reading the executable manifest, so I wrote the following function:
function Get-ManifestFromExe{
Param(
[Parameter(Mandatory=$true,Position=0,ValueFromPipelineByPropertyName=$true)]
[Alias("Path")]
[ValidateScript({Test-Path $_ -IsValid})]
[String]$FullName
)
begin{
$stringStart = '<assembly'
$stringEnd = 'assembly>'
}
process{
$content = Get-Content $FullName -Raw
$indexStart = $content.IndexOf($stringStart)
$content = $content.Substring($indexStart)
$indexEnd = ($content.IndexOf($stringEnd)) + $stringEnd.Length
$content = $content.Substring(0,$indexEnd)
if($content -match "$stringStart(.|\s)+(?=$stringEnd)$stringEnd"){
return [XML]$Matches[0]
}
}
}
function Test-IsAdminRequired{
Param(
[Parameter(Mandatory=$true,Position=0)]
[XML]$xml
)
$value = $xml.assembly.trustInfo.security.requestedPrivileges.requestedExecutionLevel.level
if(-not [String]::IsNullOrEmpty($value)){
return ($value -eq "requireAdministrator" -or $value -eq "highestAvailable")
}else{
Write-Error "Provided xml does not contain requestedExecutionLevel node or level property"
}
}
$exe = '.\Firefox Installer.exe'
Get-ManifestFromExe -Path $exe
Test-IsAdminRequired -xml $exeManifest
It works by extracting the manifest XML from the executable and checking requestedExecutionLevel node's level property, the values accepted for this property are in this page, and quoted here:
asInvoker, requesting no additional permissions. This level requires
no additional trust prompts.
highestAvailable, requesting the highest permissions available to the
parent process.
requireAdministrator, requesting full administrator permissions.
So from this we can conclude that only highestAvailable and requireAdministrator would need admin privileges, so I check those, with that we will be done EXCEPT that some executables I tested (mostly installers) don't require admin to run but instead they prompt the UAC when they ruin their child executable, I don't really see a way to check this.. sorry.
BTW I really enjoyed this question (specially the research), hope this can help you.
SOURCES
What is the difference between "asInvoker" and "highestAvailable" execution levels?
reading an application's manifest file?
https://learn.microsoft.com/en-us/visualstudio/deployment/trustinfo-element-clickonce-application?view=vs-2019#requestedexecutionlevel
It's in the System.Security.Principal classes. This returns $true if the current user is elevated to local Administrator:
(New-Object System.Security.Principal.WindowsPrincipal([System.Security.Principal.WindowsIdentity]::GetCurrent())).IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)

How to determine if Write-Host will work for the current host

Is there any sane, reliable contract that dictates whether Write-Host is supported in a given PowerShell host implementation, in a script that could be run against any reasonable host implementation?
(Assume that I understand the difference between Write-Host and Write-Output/Write-Verbose and that I definitely do want Write-Host semantics, if supported, for this specific human-readable text.)
I thought about trying to interrogate the $Host variable, or $Host.UI/$Host.UI.RawUI but the only pertinent differences I am spotting are:
in $Host.Name:
The Windows powershell.exe commandline has $Host.Name = 'ConsoleHost'
ISE has $Host.Name = 'Windows PowerShell ISE Host'
SQL Server Agent job steps have $Host.Name = 'Default Host'
I have none of the non-Windows versions installed, but I expect they are different
in $Host.UI.RawUI:
The Windows powershell.exe commandline returns values for all properties of $Host.UI.RawUI
ISE returns no value (or $null) for some properties of $Host.UI.RawUI, e.g. $Host.UI.RawUI.CursorSize
SQL Server Agent job steps return no values for all of $Host.UI.RawUI
Again, I can't check in any of the other platforms
Maintaining a list of $Host.Name values that support Write-Host seems like it would be bit of a burden, especially with PowerShell being cross-platform now. I would reasonably want the script to be able to be called from any host and just do the right thing.
Background
I have written a script that can be reasonably run from within the PowerShell command prompt, from within the ISE or from within a SQL Server Agent job. The output of this script is entirely textual, for human reading. When run from the command prompt or ISE, the output is colorized using Write-Host.
SQL Server jobs can be set up in two different ways, and both support capturing the output into the SQL Server Agent log viewer:
via a CmdExec step, which is simple command-line execution, where the Job Step command text is an executable and its arguments, so you invoke the powershell.exe executable. Captured output is the stdout/sterr of the process:
powershell.exe -Command x:\pathto\script.ps1 -Arg1 -Arg2 -Etc
via a PowerShell step, where the Job Step command text is raw PS script interpreted by its own embedded PowerShell host implementation. Captured output is whatever is written via Write-Output or Write-Error:
#whatever
Do-WhateverPowershellCommandYouWant
x:\pathto\script.ps1 -Arg1 -Arg2 -Etc
Due to some other foibles of the SQL Server host implementation, I find that you can emit output using either Write-Output or Write-Error, but not both. If the job step fails (i.e. if you throw or Write-Error 'foo' -EA 'Stop'), you only get the error stream in the log and, if it succeeds, you only get the output stream in the log.
Additionally, the embedded PS implementation does not support Write-Host. Up to at least SQL Server 2016, Write-Host throws a System.Management.Automation.Host.HostException with the message A command that prompts the user failed because the host program or the command type does not support user interaction.
To support all of my use-cases, so far, I took to using a custom function Write-Message which was essentially set up like (simplified):
$script:can_write_host = $true
$script:has_errors = $false
$script:message_stream = New-Object Text.StringBuilder
function Write-Message {
Param($message, [Switch]$iserror)
if ($script:can_write_host) {
$private:color = if ($iserror) { 'Red' } else { 'White' }
try { Write-Host $message -ForegroundColor $private:color }
catch [Management.Automation.Host.HostException] { $script:can_write_host = $false }
}
if (-not $script:can_write_host) {
$script:message_stream.AppendLine($message) | Out-Null
}
if ($iserror) { $script:has_errors = $true }
}
try {
<# MAIN SCRIPT BODY RUNS HERE #>
}
catch {
Write-Message -Message ("Unhandled error: " + ($_ | Format-List | Out-String)) -IsError
}
finally {
if (-not $script:can_write_host) {
if ($script:has_errors) { Write-Error ($script:message_stream.ToString()) -EA 'Stop' }
else { Write-Output ($script:message_stream.ToString()) }
}
}
As of SQL Server 2019 (perhaps earlier), it appears Write-Host no longer throws an exception in the embedded SQL Server Agent PS host, but is instead a no-op that emits nothing to either output or error streams. Since there is no exception, my script's Write-Message function can no longer reliably detect whether it should use Write-Host or StringBuilder.AppendLine.
The basic workaround for SQL Server Agent jobs is to use the more-mature CmdExec step type (where Write-Output and Write-Host both get captured as stdout), but I do prefer the PowerShell step type for (among other reasons) its ability to split the command reliably across multiple lines, so I am keen to see if there is a more-holistic, PowerShell-based approach to solve the problem of whether Write-Host does anything useful for the host I am in.
Just check if your host is UserInteractive or an service type environment.
$script:can_write_host = [Environment]::UserInteractive
Another way to track the output of a script in real time is to push that output to a log file and then monitor it in real time using trace32. This is just a workaround, but it might work out for you.
Add-Content -Path "C:\Users\username\Documents\PS_log.log" -Value $variablewithvalue

Service cannot be started due to the following error: Cannot open service on computer '.'

I'm trying to Start a service using Powershell and using the code below
function CheckServiceStatus {
param($winupdate)
$getservice = Get-Service -Name $winupdate
if($getservice.Status -ne $running){
stop-service $winupdate
Start-Service $winupdate
Write-output "Starting" $winupdate "service"|out-file "C:\Users\Mani\Desktop\abc.txt"
Add-Content C:\Users\Mani\Desktop\abc.txt $getservice.Status
}
}
Read-Host -Prompt "Press Enter to exit"
#Variables
$winupdate = 'vsoagent.192.Shalem'
$running = 'Running'
CheckServiceStatus $winupdate
I got the following error:
Service 'ABC' cannot be stopped due to the following error: Cannot
open ABC service on computer '.'
I found some link here on our forum but couldn't resolve. Please suggest
If you want to start/stop/etc services, you need elevated privileges (run as Admin). You can still get information about the service, but that's it. If you want to include a more verbose error, include this:
$isadmin = [bool](([System.Security.Principal.WindowsIdentity]::GetCurrent()).groups -match "S-1-5-32-544")
if($isadmin){
Write-Error "You need elevated privileges to run this script"
exit(1)
}
...
Rest of your code
Or even better, if you're running Powershell 4.0 or higher (You can get it by checking $PSVersionTable), you can include
#Requires -RunAsAdministrator
At the top of your file, and you won't be able to run it without admin privilages.
I had this issue while running the command on PowerShell ISE. All I did was start the PowerShell ISE as an administrator.
Look into Event Viewer and find more details. In my case, I have found relevant info in Administrative Events, then Service Control Manager. The error was related to insufficient privileges given for the account. The service was creating a new file and this task failed. Of course, your error's details are probabably different, but that is the tip.

DSC Script Resource's TestScript failing to return boolean

Trying to push DSC I'm hitting the following error:
Failure to get a valid result from the execution of TestScript. The Test script should return True or False.
Here's the TestScript:
return (Test-Path -Path "FullPath:\To\File")
A couple things I've tried:
The Script resource has a (unmanaged) service account's credentials specified in the Credential parameter. Thinking it might not have permissions to the directory, causing Test-Path to error, I launched powershell as the user on the target machine and ran the cmdlet. It returned False (as expected). I've since made sure that the configuration gives the account permissions to the folder anyways.
Thinking it might be some weird idiosyncrasy with returning the cmdlet, I tried assigning the cmdlet to a variable and returning that. No dice.
Any ideas would be appreciated.
Edit: Here's the full resource, for those curious. It's basically just a couple quick lines to pull a script out of source control and place it locally so that I can create a scheduled task to run said script. Casting the result to a bool didn't work (same error). I'm wondering if it's even getting inside the TestScript at this point...checking get-executionpolicy shows it as undefined for the account but at the userpolicy, machinepolicy and localmachine level they're all bypass.
Script NameOfScript {
DependsOn = "[cNtfsPermissionEntry]DirectoryPermissions"
Credential = $serviceAccountPSCredentialObject
SetScript = {
Import-Module -Name Subversion
New-SvnWorkingCopy -Url "https://svnrepourl/script.ps1" -Path "E:\Scripts\"
}
TestScript = {
[bool]$result
$result = Test-Path -Path "E:\Scripts\script.ps1" -ErrorAction Stop
return $result
}
GetScript = { }
}
Try this
return ([bool]$testPath = Test-Path -Path "FullPath:\To\File")
Figured it out, with the help of this forum post. Initially I didn't think it'd be much help since I shouldn't be experiencing double-hop issues, but I'll explain why it's germane below. #TravisEz13 made the comment that the Credential parameter isn't used, but that is incorrect.
If you look at the Script resource, when you specify credentials this is how it runs the script blocks:
$scriptExecutionResult = Invoke-Command -ScriptBlock $ScriptBlock -ComputerName . -Credential $Credential
The service account in question doesn't have remote access to the machine. So when I launch powershell locally as that user and run the Test-Path cmdlet, it works, but when I try to run the above Invoke-Command with that account's creds, it returns an access denied error.
My solution was to write a module/resource for subversion checkout. Not just to get around this, but also because the subversion powershell module I was using above doesn't provide a means to pass credentials to the svn binary.

PowerShell Script Ends in SQLSERVER:\>

I have a powershell script that does a Invoke-Sqlcmd and when the script completes it leaves me in 'SQLSERVER:>'.
Is there a way to tell my script to return me to original directory when it completes?
The canonical method for this is:
try {
$private:oldLocation = (Get-Location)
# Do Stuff
}
finally {
Set-Location $private:oldLocation
}
Import-Module SQLPS -DisableNameChecking | Out-Null
Push-Location "SQLSERVER:\sql\$Server\DEFAULT\databases\$database" | Out-Null
Invoke-Sqlcmd -Query $query
#More Work
pop-location
Alternatively you could push the location of the database you want to run queries/operations onto the location stack. Do work. Then pop the location off the location stack when done.
$Server : Being the server the db is being hosted on
$database : The database name in your database server
The Out-Null isn't required. It just prevents output being pumped into the pipeline
My preferred method is to do this:
try {
Push-Location
Import-Module SQLPS
# More code
} finally {
Pop-Location
}
This is especially nice during testing because even when you throw an exception or stop the debugger your original path is still restored.