Using RunAs in PowerShell - powershell

I have the following PowerShell script to run a quick HitmanPro scan on computers. I have deployed this script through GFI RMM and while it works, I need to pass it domain administrator information.
$HitmanParameters = "/scanonly /quick /noinstall /quiet"
$AgentPath = (${env:ProgramFiles(x86)}, ${env:ProgramFiles} -ne $null)[0]
if (Test-Path "$AgentPath\Advanced Monitoring Agent") {
$AgentPath="$AgentPath\Advanced Monitoring Agent"
} elseif (Test-Path "$AgentPath\Advanced Monitoring Agent GP") {
$AgentPath="$AgentPath\Advanced Monitoring Agent GP"
} else {
Write-Host "Agent Path Not Found"
}
if (-not (Test-Path "$AgentPath\HitmanPro")) {
Write-Host "Creating Hitman Folder"
[system.io.directory]::CreateDirectory("$AgentPath\HitmanPro")
}
$HitmanParameters = "$HitmanParameters /log=""$AgentPath\HitmanPro\results.txt"""
if (-not (Test-Path "$AgentPath\HitmanPro\HitmanPro.exe")) {
Write-Host "HitmanPro Not found"
if ($(Get-WmiObject -Query "SELECT * FROM Win32_Processor WHERE AddressWidth='64'")) {
$HMPURL = "http://dl.surfright.nl/HitmanPro_x64.exe"
} else {
$HMPURL = "http://dl.surfright.nl/HitmanPro.exe"
}
Write-Host "Downloading $HMPURL ..."
$webClient = New-Object System.Net.WebClient
$webClient.DownloadFile($HMPURL,"$AgentPath\HitmanPro\HitmanPro.exe")
if (Test-Path "$AgentPath\HitmanPro\HitmanPro.exe") {
Write-Host "Download Complete!"
} else {
Write-Host "Error Downloading Hitman Pro"
}
}
if (Test-Path "$AgentPath\HitmanPro\HitmanPro.exe") {
Write-Host "Running HitmanPro Scan..."
Write-Host "HitmanPro.exe $HitmanParameters"
Start-Process -FilePath "$AgentPath\HitmanPro\HitmanPro.exe" -ArgumentList "$HitmanParameters" -NoNewWindow -Wait
If (Test-Path "$AgentPath\HitmanPro\results.txt") {
$data = Get-Content -Encoding Unicode "$AgentPath\HitmanPro\results.txt"
remove-item "$AgentPath\HitmanPro\results.txt"
foreach ($line in $data) {
If($line.contains("Threats")) {
$Infections = [int] $line.Split(":")[1]
If($Infections -eq 0) {
Write-Host "No Infections Found"
$data
exit 0
break
} Else {
Write-Host "Infections Found!"
$data
exit 1000
break
}
} #If Line contains Threats
} #ForEach
} Else {
Write-Host "No Logfile Found"!
} #LogFile Found
} Else {
Write-Host "HitmanPro Still Not Found!"
}#HitmanPro Found

Related

PowerShell: Working with the error from Standard Out (using Nessus Essentials)

Trying to use PowerShell to capture the running status of the "Nessus Essentials" software product. Simply trying to capture product status: running, not running, or other. Getting the below error each time. I've tried changing -like to -match and changing string [warn] [scanner] Not linked to a manager to various other shorter versions, with wildcards and without, to no avail. I still get several lines of an ugly error message when all I want is one line with the string Not linked to a manager returned to console with nothing beneath that.
Pertinent snippet working incorrectly:
} elseif(($agentStatus.stdOut -like "[warn] [scanner] Not linked to a manager")) {
Throw "Not linked to a manager"
The Error:
The Code:
Function Start-ProcessGetStreams {
[CmdLetBinding()]
Param(
[System.IO.FileInfo]$FilePath,
[string[]]$ArgumentList
)
$pInfo = New-Object System.Diagnostics.ProcessStartInfo
$pInfo.FileName = $FilePath
$pInfo.Arguments = $ArgumentList
$pInfo.RedirectStandardError = $true
$pInfo.RedirectStandardOutput = $true
$pinfo.UseShellExecute = $false
$pInfo.CreateNoWindow = $true
$pInfo.WindowStyle = [System.Diagnostics.ProcessWindowStyle]::Hidden
$proc = New-Object System.Diagnostics.Process
$proc.StartInfo = $pInfo
Write-Verbose "Starting $FilePath"
$proc.Start() | Out-Null
Write-Verbose "Waiting for $($FilePath.BaseName) to complete"
$proc.WaitForExit()
$stdOut = $proc.StandardOutput.ReadToEnd()
$stdErr = $proc.StandardError.ReadToEnd()
$exitCode = $proc.ExitCode
Write-Verbose "Standard Output: $stdOut"
Write-Verbose "Standard Error: $stdErr"
Write-Verbose "Exit Code: $exitCode"
[PSCustomObject]#{
"StdOut" = $stdOut
"Stderr" = $stdErr
"ExitCode" = $exitCode
}
}
Function Get-NessusStatsFromStdOut {
Param(
[string]$stdOut
)
$stats = New-Object System.Collections.Hashtable
$StdOut -split "`r`n" | % {
if($_ -like "*:*") {
$result = $_ -split ":"
$stats.add(($result[0].Trim() -replace "[^A-Za-z0-9]","_").ToLower(),$result[1].Trim())
}
}
Return $stats
}
Function Get-DateFromEpochSeconds {
Param(
[int]$seconds
)
$utcTime = (Get-Date 01.01.1970)+([System.TimeSpan]::fromseconds($seconds))
Return Get-Date $utcTime.ToLocalTime() -Format "yyyy-MM-dd HH:mm:ss"
}
Try {
$nessusExe = Join-Path $env:ProgramFiles -ChildPath "Tenable\Nessus\nessuscli.exe" -ErrorAction Stop
} Catch {
Throw "Cannot find NessusCli.exe"
}
Write-Host "Getting Agent Status..."
$agentStatus = Start-ProcessGetStreams -FilePath $nessusExe -ArgumentList "managed status"
If($agentStatus.stdOut -eq "" -and $agentStatus.StdErr -eq "") {
Throw "No Data Returned from NessusCli"
} elseif($agentStatus.StdOut -eq "" -and $agentStatus.StdErr -ne "") {
Throw "StdErr: $($agentStatus.StdErr)"
} elseif(($agentStatus.stdOut -like "[warn] [scanner] Not linked to a manager")) {
Throw "Not linked to a manager"
} elseif(-not($agentStatus.stdOut -like "*Running: *")) {
Throw "StdOut: $($agentStatus.StdOut)"
} else {
$stats = Get-NessusStatsFromStdOut -stdOut $agentStatus.StdOut
If($stats.last_connection_attempt -as [int]) { $stats.last_connection_attempt = Get-DateFromEpochSeconds $stats.last_connection_attempt }
If($stats.last_connect -as [int]) { $stats.last_connect = Get-DateFromEpochSeconds $stats.last_connect }
If($stats.last_scanned -as [int]) { $stats.last_connect = Get-DateFromEpochSeconds $stats.last_scanned }
}
$stats | Out-Host
Note: Code above is courtesy of here, I've only made a change to the path of Nessus, and I am adding the attempt to capture that it's not connected to a manager.
Modify your code so that it separates standard output from error and so that it handles each line separately.
The following is how to capture standard output (excluding else statements and error handling) of a program (according to your $Proc variable)
if ($proc.Start())
{
while (!$proc.StandardOutput.EndOfStream)
{
$StreamLine = $proc.StandardOutput.ReadLine()
if (![string]::IsNullOrEmpty($StreamLine))
{
# TODO: Duplicate code in this scope as needed or rewrite to use multiline regex
$WantedLine = [regex]::Match($StreamLine, "(?<wanted>.*Not linked to a manager.*)")
$Capture = $WantedLine.Groups["wanted"]
if ($Capture.Success)
{
Write-Output $Capture.Value
}
}
}
}
After that deal with error output separately:
$StandardError = $Proc.StandardError.ReadToEnd()
if (![string]::IsNullOrEmpty($StandardError))
{
# Or use Write-Error
Write-Output $StandardError
}

How do I make this PowerShell script 'loop' tru multiple arrays?

This PowerShell script works (not mine, I found it - data has been changed to dummy data here) - it Syncs Documents from a SharePoint Site to the users OneDrive:
#region Functions
function Sync-SharepointLocation {
param (
[guid]$siteId,
[guid]$webId,
[guid]$listId,
[mailaddress]$userEmail,
[string]$webUrl,
[string]$webTitle,
[string]$listTitle,
[string]$syncPath
)
try {
Add-Type -AssemblyName System.Web
#Encode site, web, list, url & email
[string]$siteId = [System.Web.HttpUtility]::UrlEncode($siteId)
[string]$webId = [System.Web.HttpUtility]::UrlEncode($webId)
[string]$listId = [System.Web.HttpUtility]::UrlEncode($listId)
[string]$userEmail = [System.Web.HttpUtility]::UrlEncode($userEmail)
[string]$webUrl = [System.Web.HttpUtility]::UrlEncode($webUrl)
#build the URI
$uri = New-Object System.UriBuilder
$uri.Scheme = "odopen"
$uri.Host = "sync"
$uri.Query = "siteId=$siteId&webId=$webId&listId=$listId&userEmail=$userEmail&webUrl=$webUrl&listTitle=$listTitle&webTitle=$webTitle"
#launch the process from URI
Write-Host $uri.ToString()
start-process -filepath $($uri.ToString())
}
catch {
$errorMsg = $_.Exception.Message
}
if ($errorMsg) {
Write-Warning "Sync failed."
Write-Warning $errorMsg
}
else {
Write-Host "Sync completed."
while (!(Get-ChildItem -Path $syncPath -ErrorAction SilentlyContinue)) {
Start-Sleep -Seconds 2
}
return $true
}
}
#endregion
#region Main Process
try {
#region Sharepoint Sync
[mailaddress]$userUpn = cmd /c "whoami/upn"
$params = #{
#replace with data captured from your sharepoint site.
siteId = "{11111111-1111-1111-11111111111111111}"
webId = "{22222222-2222-2222-22222222222222222}"
listId = "{33333333-3333-3333-33333333333333333}"
userEmail = $userUpn
webUrl = "https://somecompany.sharepoint.com/sites/graphics"
webTitle = "graphics"
listTitle = "Documents"
}
$params.syncPath = "$(split-path $env:onedrive)\$($userUpn.Host)\$($params.webTitle) - $($Params.listTitle)"
Write-Host "SharePoint params:"
$params | Format-Table
if (!(Test-Path $($params.syncPath))) {
Write-Host "Sharepoint folder not found locally, will now sync.." -ForegroundColor Yellow
$sp = Sync-SharepointLocation #params
if (!($sp)) {
Throw "Sharepoint sync failed."
}
}
else {
Write-Host "Location already syncronized: $($params.syncPath)" -ForegroundColor Yellow
}
#endregion
}
catch {
$errorMsg = $_.Exception.Message
}
finally {
if ($errorMsg) {
Write-Warning $errorMsg
Throw $errorMsg
}
else {
Write-Host "Completed successfully.."
}
}
#endregion
But I need do this for several SharePoint Sites, but I'd like to avoid having to run 10 different PowerPoint Scripts, if possible.
What I've tried:
I've made an array where I've defined the variables for all the sites, like this (with the correct data):
$params = #(
[pscustomobject]#{
siteId = "SiteID";
webId = "webId";
listId = "listId";
userEmail = $userUpn;
webUrl = "webUrl";
webTitle = "webTitle";
listTitle = ""Documents"
}
[Repeated for each Site]
)
I've then altered this part of the original code, to do a ForEach loop:
#region Main Process
try {
#region Sharepoint Sync
[mailaddress]$userUpn = cmd /c "whoami/upn"
$params | ForEach-Object {
$params.syncPath = "$(split-path $env:onedrive)\$($userUpn.Host)\$($params.webTitle) - $($Params.listTitle)"
Write-Host "SharePoint params:"
$params | Format-Table
if (!(Test-Path $($params.syncPath))) {
Write-Host "Sharepoint folder not found locally, will now sync.." -ForegroundColor Yellow
$sp = Sync-SharepointLocation #params
if (!($sp)) {
Throw "Sharepoint sync failed."
}
}
else {
Write-Host "Location already syncronized: $($params.syncPath)" -ForegroundColor Yellow
}
}
#endregion
}
But it's not working as expected: Only the first Site in my Array is synced.
I'm a PowerShell beginner, so please help me: What am I doing wrong?
Thanks!
When looping through all the objects inside the $params array using a ForEach-Object, the object that you want to reference will be $_ .. not $params. So, where you are referencing $params.webTitle, etc., you should be referencing $_.webTitle, $_.listTitle, etc.
If you're new to Powershell, I would recommend you setting a variable like $paramObj for each instance using foreach ($parmObj in $params) {...} to make it clear what you are referencing, making the code look like:
# replaces the ForEach-Object
ForEach ($paramObj in $params) {
Write-Host "SharePoint params:"
$paramObj | Format-Table
# i didn't see a syncPath in your $params custom object.. better if you set a local variable
$syncPath = "$(split-path $env:onedrive)\$($userUpn.Host)\$($paramObj.webTitle) - $($paramObj.listTitle)"
if (!(Test-Path $($syncPath))) {
Write-Host "Sharepoint folder not found locally, will now sync.." -ForegroundColor Yellow
$sp = Sync-SharepointLocation #paramObj
if (!($sp)) {
Throw "Sharepoint sync failed."
}
}
else {
Write-Host "Location already syncronized: $syncPath" -ForegroundColor Yellow
}
}

Need To Install Alien Vault on Client, but Client Window Machines Run PowerShell 2.0. Need to convert to syntax that will work on that machine

Client doesn't want to upgrade, because they don't want anything to
break.
The code that I need to work on their machine is below. Right now
this script will not work because it's made to work for PowerShell 3.0 and above
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12; (new-object Net.WebClient).DownloadString("https://api.agent.alienvault.cloud/osquery-api/us-east-1/bootstrap?flavor=powershell") | iex; install_agent -controlnodeid <Agent ID>
How can this be rewritten to accomplish the same thing?
Now if you know of a simpler way to work around this issue, that will help greatly.
new-module -name install_agent -scriptblock {
function AgentDoStart() {
$kServiceName = "osqueryd"
$osquerydService = Get-WmiObject -Class Win32_Service -Filter "Name='$kServiceName'"
if ($osquerydService) {
Start-Service $kServiceName
Write-Host "'$kServiceName' system service is started." -foregroundcolor Cyan
return 1
} else {
Write-Host "'$kServiceName' is not an installed system service." -foregroundcolor Yellow
return 0
}
}
function AgentDoStop() {
$kServiceName = "osqueryd"
$osquerydService = Get-WmiObject -Class Win32_Service -Filter "Name='$kServiceName'"
if ($osquerydService) {
Stop-Service $kServiceName
Start-Sleep -s 1
$proc = Get-Process osqueryd -ErrorAction SilentlyContinue
if ($proc) {
Write-Host "osqueryd still running, killing processes"
Stop-Process -Force -Name osqueryd
}
Write-Host "'$kServiceName' system service is stopped." -foregroundcolor Cyan
return 1
} else {
Write-Host "'$kServiceName' is not an installed system service." -foregroundcolor Yellow
return 0
}
}
Function Install-Project() {
param(
[string]$apikey="",
[string]$controlnodeid="",
[string]$hostid="",
[string]$assetid=""
)
Install-Project-Internal -apikey $apikey -controlnodeid $controlnodeid -hostid $hostid -assetid $assetid
Write-Host "See install.log for details" -ForegroundColor Cyan
}
Function Download-And-Install-Sysmon() {
#===================================================
#1. Download Sysmon
#===================================================
$source = "https://download.sysinternals.com/files/Sysmon.zip"
Write-Host "Downloading Sysmon from $source" -ForegroundColor Cyan
$file = "$($env:TEMP)\Sysmon.zip"
Invoke-WebRequest $source -OutFile $file
#===================================================
#2. Clean & Prepare Sysmon installation target
#===================================================
$targetondisk = "$($env:USERPROFILE)\Documents\Sysmon\"
Write-Host "Preparing Sysmon target path $($targetondisk)" -ForegroundColor Cyan
Remove-Item $targetondisk -Recurse -ErrorAction Ignore
# Suppress output, but not errors:
[void](New-Item -ItemType Directory -Force -Path $targetondisk)
If (-Not (Test-Path -Path $targetondisk)) {
Write-Error "Skipping Sysmon... Destination path $($targetondisk) does not exist."
} Else {
#===================================================
#3. Unzip Sysmon
#===================================================
Unblock-File -Path $file
Write-Host "Uncompressing the Zip file to $($targetondisk)" -ForegroundColor Cyan
$FoundExtractionAssembly = 0
try {
# Load preferred extraction method's assembly (.NET 4.5 or later)
# Write-Host "Using preferred extraction method..."
Add-Type -As System.IO.Compression.FileSystem -ErrorAction Stop
$FoundExtractionAssembly = 1
}
catch [System.Exception] {
# Write-Host "Preferred extraction method not found. Attempting fall-back method..."
}
If ($FoundExtractionAssembly) {
[IO.Compression.ZipFile]::ExtractToDirectory($file, $targetondisk)
} Else {
# Fall-back method, may fail in sessions lacking access to interactive shell
$continue_flag = 1
try {
$shell_app = New-Object -COMObject "Shell.Application"
} catch {
Write-Error "Could not create Shell.Application object"
$continue_flag = 0
}
if ($continue_flag) {
$zip_file = $shell_app.namespace($file)
$destination = $shell_app.namespace($targetondisk)
if ($destination -ne $null) {
$destination.Copyhere($zip_file.items(), 0x10)
}
}
}
}
#===================================================
#3. Download Sysmon Config File
#===================================================
$source = "https://www.alienvault.com/documentation/resources/downloads/sysmon_config_schema4_0.xml"
Write-Host "Downloading Sysmon config file from $source" -ForegroundColor Cyan
$destination = [System.IO.Path]::GetTempFileName()
Invoke-WebRequest $source -OutFile $destination
#===================================================
#3. Install Sysmon
#===================================================
Write-Host "Installing Sysmon from $source" -ForegroundColor Cyan
If ( (get-childitem $destination).length -eq 0 ) {
$command = "& '$targetondisk\sysmon' -accepteula -h md5 -n -l -i"
Write-Host "Not using an additional Sysmon configuration file" -ForegroundColor Cyan
}
Else {
$command = "& '$targetondisk\sysmon' -accepteula -h md5 -n -l -i '$destination'"
Write-Host "Sysmon configuration file to use $destination" -ForegroundColor Cyan
}
Write-Host "Installing Sysmon with command $command" -ForegroundColor Cyan
iex $command
}
Function Install-Project-Internal() {
param(
[string]$apikey="",
[string]$controlnodeid="",
[string]$hostid="",
[string]$assetid=""
)
If (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) {
Write-Error "You do not have Administrator rights to run this script!`nPlease re-run this script as an Administrator!"
Return
}
If ($PSVersionTable.PSVersion.Major -lt 3) {
Write-Error "This script must be run using Powershell version 3 or higher. You have version $PSVersionTable.PSVersion.Major installed"
Return
}
$kServiceName = "osqueryd"
$BASE = "$($env:SYSTEMDRIVE)\Program Files\osquery"
$OLDBASE = "$($env:SYSTEMDRIVE)\ProgramData\osquery"
$secretfile = $(Join-Path $BASE "secret")
$flagfile = $(Join-Path $BASE "osquery.flags")
if ([string]::IsNullOrEmpty($hostid)) {
$hostid = $assetid
}
if ([string]::IsNullOrEmpty($apikey)) {
$apikey = $controlnodeid
}
if ([string]::IsNullOrEmpty($apikey)) {
if ([System.IO.File]::Exists("$secretfile")) {
$apikey = [IO.File]::ReadAllText("$secretfile").Trim()
}
}
if ([string]::IsNullOrEmpty($apikey)) {
# check old location in ProgramData
$oldsecretfile = $(Join-Path $OLDBASE "secret")
if ([System.IO.File]::Exists("$oldsecretfile")) {
$apikey = [IO.File]::ReadAllText("$oldsecretfile").Trim()
}
}
if ([string]::IsNullOrEmpty($apikey)) {
Write-Warning "You must supply either the -apikey or -controlnodeid parameters to identify your agent account"
return
}
# use TLS 1.2
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Download-And-Install-Sysmon
#===================================================
#4. Download and install osquery
#===================================================
try {
AgentDoStop
} catch {
Write-Error "Did not stop osqueryd service. Hopefully, this is fine."
}
Write-Host "Downloading installer"
$webclient = New-Object System.Net.WebClient
$webclient.DownloadFile("https://prod-usm-saas-agent-config.s3.amazonaws.com/repo/windows/alienvault-agent-20.01.0203.0301.msi", "$env:TEMP\alienvault-agent.msi")
Write-Host "Installing"
try {
Start-Process C:\Windows\System32\msiexec.exe -ArgumentList "/i $env:TEMP\alienvault-agent.msi ALLUSERS=1 /qn /l*v .\install.log" -wait
echo "INSTALLATION SUCCESSFULLY COMPLETED" >> .\install.log
} catch {
echo "INSTALLATION ERROR (ERRORLEVEL=%ERRORLEVEL%)" >> .\install.log
Write-Error "INSTALLATION ERROR (ERRORLEVEL=%ERRORLEVEL%)"
Return
}
# If the install directory doesn't exist, bail
if (![System.IO.Directory]::Exists("$BASE")) {
echo "Installation directory does not exist: $BASE" >> .\install.log
Write-Error "Installation directory does not exist: $BASE"
Return
}
# $osquerydService = Get-WmiObject -Class Win32_Service -Filter "Name='osqueryd'"
# if ($osquerydService) {
# Write-Host "Service exists, uninstalling"
# try {
# Stop-Service $kServiceName
# AgentDoStop
#
# Write-Host "Found '$kServiceName', stopping the system service..."
# Start-Sleep -s 5
# Write-Host "System service should be stopped."
# $osquerydService.Delete()
# Write-Host "System service '$kServiceName' uninstalled." -foregroundcolor Cyan
# } catch {
# Write-Error "Did not uninstall osqueryd service. Hopefully, it's not already installed."
# }
# }
Write-Host "Writing secret"
[IO.File]::WriteAllLines("$secretfile", $apikey)
# if hostid is not specified, try to extract from flag file
if ([string]::IsNullOrEmpty($hostid)) {
if ([System.IO.File]::Exists($flagfile)) {
$match = (Select-String -Path $flagfile -Pattern "specified_identifier=(.*)")
if ($match.Matches.Groups.success) {
$hostid = $match.Matches.Groups[1].Value.Trim()
Write-Host "Detected and re-using previously selected host id from ${flagfile}: $hostid"
} else {
Write-Host "Existing host id not found in ${flagfile}"
}
}
}
# if still not found, check old ProgramData location
if ([string]::IsNullOrEmpty($hostid)) {
$oldflagfile = $(Join-Path $OLDBASE "osquery.flags")
if ([System.IO.File]::Exists($oldflagfile)) {
$match = (Select-String -Path $oldflagfile -Pattern "specified_identifier=(.*)")
if ($match.Matches.Groups.success) {
$hostid = $match.Matches.Groups[1].Value.Trim()
Write-Host "Detected and re-using previously selected host id from ${oldflagfile}: $hostid"
} else {
Write-Host "Existing host id not found in ${oldflagfile}"
}
}
}
echo "Creating flag file"
copy $BASE\osquery.flags.example $flagfile
Write-Host "Setting host identifier"
# if still no hostid, use generated default
if ([string]::IsNullOrEmpty($hostid)) {
$hostid="00000000-8019-46ae-b324-685a63cb327a"
}
$output = "--tls_hostname=api.agent.alienvault.cloud/osquery-api/us-east-1", "--host_identifier=specified", "--specified_identifier=$hostid"
[IO.File]::AppendAllLines([string]$flagfile, [string[]]$output)
# add customer certs if present
$custpem = "$($env:SYSTEMROOT)\System32\drivers\etc\osquery_customer_certs.pem"
if ([System.IO.File]::Exists($custpem)) {
Write-Host "Adding customer certs"
type "$custpem" >> "$BASE\certs\certs.pem"
}
# start service
if (-NOT (AgentDoStop)) {
return
}
AgentDoStart
Write-Host "Deleting installer"
del $env:TEMP\alienvault-agent.msi
if (($BASE -ne $OLDBASE) -And [System.IO.Directory]::Exists($OLDBASE)) {
Write-Host "renaming old ProgramData/osquery directory"
move "$OLDBASE" "$($OLDBASE).renamed"
}
}
set-alias install_agent -value Install-Project
export-modulemember -alias 'install_agent' -function 'Install-Project'
}
If you remove this from "Function Install-Project-Internal"
If ($PSVersionTable.PSVersion.Major -lt 3) {
Write-Error "This script must be run using Powershell version 3 or higher. You have version $PSVersionTable.PSVersion.Major installed"
Return
}
Does it work? And if not, what is the error?

Not able to pass password when I deploy SSIS with powershell script

I have an ssis solution that is encrypted with password and when I deploy it directly from visual studio, it runs on the server without any problem.
I am trying to deploy it using a powershell query, it does deploy without any problems but the password does not go through, and when I try to run it, I get the following error: "The protection level of the package requires a password, but the packagepassword property is empty", I tried changing the protection level using dtutil.exe /file but it still gives me the same error.
[CmdletBinding()]
Param(
# IsPacFilePath is required
[Parameter(Mandatory=$True,Position=1)]
[string]$IspacFilePath,
# SsisServer is required
[Parameter(Mandatory=$True,Position=2)]
[string]$SsisServer,
# FolderName is required
[Parameter(Mandatory=$True,Position=3)]
[string]$FolderName,
# ProjectName is not required
# If empty filename is used
[Parameter(Mandatory=$False,Position=4)]
[string]$ProjectName,
# EnvironmentName is not required
# If empty no environment is referenced
[Parameter(Mandatory=$False,Position=5)]
[string]$EnvironmentName,
# EnvironmentFolderName is not required
# If empty the FolderName param is used
[Parameter(Mandatory=$False,Position=6)]
[string]$EnvironmentFolderName
)
if (-not $ProjectName)
{
$ProjectName = [system.io.path]::GetFileNameWithoutExtension($IspacFilePath)
}
if (-not $EnvironmentFolderName)
{
$EnvironmentFolderName = $FolderName
}
clear
Write-Host "========================================================================================================================================================"
Write-Host "== Used parameters =="
Write-Host "========================================================================================================================================================"
Write-Host "Ispac File Path : " $IspacFilePath
Write-Host "SSIS Server : " $SsisServer
Write-Host "Project Folder Path : " $FolderName
Write-Host "Project Name : " $ProjectName
Write-Host "Environment Name : " $EnvironmentName
Write-Host "Environment Folder Path: " $EnvironmentFolderName
Write-Host "========================================================================================================================================================"
Write-Host ""
if (-Not (Test-Path $IspacFilePath))
{
Throw [System.IO.FileNotFoundException] "Ispac file $IspacFilePath doesn't exists!"
}
else
{
$IspacFileName = split-path $IspacFilePath -leaf
Write-Host "Ispac file" $IspacFileName "found"
}
Write-Host "Connecting to server $SsisServer "
$SsisNamespace = "Microsoft.SqlServer.Management.IntegrationServices"
[System.Reflection.Assembly]::LoadWithPartialName($SsisNamespace) | Out-Null;
$SqlConnectionstring = "Data Source=" + $SsisServer + ";Initial Catalog=master;Integrated Security=SSPI;"
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection $SqlConnectionstring
$IntegrationServices = New-Object $SsisNamespace".IntegrationServices" $SqlConnection
if (-not $IntegrationServices)
{
Throw [System.Exception] "Failed to connect to server $SsisServer "
}
else
{
Write-Host "Connected to server" $SsisServer
}
$Catalog = $IntegrationServices.Catalogs["SSISDB"]
if (-not $Catalog)
{
Throw [System.Exception] "SSISDB catalog doesn't exist. Create it manually!"
}
else
{
Write-Host "Catalog SSISDB found"
}
$Folder = $Catalog.Folders[$FolderName]
if (-not $Folder)
{
Write-Host "Creating new folder" $FolderName
$Folder = New-Object $SsisNamespace".CatalogFolder" ($Catalog, $FolderName, $FolderName)
$Folder.Create()
}
else
{
Write-Host "Folder" $FolderName "found"
}
if($Folder.Projects.Contains($ProjectName)) {
Write-Host "Deploying" $ProjectName "to" $FolderName "(REPLACE)"
}
else
{
Write-Host "Deploying" $ProjectName "to" $FolderName "(NEW)"
}
[byte[]] $IspacFile = [System.IO.File]::ReadAllBytes($IspacFilePath)
$Folder.DeployProject($ProjectName, $IspacFile)
$Project = $Folder.Projects[$ProjectName]
if (-not $Project)
{
return ""
}
if (-not $EnvironmentName)
{
$IntegrationServices = $null
Return "Ready deploying $IspacFileName without adding environment references"
}
$EnvironmentFolder = $Catalog.Folders[$EnvironmentFolderName]
if (-not $EnvironmentFolder)
{
Throw [System.Exception] "Environment folder $EnvironmentFolderName doesn't exist"
}
if(-not $EnvironmentFolder.Environments.Contains($EnvironmentName))
{
Throw [System.Exception] "Environment $EnvironmentName doesn't exist in $EnvironmentFolderName "
}
else
{
$Environment = $Catalog.Folders[$EnvironmentFolderName].Environments[$EnvironmentName]
if ($Project.References.Contains($EnvironmentName, $EnvironmentFolderName))
{
Write-Host "Reference to" $EnvironmentName "found"
}
else
{
Write-Host "Adding reference to" $EnvironmentName
$Project.References.Add($EnvironmentName, $EnvironmentFolderName)
$Project.Alter()
}
}
$ParameterCount = 0
foreach ($Parameter in $Project.Parameters)
{
$ParameterName = $Parameter.Name
if ($ParameterName.StartsWith("CM.","CurrentCultureIgnoreCase"))
{
}
elseif ($ParameterName.StartsWith("INTERN_","CurrentCultureIgnoreCase"))
{
Write-Host "Ignoring Project parameter" $ParameterName " (internal use only)"
}
elseif ($Environment.Variables.Contains($Parameter.Name))
{
$ParameterCount = $ParameterCount + 1
Write-Host "Project parameter" $ParameterName "connected to environment"
$Project.Parameters[$Parameter.Name].Set([Microsoft.SqlServer.Management.IntegrationServices.ParameterInfo+ParameterValueType]::Referenced, $Parameter.Name)
$Project.Alter()
}
else
{
# Variable with the name of the project parameter is not found in the environment
# Throw an exeception or remove next line to ignore parameter
Throw [System.Exception] "Project parameter $ParameterName doesn't exist in environment"
}
}
Write-Host "Number of project parameters mapped:" $ParameterCount
$ParameterCount = 0
foreach ($Package in $Project.Packages)
{
foreach ($Parameter in $Package.Parameters)
{
# Get parameter name and check if it exists in the environment
$PackageName = $Package.Name
$ParameterName = $Parameter.Name
if ($ParameterName.StartsWith("CM.","CurrentCultureIgnoreCase"))
{
}
elseif ($ParameterName.StartsWith("INTERN_","CurrentCultureIgnoreCase"))
{
Write-Host "Ignoring Package parameter" $ParameterName " (internal use only)"
}
elseif ($Environment.Variables.Contains($Parameter.Name))
{
$ParameterCount = $ParameterCount + 1
Write-Host "Package parameter" $ParameterName "from package" $PackageName "connected to environment"
$Package.Parameters[$Parameter.Name].Set([Microsoft.SqlServer.Management.IntegrationServices.ParameterInfo+ParameterValueType]::Referenced, $Parameter.Name)
$Package.Alter()
}
else
{
Throw [System.Exception] "Package parameter $ParameterName from package $PackageName doesn't exist in environment"
}
}
}
Write-Host "Number of package parameters mapped:" $ParameterCount
$IntegrationServices = $null
Return "Ready deploying $IspacFileName "
i took it from deploy ssis with powershell

How to loop through a script to let a user selection different options?

Fairly new to Powershell. I'm working on a script that will let a user install different pieces of software that will be needed. This process is currently being done manually and it can take 30-45 minutes to install everything that is needed. However, not everything needs to be installed on each workstation so I need flexibility for the user. This is what I have come up with so far. (Modified for brevity)
$Software1Path = "Path to installer"
$Software2Path = "Path to installer"
$Software3Path = "Path to installer"
function Software1 {
$Software1Arguments = "/S"
Start-Process -FilePath $Software1Installer $Software1Arguments -Wait
InstallOptions
}
function Software2 {
$Software2Arguments = "/silent"
Start-Process -FilePath $Software2Installer $Software2Arguments -Wait
InstallOptions
}
function Software3 {
$Software3Arguments = "/passive"
Start-Process -FilePath $Software3Installer $Software3Arguments -Wait
InstallOptions
}
function InstallOptions {
Do {
Clear-Host
Write-Host('1. Install Software1')
Write-Host('2. Install Software1')
Write-Host('3. Install Software1')
Write-Host('4. Install All Three')
Write-Host('0. Exit')
$value = Read-Host 'Input your selection (0-3)'
}
Until ($value -eq "o"){
switch ($value) {
"0" {exit}
"1" { Software 1}
"2" { Software 2}
"3" { Software 3}
"4" { Software1
Software2
Software3}
}
}
}
It does not give the desired result. I can either install one piece of software but then the script exits and I also cannot install all three. I've played with the InstallOptions and wrote it ten different ways but I am still not getting the desired result. Any suggestions?
You can call InstallOptions in a while($true) {} (as long as you keep 0 to exit) or another type of loop to make it return to the menu. If you call the menu from the software installation-function it will never get to 2 and 3 when you use "install all". Try:
$Software1Path = "Path to installer"
$Software2Path = "Path to installer"
$Software3Path = "Path to installer"
function Software1 {
$Software1Arguments = "/S"
Start-Process -FilePath $Software1Path -ArgumentList $Software1Arguments -Wait
}
function Software2 {
$Software2Arguments = "/silent"
Start-Process -FilePath $Software2Path -ArgumentList $Software2Arguments -Wait
}
function Software3 {
$Software3Arguments = "/passive"
Start-Process -FilePath $Software3Path -ArgumentList $Software3Arguments -Wait
}
function InstallOptions {
Clear-Host
Write-Host('1. Install Software1')
Write-Host('2. Install Software2')
Write-Host('3. Install Software3')
Write-Host('4. Install All Three')
Write-Host('0. Exit')
$value = Read-Host 'Input your selection (0-3)'
switch ($value) {
"0" {exit}
"1" { Software1}
"2" { Software2}
"3" { Software3}
"4" {
Software1
Software2
Software3
}
}
}
#Start the train
while($true) { InstallOptions }
You might also want to clean this up. Ex. $Sofware1Path is outside the function while the $Software1Arguments are inside. For simple installations, you could clean this up to use ex. a csv-stored array (can be read stored in a separate file if needed). Something like:
$Installations = #(#"
Name,Step,Path,Arguments
Software1,1,"c:\Install Files\Product1\Setup.exe",/S
Software2,2,"c:\Install Files\Product2\SetupPart2.exe",/silent
Software2,1,"c:\Install Files\Product2\Setup.exe","/silent ""space test with ,"""
Software3,1,"c:\Install Files\Product3\Setup.exe",/passive "space test"
"# | ConvertFrom-Csv)
function InstallSoftware ($Name) {
Write-Host "Installing $Name..."
$Installations | Where-Object { $_.Name -eq $Name } | Sort-Object { $_.Step -as [int] } | ForEach-Object {
ExecuteStep -Path $_.Path -Arguments $_.Arguments
}
}
function ExecuteStep ($Path, $Arguments) {
Write-Host "Executing '$Path' '$Arguments'"
Start-Process -FilePath $Path -ArgumentList $Arguments -Wait
}
function Menu {
$UniqueSoftware = $Installations | Select-Object -ExpandProperty Name -Unique | Sort-Object
$NumOfSoftware = $UniqueSoftware.Count
#Generate menu
Clear-Host
for($i=0;$i -lt $NumOfSoftware; $i++) {
Write-Host ("{0}. Install {1}" -f ($i+1), $Software[$i].Name)
}
Write-Host ("{0}. Install all" -f ($NumOfSoftware+1))
Write-Host "0. Exit"
do {
#Get input
$value = (Read-Host "Input your selection (0-$($NumOfSoftware+1))") -as [int]
#Execute
switch ($value) {
0 { exit }
{ $_ -gt 0 -and $_ -le $NumOfSoftware } { InstallSoftware -Name $UniqueSoftware[($_-1)] }
($NumOfSoftware+1) { 0..($NumOfSoftware-1) | ForEach-Object { InstallSoftware -Name $UniqueSoftware[($_)] } }
default { Write-Host "Invalid input..." }
}
#Validate input or retry
} until ( $value -ge 0 -and $value -le $NumOfSoftware+1 )
}
#Start the train
while($true) { Menu }