Powershell cannot bind parameter ForegroundColor - powershell

I have created the following Powershell script which I hope to use to copy files to a network share.
function Copy-Deploy
{
param(
[Parameter(Position=0,Mandatory=$true,HelpMessage="Path to scripts")]
[Alias("pth")]
[string]$ScriptPath,
[Parameter(Position=1,Mandatory=$true,HelpMessage="Deployment script filename")]
[Alias("dep")]
[string]$PowershellDeploymentScript,
[Parameter(Position=2,Mandatory=$true,HelpMessage="MSI filename")]
[Alias("m")]
[string]$MSI,
[Parameter(Position=3,Mandatory=$true,HelpMessage="Filename of the MSBuild script (.btdfproj)")]
[Alias("msb")]
[string]$MSBuildScript,
[Parameter(Position=4,HelpMessage="UNC path to target server folder")]
[Alias("server")]
[string]$TargetServerPath
)
$ErrorActionPreference="Stop"
#Step 1 : copy the MSI, .btdfproj script and control powershell script to the remote server
Write-Host " Going to enter the mis script block"
$misScript =
{
Write-Host " Path+Filename = {0}({1})" -f $ScriptPath, $PowershellDeploymentScript
Write-Host " Going to copy files"
Write-Host " ScriptPath = $ScriptPath"
Write-Host " PowershellDeploymentScript = $PowershellDeploymentScript"
Write-Host " MSI = $MSI"
Write-Host " MSBuildScript = $MSBuildScript"
Write-Host " TargetServerPath = $TargetServerPath"
Copy-Item -Path "$ScriptPath" + "$PowershellDeploymentScript" -Destination "$TargetServerPath"
Copy-Item -Path "$ScriptPath" + "$MSI" -Destination "$TargetServerPath"
Copy-Item -Path "$ScriptPath" + "$MSBuildScript" -Destination "$TargetServerPath"
}
Invoke-Command -scriptblock $misScript
#Step2 : Execute the powershell script ExecuteBizTalkAppMSI.ps1 remotely on the target server
#using syntax... invoke-command -computer $MachineName -command { $TargetServerPath + ExecuteBizTalkAppMSI.ps1 }"
}
I run this script from the Powershell ISE with the following line:
Copy-Deploy "C:\Builds\3\x.Int.MIS\SupportBTDF\Sources\x.Int.MIS\Dev\V1.0\Src\Solutions\MIS\x.Int.MIS.Deployment\" "ExecuteBizTalkAppMSI.ps1" "bin\debug\x.Int.MIS-3.0.0.msi" "x.Int.MIS.Deployment.btdfproj" "\\d-vasbiz01\BizTalkDeployment"
I then get the following error:
Cannot bind parameter 'ForegroundColor'. Cannot convert value "C:\Builds\3\x.Int.MIS\SupportBTDF\Sources\x.Int.MIS\Dev\V1.0\Src\Solutions\MIS\x.Int.MIS.Deployment\,ExecuteBizTalkAppMSI.ps1" to type "System.ConsoleColor" due to invalid enumeration values. Specify one of the following enumeration values and try again. The possible enumeration values are "Black, DarkBlue, DarkGreen, DarkCyan, DarkRed, DarkMagenta, DarkYellow, Gray, DarkGray, Blue, Green, Cyan, Red, Magenta, Yellow, White".At C:\Builds\3\x.Int.MIS\SupportBTDF\Sources\x.Int.MIS\Dev\V1.0\Src\Solutions\MIS\x.Int.MIS.Deployment\CopyDeployScriptThenExecute.ps1:79 char:16
Could anyone please tell me where I went wrong?

The line :
Write-Host " Path+Filename = {0}({1})" -f $ScriptPath, $PowershellDeploymentScript
is the problem.
Write it like this:
Write-Host (" Path+Filename = {0}({1})" -f $ScriptPath, $PowershellDeploymentScript)
The -f was being taken as the -ForegroundColor parameter than the string format operator.

Wrap the message in parens. You can also use variable expansion and embed the variables without using the -format operator (like you did in other write-host calls):
Write-Host " Path+Filename = $ScriptPath($PowershellDeploymentScript)"

Related

giving variables to another powershell console [duplicate]

This question already has answers here:
How to pass a variable to new console window in Powershell
(2 answers)
Closed last year.
I have a script that opens a powershell console as admin and do sth in eventlog.
I have two variables that i the new admin-PS console needs.
[string] $PiEventLog = "'Company Name Prv.Limt'"
[String] $PiEventLogSource = "'XY-Test'"
I am opening the new PS-Console like this
start powershell -Verb runas {
If(Get-EventLog -List | ?{$_.Log -like $PiEventLog}){
Write-Host "EventLog already exists." -ForegroundColor Yellow
}
else{
New-EventLog -LogName $PiEventLog -Source $PiEventLogSource -ErrorAction Stop
Write-Host "EventLog was successfully created." -ForegroundColor Green
}
Read-Host "Press any key to close the console..."
}
If i try to execute the script, i get the following error:
The argument for the parameter "LogName" cannot be checked. The
argument is NULL or empty. Specify an argument that is not NULL or
empty and re-execute the command.
anyone got an idea, how i can give those two variables to the new PS-console, without having to set two different variables in the new console?
I believe this should work, it's easier if you use a Here-String. Since you're using the -like operator, I would assume you're looking for a Log that "contains" the input given in $PiEventLog, in that case, you should use wildcard characters: -like "*$PiEventLog*".
param(
[string] $PiEventLog = 'Company Name Prv.Limt',
[String] $PiEventLogSource = 'XY-Test'
)
$command = #"
If(Get-EventLog -List | Where-Object Log -Like '*$PiEventLog*'){
Write-Host 'EventLog already exists.' -ForegroundColor Yellow
}
else{
New-EventLog -LogName $PiEventLog -Source $PiEventLogSource -ErrorAction Stop
Write-Host 'EventLog was successfully created.' -ForegroundColor Green
}
Read-Host "Press any key to close the console..."
"#
Start-Process powershell -Verb RunAs -ArgumentList '-c', $command
Then you call this script like:
PS /> ./script.ps1 -PiEventLog 'something' -PiEventLogSource 'something'

PowerShell error "The argument is null or empty."

I am trying to create a PowerShell script that uses the below code. I believe that the projects folder having spaces is causing my error but I am unable to come up with a solution. I have tried numerous things from different stackoverflow solutions with no success. I am not a PowerShell guy so I know it is something simple (maybe). Anyone help me out there...
Script code:
Write-Host ""
$projectsFolder = Read-Host **'E:\Work - VS.NET 2022'**
Write-Host ""
Write-Host "Adding Path Exclusion: " $projectsFolder
Add-MpPreference -ExclusionPath $projectsFolder
foreach ($exclusion in $pathExclusions)
{
Write-Host "Adding Path Exclusion: " $exclusion
Add-MpPreference -ExclusionPath $exclusion
}
Error:
Adding Path Exclusion: Add-MpPreference : Cannot validate argument
on parameter 'ExclusionPath'. The argument is null or empty. Provide
an argument that is not null or empty, and then try the command
again. At E:\Work - VS.NET 2022\Tools\Visual
Studio\Windows_Defender_Exclusions_VS_2022.ps1:54 char:33
+ Add-MpPreference -ExclusionPath $projectsFolder
+ ~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Add-MpPreference], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Add-MpPreference
I do not think you want to read host. I think you want to get the content of a file. Your code will be like the bottom but I also added a simple read-host for you to review.
==========read-host================
$YesNoResponse = $null
while ($YesNoResponse -ne "y" -and $YesNoResponse -ne "n") {
Clear-Host
write-host “Yes or No?”
Write-Host "Please confirm."
$YesNoResponse = Read-Host " [Y/N] "
If ($YesNoResponse -eq "") {
Write-Host "Enter was inputted"
Return $null
}
}
I think you are trying to do something like this. If you need something else please expand.
Write-Host ""
$projectsFolder = Import-Csv 'E:\Work - VS.NET 2022'
Write-Host ""
Write-Host "Adding Path Exclusion: "
$projectsFolder = Add-MpPreference -ExclusionPath $projectsFolder
foreach ($exclusion in $pathExclusions) {
Write-Host "Adding Path Exclusion: "
$exclusion = Add-MpPreference -ExclusionPath $exclusion }
The problem in your script is that the array you use for your loop ($pathExclusions) is not created and thus is empty, resulting in $exclusion variable being always empty/null... which explain your error message.
If the goal is to prompt the user to enter manually a list of directories to be processed, then you can do something like that:
# Create the exclusions array (of strings)
$pathExclusions = #()
Write-Host ""
$projectsFolder = Read-Host **'E:\Work - VS.NET 2022'**
# Press Enter at read-host prompt to exit the loop
while ($projectsFolder -ne "") {
$pathExclusions += $projectsFolder
$projectsFolder = Read-Host **'E:\Work - VS.NET 2022'**
}
Write-Host ""
# Process each item in the exclusions array
# Loop not executed if $pathExclusions is empty so no error message
foreach ($exclusion in $pathExclusions) {
Write-Host "Adding Path Exclusion: " $exclusion
Add-MpPreference -ExclusionPath $exclusion
}
If the goal is to get the list of directories from a file, then just populate the exclusions array by getting the file content instead of the Read-Host loop:
$pathExclusions = Get-Content -Path "c:\temp\exclusionsfile.txt"

How to Load Component Services/DCOM Config SnapIn

I have a PS script to do some DCOM configuration. It works fine as long as I have the Component Services/DCOM Config snapin loaded. I want to load that programmatically so I can do all of this as part of an install package. Does anyone know how to do it? I don't know the name of the snapin to add/import.
To load the snapin I run comexp.msc -32 and click Component Services, Computers, My Computer, DCOM Configuration.
Thanks
I faced a similar problem. I couldn't find a way of loading Component services on the DCOM Config spapIn. But I found a workaround to add the user the Default DCOM Launch and Activation permissions using this powershell script:
https://www.peppercrew.nl/index.php/2012/03/set-dcom-remote-access-via-powershell/
That way, you don't need to assign the user to that particular DCOM App.
Hope this help
This is the powershell script:
PARAM(
[string]$Principal = $(throw "`nMissing -Principal DOMAIN\Group"),
$Computers = $(throw "`nMissing -Computers ('server01','server02')"))
# USAGE:
# .\Set-RemotePermission-DCOM.ps1 -Principal "DOMAIN\" -Computers ('', '',...)
#
# EXAMPLE:
# .\Set-RemotePermission-DCOM.ps1 -Principal "DOMAIN\LG-Citrix-Admins" -Computers ('CTX_DC001', 'CTX_DC002')
#
# Inspired by Karl Mitschke's post:
# http://unlockpowershell.wordpress.com/2009/11/20/script-remote-dcom-wmi-access-for-a-domain-user/
#
# And inspired Brad Turner's post:
# http://social.technet.microsoft.com/Forums/en-US/ilm2/thread/5db2707c-87c9-4bb2-a0eb-912363e2814a/
function get-sid
{
PARAM ($DSIdentity)
$ID = new-object System.Security.Principal.NTAccount($DSIdentity)
return $ID.Translate( [System.Security.Principal.SecurityIdentifier] ).toString()
}
$sid = get-sid $Principal
#DefaultLaunchPermission - Local Launch, Remote Launch, Local Activation, Remote Activation
$DCOMSDDLDefaultLaunchPermission = "A;;CCDCLCSWRP;;;$sid"
#DefaultAccessPermision - Local Access, Remote Access
$DCOMSDDLDefaultAccessPermision = "A;;CCDCLC;;;$sid"
#PartialMatch
$DCOMSDDLPartialMatch = "A;;\w+;;;$sid"
foreach ($strcomputer in $computers)
{
write-host "`nWorking on $strcomputer with principal $Principal ($sid):"
# Get the respective binary values of the DCOM registry entries
$Reg = [WMIClass]"\\$strcomputer\root\default:StdRegProv"
$DCOMDefaultLaunchPermission = $Reg.GetBinaryValue(2147483650,"software\microsoft\ole","DefaultLaunchPermission").uValue
$DCOMDefaultAccessPermission = $Reg.GetBinaryValue(2147483650,"software\microsoft\ole","DefaultAccessPermission").uValue
# Convert the current permissions to SDDL
write-host "`tConverting current permissions to SDDL format..."
$converter = new-object system.management.ManagementClass Win32_SecurityDescriptorHelper
$CurrentDCOMSDDLDefaultLaunchPermission = $converter.BinarySDToSDDL($DCOMDefaultLaunchPermission)
$CurrentDCOMSDDLDefaultAccessPermission = $converter.BinarySDToSDDL($DCOMDefaultAccessPermission)
# Build the new permissions
if (($CurrentDCOMSDDLDefaultLaunchPermission.SDDL -match $DCOMSDDLPartialMatch) -and ($CurrentDCOMSDDLDefaultLaunchPermission.SDDL -notmatch $DCOMSDDLDefaultLaunchPermission))
{
$NewDCOMSDDLDefaultLaunchPermission = $CurrentDCOMSDDLDefaultLaunchPermission.SDDL -replace $DCOMSDDLPartialMatch, $DCOMSDDLDefaultLaunchPermission
}
else
{
$NewDCOMSDDLDefaultLaunchPermission = $CurrentDCOMSDDLDefaultLaunchPermission.SDDL + "(" + $DCOMSDDLDefaultLaunchPermission + ")"
}
if (($CurrentDCOMSDDLDefaultAccessPermission.SDDL -match $DCOMSDDLPartialMatch) -and ($CurrentDCOMSDDLDefaultAccessPermission.SDDL -notmatch $DCOMSDDLDefaultAccessPermision))
{
$NewDCOMSDDLDefaultAccessPermission = $CurrentDCOMSDDLDefaultAccessPermission.SDDL -replace $DCOMSDDLPartialMatch, $DCOMSDDLDefaultAccessPermision
}
else
{
$NewDCOMSDDLDefaultAccessPermission = $CurrentDCOMSDDLDefaultAccessPermission.SDDL + "(" + $DCOMSDDLDefaultAccessPermision + ")"
}
# Convert SDDL back to Binary
write-host "`tConverting SDDL back into binary form..."
$DCOMbinarySDDefaultLaunchPermission = $converter.SDDLToBinarySD($NewDCOMSDDLDefaultLaunchPermission)
$DCOMconvertedPermissionDefaultLaunchPermission = ,$DCOMbinarySDDefaultLaunchPermission.BinarySD
$DCOMbinarySDDefaultAccessPermission = $converter.SDDLToBinarySD($NewDCOMSDDLDefaultAccessPermission)
$DCOMconvertedPermissionsDefaultAccessPermission = ,$DCOMbinarySDDefaultAccessPermission.BinarySD
# Apply the changes
write-host "`tApplying changes..."
if ($CurrentDCOMSDDLDefaultLaunchPermission.SDDL -match $DCOMSDDLDefaultLaunchPermission)
{
write-host "`t`tCurrent DefaultLaunchPermission matches desired value."
}
else
{
$result = $Reg.SetBinaryValue(2147483650,"software\microsoft\ole","DefaultLaunchPermission", $DCOMbinarySDDefaultLaunchPermission.binarySD)
if($result.ReturnValue='0'){write-host " Applied DefaultLaunchPermission complete."}
}
if ($CurrentDCOMSDDLDefaultAccessPermission.SDDL -match $DCOMSDDLDefaultAccessPermision)
{
write-host "`t`tCurrent DefaultAccessPermission matches desired value."
}
else
{
$result = $Reg.SetBinaryValue(2147483650,"software\microsoft\ole","DefaultAccessPermission", $DCOMbinarySDDefaultAccessPermission.binarySD)
if($result.ReturnValue='0'){write-host " Applied DefaultAccessPermission complete."}
}
}
#----------------------------------------------------------------------------------------------------------
trap
{
$exMessage = $_.Exception.Message
if($exMessage.StartsWith("L:"))
{write-host "`n" $exMessage.substring(2) "`n" -foregroundcolor white -backgroundcolor darkblue}
else {write-host "`nError: " $exMessage "`n" -foregroundcolor white -backgroundcolor darkred}
Exit
}
#----------------------------------------------------------------------------------------------------------
I faced the same issue and, I believe, it's because there's no equivalent 64-bit registry entry so PowerShell doesn't see it. Launching mmc compexp.msc /32 and expanding DCOM Config seems to create the entry in the background.
The work-around is to manually add the 64-bit AppID yourself which is simply done by the following code,
$appGUID = 'YOUR_APPNAME_OR_GUID'
New-PSDrive -PSProvider Registry -Name HKCR -Root HKEY_CLASSES_ROOT
New-Item -Path HKCR:\AppID\$appGUID -Value $appGUID
#New-Item -Path HKCR:\Wow6432Node\AppID\$appGUID -Value $appGUID
Remove-PSDrive HKCR
I've left the 32-bit location in the above code too although that should already exist. Once you run the above then PowerShell should be able to see the COM component,
Get-WMIObject -query ('SELECT * FROM Win32_DCOMApplicationSetting WHERE AppID = "' + $appGUID + '"') -EnableAllPrivileges
Hope this helps someone as it was driving me bananas for hours!

powershell input string not in correct format

I am having a bit of an annoying problem that I just can't seem to find the answer to. I am using a powershell script to uninstall programs and a batch file to run the script on the programs I want removed in a particular order. I found the script on the web and it works perfectly on my test machine. The problem begins when I run the script on another machine.
This is the error I get:
Error formatting a string: Input string was not in a correct format..
At C:\Users\currentuser\Desktop\uninstallScript.ps1:60 char:1
+ &msiexec `/qn `/x `{$stringer`}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: ({{0}}}:String) [],
RuntimeException
+ FullyQualifiedErrorId : FormatError
And here is the PowerShell script:
###########################################
######## Written by DC 2012-02-13#########
###########################################
<#
.SYNOPSIS
Uninstalls software by only passing the Software Title.
Should work with all msiexec string uninstallers.
For uninstall commands that end in uninstall.exe or helper.exe a "/S" is
used as a switch.
.PARAMETER DisplayName
The complete or partial name of the software being uninstalled. Must appear
as shown in add / remove programs (case insenstive).
.EXAMPLE
Uninstall-Program Java
Will search the registry and uninstall all instances of Java from a machine.
#>
[cmdletBinding()]
Param
(
[String]$DisplayName = $(throw "DisplayName is Required")
)
Set-Variable -Name ThirtyMachine -Value
"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" -Option Constant
Set-Variable -Name SixtyMachine -Value
"HKLM:\SOFTWARE\WOW6432NODE\Microsoft\Windows\CurrentVersion\Uninstall" -
Option Constant
Set-Variable -Name ThirtyUser -Value
"HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" -Option Constant
Set-Variable -Name SixtyUser -Value
"HKCU:\SOFTWARE\WOW6432NODE\Microsoft\Windows\CurrentVersion\Uninstall" -
Option Constant
$regs = $ThirtyMachine,$SixtyMachine,$ThirtyUser,$SixtyUser
foreach ($reg in $regs)
{
if(Test-Path $reg)
{
$SubKeys = Get-ItemProperty "$reg\*"
}
else
{
$SubKeys = $null
}
foreach($key in $SubKeys)
{
if($key.DisplayName -match "$DisplayName")
{
Write-Host "Found Software " $key.DisplayName
if($key.UninstallString -match "^msiexec")
{
$startGUID = $key.UninstallString.IndexOf("{") + 1
$endGuid = $key.UninstallString.IndexOf("}") - $startGUID
$stringer = $key.UninstallString.Substring($startGUID,$endGuid)
Write-Host "Uninstaller Known, now uninstalling"
&msiexec `/qn `/x `{$stringer`}
}
if($key.UninstallString.Replace('"',"") -match 'uninstall.exe\Z' -or
$key.UninstallString.replace('"',"") -match 'helper.exe\Z' )
{
$stringer = $key.UninstallString.Replace('"',"")
if(Test-Path $stringer )
{
Write-Host "Possible Uninstaller found. Trying" $key.UninstallString "/S"
&$stringer /S
}
}
}
}
}
I debugged the code in PowerShell ISE to verify that the variable $stringer contained the correct value. So I believe this has something to do with the version of powershell being run on the 2 machines. The test machine, where the script works, is version 2 whereas the other machine, where I get the error, is version 4. I've barely begun to learn powershell so I am scratching my head at this one. Hopefully it is simple to resolve. I appreciate any help offered.
The escape characters ``` in your msiexec call are causing the error and shouldn't be there. Here's a way to call it how you are properly:
& msiexec /qn "/x{$stringer}"
Alternatively, you can utilize Start-Process and wait on the process:
Start-Process -FilePath 'msiexec' -ArgumentList #('/qn','/x',"{$stringer}") -Wait

Filename not displaying in cmd

I have the following snippet
$svc_Files = gci | Where {$_.extension -eq ".svc"}
write-host "Building WSDL ..."
$cmd_svc = "`"C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bin\x64\SvcUtil.exe`""
Foreach ($svc_File in $svc_Files)
{
write-host "& $cmd_svc http://id.web/Services/$svc_File?wsdl"
}
The problem is that the file name is not displaying. However, once i remove "?wsdl", the filename displays.
How can I get the file name to display with "?wsdl" on the end?
write-host "& $cmd_svc http://id.web/Services/${svc_File}?wsdl"
Try this:
write-host "& $cmd_svc http://id.web/Services/$svc_File`?wsdl"
You could also do this:
write-host "& $cmd_svc http://id.web/Services/$($svc_File)?wsdl"