PowerShell, doesn't contain method 'items' - windows

When executing this code, I received the error below:
$filesExist = Test-Path($file)
if ($filesExist) {
$shell_app=new-object -com shell.application
$zip_file = Get-Item "$mindCrackFolder\files.zip"
$destination = Get-Item $mindCrackFolder
$destination.Copyhere($zip_file.items(), 0x14)
#Remove-Item "$zip_file"
#Remove-Item "install.ps1"
}
Error:
Method invocation failed because [System.IO.FileInfo] doesn't contain a method named 'items'.
At C:\Users\User1\Desktop\ps install\install.ps1:33 char:5
+ $destination.Copyhere($zip_file.items(), 0x14)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
But I already convertered $destination into a IO object to be manipulated? Can I get any help, this my first time experimenting with PS.

This has nothing do with $destination. $zip_file.items() is evaluated first and the error message is telling you that the .NET System.IO.FileInfo object returned by Get-Item has no Items() method. Get-Item only returns an object that provides information about a file - size, last write time, readonly or not, etc. You can't use Get-Item to access the contents of a ZIP file.
If you need to extract the contents of the ZIP file, consider using the PowerShell Community Exensions' Expand-Archive cmdlet.

The errors is talking about the object you use the items() method on = $zip_file. Powershell doesn't have built-in zip support, you gotta create it(using shell.application com-object, google it) or add a .net library. $zip_file is just a simple FileInfo object just as the ones you get from dir(Get-ChildItem). It does not contain an items() method.
Solution: as previously said, google powershell zip files to read about how you can use zip files in powershell. My suggestion is DotNetZip

I don't know what and where you learned these, but you seem to have copied some code wrongly and made changes ad-hoc. Try the below script which does what you want:
$shell_app=new-object -com shell.application
$filename = "test.zip"
$zip_file = $shell_app.namespace((Get-Location).Path + "\$filename")
$destination = $shell_app.namespace((Get-Location).Path)
$destination.Copyhere($zip_file.items(), 0x14)
The items and copyHere method are not available on FileInfo objects, which is what you get from Get-Item. Use them as shown above.

Related

edit an image in place

So I've got a small script which opens an image:
$file = ([System.IO.FileInfo]$FilePath);
if ($file.Exists) {
$imgInMemory = [System.Drawing.Image]::FromFile($file.FullName);
[...irrelevant code to the question...]
$imgInMemory.Save($($file.FullName + '.tmp'), $codecInfo, $encoderParams);
Move-Item -Path $($file.FullName + '.tmp') -Destination $file.FullName -Force;
}
So, I load the file contents with the Image.FromFile method, and I'm trying to save it back to the same filename. I have tried:
$imgInMemory.Dispose() and $graphics.Dispose() followed by the .tmp save call and the move-item call seen above. This still gives an access denied exception.
What am I missing in terms of an open file handle because it would appear that even a -Force on the move-item only removes the .tmp file without overwriting the original file. So if you're doing something, like adding pins to an image, is it possible to save the output back to the original file? And if so, how?
You can do this process without the need to create a temporary file, it's unclear why your code could be failing though this should work:
Open the file to be overwritten with ReadWrite FileAccess.
Use the FromStream method on the input file..
SetFileLength to 0 for the input file before saving the new content to it.
Use either Save(Stream, ImageCodecInfo, EncoderParameters) or Save(Stream, ImageFormat) overloads.
Lastly, call Dispose on all variables.
using namespace System.IO
using namespace System.Drawing
using namespace System.Drawing.Imaging
Add-Type -AssemblyName System.Drawing
$inFile = [FileInfo] 'path\to\file1.ext'
$refFile = 'path\to\file2.ext'
if ($file.Exists) {
$inStream = $inFile.Open([FileMode]::Open, [FileAccess]::ReadWrite)
$inImg = [Image]::FromStream($inStream)
$refImg = [Image]::FromFile($refFile)
# irrelevant code here...
$inStream.SetLength(0)
$inImg.Save($inStream, $imageCodecInfo, $encoderParams)
$refImg, $inImg, $inStream | ForEach-Object Dispose
}

Powershell script works but also gives an error message

The error is as follows:
You cannot call a method on a null-valued expression.
At C:\Across.ps1:6 char:21
+ $result.Handle.Close <<<< ()
+ CategoryInfo : InvalidOperation: (Close:String) [],
RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
The script is as follows:
# Load ntuser.dat
reg load HKU\Across C:\users\Default\NTUSER.DAT
# Create a new key, close the handle, and trigger garbage collection
$result = New-Item -Path
'Registry::HKEY_USERS\Across\Software\AcrossStuff'
$result.Handle.Close()
[gc]::Collect()
#Unload ntuser.dat
reg unload HKU\Across
Can you please help me fix this.
Thanks!
Your $result seems to be null, check the place where it is assigned and ensure that this is not null
It is either your script is not properly lined up or path does not exist. You have to check this.
$result = New-Item -Path 'Registry::HKEY_USERS\Across\Software\AcrossStuff'

cannot call a method on a null-valued expression - how to solve it

I have written a script that gets the zip file from a specific folder and unzip the file to a specific folder.
please check the below codes
$shell_app=new-object -com shell.application
$zip_file = $shell_app.namespace("C:\Users\jhnayak\Views_Seagate\jhnayak_DDTools_Phase14_Dev\apps\ddcli\build\win\\..\\..\\..\\..\sas2_rel\mptlib2_rel\mptlib2_rel.zip")
$destination = $shell_app.namespace("C:\Users\jhnayak\Views_Seagate\jhnayak_DDTools_Phase14_Dev\apps\ddcli\build\win\\..\\..\\..\\..\sas2_rel\mptlib2_rel")
$destination.Copyhere($zip_file.items())
$shell_app=new-object -com shell.application
$zip_file = $shell_app.namespace((Get-Location).Path + "\\..\\..\\..\\..\\sas2_rel\mptlib2_rel" + "\$filename")
$destination = $shell_app.namespace((Get-Location).Path + "\\..\\..\\..\\..\\sas2_rel\mptlib2_rel")
$destination.Copyhere($zip_file.items())
for both the codes i got the same error, please check below
You cannot call a method on a null-valued expression.
At line:1 char:38
+ $destination.Copyhere($zip_file.items <<<< ())
+ CategoryInfo : InvalidOperation: (items:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
when i hardcoded the path without using \..\ in between it worked perfectly.
please check the below code
$shell_app=new-object -com shell.application
$zip_file = $shell_app.namespace("C:\Users\jhnayak\Views_Seagate\jhnayak_DDTools_Phase14_Dev\sas2_rel\mptlib2_rel\mptlib2_rel.zip")
$destination = $shell_app.namespace("C:\Users\jhnayak\Views_Seagate\jhnayak_DDTools_Phase14_Dev\sas2_rel\mptlib2_rel")
$destination.Copyhere($zip_file.items())
but i would like to use the earlier one, so that the path should not be hard coded, it should work for all paths.
What is causing this error?
What exactly is my null valued expression?
Try parsing the path before passing it to $shell_app.namespace(). There is a handy method in .Net that does just that: System.IO.Path.GetFullPath(). Like so,
$relativeLoc = "...build\win\\..\\..\\..\\..\sas2..." # Complex dynamic path
$parsedLoc = [IO.Path]::GetFullPath($relativeLoc) # Get absolute path
$zip_file = $shell_app.namespace($parsedLoc)
As a bonus, you can use Test-Path to check that the target $parsedLoc exists.

How to enter text into an input field through Power Shell?

Here is a PowerShell script to trigger Internet Explorer, open LinkedIn login page and enter some text in the username text field.
$ie = New-Object -Com "InternetExplorer.Application"
$ie.Navigate("www.linkedIn.com")
$ie.Visible = $true
$doc = $ie.document
$usernameElement = $doc.getElementByTagName("input") | Where-Object {$_.id = "session_key-login""}
$usernameElement.Click()
Get-Process iexplore | Foreach-Object {$_.CloseMainWindow()}
Unfortunately, I keep getting the following error:
You cannot call a method on a null-valued expression.
At C:\Users\Pinku\Desktop\Untitled1.ps1:7 char:23
+ $usernameElement.Click <<<< ()
+ CategoryInfo : InvalidOperation: (Click:String) [], RuntimeExcepti
on
+ FullyQualifiedErrorId : InvokeMethodOnNull
I have tried but have not been able to alleviate myself from this issue.Please suggest!
Instead of using $doc.getElementsByTagName("input") and then trying to filter through the results, try retrieving the ID directly using getElementById:
$usernameElement = $doc.getElementById("session_key-login")
$usernameElement.Click()
---Edit---
Response to still getting the null-valued expression after using the above:
The error message is that it can't find any elements called "session_key-login", and so it returns $null, and hence, when you try to invoke the Click() method, it throws the error. Some things to try:
-Check to see if the id exists. Run the following code after creating your $ie object, and see if there is an ID that matches "session_key-login":
$ie = New-Object -Com "InternetExplorer.Application"
$ie.Navigate("www.linkedIn.com")
$ie.Visible = $true
$doc = $ie.document
$doc.getElementsByTagName("Input") | Select Id, Name
-Try running your PowerShell session as Administrator. I know I wasn't able to launch IE properly until I ran PowerShell as Administrator. For ex. even though the iexplore process was created, the physical Internet Explorer window didn't open for me.

Creating a zipped/compressed folder in Windows using Powershell or the command line

I am creating a nightly database schema file and would like to put all the files created each night, one for each database, into a folder and compress that folder.
I have a PowerShell script that creates the schema.Only creation script of the db's and then adds all the files to a new folder. The problem lies within the compression portion of this process.
Does anybody have any idea if this can be accomplished with the pre-installed Windows utility that handles folder compression?
It would be best to use that utility if possible rather than something like 7zip (I don't feel like installing 7zip on every customers' server and it may take IT years to do it if I ask them).
A native way with latest .NET 4.5 framework, but entirely feature-less:
Creation:
Add-Type -Assembly "System.IO.Compression.FileSystem" ;
[System.IO.Compression.ZipFile]::CreateFromDirectory("c:\your\directory\to\compress", "yourfile.zip") ;
Extraction:
Add-Type -Assembly "System.IO.Compression.FileSystem" ;
[System.IO.Compression.ZipFile]::ExtractToDirectory("yourfile.zip", "c:\your\destination") ;
As mentioned, totally feature-less, so don't expect an overwrite flag.
Here's a couple of zip-related functions that don't rely on extensions: Compress Files with Windows PowerShell.
The main function that you'd likely be interested in is:
function Add-Zip
{
param([string]$zipfilename)
if(-not (test-path($zipfilename)))
{
set-content $zipfilename ("PK" + [char]5 + [char]6 + ("$([char]0)" * 18))
(dir $zipfilename).IsReadOnly = $false
}
$shellApplication = new-object -com shell.application
$zipPackage = $shellApplication.NameSpace($zipfilename)
foreach($file in $input)
{
$zipPackage.CopyHere($file.FullName)
Start-sleep -milliseconds 500
}
}
Usage:
dir c:\demo\files\*.* -Recurse | Add-Zip c:\demo\myzip.zip
There is one caveat: the shell.application object's NameSpace() function fails to open up the zip file for writing if the path isn't absolute. So, if you passed a relative path to Add-Zip, it'll fail with a null error, so the path to the zip file must be absolute.
Or you could just add a $zipfilename = resolve-path $zipfilename at the beginning of the function.
As of PowersShell 5 there is a Compress-Archive cmdlet that does the task out of the box.
This compresses .\in contents to .\out.zip with System.IO.Packaging.ZipPackage following the example here
$zipArchive = $pwd.path + "\out.zip"
[System.Reflection.Assembly]::Load("WindowsBase,Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")
$ZipPackage=[System.IO.Packaging.ZipPackage]::Open($zipArchive, [System.IO.FileMode]"OpenOrCreate", [System.IO.FileAccess]"ReadWrite")
$in = gci .\in | select -expand fullName
[array]$files = $in -replace "C:","" -replace "\\","/"
ForEach ($file In $files) {
$partName=New-Object System.Uri($file, [System.UriKind]"Relative")
$part=$ZipPackage.CreatePart($partName, "application/zip", [System.IO.Packaging.CompressionOption]"Maximum")
$bytes=[System.IO.File]::ReadAllBytes($file)
$stream=$part.GetStream()
$stream.Write($bytes, 0, $bytes.Length)
$stream.Close()
}
$ZipPackage.Close()
Used voithos' answer to zip files up in powershell, just had one problem with the Add-Zip function, the Start-sleep -milliseconds 500 caused problems if the file couldn't be fully zipped up in that time -> the next one starting before it was complete caused errors and some files not to be zipped.
So after playing around for a bit, first trying to get a counter going to check the count of the $zipPackage.Items() and only continuing after the items count increased (which did not work as it would return 0 in some cases when it should not) I found that it will return 0 if the package is still zipping/copying the files up (I think, haha). Added a simple while loop with the start-sleep inside of it, waiting for the zipPackage.Items().count to be a non-zero value before continuing and this seems to solve the problem.
function Add-Zip
{
param([string]$zipfilename)
if(-not (test-path($zipfilename)))
{
set-content $zipfilename ("PK" + [char]5 + [char]6 + ("$([char]0)" * 18))
(dir $zipfilename).IsReadOnly = $false
}
$shellApplication = new-object -com shell.application
$zipPackage = $shellApplication.NameSpace($zipfilename)
foreach($file in $input)
{
$zipPackage.CopyHere($file.FullName)
do
{
Start-sleep -milliseconds 250
}
while ($zipPackage.Items().count -eq 0)
}
}
Using PowerShell Version 3.0:
Copy-ToZip -File ".\blah" -ZipFile ".\blah.zip" -Force
Hope this helps.

Resources