Send-SSMCommand to resize windows drive - amazon-ec2

I currently have the following in a powershell script
$diskNumber = (Get-Disk | ? { $_.PartitionStyle -eq "RAW" }).Number
Initialize-Disk -Number $diskNumber -PartitionStyle "MBR"
$part = New-Partition -DiskNumber $diskNumber -UseMaximumSize -IsActive -DriveLetter "e"
Format-Volume -DriveLetter $part.DriveLetter -Confirm:$FALSE
I was able to manually run these commands sucessfully in aws SSM console but I am not able to do it from a remote laptop
any idea?
command i used is
Send-SSMCommand -InstanceId i-092bbabaf1e82f5a1 -Parameters #{commands = "ssm_add_drive.ps1"} -DocumentName "AWS-RunPowerShellScript"

Related

Problem with Connect-VIServer and Disconnect-VIServer on my powershell script

I've a problem with my powershell script and I don't know how to fix it.
My script allow to recover the VM protected by Zerto and to get each tags of these VMs on the vcenter.
My problem is on how my script works.
At the beginning, I initiate a connexion on each Vcenter because the VMs are located on two differents Vcenter. Then I can recover the information that I want for each VM.
#### Skip SSL/TSL verification
add-type #"
using System.Net;
using System.Security.Cryptography.X509Certificates;
public class TrustAllCertsPolicy : ICertificatePolicy {
public bool CheckValidationResult(
ServicePoint srvPoint, X509Certificate certificate,
WebRequest request, int certificateProblem) {
return true;
}
}
"#
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
#### Set connexion to each Vcenters
#### Connect to XXX
Connect-VIServer -Server Vcenter1 -User My_User#my.domain -Password XXXX
#### Connect to XXX
Connect-VIServer -Server Vcenter2 -User My_User#my.domain -Password XXXX
[...]
#### Create post-script file with VM + Vcenter + Tags + Cluster
foreach ($VPG in $Get_VPG){
$VM_List = $BaseURL+"vms?vpgName=$VPG"
$VM1 = Invoke-RestMethod -Uri $VM_List -TimeoutSec 100 -Headers $zertSessionHeader_json -ContentType $TypeJSON | ConvertTo-Json
$VM2 = $VM1 | ConvertFrom-Json
$VM3 = $VM2.value.VmName
foreach($VM in $VM3){
$Get_Tag = Get-VM $VM | Get-TagAssignment
$Get_Tag_And_VM = Get-VM -Name $VM | Select-object Name,
#{N = 'vCenter'; E = {([system.uri]$_.ExtensionData.Client.ServiceUrl).Host}},
#{N = 'Tags'; E = {(Get-TagAssignment -Entity $_).Tag -join ', '}},
#{N = 'Cluster';E={Get-Cluster -VM $_}}
$Get_Tag_And_VM2 = $Get_Tag_And_VM | Where-Object {$_ -match 'Tags=;'}
Add-Content $Result -Value $Get_Tag_And_VM2
}
}
Write-Output "[+] Deconnexion Vcenter1 et Vcenter2"
Disconnect-VIServer -Server Vcenter1 -Confirm:$false
Disconnect-VIServer -Server Vcenter2 -Confirm:$false
I can see that at the beginning of the script, each connexions are done :
And I can see that I can recover each informations that I need from a CSV file.
At the end, I have a two disconnect. But at this step, I've this error :
You can see that in the script, the disconnect part is Disconnect-VIServer * -Confirm:$false.
I have the same problem with Disconnect-VIServer * -Confirm:$false and with a disconnect for each Vcenter.
Are able to tell me why I've this error whereas each connexion are done well at the beginning ? And I don't know why this problem doesn't appears everytime. The problem appears occasionally.
Does anyone have an idea about this issue ?
Thanks a lot !

output results from a Powershell script [duplicate]

How do I properly use $_ in out-file? Here's my code:
get-content computers.txt |
Where {$_ -AND (Test-Connection $_ -Quiet)} |
foreach { Get-Hotfix -computername $_ } |
Select CSName,Description,HotFixID,InstalledBy,InstalledOn |
convertto-csv | out-file "C:\$_.csv"
I'm trying to execute a get-hotfix for all the computers listed in the text file then I want them to be exported to CSV with the computer name as the filename.
You need one pipeline to process the computers.txt files, and a nested one inside the foreach to process the list of hotfixes for each computer:
get-content .\computers.txt |
Where {$_ -AND (Test-Connection $_ -Quiet)} |
foreach {
Get-Hotfix -computername $_ |
Select CSName,Description,HotFixID,InstalledBy,InstalledOn |
convertto-csv | out-file "C:\$_.csv"
}
Edit: Changed computers.txt to .\computers.txt, as this is required for local paths in powershell
i can see with this:
get-content .\computers.txt | Where {$_ -AND (Test-Connection $_ -Quiet)} | foreach{ Get-Hotfix -id KB4012212 -computername $_ | Select CSName,Description,HotFixID,InstalledBy,InstalledOn | convertto-csv | out-file "C:\$_.csv" }
i can see only in which PC is the fix (KB4012212) installed.
it's possible to see the following
CSNAME Fix(Inst/NotInst)
PC1 FIxInstalled
PC2 FixNotinstalled
PC3 FixnotInstalled
..
..
etc
I monkeyed with this for a while and nothing I found on-line worked until I used this combo. 
I used the method is this thread but it was SO slow and I wanted to learn more about using jobs so this is what ended up working for me on Windows 7 PS Ver 4.
All other options were either too slow or did not return data from the remote system.
$VMs = get-content C:\WinVms.txt #Generate your hostnames list however you deem best.
foreach ($vm in $vms)
{
Write-Host "Attempting to get hotfixes on:" $vm
invoke-command -computername $vm -ScriptBlock {start-job -scriptblock {(get-hotfix | sort installedon)[-1]} | wait-job | receive-job} -AsJob
}
start-sleep 60 # give it a minute to complete
get-job | ? { $_.state -eq "Completed"} | receive-job -keep | export-csv c:\temp\win-patch.csv
you can check your failures too like this: 
get-job | ? { $_.state -eq "Failed"}

How to map Network Printers with PowerShell and CSV

I want to deploy our Network Printers that are shared from a Print-Server to Windows 10 PCs, on per-machine basis.
Currently we do this with a Kix-Script and ini file, but I want to move this to PowerShell and deploy it as a Startup/Login Script with Group Policy. The deployment must be with PowerShell not purely GPO, with a script we are more flexible to deploy to singular machines.
I've written a PS Script and using a CSV File containing the PCs and Printers to map, but it seams completely wrong. Is there a better way to deploy the printers?
Here are my CSV, 'True' is to set Printer as Default:
#TYPE Selected.System.Management.ManagementObject.Data.DataRow
Name
PC0001
\\SV0002\PR0001, True
\\SV0002\PR00002
Name
PC0002
\\SV0002\PR0001, True
\\SV0002\PR00002​
and the PS-Script:
Get–WMIObject Win32_Printer | where{$_.Network -eq ‘true‘} | foreach{$_.delete()}
$Printers=IMPORT-CSV \\server\$env:username\printers.csv
FOREACH ($Printer in $Printers) {
Invoke-Expression 'rundll32 printui.dll PrintUIEntry /in /q /n $($Printer.Name)'
}​
I edited the csv File, and it looks like this now:
Client;1;2;3;4;5;6;7;8;9;10;11;12;13;14;15;Default
PC0001;\\SV0001\PR0001;\\SV0001\PR0002;;;;;;;;;;;;;;pr_01
PC0002;\\SV0001\PR0001;\\SV0001\PR0002;\\SV0001\PR0003;;;;;;;;;;;;;pr_03
We did that with Excel, so it's easier to edit, and save it as csv.
Also where is located, we changed it to \Server\Netlogon\Subfolder\Printers.csv so that also the the Variable is changed to:
$Printers=IMPORT-CSV \\server\Netlogon\Subfolder\printers.csv
But now I think the whole script is wrong?
Using a CSV like this:
name,printers,defaultprinter
PC0001,\\SV0001\PR0001;\\SV0001\PR0002,PR0002
PC0002,\\SV0001\PR0001;\\SV0001\PR0003,PR0003
PC0003,\\SV0001\PR0001;\\SV0001\PR0004,PR0004
The code would be:
$csv = "\\server\Netlogon\Subfolder\printers.csv"
$Computers = Import-Csv $csv
foreach ($Computer in $Computers){
If ($Computer.name -eq $env:computername) {
$Printers = ($Computer.printers).split(";")
foreach ($Printer in $Printers) {Add-Printer $Printer -ErrorAction SilentlyContinue}
(New-Object -ComObject WScript.Network).SetDefaultPrinter("$($Computer.defaultprinter)")
}
}
The way we do (did) it here at work was by invoking some VBScript from within the PowerShell script.
Print server and Printer are obtained via AD cmdlets.
$net = New-Object -Com WScript.Network
$net.AddWindowsPrinterConnection("\\" + $PRINT_SERVER + "\" + $PRINTER)
Starting from Windows 8 :
# Add the printer
Add-Printer -ConnectionName ("\\" + $printServer + "\" + $printerName) -Name $printerName
# Get the printer
$printer = Get-WmiObject -Query "Select * From Win32_Printer Where ShareName = '$printerName'"
# Set printer as default
$printer.SetDefaultPrinter()
I solved the Problem with the Script of James C., many thanks to him, it was a big help!.
The only wrong Thing was that between Add-Printer and $Printer, it had to be -ConnectionName. After that Little Edit in the script, everything was fine.
So we made a GP_Printers, where we putted under Computer Configuration/Windows Settings/Scripts/Startup this Script as printermapping.ps1
Also we putted into Shutdown a PowerShell Script where all Printer Connection are deleted.
Here are all the scripts.
CSV:
name,printers,defaultprinter
PC0001,\\SV0001\PR0001;\\SV0001\PR0002,PR0002
PC0002,\\SV0001\PR0001;\\SV0001\PR0003,PR0003
PC0003,\\SV0001\PR0001;\\SV0001\PR0004,PR0004
Printer Mappings with PowerShell depending on CSV:
$csv = "\\server\Netlogon\Subfolder\printers.csv"
$Computers = Import-Csv $csv
foreach ($Computer in $Computers){
If ($Computer.name -eq $env:computername) {
$Printers = ($Computer.printers).split(";")
foreach ($Printer in $Printers) {Add-Printer-ConnectionName $Printer -ErrorAction SilentlyContinue}
(New-Object -ComObject WScript.Network).SetDefaultPrinter("$($Computer.defaultprinter)")
}
}
And the Printer Disconnection:
Get-WmiObject -Class Win32_Printer | where{$_.Network -eq ‘true‘}| foreach{$_.delete()}
I hope this could be helpfoul for others.
Again many thanks to James C.
WBZ-ITS
I've made some correction and improvements to the script, and found also some Problem that Comes if you use it on a GPO, the changes are following:
CSV:
name,printers,defaultprinter
PC0001,\\SV0001\PR0001;\\SV0001\PR0002,PR0002
PC0002,\\SV0001\PR0001;\\SV0001\PR0003,PR0003
PC0003,\\SV0001\PR0001;\\SV0001\PR0004,PR0004
The Connection Script:
$csv = "\\server\Netlogon\Subfolder\printers.csv"
$Computers = Import-Csv $csv
foreach ($Computer in $Computers){
If ($Computer.name -eq $env:computername) {
$Printers = ($Computer.printers).split(";")
foreach ($Printer in $Printers) {Add-Printer-ConnectionName $Printer -ErrorAction SilentlyContinue}
(New-Object -ComObject WScript.Network).SetDefaultPrinter("$($Computer.defaultprinter)")
}
}
And also a disconnect Script when logging off:
#$a = Get-WMIObject -query "Select * From Win32_Printer Where Name = 'Microsoft Print to PDF'"
#$a.SetDefaultPrinter()
$TargetPrinter = "Microsoft Print to PDF"
$ErrorActionPreference = “SilentlyContinue”
$LocalPrinter = GWMI -class Win32_Printer | Where {$_.Name -eq $TargetPrinter}
$LocalPrinter.SetDefaultPrinter()
$ErrorActionPreference = “Stop”
Get-WmiObject -Class Win32_Printer | where{$_.Network -eq ‘true‘}| foreach{$_.delete()}
To disconnect the default printer must be changed, otherwise it won't be disconnected.
After all Script was made, we putted them in a GPO under User Configuration\Policies\Windows Settings\Scripts and there on Logon and Logoff.
You may have some troubles that the GPOs won't run, so here some usefull troubleshooting guides that i found:
The Scripts aren't working as Machine Policies under Startup and Shutdown, they have to be in the User Configuration as mentioned above.
Also you have to configure the Policie that deley the Script of 5 minutes. These are under Computer Configuration\Administrative Templates\System\Group Policy\Configure Logon Script Delay aktivate them and set the delay to 0 minutes, otherwise any Script will be deleyed to 5 minutes after logon.
Also a problem could be, if you are running the GPO on Windows 8/10 System, and you made them on a WIndows 7 PC. Create GPOs allways on the Server 2008/R2 or 2012R2 for this kind of system.
It could be helpfoul also if you configure the Logon/Logoff GPO as follows: As Scriptname "powershell.exe" (without quotes) and as Script Parameters -F "\SERVER\FREIGABE\meinskript.ps1" (with quotes.
I hope this could help someone else.
Thanks to who hleped me.
WBZ-ITS

Assigning fixed drive letters to USB Devices on Windows Server (2012)

Hello fellow Stackoverflowers :)
I am looking for ways to assign a fixed Driveletter to USB Drives on Windows Server 2012 (Foundation).
The Scenario:
One of my smaller customers has 2 USB Drives for his serverbackup, which are swapped every day to have an offsite backup. Currently they are manually reassigning the Driveletters if there is a mismatch.
I already have a plan to realize this but wanted to ask for advice before implementing it since i am not sure this is the best possible solution.
I would go about it the following way:
Enable the DriverFramework-UserMode log if it is not enabled
Create a scheduled task triggered by EventID 2106
run a powershell script (via the scheduled task) that assigns the driveletter if the DeviceID matches one of the backup drives
So the question is:
Is it somehow possible to assign a fixed driveletter to a set of usb devices without having to run a script everytime a device is attached?
And if not is there a better way to detect when a device is attached and trigger the task?
Of course i did some research but only found solutions for Windows7 or Server2008. I would prefer to solve this without 3rd party tools.
Thank you in advance for any insight you can give on this topic
Regards Paul
I don't know if this helps much, but I found a nice post at https://social.technet.microsoft.com/Forums/windowsserver/en-US/09c9814a-38fa-4b16-bc8f-01329882a791/powershell-wmi-get-usb-storage-devices-only where the following code helps detect a connected USB device:
$diskdrive = gwmi win32_diskdrive | ?{$_.interfacetype -eq "USB"}
$letters = $diskdrive | %{gwmi -Query "ASSOCIATORS OF {Win32_DiskDrive.DeviceID=`"$($_.DeviceID.replace('\','\\'))`"} WHERE AssocClass = Win32_DiskDriveToDiskPartition"} | %{gwmi -Query "ASSOCIATORS OF {Win32_DiskPartition.DeviceID=`"$($_.DeviceID)`"} WHERE AssocClass = Win32_LogicalDiskToPartition"} | %{$_. deviceid}
$drive = gwmi win32_volume | ? {$letters -contains ($_.name -replace "\\")}
Then you can change the drive letter with the following (must be admin)
$drive.DriveLetter = "O:"
$drive.Put()
EDIT
OK here is another try. The following code (which I found here: http://blogs.technet.com/b/heyscriptingguy/archive/2010/04/13/hey-scripting-guy-april-13-2010.aspx) allows to create a WMI event which will fire when a USB drive is plugged in.
I've added an action to that event so that a script block executes.
The script block checks the letter of the USB drive and if it's not, say, "O:", it will set it.
I didn't use Wait-Job, as the job will continue running for as long as the event exists, and I wanted to see some output for testing.
In anycase, this should be closer to what you want to do:
$scriptblock = {
$driveLetter = "O:"
$diskdrive = gwmi win32_diskdrive | ?{$_.interfacetype -eq "USB"}
$letters = $diskdrive | %{gwmi -Query "ASSOCIATORS OF {Win32_DiskDrive.DeviceID=`"$($_.DeviceID.replace('\','\\'))`"} WHERE AssocClass = Win32_DiskDriveToDiskPartition"} | %{gwmi -Query "ASSOCIATORS OF {Win32_DiskPartition.DeviceID=`"$($_.DeviceID)`"} WHERE AssocClass = Win32_LogicalDiskToPartition"} | %{$_. deviceid}
$drive = gwmi win32_volume | ? {$letters -contains ($_.name -replace "\\")}
if ($drive.DriveLetter -ne $driveLetter)
{
$drive.DriveLetter = $driveLetter
$drive.Put()
}
$drive.DriveLetter
}
$job = Register-WmiEvent -Query "Select * from __InstanceCreationEvent within 5 where targetinstance isa 'win32_logicaldisk'" -SourceIdentifier usb -Timeout 1000 -Action $scriptblock
while ($job.State -ne 'Stopped')
{
$job | Receive-Job
sleep 5
}
Unregister-Event -SourceIdentifier usb -Force | Out-Null
$job | Remove-Job -force
Worth noting:
The script block will receive $args as well as $event. I didn't use them but they will probably help optimize the script further.
Here is the code i will probably end up using:
To create a permanent wmi consumer that runs a script:
$computer = "xxx"
$filterNS = "root\cimv2"
$wmiNS = "root\subscription"
$query = "Select * from __InstanceCreationEvent within 5 where targetinstance isa 'win32_logicaldisk'"
$filterName = "TestFilter"
$filterPath = Set-WmiInstance -Class __EventFilter `
-ComputerName $computer -Namespace $wmiNS -Arguments `
#{name=$filterName; EventNameSpace=$filterNS; QueryLanguage="WQL";
Query=$query}
$consumerPath = Set-WmiInstance -Class CommandLineEventConsumer `
-ComputerName $computer -Namespace $wmiNS `
-Arguments #{
name="TestConsumer";
ExecutablePath= "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe";
CommandLineTemplate = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -executionpolicy bypass -file D:\\reassignDriveletter.ps1"
}
Set-WmiInstance -Class __FilterToConsumerBinding -ComputerName $computer `
-Namespace $wmiNS -arguments #{Filter=$filterPath; Consumer=$consumerPath} |
out-null
And here is the script that changes the driveletter if the Serialnumber of the drive matches one of the Backupdrives
$driveLetter = "Z:"
$diskdrive = gwmi win32_diskdrive | ?{($_.interfacetype -eq "USB") -and $_.serialnumber.trim() -eq "761203FA9J813S" -or $_.serialnumber.trim() -eq "761239FA9J813S"}
$letters = $diskdrive | %{gwmi -Query "ASSOCIATORS OF {Win32_DiskDrive.DeviceID=`"$($_.DeviceID.replace('\','\\'))`"} WHERE AssocClass = Win32_DiskDriveToDiskPartition"} | %{gwmi -Query "ASSOCIATORS OF {Win32_DiskPartition.DeviceID=`"$($_.DeviceID)`"} WHERE AssocClass = Win32_LogicalDiskToPartition"} | %{$_. deviceid}
$drive = gwmi win32_volume | ? {$letters -contains ($_.name -replace "\\")}
if ($drive.DriveLetter -ne $driveLetter)
{
$drive.DriveLetter = $driveLetter
$drive.Put()
}

Powershell Control Windows Search through command line

I am trying to write a powershell script that will disable indexing on some drives but keep it activated on some others (ex: C:).
Has anyone done it before ?
Thanks
try this, (not tested):
function Disable-Indexing{
Param($Drive)
$obj = Get-WmiObject -Class Win32_Volume -Filter "DriveLetter='$Drive'"
$indexing = $obj.IndexingEnabled
if("$indexing" -eq $True){
write-host "Disabling indexing of drive $Drive"
$obj | Set-WmiInstance -Arguments #{IndexingEnabled=$False} | Out-Null
}
}
use:
disable-indexing "c:"

Resources