powershell error wmi - wmi

Hi i am new to power shell and i cant seem to get this script to run it is to remote execute a command using the command prompt on a computer in a workgroup here is the error i get the script is below i am running the script on a win 7 machine the machine i want to remote execute on is windows xp sp3 the fire wall is off and the com settings are set for default for authentication settings and identify for impersonate and help would be great
here is the Error
Invoke-WmiMethod : Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))
At C:\Users\Kevin\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1:57 char:40
+ $newproc = Invoke-WmiMethod <<<< -class Win32_process -name Create `
+ CategoryInfo : NotSpecified: (:) [Invoke-WmiMethod], UnauthorizedAccessException
+ FullyQualifiedErrorId : System.UnauthorizedAccessException,Microsoft.PowerShell.Commands.InvokeWmiMethod
$command = Read-Host " Enter command to run"
$user = "\Administrator"
$Domainname = $HostName +$user
$login = Get-Credential $domainname
[string]$cmd = "CMD.EXE /C " +$command
}
process {
$newproc = Invoke-WmiMethod -class Win32_process -name Create `
-ArgumentList ($cmd) -EnableAllPrivileges -ComputerName $HostName -authentication Packetprivacy -Impersonation 3 -Credential $login
if ($newproc.ReturnValue -eq 0 )
{ Write-host -foregroundcolor Green "Command $($command) Ran Sucessfully on $($HostName)"}

I think this is because Get-Credential won't pass the password to the -credential of Invoke-WmiMethod. I do this exact thing by creating the credential password using "convertto-securestring"
I know it's not as secure as you have to put the password in as plain text, but if you're the only one using the script to do maintenance or such..it's no biggie.
Try this:
$command = Read-Host " Enter command to run"
$pass = ConvertTo-SecureString "yourpassword" -Force -AsPlainText
$Domainname = 'Domain'
$user = '\administrator'
$login = $Domainname + $user
$cred = (New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $login, $pass)
[string]$cmd = "CMD.EXE /C " +$command
}
process {
$newproc = Invoke-WmiMethod -class Win32_process -name Create `
-ArgumentList ($cmd) -EnableAllPrivileges -ComputerName $HostName -authentication Packetprivacy -Impersonation 3 -Credential $cred
if ($newproc.ReturnValue -eq 0 )
{ Write-host -foregroundcolor Green "Command $($command) Ran Sucessfully

Related

Trying to use PowerShell to install Microsoft sql management studio (ssms)

I'm trying to install Microsoft sql server management studio on my AWS windows server and I keep getting this error on PowerShell
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$here = pwd
$software = "SQL Server Management Studio";
$installed = (Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* | Where { $_.DisplayName -eq $software }) -ne $null
#If SQSS was not installed before, it will be download required files and install it.
If(-Not $installed)
{
Write-Host "'$software' is NOT installed.";
wget https://aka.ms/ssmsfullsetup -outfile "SSMS-Setup-ENU.exe"
.\SSMS-Setup-ENU.exe /install /quiet /norestart
}
#If SQSS was installed before, it will try to update it to the newer version, if available.
#If no updates available, it will do nothing.
else
{
Write-Host "'$software' is installed."
if ( Test-Path -Path $here\SSMS-Setup-ENU.exe )
{
.\SSMS-Setup-ENU.exe /update /quiet /norestart
}
else {
wget https://aka.ms/ssmsfullsetup -outfile "SSMS-Setup-ENU.exe"
.\SSMS-Setup-ENU.exe /update /quiet /norestart
}
}
Here is the error I keep getting
wget : The remote name could not be resolved: 'download.microsoft.com'
At C:\Temp\mqss-1.ps1:12 char:1
wget https://aka.ms/ssmsfullsetup -outfile "SSMS-Setup-ENU.exe"
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
Continuing from my comment. The installer does not offer an /update switch, so you can just use install for both. I would use Start-Process to execute the command and let it provide the array of arguments to it.
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Push-Location $env:temp
$software = "SQL Server Management Studio"
$installed = (Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* | Where-Object DisplayName -eq $software )
If(-Not $installed){
Write-Verbose "'$software' is NOT installed, installing" -Verbose
}
else{
Write-Verbose "'$software' is installed, updating" -Verbose
}
Write-Verbose "Downloading SSMS-Setup-ENU.exe" -Verbose
try{
Invoke-WebRequest https://aka.ms/ssmsfullsetup -OutFile '.\SSMS-Setup-ENU.exe' -ErrorAction Stop
}
catch{
Write-Warning "Error downloading file: $($_.exception.message)"
break
}
$arguments = "/install","/quiet","/norestart"
Write-Verbose "Executing 'SSMS-Setup-ENU.exe $arguments'" -Verbose
try{
$result = Start-Process .\SSMS-Setup-ENU.exe -ArgumentList $arguments -PassThru -Wait
}
catch{
Write-Warning $_.exception.message
}
switch -Exact($result.ExitCode){
1603 {
Write-Verbose "Reboot is required" -Verbose
}
0 {
Write-Verbose "Installation successful" -Verbose
}
default{
Write-Verbose "Installation was not successful" -Verbose
}
}

How to hide press any key to continue when running powershell script in c++

Below is the C++ code where I am running powershell script. The script is running fine but after the script is completed it is asking to press any key in command prompt.
c++
void main()
{
string strPath = "D:\Share\Mail.ps1";
system("powershell -ExecutionPolicy Bypass -F D:\\Share\\Mail.ps1");
executeFile();
}
Powershell:
$SmtpServer = 'smtp.server.net'
$SmtpPort = '2525'
$SmtpUser = 'test'
$smtpPassword = '**********'
$MailtTo = 'test#gmail.com'
$MailFrom = 'test#test.com'
$Credentials = New-Object System.Management.Automation.PSCredential -ArgumentList $SmtpUser,
$($smtpPassword | ConvertTo-SecureString -AsPlainText -Force)
$MailSubject = 'Alert : Breach Notification'
$Body = 'Test'
$MailCount=0
$file = 'Test_10242019_5.20.txt'
Send-MailMessage -To $MailtTo -from $MailFrom -Subject $MailSubject -Body $Body -Attachment
$file -SmtpServer $SmtpServer -Port $SmtpPort -UseSsl -Credential $Credentials
Command prompt giving Press any key to continue.
How can I hide this cmd.
Add #include <Windows.h> at the begining of your main.cpp
and at the end of your Main function, add:
HWND wnd = GetConsoleWindow();
ShowWindow(wnd, 0);

EC2 User data - Disable it after all conditions are met in user data

I'm trying to rename hostname and add to AD of a spot instance. It is a simple powershell script. I've read the docs that by default user data will be disable after it gets executed once and if <persist>true</persist> is used it will not be disabled.
I think I saw somewhere this(enabling to be run at each startup) is done via taskscheduler but can't find the link.
Can someone point me to the task scheduler job or the way to manually disable the userdata once my if conditions are met.
<powershell>
Set-ExecutionPolicy unrestricted -Force
$instanceName = "test-name5"
$username = "domain\username"
$password = "password" | ConvertTo-SecureString -AsPlainText -Force
$cred = New-Object -typename System.Management.Automation.PSCredential($username, $password)
Start-Sleep -s 5
$hostname = hostname
$domain = (Get-WmiObject win32_computersystem).Domain
if (!($hostname -eq $instanceName)){
Rename-Computer -NewName $instanceName -restart -force
}Elseif (!($domain -eq 'my.domain.local')){
Start-Sleep -s 5
Add-Computer -DomainName my.domain.local -OUPath "OU=Windows,OU=QAServers,OU=Servers,DC=my,DC=domain,DC=local" -Credential $cred -Force -Restart -erroraction 'stop'
}Else {
####code to disable the running of userdata once above conditions
are met####
}
</powershell>
<persist>true</persist>
It's worth reading the ec2config-service documentation, as the setting you want is referenced in there.
You want the Ec2HandleUserData setting, which is configured in the Config.xml.
Powershell can easily update this setting:
$path = 'C:\Program Files\Amazon\Ec2ConfigService\Settings\config.xml'
$xml = [xml](Get-Content $path)
$state = $xml.Ec2ConfigurationSettings.Plugins.Plugin | where {$_.Name -eq 'Ec2HandleUserData'}
$state.State = 'Disabled'
$xml.Save($path)
I use this code when creating custom AMI's to re-enable userdata handling ($state.State = 'Enabled').
EDIT: The above is for ec2config not ec2launch which is what the OP is using. I'd missed this originally.
I this case I think you need to change the way your script runs, rather than use <persist> and then try to disable its functionality, I would remove the persist tag and call InitializeInstance.ps1 –Schedule (documentation link) in your if for the conditions you want the userdata to re-run:
if ($hostname -ne $instanceName) {
& C:\ProgramData\Amazon\EC2-Windows\Launch\Scripts\InitializeInstance.ps1 -Schedule
Rename-Computer -NewName $instanceName -Restart -Force
}
elseif ($domain -ne 'my.domain.local') {
& C:\ProgramData\Amazon\EC2-Windows\Launch\Scripts\InitializeInstance.ps1 -Schedule
Add-Computer -DomainName aws.macmillan.local -OUPath "OU=Windows,OU=QAServers,OU=Servers,DC=my,DC=domain,DC=local" -Credential $cred -Force -Restart -ErrorAction 'stop'
}
As I said in the comments of the previous answer, I had 3 options and since I found the aws scheduled task I went with the last option. Answering my own question since it'll be easy to spot the code.
<powershell>
Set-ExecutionPolicy unrestricted -Force
#Enter instance hostname here
$instanceName = "test-name8"
$username = "domain\username"
#Using ssm parameter store to avoid having the password in plaintext
$password = (Get-SSMParameterValue -Name AD-Password -WithDecryption $True -Region us-east-1).Parameters[0].Value | ConvertTo-SecureString -asPlainText -Force
Start-Sleep -s 3
$cred = New-Object -typename System.Management.Automation.PSCredential($username, $password)
Start-Sleep -s 5
$hostname = hostname
$domain = (Get-WmiObject win32_computersystem).Domain
if ($hostname -ne $instanceName){
Rename-Computer -NewName $instanceName -restart -force
}Elseif ($domain -ne 'my.domain.local'){
Start-Sleep -s 5
Add-Computer -DomainName my.domain.local -OUPath "OU=Windows,OU=QAServers,OU=Servers,DC=my,DC=domain,DC=local" -Credential $cred -Force -Restart -erroraction 'stop'
}Else {
Disable-ScheduledTask -TaskName "Amazon Ec2 Launch - Userdata Execution"
Unregister-ScheduledTask -TaskName "Amazon Ec2 Launch - Userdata Execution"
}
</powershell>
<persist>true</persist>
note: a role that has ssm policies must be attached while launching the server for this ssm parameter command to work.
I was solving similar issue and I had to change Windows Server 2016 hostname and enroll it to Elastic Server Fleet. Also I could not allow instance to be rebooted. I used this code to solve this.
NB. I understand that it is not direct way of doing this and has numerous drawbacks, but in my circumstances goal was achieved without negative impact.
<powershell>
$ComputerName = "MyPCRandomName"
Set-ItemProperty -path "HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters" -name "Hostname" -value $ComputerName
elastic-agent enroll --enrollment-token 123 --url=321
</powershell>

Why Am I Seeing These Errors in My SSRS Powershell Script in One Environment but Not Another?

I have a Powershell Script I'm working on for post-migration SSRS report administration tasks.
In this particular scenario we have a DEV environment (where I've been primarily testing) which hosts a single instance of SSRS, and a Prod environment which is a scaled out deployment across 4 nodes.
I'm new to Powershell (just discovered it 2 days ago...) and the script I have is pretty simple:
Clear-Host 
$Username = "domain\myUsername"
$Password = "myPassword"
$Cred = New-Object System.Management.Automation.PSCredential -ArgumentList #($Username,(ConvertTo-SecureString -String $Password -AsPlainText -Force))
# Dev Connection String
$webServiceUrl = 'http://DEVwebServer.domain.com/reportserver/reportservice2010.asmx?WSDL'
# Prod Connection String
# $webServiceUrl = 'http://PRODwebServerNode1.domain.com/reportserver/reportservice2010.asmx?WSDL'
$rs = New-WebServiceProxy -Uri $webServiceUrl -Credential $Cred
 
$reports = $rs.ListChildren("/Some Folder Under Root", $true) | Where-Object { $_.TypeName -eq "Report" }
$type = $ssrsProxy.GetType().Namespace;
$schedDefType = "{0}.ScheduleDefinition" -f $type;
$schedDef = New-Object ($schedDefType)
$warning = #();
foreach ($report in $reports) {
$sched = $rs.GetExecutionOptions($report.Path, [ref]$schedDef);
$snapShotExists = $rs.ListItemHistory($report.Path);
if($sched -eq "Snapshot") {
Write-Host "Following report is configured to run from Snapshot:" -ForegroundColor Yellow
Write-Host ("Report Name: {0}`nReport Path: {1}`nExecution Type: {2}`n" -f $report.Name, $report.Path, $sched)
if ($snapShotExists) {
Write-Host "Does Snapshot Exist..?`n" -ForegroundColor Yellow
Write-Host "Yes!`tNumber of Snapshots: " $snapShotExists.Count -ForegroundColor Green
$snapShotExists.CreationDate
Write-Host "`n------------------------------------------------------------"
}
elseif (!$snapShotExists) {
Write-Host "Does Snapshot Exist..?`n" -ForegroundColor Yellow
Write-Host ("No!`n") -ForegroundColor Red
Write-Host "Creating Snapshot.......`n" -ForegroundColor Yellow
$rs.CreateItemHistorySnapshot($report.Path, [ref]$warning);
Write-Host "Snapshot Created!`n" -ForegroundColor Green
$snapShotExists.CreationDate
Write-Host "`n------------------------------------------------------------"
}
}
}
The purpose of the script is simply to recursively iterate over all of the reports for the given folder in the $reports variable, check to see if the execution type is set to "Snapshot", if it is check to see if a "History Snapshot" exists, and if one does not exist, create one.
When I run this in Dev it works just fine, but when I run in PROD I get the following error repeated for each $report in my foreach loop:
Any ideas on why this would work in one and not the other and how to overcome this error?
I was able to get this working on the Prod instance by making some adjustments using this answer as a guide:
By updating my call to New-WebServiceProxy to add a Class and Namespace flag, I was able to update the script in the following ways:
...
# Add Class and Namespace flags to New-WebServiceProxy call
$rs = New-WebServiceProxy -Class 'RS' -Namespace 'RS' -Uri $webServiceUrl -Credential $Cred
 
$reports = $rs.ListChildren("/Business and Technology Solutions", $true) | Where-Object { $_.TypeName -eq "Report" }
# Declare new "ScheduleDefintion object using the Class declared in the New-WebServiceProxy call
$schedDef = New-Object RS.ScheduleDefinition
$warning = #();
foreach ($report in $reports) {
# Referencing the "Item" property from the ScheduleDefinition
$execType = $rs.GetExecutionOptions($report.Path, [ref]$schedDef.Item)
...
I don't think the adding of the Class and Namespace flags on the New-WebServiceProxy call was exactly what did it, as I think it's just a cleaner way to ensure you're getting the proper Namespace from the WebService. Maybe just a little sugar.
I think the key change was making sure to the "Item" property from the schedule definition object, although I'm not sure why it was working in Dev without doing so...

Powershell v2.0 - find start path and instance and starting an application

I am trying to write a simple script that stops and then starts a process (Application).
I can stop it fine, but can't find a way to start it again.
The string to start the process should be: "c:\AppFolder\AppName.exe" instance1
my script is:
$appName = "AppName.exe"
$filter = "name like '%"+$appName+"%'"
$result = Get-WmiObject win32_process -Filter $filter
$processid = $result.ProcessId
$command = $result.CommandLine
stop-process $processid
start $command
If I run $result | select * I see that there is an item for CommandLine which is "C:\AppFolder\AppName.exe" instance1
But If I try and do:
$command = $result.CommandLine
stop-process $processid
start $command
I get start-process : This command cannot be executed due to the error: The system cannot find the file specified
But if I manually type into a powershell window start "c:\AppFolder\AppName.exe" instance1 the Application starts fine.
Am I missing something here?
(n.b. it was suggested to me in "powershell v2 - how to get process ID" that I could use
$processid = get-process appName | select -expand id to get the processid, but when I expanded this to get all the items (probably not the correct term?)
in the object I couldn't see an option for CommandLine or similar)
I found the following (but still doesn't work)
$command = Get-WmiObject win32_process -Filter $filter | select -expandproperty CommandLine
write-host $command
This writes "c:\AppFolder\AppName.exe" instance1
start-process $command
But this then results in the following error:
Start-Process : This command cannot be executed due to the error: The system cannot find the file specified
.
At line:11 char:14
+ start-process <<<< $command
+ CategoryInfo : InvalidOperation: (:) [Start-Process], InvalidOperationException
+ FullyQualifiedErrorId : InvalidOperationException,Microsoft.PowerShell.Commands.StartProcessCommand
However, running:
start-process "c:\AppFolder\AppName.exe" instance1
starts the application?
I think I've solved it!! (and it's quite simple really) After much googling. . .
Apparently the start-process cmdlet only accepts a file location.
In order to add an argument (in this case the instance name) I need to use the attribute -ArgumentList
So I need to get the CommandLine item, and split it up, then pass it back in two parts
e.g.
$result = Get-WmiObject win32_process -Filter $filter
$comLine = $result.CommandLine -split"( )"
$comm = $commLine[0]
$inst = $commLine[2]
start-process -FilePath $comm -ArgumentList $inst
And this works as I expected it to.