Running powershell script on asp.net site - asp.net

I am trying to run a powershell script and have it output to my asp.net site. I have made it work with a very simple script where the only command in the script was
Get-Service | Out-String
and this output onto my site everything I expected
but when I use the script I actually want info from it doesn't output anything
I can tell it runs (or trys to run) because when my site hits the code that invokes the script it hangs about 10 seconds.
The script I am trying to run is
$user = "user"
$token = "token"
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,$token)))
$result = Invoke-WebRequest -Method Get -Uri 'https://site.vsrm.visualstudio.com/defaultcollection/product/_apis/release/releases?definitionId=1&api-version=3.0-preview.2&$expand=environments' -ContentType "application/json" -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)}
$releaseArr = $result.Content | ConvertFrom-Json
[System.Collections.ArrayList]$enviromentName = #()
[System.Collections.ArrayList]$latestRelease = #()
foreach($env in $releaseArr.value[0].environments)
{
$enviromentName.Add($env.name) | Out-Null
}
foreach($releaseValue in $releaseArr.value)
{
For($i = 0; $i -lt $enviromentName.Count; $i++)
{
if($latestRelease[$i] -eq $null)
{
foreach($release in $releaseValue.environments)
{
if($release.name -eq $enviromentName[$i] -and $release.status -eq "succeeded")
{
$latestRelease.Add($releaseValue.name) | Out-Null
}
}
}
}
}
For($i = 0; $i -lt $enviromentName.Count; $i++)
{
Write-Host $enviromentName[$i] " : " $latestRelease[$i]
}
I know this script runs and outputs, but is there some code in this script that would cause it to not output properly.
The code in my asp.net site I am using to call the script is
ResultBox.Text = string.Empty;
// Initialize PowerShell engine
var shell = PowerShell.Create();
// Add the script to the PowerShell object
shell.Commands.AddScript(#"C:\Users\user\Desktop\script.ps1");
// Execute the script
var results = shell.Invoke();
// display results, with BaseObject converted to string
// Note : use |out-string for console-like output
if (results.Count > 0)
{
// We use a string builder ton create our result text
var builder = new StringBuilder();
foreach (var psObject in results)
{
// Convert the Base Object to a string and append it to the string builder.
// Add \r\n for line breaks
builder.Append(psObject.BaseObject.ToString() + "\r\n");
}
// Encode the string in HTML (prevent security issue with 'dangerous' caracters like < >
ResultBox.Text = Server.HtmlEncode(builder.ToString());
}

Change "Write-Host" to "Write-Output." Write-Host only outputs to interactive consoles.
You can see this in action:
Make a new PowerShell file and add a write-host statement to it:
[nick#nick-lt temp]$ New-Item -Type File -Path .\example.ps1 -Force
[nick#nick-lt temp]$ Set-Content .\example.ps1 "Write-Host 'Hello World'"
Then try and set a variable to the result of the script:
[nick#nick-lt temp]$ $what = .\example.ps1
Hello World
[nick#nick-lt temp]$ $what
[nick#nick-lt temp]$
Hello World shows up when the script executes but the variable is empty.
Now change it to write-output:
[nick#nick-lt temp]$ Set-Content .\example.ps1 "Write-Output 'Hello World'"
[nick#nick-lt temp]$ $what = .\example.ps1
[nick#nick-lt temp]$ $what
Hello World
The variable actually contains what it is supposed to now.
One of the cardinal rules of PowerShell is to not use Write-Host except in script that will be run interactively. .NET needs the results in the output stream not the host stream.

Related

No results while applying Export-Csv command in PowerShell script

The following script execute a query against a database with the command $con.ConnectionString = "Data Source=$DB_PATH" and export all the results to a CSV file. Firstly, when I createad it, the file was working fine with no issue.
$DB_PATH = "C:\ProgramData\PROISER\ISASPSUS\datastore\dsfile.db"
Add-Type -Path "C:\Program Files\System.Data.SQLite\2010\bin\System.Data.SQLite.dll"
$con = New-Object -TypeName System.Data.SQLite.SQLiteConnection
$con.ConnectionString = "Data Source=$DB_PATH"
$con.Open()
$sql = $con.CreateCommand()
$sql.CommandText = "SELECT * FROM analysis"
$adapter = New-Object -TypeName System.Data.SQLite.SQLiteDataAdapter $sql
$data = New-Object System.Data.DataSet
[void]$adapter.Fill($data)
$table = $data.Tables
foreach ($t in $table) {
$CurrentDate = Get-Date
$CurrentDate = $CurrentDate.ToString('MM-dd-yyyy')
$t | Export-Csv -Path "C:\Users\santiago.corso\analisis_$CurrentDate" -NoTypeInformation -Append
}
$sql.Dispose()
$con.Close()
From one point to another, the execution of the ps1 file stored in a task scheduled inside Task Scheduler in Windows started showing the "how to open this file" window and no file was created from that point onwards.
Executing the ps1 file on its own works fine, but inside a scheduled task is when the problem occurs.

Creating multiple zip files with PHP

I have a problem in PHP / Laravel to create multiple zip files synchronously, I copy all commands that is generated and squeeze into the Shell, it executes normally, but when I step into the PHP run it only generates the first file = /.
Controller code.
foreach ($passwords as $p){
if($i == 0){
$command = 'zip -u -j -P '.$p.' '.$dir.'/'.$count.'.zip '.storage_path().'/app/'.$directory.'/'.$file1->getClientOriginalName();
$commands->push($command);
}else{
$command = 'zip --quiet -j -P '.$p.' '.$dir.'/'.$count.'.zip '.storage_path().'/app/'.$directory.'/'.($count+1).'.zip';
$commands->push($command);
}
$count--;
$i++;
}
foreach ($commands as $p){
echo $p.'<br/>';
}
foreach ($commands as $c){
$process = new Process($c);
$process->start();
sleep(10);
if($process->isTerminated()){
sleep(1);
}
if ($errorOutput = $process->getErrorOutput()) {
throw new RuntimeException('Process: ' . $errorOutput);
}
}
Data $commands
The script only generates the file 50.zip.
Not sure if sleep could interfere with subprocess (shell command). Please try:
foreach ($commands as $c){
$process = new Process($c);
// Set the timeout instead of sleeping
$process->setTimeout(10);
$process->start();
// Wait for the process to finish
$process->wait();
if ($errorOutput = $process->getErrorOutput()) {
throw new RuntimeException('Process: ' . $errorOutput);
}
}
wait() call uses usleep in a more fine-grained manner it might help with that.
Does it work like this?

Returning output from scriptblock from Get-Job?

I'm trying to test out asynchronous functionality in PowerShell 3.
So I figured I would query the uptimes of some servers remotely, and wrote the following script:
function getServerUptimes() {
# Obtain credentials for logging into
# the remote machines...
$cred = Get-Credential
$compsHash = #{
"server1.domain.com" = $null;
"server2.domain.com" = $null;
}
# Define an async block to run...no blocking in this script...
$cmd = {
param($computer, $dasCred)
Write-Host "which: $($computer)"
$session = new-cimsession $computer -Credential $dasCred
return (get-CimInstance win32_operatingsystem -CimSession $session | Select PScomputername, LastBootuptime);
}
ForEach($comp in $compsHash.Keys) {
Write-Host "${comp}"
# Kick off an async process to create a cimSession
# on each of these machines...
Start-Job -ScriptBlock $cmd -ArgumentList $comp, $cred -Name "Get$($comp)"
}
$results = Get-Job | Wait-Job | Receive-Job
# Retrieve the job, so we can look at the output
ForEach($comp in $compHash.Keys) {
$dasJob = Get-Job -Name "Get$($comp)"
Write-Host $dasJob.output
}
}
However, I don't really seem to get back any output in the resulting $dasJob object, I returned the value in my scriptblock, where is it going?
You already have the output (not including Write-Host output, of course) in the variable $results. In PowerShell you retrieve job output via Receive-Job. The property Output seems to always be empty (not sure why).

MSB4018 Error Visual Studio 2015 ASP.Net and Error Publish Web App to Azure

I am working with Visual Studio 2015 Community with Azure 2.9 For the first time. I tried creating a brand new ASP.Net Web Application. The default template build and viewed in the Browser with no issues.
I tried publishing the site using Azure. When doing so I get this error
The "InvokePowerShell" task failed unexpectedly.
System.Management.Automation.CommandNotFoundException: The term '[cmdletbinding(SupportsShouldProcess=$true)]
param($publishProperties, $packOutput, $nugetUrl)
# to learn more about this file visit http://go.microsoft.com/fwlink/?LinkId=524327
$publishModuleVersion = '1.0.1'
function Get-VisualStudio2015InstallPath{
[cmdletbinding()]
param()
process{
$keysToCheck = #('hklm:\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\14.0',
'hklm:\SOFTWARE\Microsoft\VisualStudio\14.0',
'hklm:\SOFTWARE\Wow6432Node\Microsoft\VWDExpress\14.0',
'hklm:\SOFTWARE\Microsoft\VWDExpress\14.0'
)
[string]$vsInstallPath=$null
foreach($keyToCheck in $keysToCheck){
if(Test-Path $keyToCheck){
$vsInstallPath = (Get-itemproperty $keyToCheck -Name InstallDir -ErrorAction SilentlyContinue | select -ExpandProperty InstallDir -ErrorAction SilentlyContinue)
}
if($vsInstallPath){
break;
}
}
$vsInstallPath
}
}
$vsInstallPath = Get-VisualStudio2015InstallPath
$publishModulePath = "{0}Extensions\Microsoft\Web Tools\Publish\Scripts\{1}\" -f $vsInstallPath, $publishModuleVersion
if(!(Test-Path $publishModulePath)){
$publishModulePath = "{0}VWDExpressExtensions\Microsoft\Web Tools\Publish\Scripts\{1}\" -f $vsInstallPath, $publishModuleVersion
}
$defaultPublishSettings = New-Object psobject -Property #{
LocalInstallDir = $publishModulePath
}
function Enable-PackageDownloader{
[cmdletbinding()]
param(
$toolsDir = "$env:LOCALAPPDATA\Microsoft\Web Tools\Publish\package-downloader-$publishModuleVersion\",
$pkgDownloaderDownloadUrl = 'http://go.microsoft.com/fwlink/?LinkId=524325') # package-downloader.psm1
process{
if(get-module package-downloader){
remove-module package-downloader | Out-Null
}
if(!(get-module package-downloader)){
if(!(Test-Path $toolsDir)){ New-Item -Path $toolsDir -ItemType Directory -WhatIf:$false }
$expectedPath = (Join-Path ($toolsDir) 'package-downloader.psm1')
if(!(Test-Path $expectedPath)){
'Downloading [{0}] to [{1}]' -f $pkgDownloaderDownloadUrl,$expectedPath | Write-Verbose
(New-Object System.Net.WebClient).DownloadFile($pkgDownloaderDownloadUrl, $expectedPath)
}
if(!$expectedPath){throw ('Unable to download package-downloader.psm1')}
'importing module [{0}]' -f $expectedPath | Write-Output
Import-Module $expectedPath -DisableNameChecking -Force
}
}
}
function Enable-PublishModule{
[cmdletbinding()]
param()
process{
if(get-module publish-module){
remove-module publish-module | Out-Null
}
if(!(get-module publish-module)){
$localpublishmodulepath = Join-Path $defaultPublishSettings.LocalInstallDir 'publish-module.psm1'
if(Test-Path $localpublishmodulepath){
'importing module [publish-module="{0}"] from local install dir' -f $localpublishmodulepath | Write-Verbose
Import-Module $localpublishmodulepath -DisableNameChecking -Force
$true
}
}
}
}
try{
if (!(Enable-PublishModule)){
Enable-PackageDownloader
Enable-NuGetModule -name 'publish-module' -version $publishModuleVersion -nugetUrl $nugetUrl
}
'Calling Publish-AspNet' | Write-Verbose
# call Publish-AspNet to perform the publish operation
Publish-AspNet -publishProperties $publishProperties -packOutput $packOutput
}
catch{
"An error occurred during publish.`n{0}" -f $_.Exception.Message | Write-Error
}' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
at System.Management.Automation.Runspaces.AsyncResult.EndInvoke()
at System.Management.Automation.PowerShell.EndInvoke(IAsyncResult asyncResult)
at Microsoft.Web.Publishing.Tasks.InvokePowerShell.Execute()
at Microsoft.Build.BackEnd.TaskExecutionHost.Microsoft.Build.BackEnd.ITaskExecutionHost.Execute()
at Microsoft.Build.BackEnd.TaskBuilder.<ExecuteInstantiatedTask>d__26.MoveNext() WebApplication1 0
I am assuming I missed something in my install? Anyone know what this error is or how to get passed it?
I upvoted this in the past, then apparently found the answer somewhere else, then forgot the answer again and ended up here again.
Adding <AutoParameterizationWebConfigConnectionStrings>False</AutoParameterizationWebConfigConnectionStrings>
in the csproj on the right PropertyGroup fixed the problem for me.

Powershell Scheduled Task Open Web Page to Execute Script

In an effort to setup a "cron job" like scheduled task on Windows I've setup a Powershell script using code recommended via previous stackoverflow question.
I have some backups that I need to cleanup daily and delete old backups so I created a asp.net script to perform this task - the file name is BackupCleanup.aspx and I have confirmed that the ASP.net script does work when executed on its own by visiting the above url - I however cannot get it to execute using the Powershell script below.
The Powershell Script code I'm using is:
$request = [System.Net.WebRequest]::Create("http://127.0.0.1/BackupCleanup.aspx")
$response = $request.GetResponse()
$response.Close()
I have created this file with a PS1 extension, it shows properly in my os (Windows 2008) - I have tried both manually executing this task by right clicking and choosing "Run with Powershell" and also have scheduled this as a task - both to no avail.
I cannot figure out why the script does not work - any help would be GREATLY appreciated.
Here is the Powershell script I use to call up web pages using IE. Hopefully this will work for you as well.
Function NavigateTo([string] $url, [int] $delayTime = 100)
{
Write-Verbose "Navigating to $url"
$global:ie.Navigate($url)
WaitForPage $delayTime
}
Function WaitForPage([int] $delayTime = 100)
{
$loaded = $false
while ($loaded -eq $false) {
[System.Threading.Thread]::Sleep($delayTime)
#If the browser is not busy, the page is loaded
if (-not $global:ie.Busy)
{
$loaded = $true
}
}
$global:doc = $global:ie.Document
}
Function SetElementValueByName($name, $value, [int] $position = 0) {
if ($global:doc -eq $null) {
Write-Error "Document is null"
break
}
$elements = #($global:doc.getElementsByName($name))
if ($elements.Count -ne 0) {
$elements[$position].Value = $value
}
else {
Write-Warning "Couldn't find any element with name ""$name"""
}
}
Function ClickElementById($id)
{
$element = $global:doc.getElementById($id)
if ($element -ne $null) {
$element.Click()
WaitForPage
}
else {
Write-Error "Couldn't find element with id ""$id"""
break
}
}
Function ClickElementByName($name, [int] $position = 0)
{
if ($global:doc -eq $null) {
Write-Error "Document is null"
break
}
$elements = #($global:doc.getElementsByName($name))
if ($elements.Count -ne 0) {
$elements[$position].Click()
WaitForPage
}
else {
Write-Error "Couldn't find element with name ""$name"" at position ""$position"""
break
}
}
Function ClickElementByTagName($name, [int] $position = 0)
{
if ($global:doc -eq $null) {
Write-Error "Document is null"
break
}
$elements = #($global:doc.getElementsByTagName($name))
if ($elements.Count -ne 0) {
$elements[$position].Click()
WaitForPage
}
else {
Write-Error "Couldn't find element with tag name ""$name"" at position ""$position"""
break
}
}
#Entry point
# Setup references to IE
$global:ie = New-Object -com "InternetExplorer.Application"
$global:ie.Navigate("about:blank")
$global:ie.visible = $true
# Call the page
NavigateTo "http://127.0.0.1/BackupCleanup.aspx"
# Release resources
$global:ie.Quit()
$global:ie = $null
I had the same issue. I manually opened powershell and executed my script and I received "WebPage.ps1 cannot be loaded because running scripts is disabled on this system.".
You have to allow scripts to run
Execute the below in PowerShell
Set-ExecutionPolicy RemoteSigned -Scope LocalMachine

Resources