Powershell not sending the right path for a file as argument - powershell

I'm trying to apply a hash function to all the files inside a folder as some kind of version control. The idea is to make a testfile that lists the name of the file and the generated checksum. Digging online I found some code that should do the trick (in theory):
$list = Get-ChildItem 'C:\users\public\documents\folder' -Filter *.cab
$sha1 = New-Object System.Security.Cryptography.SHA1CryptoServiceProvider
foreach ($file in $list) {
$return = "" | Select Name, Hash
$returnname = $file.Name
$returnhash = [System.BitConverter]::ToString($sha1.ComputeHash([System.IO.File]::ReadAllBytes($file.Name)))
$return = "$returnname,$returnhash"
Out-File -FilePath .\mylist.txt -Encoding Default -InputObject ($return) -Append
}
When I run it however, I get an error because it tries to read the files from c:\users\me\, the folder where I'm running the script. And the file c:\users\me\aa.cab does not exist and hence can't be reached.
I've tried everything that I could think of, but no luck. I'm using Windows 7 with Powershell 2.0, if that helps in any way.

Try with .FullName instead of just .Name.
$returnhash = [System.BitConverter]::ToString($sha1.ComputeHash([System.IO.File]::ReadAllBytes($file.FullName)))

Related

Read XML in Powershell 2.0

Note: When use Get-Host getting Version: 2.0 in powershell.
In Windows 2008 server, executed below code to create domainlist.xml file at System32 folder.
Start-Process -FilePath "C:\Windows\System32\rendom.exe" -ArgumentList "/list"
Using below query to read the xml but it is error out.
$path = "C:\Users\074129\Desktop\Domainlist.xml"
$xml = [xml](Get-Content -Path $path)
$xml.Forest.Domain.NetBiosName[2]
Error Message: Cannot index into a null array
No value is returning even for '$xml.Forest' command.
Please help to read and replace the node value in domainlist.xml file.
Let me know if any additional details required from my end.
If I correctly understood your situation you cannot get NetBiosName node from Domainlist.xml. Actually, there is a scenario when all NetBiosName nodes are empty that's why you should check them first (the reasons of this behavior are different).
$xml = 'C:\Users\074129\Desktop\Domainlist.xml'
if (($col = Select-Xml -Path $xml -XPath //NetBiosName) -is [Array]) {
$col[2].Node
# or if you need find all non-empty nodes
# $col | Where-Object {$_.Node.'#text' -ne $null}
}
This is a known problem of old powershell versions.
It should work if you load the xml manually instead if I remember correctly:
$path = "C:\Users\074129\Desktop\Domainlist.xml"
$xml = New-Object -TypeName "System.Xml.XmlDocument"
$xml.Load($path)
$xml.Forest.Domain.NetBiosName[2]

Saving SHA1 algorithm outputs to a text file

Morning,
I've got this powershell script as followed:
$zips = Get-ChildItem 'C:\Users\X\Desktop\Powershell\Zip\' - Filter *.zip
$sha1 = New-Object System.Security.Cryptography.SHA1CryptoServiceProvider
foreach ($file in $zips) {
$return = "" | Select Name, Hash
$return.name = $file.Name
$return.hash = [System.BitConverter]::ToString($sha1.ComputeHash([System.IO.File]::ReadAllBytes($file.FullName)))
Write-Output $return
[System.IO.File}::WriteAllText("C:\Users\X\Desktop\Info\"+ $_.Name + ".txt", $_.FullName)
}
Read-Host -Prompt "Press Enter to Exit"
So it calculates the SHA1 hash for all the zip files in the folder 'zip', I am trying to get it to save the hashes to a text file in the location \desktop\info\, with an individual text file for each zip file.
The hash is calculated with no problems, and it prints it within the powershell window, but all it does at the moment is create a singular text file with no data in it, and with no name.
What am I missing? I've tried using information from another script that does something very similar, but I cant seem to produce the same result.
Any help is appreciated.
Try this:
[System.IO.File]::WriteAllText("C:\Users\X\Desktop\Info\"+$return.Name+".txt",$return.Hash)
Instead of
[System.IO.File}::WriteAllText("C:\Users\X\Desktop\Info\"+ $_.Name + ".txt", $_.FullName)
try this:
$return.hash | Out-File "C:\Users\X\Desktop\Info\$($file.BaseName).txt"

How can I save an XML in a path with 260+ characters?

Here is my situation. I have an XML that resides in a path that contains 260+ characters. One of the folders in this path will always be random, another one is based on versions so it could be different as well.
I am trying to load the XML, make changes to it, and save it back. So far I haven't been able to do that in place so I am copying it to C:\Windows\Temp, making the changes there, and then trying to copy it back in place, which has worked in manual tests.
My main problem is the file path contains more than 260+ characters so Copy-Item hasn't worked properly and I haven't been able to figure out how to get Robocopy to work since I have to use a variable for the path because of the random folders.
XML modification works, copying out to Temp works, the problem I am having is copying it back to the 260+ character path.
I am very new to Powershell as an FYI. Here is what I have come up with so far:
$folderLocation = Get-ChildItem -Path C:\Windows\System32\config\systemprofile\AppData\Local\ProgramA\ -Filter userConfig.xml -Recurse |
Sort-Object LastWriteTime |
Select-Object -last 1 |
Select-Object Directory |
Format-Table -hide
foreach ($f in $folderLocation){
Copy-Item userConfig.xml C:\Windows\Temp
}
$myXML = New-Object System.Xml.XmlDocument
$myXML.Load("C:\Windows\Temp\userConfig.xml")
$isActive = $myXML.SelectSingleNode("//setting[#name = 'Active']")
$isActive.value = "True"
$myXML.Save("C:\Windows\Temp\userConfig.xml")
$convertFolder = [System.String]$folderLocation
Copy-Item ("C:\Windows\Temp\userConfig.xml") $convertFolder
Here is the Robocopy code I tried, I know it's a hackjob but I tried to imitate some things I saw online:
function copy-stuff
{
param([string]$source = "C:\Windows\Temp",
[string]$destination = $convertFolder,
[string]$options = “/R:0″,”/W:0″,”/COPY:DAT”)
[string]$file = "userConfig.xml"
robocopy $source $destination $file $options
}
I tried a couple different things with robocopy but this is what I still had saved. I haven't studied up on creating and using functions in Powershell so this was a monkey see monkey do attempt.
Addressing the Robocopy part of your code:
It looks like you aren't passing anything to your function, but are relying on default values. Try this:
function Copy-Stuff {
param (
[string]$source,
[string]$destination,
[string]$file
)
robocopy $source $destination $file /R:0 /W:0 /COPY:DAT
}
$convertFolder = "blahblah"
Copy-Stuff -Source "C:\Windows\Temp" -Destination $convertFolder -File "userConfig.xml"
If the options never change, then don't bother making them a variable.

Powershell script to extract Cab file contents and move files to new locations

I've been given 14K CAB files each containing 200 files which need to be unzipped into their original locations.
Unfortunately it's not as easy as all of them being extracted to the same location :-(
I've decided to use PowerShell and have generated a list of individual file locations for each file using SQL and can extract the CABs, unfortunately they all extract to the current location.
I am trying to move them to their respective locations, but am struggling.
Here's the code, I've got so far
$shell_app=new-object -com shell.application
$CABfilename= Import-CSV "CABFileList.csv" -Header CABfilename | Foreach-object {
$zip_file = $shell_app.namespace((Get-Location).Path + "\$CABfilename")
$destination = $shell_app.namespace((Get-Location).Path)
$destination.Copyhere($zip_file.items())
$dvs = Import-csv "CABFileList.csv" -Header Path, DVSFilename |
Foreach-object{
Move-item $_.DVSFilename* $_.Path
}
This is an old question, but someone might find the answer useful anyway. I have adapted one I made today to download all WSPs from a farm and extract their contents.
$CABfilename = Import-CSV "CABFileList.csv" -Header CABfilename | Foreach-object {
# Grab the Solution
$Path = $SaveLocation + $CABfilename
# Check the path is ok
$Path
# Make a copy with extension '.cab' for extraction
$DotCab = $CABfilename + ".cab"
$SolutionDir = $Dotcab -replace '.wsp.cab'
mkdir $SolutionDir
copy-item $CABfilename $DotCab
# Now extract it, assuming you have expand.exe in the filsystem (should be in everything post Server 2008 / Vista)
if(C:\Windows\System32\expand.exe) {
try { cmd.exe /c "C:\Windows\System32\expand.exe -F:* $Dotcab $SolutionDir"}
catch { Write-host "Nope, don't have that, soz."}
}}

(Powershell) Loop to delete files from an FTP Location

Good morning!
I have made it to the last (and rather pivotal) stage in my script, which is looping to delete files from a directory. I'm not going to pretend I'm knowledgeable at Powershell (far from it), so I'm sort-of chopping up blocks of code I find on the net, improvising and hoping it works.
I'm hoping someone can decipher what I'm trying to do here and see what I'm doing wrong!
# Clear FTP Directory
$DelLoop=1
$server = "www.newsbase.com"
$dir = "/usr/local/tomcat/webapps/newsbasearchive/monitors/asiaelec/"
"open $server
user Canttell Youthis
binary
cd $dir
" +(
For ($DelLoop=1; $DelLoop -le 5; 5)
{
$FileList[$DelLoop] | %{ "delete ""$_""`n" }
$DelLoop++
})| ftp -i -in
I know that the 'Open Connection' portion works, it's just the loop. It just keeps complaining about misplaced operators, and when I fix those, it doesn't throw up any errors - but it doesn't do anything either.
I spent the best part of 4 hours researching this yesterday, and I'm hoping one of you guys can help me.
Thanks in advance!
ADDENDUM:
Here is more of the code, as requested:
# Clear existing .htm file to avoid duplication
Get-ChildItem -path ".\" -recurse -include index.jsp | ForEach-Object {
Clear-Content "index.jsp"
}
# Set first part of .JSP Body
$HTMLPart1="</br><tr><td colspan=9 align=center><p style=""font-family:Arial"">Here are the links to the last 3 AsiaElec PDFs:</br><ul>"
# Recurse through directory, looking for 3 most recent .PDF files 3 times
$Directory="C:\PDFs"
$HTMLLinePrefix="<li><a style=""font-family:Arial""href="""
$HTMLLineSuffix="</a></li>"
$HTMLLine=#(1,2,3,4)
$Loop=1
$PDF=#(1,2,3,4)
Get-ChildItem -path $Directory -recurse -include *.pdf | sort-object -Property LastWriteTime -Descending | select-object -First 3 | ForEach-Object {
$PDF[$Loop]=$_.name
$HTMLLine[$Loop]=$HTMLLinePrefix + $_.name + """>" + $_.name + $HTMLLineSuffix
$Loop++
}
# Final .JSP File Assembly
Get-Content "header.html" >> "index.jsp"
$HTMLPart1 >> "index.jsp"
$LineParse=""
$Loop2=1
For ($Loop2=1; $Loop2 -le 3; 3)
{
$HTMLLine[$Loop2] >> "index.jsp"
$Loop2++
}
Get-Content "tail.html" >> "index.jsp"
# Prepare File List
$FileList=#(1,2,3,4,5)
$FileList[2]=$PDF[2]
$FileList[3]=$PDF[3]
$FileList[4]="index.jsp"
# Clear FTP Directory
$DelLoop=1
$server = "www.newsbase.com"
$dir = "/usr/local/tomcat/webapps/newsbasearchive/monitors/asiaelec/"
"open $server
user derek bland1ne
binary
cd $dir
" +(
For ($DelLoop=1; $DelLoop -le 5; 5)
{
$FileList[$DelLoop] | %{ "delete ""$_""`n" }
$DelLoop++
})| ftp -i -in
This isn't all of it, but I believe it contains all the relevant info.
Your $dir path looks like you're on a unix system so this may be a little different, but all you need to do is change your final loop a little bit:
For ($DelLoop=1; $DelLoop -le 5; $DelLoop++)
{
$FileList[$DelLoop] | % { rm $FileList[$DelLoop] }
}
This is assuming that $FileList contains the files you want to delete and not only (what I'm guessing are dummy) numbers. I also suggest that you download the Module that #Graimer mentions and then put it in WindowsPowerShell > Modules > %ModuleFolder% > %Module.psm1% and import it from your profile.
You can then just use PS> Remove-FTPItem -Path "/myFolder" -Recurse to remove your FTP stuff. Making your life easier.
Tweaking the solution to this post may also help Upload files with FTP using PowerShell
e.g:
Using $ftp.Method = [System.Net.WebRequestMethods+Ftp]::DeleteFile to delete the file,
and $response = $ftp.GetResponse() to find out if things went smoothly.
EDIT
Wrote this function after doing a little bit of research from here http://social.msdn.microsoft.com/forums/en-US/netfxnetcom/thread/17a3abbc-6144-433b-aadd-1f776c042bd5 and adapting the code from the Accepted Answer in the above link as well as the module #Graimer talked about.
function deleteFTPSide
{
Param(
[String] $ftpUserName = "muUserName",
[String] $ftpDomain = "ftp.place.com", # Normal domains begin with "ftp" here
[String] $ftpPassword = "myPassword",
[String] $ftpPort = 21, # Leave as the default FTP port
[String] $fileToDelete = "folder.domain.com/subfolder/file.txt"
)
# Create the direct path to the file you want to delete
[String] $ftpPath = "ftp://"+"$ftpUserName"+":"+"$ftpPassword#$ftpDomain"+":"+"$ftpPort/$fileToDelete"
# create the FtpWebRequest and configure it
$ftp = [System.Net.FtpWebRequest]::Create($ftpPath)
$ftp.Method = [System.Net.WebRequestMethods+Ftp]::DeleteFile
$ftp.Credentials = new-object System.Net.NetworkCredential($ftpUserName,$ftpPassword)
$ftp.UseBinary = $true
$ftp.UsePassive = $true
$response = [System.Net.FtpWebResponse]$ftp.GetResponse()
$response.Close()
}
While, admittedly, not one of the most elegant solutions written, I've tested it and it works at deleting a specified file off an FTP server.