Put() sometimes throws exception when trying to assign drive letter to partition - windows

I have a simple script that assigns a drive letter to any unlettered partition, like the following:
function GetNextAvailableLetter
{
#returns an unused char for drive letter assignment, or $null if none are available
}
foreach ($disk in ( get-wmiobject -class win32_volume | where-object { $_.DriveLetter -eq $null } ) )
{
$letter = GetNextAvailableLetter
if ( $letter -ne $null )
{
$disk.DriveLetter = $letter + ":"
$disk.Put()
}
}
Oddly, sometimes it'll work, and sometimes Put() throws an exception:
Exception calling "Put" with "0" argument(s): "Not supported"
I have no idea why Put() would throw.

I made a couple of empty, driveletterless drives on my computer and was able to recreate this and one other error that I think you might have neglected to mention.
Property 'DriveLetter' cannot be found on this object; make sure it exists and is settable.
At line:2 char:1
+ $disk.DriveLetter = "Q:"
+ ~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyAssignmentException
Exception calling "Put" with "0" argument(s): "Access is denied.
"
At line:3 char:1
+ $disk.Put()
+ ~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
The way to solve this would be run the variable $disk though for each loop or something along those lines. Another approach would be to check the $disk.Count ahead of time.
$disk = get-wmiobject -class win32_volume | where-object { $_.DriveLetter -eq $null }
If (($disk) -and ($disk.Count -eq 1)){
$disk.DriveLetter = "Q:"
$disk.Put()
}
The If should in theory protect you from errors when $disk is empty or returns more that one object.

According to the Scripting Guys:
The reason for this error is that the Windows PowerShell prompt is not running with Administrator rights. Unfortunately, the error that bubbles back up from WMI does not tell us that the problem is related to rights.

Related

How do I download a file using windows command line without having to input a proxy password?

After looking at various stackoverflow questions, I found several ways to download a file from a command line without interaction from the user.
The only one that worked for me also works only on Windows 10 natively :
curl -sko %TEMP%\file.txt "https://some.hostname/file.txt"
But installing an external tool like wget/curl is what I want to avoid.
What didn't work for me because of proxy errors :
Command:
bitsadmin.exe /transfer "dljob" "https://some.hostname/file.txt" %TEMP%\file.txt
Error:
DISPLAY: 'dljob' TYPE: DOWNLOAD STATE: ERROR
PRIORITY: NORMAL FILES: 0 / 1 BYTES: 0 / UNKNOWN
Unable to complete transfer.
ERROR FILE: https://some.hostname/file.txt -> E:\Users\xxx\AppData\Local\Temp\file.txt
ERROR CODE: 0x80190197
ERROR CONTEXT: 0x00000005
Command:
powershell -Command "(New-Object Net.WebClient).DownloadFile('https://some.hostname/file.txt', '%TEMP%\file.txt')"
Error:
Exception calling "DownloadFile" with "2" argument(s): "The remote server returned an error: (407) Proxy Authentication Required."
At line:1 char:1
+ (New-Object Net.WebClient).DownloadFile('https://some.hostname/file.txt ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : WebException
Command:
powershell -Command "Invoke-WebRequest 'https://some.hostname/file.txt' -OutFile %TEMP%\file.txt
Error:
Invoke-WebRequest :
Authentication required
You must be authenticated to access this URL.
...
Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.1.17763.1007
At line:1 char:1
+ Invoke-WebRequest 'https://some.hostname/file.txt ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
This didn't work either :
powershell -Command "$client.Credentials = Get-Credential; $browser.Proxy.Credentials =[System.Net.CredentialCache]::DefaultNetworkCredentials; (New-Object Net.WebClient).DownloadFile('https://some.hostname/file.txt', 'file.txt')"
Error :
cmdlet Get-Credential at command pipeline position 1
Supply values for the following parameters:
Credential
Get-Credential : Cannot process command because of one or more missing mandatory parameters: Credential.
At line:1 char:23
+ $client.Credentials = Get-Credential; $browser.Proxy.Credentials =[Sy ...
+ ~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Get-Credential], ParameterBindingException
+ FullyQualifiedErrorId : MissingMandatoryParameter,Microsoft.PowerShell.Commands.GetCredentialCommand
The property 'Credentials' cannot be found on this object. Verify that the property exists and can be set.
At line:1 char:39
+ ... Credential; $browser.Proxy.Credentials =[System.Net.CredentialCache]: ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyNotFound
Exception calling "DownloadFile" with "2" argument(s): "The remote server returned an error: (407) Proxy
Authentication Required."
At line:1 char:124
+ ... redentials; (New-Object Net.WebClient).DownloadFile('https://some.hostname ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : WebException
Refer to this question Access web using Powershell and Proxy
You can try something like that in Powershell and suppose that you have already created a folder named as C:\Test:
$url = "https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png"
$file = "C:\Test\" + $url.Split("/")[-1]
$wb = New-Object System.Net.WebClient
$wb.Proxy.Credentials =[System.Net.CredentialCache]::DefaultNetworkCredentials
$wb.DownloadFile($url,$file)
EDIT : 14/08/2020 #17:08
I tried this on Windows Powershell ISE and it works 5/5 :
cls
$start_time = Get-Date
$url = "https://cdn2.unrealengine.com/Fortnite%2FBoogieDown_GIF-1f2be97208316867da7d3cf5217c2486da3c2fe6.gif"
$Folder = "$Env:Temp\DownloadFolder"
# We create a SubFolder Named "DownloadFolder" in the temporary file %Temp% if it doesn't exists yet !
If ((Test-Path -Path $Folder) -eq 0) { New-Item -Path $Folder -ItemType Directory | Out-Null }
# We can get the name of the file to be downloaded from the variable $url
# $url = "https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png"
# In our case the FileName will be = "googlelogo_color_272x92dp.png" or
# Fortnite%2FBoogieDown_GIF-1f2be97208316867da7d3cf5217c2486da3c2fe6.gif
$file = $Folder+ "\" + $url.Split("/")[-1]
Try
{
$wb = New-Object System.Net.WebClient
$wb.Proxy.Credentials =[System.Net.CredentialCache]::DefaultNetworkCredentials
$wb.DownloadFile($url,$file)
# better use Invoke-Item $Folder instead of ii
Invoke-Item $Folder
Write-Output "Running Script Time taken is : $((Get-Date).Subtract($start_time).Milliseconds) millisecond(s)"
}
Catch
{
Write-Host "Error from $url" `n"Message: [$($_.Exception.Message)"] -ForegroundColor Red -BackgroundColor DarkBlue
}
This worked for me :
powershell -Command "[System.Net.WebRequest]::DefaultWebProxy = [System.Net.WebRequest]::GetSystemWebProxy(); [System.Net.WebRequest]::DefaultWebProxy.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials; (New-Object Net.WebClient).DownloadFile('https://some.hostname/file.txt', 'file.txt')"

Trying to automate filling input fields of web page a with powershell. But stuck with errors

I am trying to fill the input fields with powershell but facing these issues.
$ie = New-Object -com internetexplorer.application;
$ie.visible = $true;
$ie.navigate("https://mxtoolbox.com/blacklists.aspx");
while ($ie.Busy -eq $true) { Start-Sleep -Seconds 1; }
($ie.document.getElementsByName("ctl00$ContentPlaceHolder1$ucToolhandler$txtToolInput") |select -first 1).value ="99.99.99.999";
$ie.Document.getElementsByName("ctl00$ContentPlaceHolder1$ucToolhandler$btnAction").click()
while ($ie.Busy -eq $true) { Start-Sleep -Seconds 1; }
Output :
The property 'value' cannot be found on this object. Verify that the
property exists and can be set. At line:5 char:1
+ ($ie.document.getElementsByName("ctl00$ContentPlaceHolder1$ucToolhand
...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyNotFound Method invocation failed because [System.__ComObject] does not contain a method named
'click'. At line:6 char:1
+ $ie.Document.getElementsByName("ctl00$ContentPlaceHolder1$ucToolhandl
...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (click:String) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound

Method invocation failed because [Microsoft.ActiveDirectory.Management.ADPropertyValueCollection] does not contain a method named 'op_Division'

I am using the progress bar to check how many computers exist in the “COMPUTERS” container prior to moving of the computers to the specific OU “LAPTOPS. Keep in mind, when only one computer exists in the “COMPUTERS” container, I received the error message below. The computer then gets moved successfully. However, when two or more computers exist in the COMPUTER container, it did NOT project the error when moving from the container to OU. I’ve been searching to find answer but no luck. Please I need some help.
Note: I’m using Powershell version 5.1.14409.1012
error: Does not contain method name 'op_Division'
Method invocation failed because
[Microsoft.ActiveDirectory.Management.ADPropertyValueCollection] does not contain a
method named 'op_Division'.
At line:13 char:5
+ $percent = ($counter / $pcName.count) * 100
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (op_Division:String) [], RuntimeExcepti
on
+ FullyQualifiedErrorId : MethodNotFound
$computerCN = 'CN=COMPUTERS,DC=MYTEST,DC=LOCAL'
$pcName = Get-ADComputer -Filter * -SearchBase $computerCN -SearchScope OneLevel
$computerOU = 'OU=LAPTOP,OU=MYHOME,DC=MYTEST,DC=LOCAL'
$counter = 0
Foreach ( $computer in $pcName )
{
$prefix = $computer.name
$percent = ($counter / $pcName.count) * 100
$counter++
Write-Progress -Activity 'Processing computers' -Status "Scanning... $counter out of $($pcName.count)" -CurrentOperation $prefix -PercentComplete $percent
Start-Sleep -Milliseconds 500
Switch -Wildcard ( $prefix )
{
'LAP*' { 'Moved'; Get-ADComputer $computer | Move-ADObject -TargetPath $computerOU }
Default { 'Skip' }
}
}
Are you certain that GetADComputer is returning more than one object? You should always force results of a command to a collection with the array subexpression operator when you are expecting a collection.
$pcname = #(Get-ADComputer -Filter * -SearchBase $computerCN -SearchScope OneLevel)

Substring() fails - need to cast result as string instead of default double

I thought substring is easy until I tried:
# extract from a webpage with regex into $mmdd the value like 08/09
Write-Host $mmdd
08/09
$mmdd.Substring(0,2)
Then I get:
Method invocation failed because [System.Double] does not contain a method named 'Substring'.
At line:1 char:1
+ $test.Substring(0,2)
+ ~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
> $test.Substring(3)
Method invocation failed because [System.Double] does not contain a method named 'Substring'.
At line:1 char:1
+ $test.Substring(3)
+ ~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
How do I cast the variable $mmdd to string so I can use Substring() on it?
I suspect I have to do something to the following:
$page | Select-String -Pattern $mmddyyyyRgx -AllMatches |
% { $_.Matches } |
% { $_.Value } |
Select-String -Pattern $mmddRgx -AllMatches |
% { $_.Matches } |
% { $_.Value } -Outvariable mmdd
Since $mmdd gave me:
0.888888888888889
it's a double balue, casting like below will not work as expected:
[string]$mmdd.Substring(0,2)
it will give me
0.
instead of
08
Just call the ToString() method on $mmdd so you can use SubString():
$mmdd.ToString().SubString(0,2)
However, maybe you tell us about your actual problem since this could be a XY Problem.

Remove-Item doesn't work, Delete does

Does anyone have any idea why Remove-Item would fail while Delete works?
In below script, I get a list of files I'd like to delete.
Using Remove-Item I get following error message:
VERBOSE: Performing the operation "Remove File" on target
"\\UncPath\Folder\test.rtf". Remove-Item : Cannot remove item
\\UncPath\Folder\test.rtf: Access to the path is denied.
but using Delete is deleting those files as we speak.
Script
$files = gci \\UncPath\Folder| ?{ $_.LastWriteTime -le (Get-Date).addDays(-28) }
# This doesn't work
$files | Remove-Item -force -verbose
# But this does
$files | % { $_.Delete() }
powershell may act strange with UNC path, I think it prepends the UNC Path with the current provider you can verify this with :
cd c:
test-path \\127.0.0.1\c$
returns TRUE
cd HKCU:
test-path \\127.0.0.1\c$
returns FALSE
when specifying the fullpath we're telling powershell to use the filesystem provider, that solves the problem. you could also specify the provider like remove-item filesystem::\\uncpath\folder
I can finally repro this and IMO it appears to be a bug. The repro is to have an open share like C$ but to set Deny Modify perms for the user on the file. When I do that, I observe this:
PS> gci '\\Keith-PC\C$\Users\Keith\foo.txt' | ri -for
ri : Cannot remove item \\Keith-PC\C$\Users\Keith\foo.txt: Access to the path is denied.
At line:1 char:43
+ gci '\\Keith-PC\C$\Users\Keith\foo.txt' | ri -for
+ ~~~~~~~
+ CategoryInfo : InvalidArgument: (\\Keith-PC\C$\Users\Keith\foo.txt:FileInfo) [Remove-Item], ArgumentExc
eption
+ FullyQualifiedErrorId : RemoveFileSystemItemArgumentError,Microsoft.PowerShell.Commands.RemoveItemCommand
PS> gci '\\Keith-PC\C$\Users\Keith\foo.txt' | %{$_.Delete()} # <== this works!
I also observe that removing the -Force parameter deletes the file without error as well. The deny perms still allow me to delete the file from Windows Explorer so that leads me to believe that the file should delete. So what is up with using the -Force parameter? When I delve into the ErrorRecord I see this:
Message : Access to the path is denied.
ParamName :
Data : {}
InnerException :
TargetSite : Void set_Attributes(System.IO.FileAttributes)
StackTrace : at System.IO.FileSystemInfo.set_Attributes(FileAttributes value)
at Microsoft.PowerShell.Commands.FileSystemProvider.RemoveFileSystemItem(FileSystemInfo
fileSystemInfo, Boolean force)
It seems that the -Force parameter is trying to set (more likely reset) attributes and the permissions on the file don't allow it e.g.:
PS> gci '\\Keith-PC\C$\Users\Keith\foo.txt' | %{$_.Attributes = 'Normal'}
Exception setting "Attributes": "Access to the path is denied."
At line:1 char:45
+ gci '\\Keith-PC\C$\Users\Keith\foo.txt' | %{$_.Attributes = 'Normal'}
+ ~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], SetValueInvocationException
+ FullyQualifiedErrorId : ExceptionWhenSetting
So it seems to me that PowerShell should first try as if the -Force weren't present and if that fails, then try resetting attributes.

Resources