Powershell Help

I am trying to get some powershell scripts written by IBM to work on my IEM instance. I have tried serval variations to get the scripts to run, but nothing seems to work.

Here is my current fixlet.

if {name of operating system as lowercase contains “win” and architecture of operating system = “x86”}

regset “HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell” “ExecutionPolicy”=“Unrestricted”

//64bit

else

regset “HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell” “ExecutionPolicy”=“Unrestricted”

endif

if {name of operating system as lowercase contains “win” and architecture of operating system = “x86”}

waithidden cmd.exe /C “powershell.exe” scriptsrunner.ps1

else

waithidden cmd.exe /C “C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe” scriptsrunner.ps1

endif

It shows that it completes successfully, but it never actually runs the powershell script.

Here is the actual script that I am trying to get to run. This scripts also calls serveral others depending on what it finds.

Any help would be greatly appreciated.

#************* Begin Standard Header - Do not add comments here** ***************
#
# Licensed Materials - Property of IBM
#
# Restricted Materials of IBM
#
# 5724-N55
#
# © COPYRIGHT IBM CORP. 2013. All Rights Reserved.
#
# US Government Users Restricted Rights - Use, duplication or
# disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
#
# **************************** End Standard Header *******************************

#files
$ASDTEMPDIR="%windir%\temp\taddm7.3\asd"
# Resolve ASD path if include system enviroment variables
if($ASDTEMPDIR -match “%[\w-]+%”){
$newPath = New-Object System.Text.StringBuilder
$path=$ASDTEMPDIR.Split("")
$index=0
$path |foreach{
$index++
if($_ -match “%[\w-]+%”){
$resolvedPath=[System.Environment]::ExpandEnvironmentVariables($_)
$newPath.append("$resolvedPath")|Out-Null
}
else{
$newPath.append("$_")|Out-Null
}
if($index -lt $path.Count){
$newPath.append("")|Out-Null
}

**}**
**$ASDTEMPDIR=$newPath.ToString()**

}
if(!(Test-Path -Path $ASDTEMPDIR)){
New-Item -Path “$ASDTEMPDIR” -type directory -ErrorAction SilentlyContinue -ErrorVariable err| Out-Null
if($err){
Write-Output "Unable to create $ASDTEMPDIR directory : $err"
return
}
}

$MAIN="$ASDTEMPDIR\tmpoutput.txt"
$ALLERRORS="$ASDTEMPDIR\allerrors.txt"
$ERRORFILE=“output.txt”

$hostname=gwmi -Namespace root\CIMV2 Win32_ComputerSystem -ErrorAction SilentlyContinue | Select Name
$asdFile=“taddmasd-”+$hostname.Name+"-"+(Get-Date -Format “yyMMddHHmm”)
$OUTPUTDIR="$ASDTEMPDIR$asdFile" ## temporary

## if exist, remove old allerrors.txt file
if(Test-Path $ALLERRORS){
Remove-Item $ALLERRORS
}
#########################################
function createItem($name, $cmd, $data, $err){
$UnicodeBomEncoding = New-Object System.Text.UnicodeEncoding($false, $true)
$fileMain=New-Object System.IO.StreamWriter -ArgumentList $MAIN,$false,$UnicodeBomEncoding
$fileMain.WriteLine(“TADDM_DATA_NAME”)
$fileMain.WriteLine($name)
$fileMain.WriteLine(“TADDM_DATA_TYPE”)
$fileMain.WriteLine(“COMMAND”)
$fileMain.WriteLine(“TADDM_DATA_COMMAND”)
$fileMain.WriteLine($cmd)
$fileMain.WriteLine(“TADDM_DATA_VALUE”)
foreach($item in $data){
if($item){
$fileMain.WriteLine($item)
}
else{
$fileMain.WriteLine("")
}
}
$fileMain.WriteLine(“TADDM_DATA_EXITCODE”)
if($err){
$fileMain.WriteLine(“1”)
}
else{
$fileMain.WriteLine(“0”)
}
$fileMain.WriteLine(“TADDM_DATA_ERROR”)
if($err){
$fileMain.WriteLine($err)
}
else{
$fileMain.WriteLine("")
}
$fileMain.WriteLine(“TADDM_DATA_END”)
$fileMain.close()}

function runCmd($name, $cmd){
$EC=0
$ErrorActionPreference='Stop’
try{
$data=Invoke-Expression “$cmd”
}catch {
##terminating error, command failedD7ominika
$err=$error[0]
$EC=1
}
$ErrorActionPreference='Continue’
createItem $name $cmd $data $err
reportErrors $err
}

function logError($name, $err){
$data=""
$cmd=""
$EC=1
createItem $name $cmd $data $err
reportErrors $err
}

function reportErrors($err){
if($err){
$UnicodeBomEncoding = New-Object System.Text.UnicodeEncoding($false, $true)
$fileAllErrors=New-Object System.IO.StreamWriter -ArgumentList $ALLERRORS,$true,$UnicodeBomEncoding
$fileIn = New-Object -typename System.IO.StreamReader -argumentlist $MAIN
$fileAllErrors.WriteLine($fileIn.ReadToEnd())
$fileIn.close()
$fileAllErrors.close()
}
}

#########################################

function runSensorScript ($sensor, $script){
Write-Output “[$sensor, $script]”
$ERRORFILEPATH="${OUTPUTDIR}$sensor$ERRORFILE"
$EC=0

**runCmd "executeMainScript" "powershell.exe -noprofile -file .\$sensor\$script"**
**if($EC -eq 1){**
    **return**
**}**

**## find scripts number to run**
**$commonContent=[IO.File]::ReadAllText($MAIN)**
**$pattern='(?s)^.+(TADDM_DATA_VALUE)(.*)(TADDM_DATA_EXITCODE).+$'**
**if($commonContent -match $pattern){**
    **$scriptInfo=$Matches[2].Trim().Split("`n")**
    **$list=New-Object System.Collections.ArrayList(,$scriptInfo)**
**}**
**else{**
    **Write-Output "Unexpected executeMainScript output for $script"**
    **return**
**}**
**[int]$scriptsCount=$list.Count/3**

**if($scriptsCount -gt 0){**
    **New-Item -Path "$OUTPUTDIR\$sensor" -type directory -ErrorAction SilentlyContinue -ErrorVariable err| Out-Null**
    **if($err){**
        **Write-Output "Unable to create $OUTPUTDIR\$sensor directory"**
        **return**
    **}**
    **Copy-Item "$sensor\*" "$OUTPUTDIR\$sensor" -ErrorAction SilentlyContinue -ErrorVariable err**
    **if($err){**
        **Write-Output "Unable to copy scripts to $OUTPUTDIR\$sensor directory"**
        **return**
    **}**
**}**

**$index=0**
**while($index -lt $scriptsCount){**
    **$index++**
    **$script=$list.get_Item(0).Replace('SCRIPT:','').Trim()**
    **$user=$list.get_Item(1).Replace('USER:','').Trim()**
    **$params=$list.get_Item(2).Replace('PARAMS:','').Trim()**
    **Write-Output "$script $user $params"**
    **if(Test-Path -Path "$OUTPUTDIR\$sensor\$script"){**
        **$INST_OUTPUT="$OUTPUTDIR\$sensor\out$index"**
        **New-Item -Path $INST_OUTPUT -type directory -ErrorAction SilentlyContinue -ErrorVariable err| Out-Null**
        **if($err){**
            **return**
        **}**
        **if($user.Length -eq 0){**
            **## run script for session user**
            **runCmd "instanceScript" "$OUTPUTDIR\$sensor\$script $INST_OUTPUT $PARAMS"**
            **if($EC -eq 1){**
                **## error during script execution**
                **Get-Content $MAIN | Out-File -FilePath $ERRORFILEPATH -Append**
            **}**
        **}**
        **else{**
            **Write-Output "Windows ASD discovery does not support non-admin users"**
        **}**
    **}**
    **else{**
        **logError "checkFileExists" "There is no regular script file named $OUTPUTDIR\$sensor\$script"**
        **Get-Content $MAIN | Out-File -FilePath $ERRORFILEPATH -Append**
    **}**
    **$list.RemoveRange(0,3)**
**}**
**##end while**

}
runSensorScript com.ibm.cdb.discover.sensor.app.mq.mqserver_7.6.0 sensorCommon.ps1
runSensorScript com.ibm.cdb.discover.sensor.asd.asdsensor_1.2.0 sensorCommon.ps1
runSensorScript com.ibm.cdb.discover.sensor.app.exchange.exchange_1.1.0 sensorCommon.ps1
runSensorScript com.ibm.cdb.discover.sensor.sys.windowscomputersystem_7.3.0 sensorCommon.ps1
runSensorScript com.ibm.cdb.discover.sensor.app.genericserver_7.6.0 sensorCommon.ps1
runSensorScript com.ibm.cdb.discover.sensor.app.j2ee.jboss7_1.0.0 sensorCommon.ps1
runSensorScript com.ibm.cdb.discover.sensor.app.web.iisserver_1.0.0 sensorCommon.ps1

########################## Create archive file #####################
if(Test-Path $OUTPUTDIR){
$zipDirectory = Get-Item $OUTPUTDIR
$zipfilename="$OUTPUTDIR.zip"
set-content $zipfilename (“PK” + [char]5 + [char]6 + ("$([char]0)" * 18))
(dir $zipfilename).IsReadOnly = $false
$shellApplication = new-object -com shell.application
$zipPackage = $shellApplication.NameSpace($zipfilename)
$zipPackage.CopyHere($zipDirectory.FullName)
#copyHere works asynchronously, short sleep is required
Start-Sleep -Seconds 4
}

########################## ASD statistics ##########################
if((Test-Path $ALLERRORS)-and(Get-Item $ALLERRORS).length -gt 0){
Write-Output “Execution finished with errors, check $ALLERRORS”
}
else{
Write-Output "Execution completed successfully."
Write-Output “Output file created: $zipfilename”
}
########################## Remove temporary files #####################
if(Test-Path -Path $MAIN){
Remove-Item -Path $MAIN
}
if(Test-Path -Path $OUTPUTDIR){
Remove-Item -Path $OUTPUTDIR -Recurse
}

1 Like

Try running it without the “cmd.exe /C”.

waithidden "C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe" "Path\to\script\scriptsrunner.ps1"

I changed it to this.

waithidden “C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe” "{pathname of storage folder of client}\taddmasd\scriptsrunner.ps1

Actually came back completed faster, never say it go to a running state, if I did this

waithidden “C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe” scriptsrunner.ps1

it stayed in a running state for a bit, but never actually kicked off the Powershell script.

Is the script your using being downloaded or created with the action or is it sitting in a folder on the client before the action?

It is downloaded and sitting on the client prior to the action, in this case E:\Program Files (x86)\BigFix Enterprise\BES Client\taddmasd However, it isn’t always installed in the same place.

Ummm did you read the header of the script you posted?

#
# Licensed Materials - Property of IBM
#
# Restricted Materials of IBM
#
# 5724-N55
#
# © COPYRIGHT IBM CORP. 2013. All Rights Reserved.
#
# US Government Users Restricted Rights - Use, duplication or
# disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
#

In any case, I’ve run into my own issues where ‘waithidden’ can give odd behavior depending upon the number of quoted parameters on the line, varying between which type of process is being created the parameters aren’t passed correctly or it fails to launch at all. What I end up doing for this is creating a one-line batch file, and then using waithidden to execute the batch. For instance

delete __appendfile
appendfile “C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe” scriptsrunner.ps1
delete "RunIt.cmd"
move __appendfile RunIt.cmd
waithidden cmd /c RunIt.cmd > c:\log.txt 2>&1

By setting up the output redirection, you’ll at least have an error message you can work with if the script fails to execute.

While we’re looking at this, you should be able to collapse the following into one line:
if {name of operating system as lowercase contains “win” and architecture of operating system = “x86”}

waithidden cmd.exe /C “powershell.exe” scriptsrunner.ps1

else

waithidden cmd.exe /C “C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe” scriptsrunner.ps1

endif

–instead:

“{pathname of file “powershell.exe” of folder “WindowsPowerShell\v1.0” of system folder}” scriptsrunner.ps1

‘system folder’ should evaluate to either system32 or syswow64, depending on architecture, so long as you haven’t used ‘action uses wow64 redirection false’.

That sounds like a problem that should definitely get figured out first. This sounds like BigFix is just not fithe nding the script to run and this may be caused by the differences in 32/64-bit folders/registry and how BigFix client reads your action script.

I’ve dipped into this about a year ago with powershell and the issues that I came across were all tied into 32/64-bit snaffus in the action script. 32/64-bit folder location and 32/64-bit
powershell version. Once that got straightened, clear sailing.

I would give this a read if you aren’t familiar yet and modify your action script accordingly.
https://www.ibm.com/developerworks/community/wikis/home?lang=en#!/wiki/Tivoli%20Endpoint%20Manager/page/Using%20WOW64%20Redirection

I’ve used the WOW6432 path when setting reg values initially and it can get dicey. I suggest using regset64 instead of just regset to set the 64-bit reg values.

I would also recommend copying the file to c:\windows\temp and ensuring it is there first. Then when you run the powershell.exe command, include the flag “-executionpolicy bypass” and the path to the file. I don’t have my console open and am doing this from home, so I’m not 100% sure if this is the correct syntax but it should be in the ball park

action uses wow64 redirection {not x64 of operating system}
run cmd.exe /C “C:\Windows\WindowsPowerShell\v1.0\powershell.exe” -executionpolicy bypass “c:\windows\temp\nameofscript.ps1”

2 Likes

This is where I would agree. Usually you can direct BigFix to run the script by inserting a “pathname of” relevance because, since the script is being pulled down with the task, the action knows where the script should be because it put it there so try this:

waithidden "C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe" "{(client folder of current site as string) & "\__Download\scriptsrunner.ps1"}"
1 Like

I have had issues myself trying to get scripts to run by invoking PowerShell from the command line. The line I usually use is this:

powershell.exe -ExecutionPolicy Bypass -Command "PATH\TO\SCRIPT.ps1"

I would assume dropping a waithidden in front and modifying your paths with the appropriate substitution would work.

Also, if you are working on a US Government system it more than likely is STIG’d and has some sort of HBSS running on it. I know that it is common policy to not allow anything to execute out of the TEMP directory. Not sure about calling scripts from that directory as I have not tried it. Just a heads up if you try to go that route.

1 Like

@jjusmc It should be noted that not all government agencies adopt all STIGs because some are considered “too stringent”. They SHOULD adopt them all but not all do.

@jmaple Agreed. Just an extra place to look should @tjessee run into issues.

combine @cdh and @jmaple 's answers:

waithidden "C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe" -executionpolicy bypass "{(client folder of current site as string) & "\__Download\scriptsrunner.ps1"}"

You should use the executionpolicy bypass regardless of the settings on the particular machine just in case, and you should use the full path to the ps1 file.

@jgstew and @cdh, @jmaple

I have tried all of the different methods with still the same outcome. It appears to be doing something, but nothing ever happens. I does not kick off powershell, as I have task manager open and watching to see if powershell actually ever runs.

I have even tried waithidden cmd.exe /C “{(client folder of current site as string) & “__Download\scriptsrunner.bat”}” with the supplied bat file

powershell.exe Invoke-Command -ScriptBlock {Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force -Scope Process; .\scriptsRunner.ps1}

It does the same thing, says running for a time, but never executes the powershell command to initiate the scan.

Thank you very much for all the help, hopefully something will get this to work.

Does it work if you do it on the command line?

Does it work if you execute it as the system account using PSExec?

Try running a single command using powershell to write to a log file and see if that works, and work your way up from there.

This works for me on both 32bit and 64bit machines:

waithidden "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -ExecutionPolicy Bypass -command "get-help | out-file C:\windows\temp\test_powershell.txt"

Here is a task I created to test powershell and report the major version through the exit code: http://bigfix.me/fixlet/details/5019